When starting up, the compositor might call wlr_output_set_mode()
with a mode which is already the current one. wlroots will detect
this and make the wlr_output_set_mode() call a no-op. During the
next wlr_output_commit() call, wlroots will perform an atomic
commit without the ALLOW_MODESET flag.
This is an issue, because some drivers need ALLOW_MODESET even if
the mode is the same. For instance, if the FB stride or modifier
changed, some drivers require a modeset.
Add a new flag "allow_artifacts" which is set when the compositor
calls mode-setting functions. Use this flag to figure out whether
we want to perform atomic commits with ALLOW_MODESET.
(The name "allow_artifacts" is picked because ALLOW_MODESET is a
misnomer, see [1].)
[1]: https://patchwork.freedesktop.org/patch/505107/
Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3499
Instead of using low-level wl_shm_buffer and wlr_dmabuf_v1_buffer
APIs, use the unified wlr_buffer APIs. That way it doesn't matter
what the exact wlr_buffer implementation is used, any which provides
the necessary capabilities (data_ptr or dmabuf) would work.
Simplifies the logic a bit, and will make the transition to wlr_shm
easier.
There doesn't appear to be any good reason to warp the cursor to
the top-left corner when all outputs are disconnected; it's no more
valid than any other (x,y) point in that case.
The real-world case here is a user with a single external monitor
turning it off (which apparently counts as disconnected depending
on the connection type/hardware). For that user, it's desirable to
have the cursor remain in its original location when the monitor
is turned back on.
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