It should be considered a bug if a compositor sets a non-finite
cursor position, so fail loudly (in debug builds) if that happens.
The existing check in wlr_cursor_warp_closest() is now redundant,
and would silently hide such bugs, so remove it.
In wlr_output_attach_render(), stop setting
wlr_output.pending.buffer. This removes one footgun: using the
wlr_buffer at that stage is invalid, because rendering operations
haven't been flushed to the GPU yet. We need to wait until
output_clear_back_buffer() for the wlr_buffer to be used safely.
Instead, set wlr_output.pending.buffer in wlr_output_test() and
wlr_output_commit().
Additionally, move the output_clear_back_buffer() from
wlr_output_commit_state() to wlr_output_commit(). This reduces the
number of calls in the failure path.
We can just use pending.buffer instead. It's completely fine to
call wlr_swapchain_set_buffer_submitted() with a buffer which
doesn't come from the swapchain, in which case it's a no-op.
This is documented to reset the gamma LUT, but we don't handle this
properly.
While at it, make sure we leave wlr_output.pending in a good state
on allocation failure.
wlr_buffer.c is difficult to read because it contains a mixed bag
of unrelated things: base buffer type, buffer implementations,
buffer resource factory, and client buffer.
Split each of these into their own file.
valgrind said (on exit from labwc):
Invalid write of size 8
at 0x487DEAF: wl_list_remove (wayland-util.c:56)
by 0x487DF80: wl_signal_emit_mutable (wayland-server.c:2182)
by 0x48CD6B7: backend_destroy.part.0.lto_priv.0 (backend.c:41)
by 0x48DC19D: multi_backend_destroy (backend.c:58)
by 0x4880286: UnknownInlinedFun (wayland-server.c:2315)
by 0x4880286: wl_display_destroy (wayland-server.c:1170)
by 0x112491: UnknownInlinedFun (server.c:485)
by 0x112491: main (main.c:110)
Address 0x1f9d0210 is 112 bytes inside a block of size 136 free'd
at 0x484426F: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x487DF6D: wl_signal_emit_mutable (wayland-server.c:2179)
by 0x48CD6B7: backend_destroy.part.0.lto_priv.0 (backend.c:41)
by 0x48DC19D: multi_backend_destroy (backend.c:58)
by 0x4880286: UnknownInlinedFun (wayland-server.c:2315)
by 0x4880286: wl_display_destroy (wayland-server.c:1170)
by 0x112491: UnknownInlinedFun (server.c:485)
by 0x112491: main (main.c:110)
Block was alloc'd at
at 0x4846A73: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x4918D4E: drm_lease_device_v1_create (wlr_drm_lease_v1.c:639)
by 0x48D3B00: wlr_multi_for_each_backend (backend.c:249)
by 0x49191D2: wlr_drm_lease_v1_manager_create (wlr_drm_lease_v1.c:706)
by 0x111EE9: UnknownInlinedFun (server.c:384)
by 0x111EE9: main (main.c:92)
dac040f87f mistakenly renamed
xdg_surface_destroy listener, which was listening to *unmap* events, to
xdg_surface_unmap. The actual fix, however, is to listen to destroy
events. This fixes various crashes.
If the first test in output_ensure_buffer() fails with modifiers we
replace the swapchain with a modifierless swapchain and try again.
However if that fails as well the output is currently stuck without
modifiers until the next modeset.
To fix this, destroy the modifierless swapchain if the test using it
fails. The next output_attach_back_buffer() call will create a swapchain
that allows modifiers when needed.
Originally, I thought that we could safely subtract opaque regions
from the background even if the black rect optimization was kicking in.
This is wrong because a scene node that isn't fully occluded will still
appear in the render list even if its partially under a black rect. We
need to make sure that while culling the background, we only consider
opaque regions that are also visible. This will fix the black rect
optimization with the background.
We don't need to worry about the black rect optimization here (that
always assumes that there will be a black background) because the
background is culled based on the render list. That means if a black rect
is removed, the visibility will reach all the way to the bottom forcing
the renderer to clear the area not breaking the assumption.
If culling is not enabled, there is no longer any guarantee that the
elements behind the rect won't be rendered. We must render the black rect
in all circumstances to cover up anything rendered.
This fixes the WLR_SCENE_DISABLE_VISIBILTY option.
If the client binds to version 3 of zxdg_output_v1 and version 1 of
wl_output no wl_output.done or zxdg_output_v1.done event is
emitted [1].
Also no wl_output.done event is emitted when version 2 or lower of
zxdg_output_v1 is bound to.
Add a version check to output_manager_handle_get_xdg_output so that no
wl_output.done event is emitted when using version 1 of wl_output and
version 2 or lower of zxdg_output_v1.
[1]: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/issues/81
This has a few benefits one of them crucial for proper operation:
- The primary output will be based on the largest area that is actually
visible to the user. Presentation and frame done events are based on
this state. This is important to do since we cull frame done events.
If we happen to be in a situation where a surface sits mostly on output
A and some on output B but is completely obstructed by for instance a
fullscreen surface on output A we will erroneously send frame_done
events based on output A. If we base things as they are in reality
(visibility) the primary output will instead be output B and things will
work properly.
- The primary output will be NULL if the surface is completely hidden.
Due to quirks with wayland, on a surface commit, frame done events are
required to be sent. Therefore, a new frame will be submitted for rendering
on the primary output. We can improve adaptive sync on completely hidden
but enabled surfaces if we null out the primary output in this state.
- The client will be more likely to choose better metadata to use
for rendering to an output's optimal rendering characteristics.