output: don't trigger a frame immediately in schedule_frame

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 #617
Fixes swaywm/sway#2748
This commit is contained in:
emersion 2018-10-05 16:14:22 +02:00
parent 4e89a21397
commit ba91422747
4 changed files with 63 additions and 3 deletions

View file

@ -546,7 +546,13 @@ static void schedule_frame_handle_idle_timer(void *data) {
struct wlr_output *output = data;
output->idle_frame = NULL;
if (!output->frame_pending) {
wlr_output_send_frame(output);
if (output->impl->schedule_frame) {
// Ask the backend to send a frame event when appropriate
output->frame_pending = true;
output->impl->schedule_frame(output);
} else {
wlr_output_send_frame(output);
}
}
}
@ -555,7 +561,8 @@ void wlr_output_schedule_frame(struct wlr_output *output) {
return;
}
// TODO: ask the backend to send a frame event when appropriate instead
// We're using an idle timer here in case a buffer swap happens right after
// this function is called
struct wl_event_loop *ev = wl_display_get_event_loop(output->display);
output->idle_frame =
wl_event_loop_add_idle(ev, schedule_frame_handle_idle_timer, output);