Commit graph

310 commits

Author SHA1 Message Date
llyyr
5529aae3e6 wlr_scene: fix direct scanout for gamma2.2 buffers
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.
2025-10-05 23:53:25 +05:30
llyyr
6e1c8748ff render: introduce bt.1886 transfer function 2025-10-04 18:13:37 +05:30
Félix Poisot
d8fb7adcf0 scene, render: use Gamma 2.2 TF as default 2025-10-03 19:48:12 +00:00
Félix Poisot
c2d9ae2142 render: introduce Gamma 2.2 color transform 2025-10-03 19:39:17 +00:00
Simon Ser
6978509f64 Revert "wlr_scene: fix tf/prim comparison for scanout attempt"
This reverts commit dde07b6840.

This is incorrect as discussed here:
https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5163#note_3118744
2025-10-03 20:42:21 +02:00
llyyr
2252854297 wlr_scene: return scene_direct_scanout_result instead of bool 2025-10-02 13:51:41 +05:30
llyyr
dde07b6840 wlr_scene: fix tf/prim comparison for scanout attempt
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")
2025-10-02 11:57:52 +05:30
Simon Ser
7cb3393e75 scene: send color_management_v1 surface feedback
Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3999
2025-09-23 09:22:00 -04:00
Simon Ser
bd566225ea scene/surface: fix NULL deref when source buffer is destroyed
Fixes the following crash, witnessed after a GPU reset:

    #0  0x00007fba9a32774c n/a (libc.so.6 + 0x9774c)
    #1  0x00007fba9a2cddc0 raise (libc.so.6 + 0x3ddc0)
    #2  0x00007fba9a2b557a abort (libc.so.6 + 0x2557a)
    #3  0x00007fba9a2b54e3 n/a (libc.so.6 + 0x254e3)
    #4  0x00007fba9a53fb78 wlr_linux_drm_syncobj_v1_state_signal_release_with_buffer (libwlroots-0.20.so + 0x26b78)
    #5  0x00007fba9a590846 surface_reconfigure (libwlroots-0.20.so + 0x77846)
    #6  0x00007fba9a590cbb scene_surface_set_clip (libwlroots-0.20.so + 0x77cbb)
    #7  0x00007fba9a590efa subsurface_tree_set_clip (libwlroots-0.20.so + 0x77efa)
    #8  0x00007fba9a590f1f subsurface_tree_set_clip (libwlroots-0.20.so + 0x77f1f)
    #9  0x00007fba9a590f1f subsurface_tree_set_clip (libwlroots-0.20.so + 0x77f1f)
    #10 0x00007fba9a590f8d wlr_scene_subsurface_tree_set_clip (libwlroots-0.20.so + 0x77f8d)

Reported-by: Hubert Hirtz <hubert@hirtz.pm>
2025-09-11 12:33:04 +00:00
Simon Ser
b62c6878e1 scene/surface: simplify single-pixel-buffer check in surface_reconfigure()
No need to call wlr_client_buffer_get() on wlr_client_buffer.base:
we're already manipulating a wlr_client_buffer.
2025-09-11 12:33:04 +00:00
Simon Ser
2f2c0dfcc6 scene: use helpers to convert TF/primaries enums 2025-07-24 15:02:39 +00:00
Félix Poisot
31b78a4f3a scene: fix output transfer functions
fixes: bf40f396b
2025-07-03 12:29:27 +00:00
David Turner
58c3680d96 scene: Block damage on single-pixel buffer textures
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
2025-07-01 11:38:56 +01:00
Simon Ser
bf40f396bf scene: grab image description from output state
Alternative to https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5089
2025-06-26 09:56:12 +00:00
Simon Ser
0c272a3842 scene: add support for color-management-v1 primaries 2025-06-18 19:37:55 +00:00
Simon Ser
071773cb27 scene: add primaries support to wlr_scene_buffer 2025-06-18 19:37:55 +00:00
Simon Ser
7a1161438c scene: add support for color-management-v1 transfer functions 2025-06-18 19:37:55 +00:00
Simon Ser
4efec11721 scene: add transfer function support for wlr_scene_buffer 2025-06-18 19:37:55 +00:00
Simon Ser
c6133f9912 scene: send surface preferred transform alongside DMA-BUF feedback
wl_surface.preferred_buffer_transform is mainly useful to make
direct scan-out more likely. It shouldn't make a difference with
GL/Vulkan rendering.
2025-06-16 07:54:00 +00:00
Simon Ser
6204fc3278 scene: use output with highest refresh rate for frame pacing
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.
2025-06-16 07:54:00 +00:00
Simon Ser
51d051497d scene: filter frame_done primary output in surface handler
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.
2025-06-16 07:54:00 +00:00
Simon Ser
8713ac72fb scene: configure clients with the highest output scale
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
2025-06-16 07:54:00 +00:00
Simon Ser
95b2771bfd scene: ignore outputs with too small intersection with nodes
If a node has a very small intersection with an output, there's no
point in trying to adapt the node's rendering to that output.
2025-06-16 07:54:00 +00:00
Simon Ser
da820070f4 ext_image_capture_source_v1: add helper to capture scene nodes 2025-06-16 07:54:00 +00:00
Kenny Levinsen
4277d8cfdc scene: Fix scanout log to respect SCANOUT_SUCCESS
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
2025-04-14 20:36:09 +02:00
David Turner
0bf0c55ad2 scene: Move single-pixel buffer things to scene_buffer
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.
2025-04-11 14:01:35 +00:00
Kenny Levinsen
c450991c4b wlr_scene: Debounce dmabuf feedback on scanout
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.
2025-04-10 12:44:03 +00:00
David Turner
792bee9657 scene: Optimize rendering of single-pixel buffers
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.
2025-04-07 13:28:51 +01:00
Simon Ser
128cd07e91 scene/surface: use source buffer to signal release timeline point
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")
2025-03-22 23:55:24 +00:00
Kirill Primak
a9542b9565 scene: don't mention damage in region-scaling functions 2025-03-03 17:57:48 +03:00
Kirill Primak
602a00ec1f scene: don't always round scaled regions up
It makes sense for damage, less so for opaque regions.
2025-03-03 14:50:57 +03:00
David Turner
c9d6339b60 Fix includes of wlr_output.h
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.
2025-02-21 13:44:42 +00:00
Kenny Levinsen
dc7dba8b1f scene/surface: Do not use buffer dimensions for clip
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.
2025-02-18 14:39:17 +00:00
Simon Ser
83c5b15194 Remove all calls to pixman_region32_not_empty()
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.
2025-01-29 23:37:06 +01:00
Guido Günther
1ee3ed4310 buffer: Make wlr_buffer_is_opaque public
It's useful for compositors.
2025-01-25 23:42:49 +01:00
Kirill Primak
8f56f7ca43 Assert (almost all) signals have no attached listeners on destroy 2025-01-15 19:53:11 +03:00
Simon Ser
b2c3c371fc scene: assert on bad wlr_scene_buffer params
We assert in wlr_renderer if these are invalid. Assert earlier to
make debugging easier.
2024-11-22 18:49:50 +00:00
Alexander Orzechowski
0d6cc471e9 scene: Assert all signals are clear when destroying 2024-11-22 09:55:51 -05:00
Kenny Levinsen
c3acef0dc0 scene: Only unwrap client buffer when underlying buffer is held
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.
2024-11-10 00:22:17 +01:00
Simon Ser
9e71c88467 scene: unwrap wlr_client_buffer for direct scan-out
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
2024-11-07 14:17:35 +00:00
David Turner
cf43a447cb scene: Transform coordinates for direct scanout
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.
2024-10-28 13:28:23 +00:00
David Turner
e51ce333bc scene: Apply output offset for direct scanout
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
2024-10-24 16:03:17 +01:00
David Turner
c87ab6465d Support direct scanout with src crop and dst boxes
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).
2024-10-22 18:28:09 +01:00
Kirill Primak
7952658367 scene: crop output buffer damage before adding
This piece of logic was accidentally removed in
009515161b.
2024-10-15 12:59:40 +00:00
Alexander Orezechowski
402a862413 output: Change wlr_output_add_software_cursors_to_render_pass to take buffer coordinates
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.
2024-10-12 07:30:11 +00:00
Simon Ser
785e340f01 scene: use backend-wide timeline feature flag 2024-10-11 17:11:35 +00:00
Alexander Orezechowski
8d8d5f5e94 scene: Rename some functions 2024-10-11 00:37:55 +03:00
Alexander Orezechowski
009515161b scene: Only accept buffer coordinates for damage 2024-10-11 00:37:55 +03:00
Alexander Orezechowski
f1b8937345 scene: Factor scaling into output transform function 2024-10-11 00:37:51 +03:00
Alexander Orezechowski
b9f0b9c766 scene: Apply damage ring as buffer local coordinates 2024-10-11 00:37:51 +03:00