Fixes incorrectly rejecting scanout for gamma2.2 buffers when the output
has no image description set. This happens on `hdr off` mode on sway.
Also refactor the scanout check into its own function while at it to
make it easier to follow.
We were incorrectly doing comparison with `!= 0` to detect non-sRGB
tf/primaries. Since these enums are bit flags, the default sRGB values
are 1, not 0, so sRGB buffers were incorrectly rejected.
Fixes: bf40f396bf ("scene: grab image description from output state")
We cache whether buffers are single-pixel buffers (and if so what color
they are) to allow rendering optimizations. But this breaks if the
client changes out the single-pixel buffer for one with a different
color, because this updates the texture in-place instead of actually
changing the buffer.
We can fix this by blocking in-place texture updates for single pixel
buffers.
Original bug: https://codeberg.org/ifreund/waylock/issues/121
See also: !5092
If a surface is mirrored on two outputs, we don't want to pick the
first output if the second has a higher refresh rate.
Also fixes duplicate frame/feedback events when a surface is added
to multiple scenes.
This lets the surface handler decide which output to send frame
callbacks from. The output_sample event already works this way.
Introduce wlr_scene_surface_send_frame_done() as a replacement for
wlr_scene_buffer_send_frame_done() when a compositor doesn't have
an output at hand.
If a surface appears on two outputs with the same intersection
area, or even if a surface appears on an output with a small
intersection area, we want to use the highest scale.
Fixes flip-flop when a surface is added to multiple scenes.
References: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3901
scene_entry_try_direct_scanout returns a tristate value, but the log
message was not updated to account for this.
Compare whether or not the state is specifically SCANOUT_SUCCESS for
logging purposes.
Fixes: c450991c4b
Move single-pixel buffer status cache from wlr_scene_surface to
wlr_scene_buffer, it makes more sense there and means the optimisations
will still work if wlr_scene_buffer is used without wlr_scene_surface.
Direct scanout can be enabled and disabled on a frame-by-frame basis,
and so we could end up sending different feedback to a surface on every
other frame. Reacting to new feedback is expensive, as the client may
need to reallocate their swapchain.
Debounce the state change a number of frames, for now set to 30, to
avoid immediate reaction to scanout (or composition) that only lasts a
few frames.
A timer could be used instead, but it did not seem worth the complexity.
What just want to know that the state has been stable across a
reasonable number of samples, and a counter seems sufficient for that.
The single-pixel buffer protocol is used to allow wayland clients to
easily draw solid-color rectangles by presenting a 1x1-pixel buffer and
scaling it to the desired size. This patch improves how these buffers
are then handled in the scene-tree renderer.
We already ignore opaque black rectangles at the very bottom (and
anything under them) because we assume we'll be rendering on a black
background. This patch detects black opaque single-pixel buffers and
handles them in the same way as black opaque rectangles. It also
renders single-pixel buffers as rectangles rather than buffers because
this is probably more efficient in the underlying renderer.
In wlr_scene_surface we cache whether the attached buffer is a
single-pixel buffer. This is done because the
wlr_single_pixel_buffer_v1 will be destroyed after texture upload, after
which it becomes much more annoying to check if the buffer is a
single-pixel buffer.
We were signaling the release timeline point when the
wlr_client_buffer was released. However, the wlr_client_buffer isn't
necessarily released at the same time as the underlying source
wlr_buffer. For instance, with wl_shm the source buffer is released
before the wlr_client_buffer, and with linux-dmabuf-v1 the source
buffer is released after the wlr_client_buffer. However, we want
to signal the release timeline point exactly at the same time we
send the wl_buffer.release event to the client.
Use surface->buffer->source instead of &surface->buffer->base to
fix this.
linux-drm-syncobj-v1 can only be used with DMA-BUFs, and
wlr_client_buffer.texture will keep the source locked, so
surface->buffer->source is guaranteed to be non-NULL and unreleased.
Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3940
Fixes: 9e71c88467 ("scene: unwrap wlr_client_buffer for direct scan-out")
Remove unneeded includes of wlr_output.h from wlr_compositor.h and
wlr_cursor.h (unneeded now that we forward-declare struct wlr_surface)
and put the actually-required includes in the right places.
The surface's buffer dimensions were used to scale the clip's x/y
offset. If a surface had a larger buffer than src_box, the calculations
to scale the x/y portion of the clip would be incorrect, yielding
graphical glitches.
This was noticed with Chromium in sway, which during resize uses a
viewport with a src_box to avoid immediate buffer reallocation. While
the viewport was in use, the surface would be shifted so that too much
content was cropped in the upper left, and damage glitching was visible
in the lower right.
Use the buffer source box dimensions instead.
Replace them with pixman_region32_empty(), which avoids using a
double-negative when checking if a region is empty. Also use that
new function when checking for non-empty regions so that only one
variant of the Pixman API is used.
Client buffers backed by wl_shm is aggressively released, in which case
we are not allowed to access it. Locking an already released buffer and
later unlocking it will also re-trigger release, confusing clients.
As a quick workaround, guard the unwrap by checking if the buffer is
locked, which will be the case for non-wl_shm buffers.
Passing the wlr_client_buffer directly has a downsides because a
fresh wlr_buffer pointer is passed each output commit instead of
cycling through existing wlr_buffer objects:
- The FDs are re-imported each time in the backend.
- Any import failure is logged every output commit [1].
- The Wayland backend cannot handle import failures without
roundtripping each output commit [2].
Instead, extract the source buffer from the wlr_client_buffer and
pass that to the backend.
[1]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4836
[2]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4841
We support direct scanout when there is an output and buffer
transform so long as the transforms are the same (so cancel out for the
buffer contents). But we still need to apply the output transform to
the destination box location and size.
When setting the primary buffer location for direct scanout, subtract
the offset of that output to put the buffer location in output-relative
coordinates.
Fixes#3910
Enable scene-tree direct scanout of a single buffer with various options
for scaling and source crop. This is intended to support direct scanout
for fullscreen video with/without scaling, letterboxing/pillarboxing
(e.g. 4:3 content on a 16:9 display), and source crop (e.g. when
1920x1088 planes are used for 1920x1080 video).
This works by explicitly specifying the source crop and destination box
for the primary buffer in the output state. DRM atomic and libliftoff
backends will turn this into a crop and scale of the plane (assuming the
hardware supports that). For the Wayland/X11/DRM-legacy backends I just
reject this so scanout will be disabled.
The previous behaviour is preserved if buffer_src_box and buffer_dst_box
are unset: the buffer is displayed at native size at the top-left of the
output with no crop.
The change to `struct wlr_output_state` makes this a binary breaking
change (but this works transparently for scene-tree compositors like
labwc after a recompile).
Since wlr_damage_ring now only works with buffer local coordinates, this
creates an inpedance mismatch for compositors that want to use this
function. Instead of compositors needing to the the conversion itself,
change thu function to take buffer local coordinates directly.