wl_backend: fix client surface rendering with proper scene output commit

Client surfaces (e.g. foot terminal) were not updating after initial
map. Two issues:

1. wlr_scene_output_commit(scene_output, NULL) in wlroots 0.19 may
   skip rendering if it determines no damage is pending, even when
   client surfaces have committed new buffers.

2. Frame scheduling was dependent on host compositor timing.

Fix: Replace wlr_scene_output_commit with explicit build_state +
commit_state cycle which properly tracks damage. Also schedule a
frame unconditionally every loop iteration to ensure continuous
rendering in nested mode.
This commit is contained in:
Ollie 2026-05-23 19:11:37 +02:00
parent a438713b92
commit 4b338d11d0
1 changed files with 7 additions and 1 deletions

View File

@ -1972,8 +1972,12 @@ handle_output_frame(struct wl_listener *listener, void *data)
++frame_count;
if (wl_state.allocator) {
/* Full scene commit — renders client surfaces and fires
* wl_surface.frame callbacks so clients can submit next buffer. */
* wl_surface.frame callbacks so clients can submit next buffer.
* Also send frame_done unconditionally so clients aren't stalled. */
wlr_scene_output_commit(wl_state.scene_output, NULL);
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
wlr_scene_output_send_frame_done(wl_state.scene_output, &now);
} else {
/* No GPU allocator available (e.g. headless without DRI access).
* Skip rendering but still fire wl_surface.frame callbacks so
@ -3236,6 +3240,8 @@ wl_event_loop_run(void)
struct wl_event_loop *loop = wl_display_get_event_loop(wl_state.display);
while (!wl_state.terminate) {
wl_display_flush_clients(wl_state.display);
if (wl_state.output)
wlr_output_schedule_frame(wl_state.output);
wl_event_loop_dispatch(loop, 16);
/* Drain WINGs event queue */