Add opt-in portal resize for fractional Wayland scaling - #42
Open
espentveit wants to merge 1 commit into
Open
Conversation
espentveit
force-pushed
the
main
branch
2 times, most recently
from
September 5, 2026 10:30
b017fad to
a9990b5
Compare
On fractionally scaled Wayland outputs, xdg-desktop-portal reports the logical output size while PipeWire delivers a physical-size buffer. The compositor output is pinned to the reported size, but its sink pad does not scale, so it crops the larger frame to the top-left corner. Add -portal-resize to fit the captured frame to the reported canvas with vapostproc before compositing. Since the portal does not expose the physical size, request the caps whenever the option is enabled and rely on vapostproc to negotiate passthrough when the sizes already match. Limit the resize to the GPU path. Systems without vapostproc retain the existing behavior instead of paying for an additional software scale.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This fixes cropped screen mirroring on fractionally scaled Wayland
outputs.
The ScreenCast portal reports the output's logical size, while PipeWire
delivers a physical-size buffer. For example, a 2560x1600 panel at 166%
scale is reported as 1536x960, but the stream carries 3072x1920 frames.
The pipeline pins the compositor output to 1536x960, and the compositor
places its input at 0,0 without scaling it. The result is the top-left
1536x960 portion of the frame rather than the full desktop.
The new
-portal-resizeoption adds a caps filter aftervapostproc,fitting the frame to the portal-reported canvas on the GPU before it
reaches the compositor.
The portal does not provide the physical buffer size, so the target caps
are requested unconditionally when the option is enabled. This is safe
when the dimensions already match because
vapostprocnegotiatespassthrough.
Performance
These measurements processed 600 buffers, with two runs per case:
fakesink, novapostprocvapostprocto 1536x960fakesink, novapostprocvapostprocto 1536x960The matching-size case confirms that
vapostprocpasses the framethrough. The cost of the real resize is below the measurement noise.
Only the
vapostprocpath is fitted. Adding the same operation to thesoftware path would impose another scale on the systems least able to
absorb it. If
vapostprocis unavailable, the option logs that it isinactive and preserves the existing cropped behavior.
I also tried removing the compositor caps pin and allowing the physical
frame to reach the existing software
videoconvertandvideoscale.That fixed the crop, but the 10-bit pipeline could not sustain 30 fps at
the physical resolution. Source age passed 1.7 seconds and continued to
rise while presentation slack became steadily more negative.
Verification
I tested against an Apple TV 4K (AppleTV14,1) running tvOS 26.6. The
full desktop was visible with the correct aspect ratio, source age
remained between 35 and 50 ms with positive presentation slack, and the
stream stayed stable for several minutes.
The sender was running GNOME 50.1 on Wayland at 166% scaling, GStreamer
1.28.2, Mesa radeonsi on a Radeon 860M, and NVENC HEVC on an RTX 5070.
go test ./...passes.The option is off by default. I am happy to make it the default if you
prefer.