Skip to content

feat(linux/wlr): Implement ext-image-copy-capture - #4788

Draft
Dregu wants to merge 1 commit into
LizardByte:masterfrom
Dregu:icc
Draft

Dregu wants to merge 1 commit into
LizardByte:masterfrom
Dregu:icc

Conversation

@Dregu

@Dregu Dregu commented Feb 27, 2026 •

Copy link
Copy Markdown
Contributor

I'm putting this draft up simply because these linux prs keep popping up every day and by monday three more people will have implemented this probably, so it would be silly to keep it to myself when it's already pretty much done.

Description

Adds the ext-image-copy-capture protocol as primary backend for the wayland capture method, but keeps wlr-screencopy as a fallback, as it is still slightly better supported. Also supports actual output names in output_name, like that other pr.

  • Implements ext-image-copy-capture-v1 protocol, mostly
  • Some fixes to wlr-screencopy, like picking the wrong drm device on multi gpu
  • Adds support for connector names in output_name

Screenshot

Issues Fixed or Closed

Roadmap Issues

Type of Change

  • feat: New feature (non-breaking change which adds functionality)
  • fix: Bug fix (non-breaking change which fixes an issue)
  • docs: Documentation only changes
  • style: Changes that do not affect the meaning of the code (white-space, formatting, missing semicolons, etc.)
  • refactor: Code change that neither fixes a bug nor adds a feature
  • perf: Code change that improves performance
  • test: Adding missing tests or correcting existing tests
  • build: Changes that affect the build system or external dependencies
  • ci: Changes to CI configuration files and scripts
  • chore: Other changes that don't modify src or test files
  • revert: Reverts a previous commit
  • BREAKING CHANGE: Introduces a breaking change (can be combined with any type above)

Checklist

  • Code follows the style guidelines of this project
  • Code has been self-reviewed
  • Code has been commented, particularly in hard-to-understand areas
  • Code docstring/documentation-blocks for new or existing methods/components have been added or updated
  • Unit tests have been added or updated for any new or modified functionality

AI Usage

  • None: No AI tools were used in creating this PR
  • Light: AI provided minor assistance (formatting, simple suggestions)
  • Moderate: AI helped with code generation or debugging specific parts
  • Heavy: AI generated most or all of the code changes

@ReenigneArcher

Copy link
Copy Markdown
Member

Thanks! It seems the PR was not based on an updated version of master. Could you rebase it?

@Dregu

Dregu commented Feb 27, 2026

Copy link
Copy Markdown
Contributor Author

Yeah sure next week, I just pushed it as a placeholder.

@Dregu
Dregu force-pushed the icc branch 3 times, most recently from a531c36 to 66e784a Compare March 1, 2026 15:35
@Dregu

Dregu commented Mar 1, 2026

Copy link
Copy Markdown
Contributor Author

I hate submodules.

@sonarqubecloud

sonarqubecloud Bot commented Mar 1, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
16 New issues
16 New Code Smells (required ≤ 0)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@LizardByte-bot

Copy link
Copy Markdown
Member

It looks like this PR has been idle for 90 days. If it's still something you're working on or would like to pursue, please leave a comment or update your branch. Otherwise, we'll be closing this PR in 10 days to reduce our backlog. Thanks!

@Dregu

Dregu commented Aug 21, 2026

Copy link
Copy Markdown
Contributor Author

Oh hi bot, had a nice summer? I honestly have not followed or used sunshine for 90 days, but I'm kinda still invested in rebasing this and getting it over with. I'll try to remember to do something in the next few weeks. wlr-screencopy has been deprecated for 2 years anyway and should die.

Adds the new image-copy-capture protocol in staging as primary backend for
the wayland capture method, but keeps wlr-screencopy as a fallback
Also supports actual output names in output_name
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
5 New issues
5 New Code Smells (required ≤ 0)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@Dregu

Dregu commented Aug 25, 2026

Copy link
Copy Markdown
Contributor Author

Rebased. There are only minor changes since Feb, like letting gbm pick the modifiers. May have somehow degraded the fixes that were made to the old screencopy proto while I was out, but it's not even supposed to be used.

MrOz59 pushed a commit to MrOz59/Hermes that referenced this pull request Sep 1, 2026
wlr-screencopy is a wlroots protocol. Hyprland, labwc and sway offer it;
the compositors that never did - GNOME among them - had no capture path
here at all. ext-image-copy-capture is what replaced it, and this is the
backend that reads it.

Nothing that works today moves. Where a compositor offers both,
screencopy stays the default: every working deployment is on that path
and a stream is not worth trading for a newer protocol.
HERMES_WAYLAND_CAPTURE=icc or =screencopy forces one, which is how the
other gets tested on a session that offers both.

The two are asked for a frame differently. Screencopy negotiates a
buffer per frame; an image-copy-capture session negotiates once - size,
format and modifiers - and then hands out frames, so a frame arrives
only when the output is next presented. A desktop with nothing moving on
it produces none, which reaches the encoder as a timeout and re-sends
the previous frame, exactly as an idle screencopy capture does.

Two things this protocol gives that screencopy could not. The compositor
names the DRM device it renders on, which is the question init_gbm()
otherwise has to guess the answer to on a machine with two GPUs; it is
taken as the answer, after the same allocation probe every other
candidate gets, so a compositor naming a device nothing can allocate on
still falls through to the search. And it offers format modifiers, which
on AMD means the buffer can have more than one plane - every plane is
shared, because a compositor handed only the first plane of a compressed
buffer fails the frame with no reason attached.

That probe is also exposed as wl::render_node_can_allocate(), since
"this node opens" and "this node can produce a buffer" are different
questions and only the second one matters.

Verified against a headless labwc: a session negotiated, frames
produced, and repeated capture on one session. The tests talk to
whatever compositor is on WAYLAND_DISPLAY and skip when there is none.

Note what this does not deliver: KWin 6.7 does not implement the
protocol at all - it speaks only zkde_screencast_unstable_v1 - so
capturing an existing KDE desktop still has no path.

The protocol sequence follows Dregu's draft for upstream Sunshine
(LizardByte/Sunshine#4788), credited in the source beside the three
places this departs from it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants