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-drm.c b/src/compositor-drm.c
index 8a70674..9922708 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -576,7 +576,7 @@
weston_log("set gamma failed: %m\n");
}
-static void
+static int
drm_output_repaint(struct weston_output *output_base,
pixman_region32_t *damage)
{
@@ -588,12 +588,12 @@
int ret = 0;
if (output->destroy_pending)
- return;
+ return -1;
if (!output->next)
drm_output_render(output, damage);
if (!output->next)
- return;
+ return -1;
mode = container_of(output->base.current_mode, struct drm_mode, base);
if (!output->current) {
@@ -603,7 +603,7 @@
&mode->mode_info);
if (ret) {
weston_log("set mode failed: %m\n");
- return;
+ goto err_pageflip;
}
output_base->set_dpms(output_base, WESTON_DPMS_ON);
}
@@ -612,7 +612,7 @@
output->next->fb_id,
DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
weston_log("queueing pageflip failed: %m\n");
- return;
+ goto err_pageflip;
}
output->page_flip_pending = 1;
@@ -664,7 +664,15 @@
output->vblank_pending = 1;
}
- return;
+ return 0;
+
+err_pageflip:
+ if (output->next) {
+ drm_output_release_fb(output, output->next);
+ output->next = NULL;
+ }
+
+ return -1;
}
static void