The backend doesn't need to handle transform changes, since everything is done
in software. In fact, all of the implementations were all identical and just
set the transform.
We could add support for hardware transforms, but:
- This would require a different field (something like hardware_transform)
- Not all combinations are possible because there often are hardware
limitations
- The Wayland protocol isn't ready for this (in particular xdg-output, see [1])
This belongs to a different patch series anyway.
[1]: https://patchwork.freedesktop.org/series/52324/
It can be surprising for callers to stash pending changes, commit, get a
failure, then set some other pending changes, commit again, and get another
failure because of the previously-pending changes.
Instead, make commit reset the pending state on failure.
If an output is destroyed while an idle_done event is scheduled, it
results in the following Address Sanitizer Output:
==1469==ERROR: AddressSanitizer: heap-use-after-free on address 0x6170000bb668 at pc 0x7f49aaa0c348 bp 0x7ffed5da35b0 sp 0x7ffed5da35a0
WRITE of size 8 at 0x6170000bb668 thread T0
#0 0x7f49aaa0c347 in schedule_done_handle_idle_timer ../subprojects/wlroots/types/wlr_output.c:265
#1 0x7f49aa2f875b in wl_event_loop_dispatch_idle (/usr/lib/libwayland-server.so.0+0xa75b)
#2 0x7f49aa2f8815 in wl_event_loop_dispatch (/usr/lib/libwayland-server.so.0+0xa815)
#3 0x7f49aa2f739b in wl_display_run (/usr/lib/libwayland-server.so.0+0x939b)
#4 0x556622dadd51 in server_run ../sway/server.c:216
#5 0x556622dac25d in main ../sway/main.c:397
#6 0x7f49aa0d0ce2 in __libc_start_main (/usr/lib/libc.so.6+0x23ce2)
#7 0x556622d8d09d in _start (/usr/local/bin/sway+0x3909d)
0x6170000bb668 is located 488 bytes inside of 672-byte region [0x6170000bb480,0x6170000bb720)
freed by thread T0 here:
#0 0x7f49aabc8f89 in __interceptor_free /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:66
#1 0x7f49aa968fc2 in drm_connector_destroy ../subprojects/wlroots/backend/drm/drm.c:829
#2 0x7f49aaa0cc52 in wlr_output_destroy ../subprojects/wlroots/types/wlr_output.c:357
#3 0x7f49aa96d2e9 in scan_drm_connectors ../subprojects/wlroots/backend/drm/drm.c:1265
#4 0x7f49aa961a59 in drm_invalidated ../subprojects/wlroots/backend/drm/backend.c:135
#5 0x7f49aaa2e1e9 in wlr_signal_emit_safe ../subprojects/wlroots/util/signal.c:29
#6 0x7f49aa98319f in udev_event ../subprojects/wlroots/backend/session/session.c:52
#7 0x7f49aa2f87f1 in wl_event_loop_dispatch (/usr/lib/libwayland-server.so.0+0xa7f1)
previously allocated by thread T0 here:
#0 0x7f49aabc95a1 in __interceptor_calloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:95
#1 0x7f49aa96b7a2 in scan_drm_connectors ../subprojects/wlroots/backend/drm/drm.c:1114
#2 0x7f49aa961a59 in drm_invalidated ../subprojects/wlroots/backend/drm/backend.c:135
#3 0x7f49aaa2e1e9 in wlr_signal_emit_safe ../subprojects/wlroots/util/signal.c:29
#4 0x7f49aa98319f in udev_event ../subprojects/wlroots/backend/session/session.c:52
#5 0x7f49aa2f87f1 in wl_event_loop_dispatch (/usr/lib/libwayland-server.so.0+0xa7f1)
SUMMARY: AddressSanitizer: heap-use-after-free ../subprojects/wlroots/types/wlr_output.c:265 in schedule_done_handle_idle_timer
Shadow bytes around the buggy address:
0x0c2e8000f670: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2e8000f680: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2e8000f690: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2e8000f6a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2e8000f6b0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
=>0x0c2e8000f6c0: fd fd fd fd fd fd fd fd fd fd fd fd fd[fd]fd fd
0x0c2e8000f6d0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2e8000f6e0: fd fd fd fd fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2e8000f6f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2e8000f700: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2e8000f710: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Remove the idle_done idle timer when the output is destroyed
This commit introduces wlr_output_schedule_done and refactors the mechanism
used to send wl_output events to clients.
wlr_output_schedule_done schedules a wl_output.done event. This allows clients
to see wlr_output property changes as atomic.
This function is also useful for add-on interfaces like xdg_output which need
to trigger a wl_output.done event to apply their new state.
wlr_output_damage_make_current has been renamed to
wlr_output_damage_attach_render, since it's just a wrapper for
wlr_output_attach_render.
wlr_output_damage_swap_buffers has been removed completely. Instead,
wlr_output_damage now listens to successful wlr_output commits and updates its
internal state accordingly.
This updates the backend part of the output API. This is mostly renaming:
make_current becomes attach_render and swap_buffers becomes commit.
This also fixes the RDP backend to support NULL damage.
This is necessary for direct scan-out and other upcoming features. This patch
changes the output API to look like the wl_surface API.
Outputs now have some double-buffered state: the frame to be submitted
(currently only wlr_renderer frames are supported) and the damaged region.
To attach a pending frame, use wlr_output_attach_render. To set the pending
damaged region, use wlr_output_set_damage.
To submit the pending state, call wlr_output_commit. This will submit the
pending frame to the backend.
To migrate from the old API to the new one:
- Replace wlr_output_make_current calls by wlr_output_attach_render
- Replace wlr_output_swap_buffers calls by wlr_output_set_damage and
wlr_output_commit
There is no point in modesetting an output to a mode that it is already
set to. Modesetting will cause the output to briefly flicker which is
undesirable for a noop. This prevents modesetting any wlr_output,
regardless of the backend, to it's currently set mode.
When there aren't enough CRTCs for all outputs, we try to move a CRTC from a
disabled output to an enabled one. When this happens, the old output's state
wasn't changed, so the compositor thought it was still enabled and rendering.
This commit marks the old output as WLR_DRM_CONN_NEEDS_MODESET and sets its
current mode to NULL.
The read format is dependent on the output, so we first need to make it
current. This fixes a race condition in wlr-screencopy-v1 where a dmabuf
client would cause EGL_NO_SURFACE to be bound at the time when
screencopy needs to query for the preferred format, causing GL errors.
There was a missing copy_drm_surface_mgpu call in drm_connector_schedule_frame
so we asked for a pageflip with an unknown BO, resulting in ENOENT.
Additionally, this commit makes schedule_frame return a bool indicating
failures. This allows schedule_frame_handle_idle_timer to only set
frame_pending to true if a frame has been successfully scheduled. Thus, if a
pageflip fails, rendering won't be blocked forever anymore.
In case a pageflip is already pending, true is returned because a frame has
already been scheduled and will be sent sometime soon.
This prevents the idle event to be activated on a destroyed
output.
This also makes the backend responsible for free-ing modes, as it
is the one allocating them and adding them to the list. Note that
the DRM backend (the only one using modes) already frees them.
This desynchronizes our rendering loop with the vblank cycle.
In case a compositor doesn't swap buffers but schedules a frame,
emitting a frame event immediately enters a busy-loop.
Instead, ask the backend to send a frame when appropriate. On
Wayland we can just register a frame callback on our surface. On
DRM we can do a no-op pageflip.
Fixes#617Fixesswaywm/sway#2748
When we send an output frame event, we should not assume that the
compositor is going to call wlr_output_swap_buffers in response to it.
If the compositor does not swap the buffers, the idle event source still
exists and is executed every time the Wayland event loop becomes idle,
which means we send frame events repeatedly until the buffers are
swapped.
This moves the removal of the idle event source out of
wlr_output_swap_buffers and into wlr_output_send_frame, where it is
guaranteed to be removed.