compositor: finish frame if redraw fails
If we are about to finish a frame, but a redraw is pending and we let the
compositor redraw, we need to check for errors. If the redraw fails and
the backend cannot schedule a page-flip, we need to finish the frame,
anyway.
All backends except DRM use a timer to schedule frames. Hence, they cannot
fail. But for DRM, we need to be able to handle drmModePageFlip() failures
in case access got revoked.
This fixes a bug where logind+drm caused keyboard input to be missed as we
didn't reenable it after a failed page-flip during deactivation.
diff --git a/src/compositor.c b/src/compositor.c
index 7e2a394..59a5abd 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -1365,7 +1365,7 @@
}
}
-static void
+static int
weston_output_repaint(struct weston_output *output, uint32_t msecs)
{
struct weston_compositor *ec = output->compositor;
@@ -1374,6 +1374,7 @@
struct weston_frame_callback *cb, *cnext;
struct wl_list frame_callback_list;
pixman_region32_t output_damage;
+ int r;
/* Rebuild the surface list and update surface transforms up front. */
weston_compositor_build_surface_list(ec);
@@ -1404,7 +1405,7 @@
if (output->dirty)
weston_output_update_matrix(output);
- output->repaint(output, &output_damage);
+ r = output->repaint(output, &output_damage);
pixman_region32_fini(&output_damage);
@@ -1422,6 +1423,8 @@
animation->frame_counter++;
animation->frame(animation, output, msecs);
}
+
+ return r;
}
static int
@@ -1440,15 +1443,16 @@
struct weston_compositor *compositor = output->compositor;
struct wl_event_loop *loop =
wl_display_get_event_loop(compositor->wl_display);
- int fd;
+ int fd, r;
output->frame_time = msecs;
if (output->repaint_needed &&
compositor->state != WESTON_COMPOSITOR_SLEEPING &&
compositor->state != WESTON_COMPOSITOR_OFFSCREEN) {
- weston_output_repaint(output, msecs);
- return;
+ r = weston_output_repaint(output, msecs);
+ if (!r)
+ return;
}
output->repaint_scheduled = 0;