compositor-drm: Wait for vblank events before starting next frame
Besides the fact of the frame not being done, assigning planes before
the vblank handler is called will make the state inconsistent, leading
to a crash.
diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 5543462..d969d52 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -98,6 +98,9 @@
uint32_t connector_id;
drmModeCrtcPtr original_crtc;
+ int vblank_pending;
+ int page_flip_pending;
+
struct gbm_surface *surface;
struct gbm_bo *cursor_bo[2];
int current_cursor;
@@ -118,6 +121,8 @@
struct weston_surface *surface;
struct weston_surface *pending_surface;
+ struct drm_output *output;
+
struct drm_compositor *compositor;
struct wl_listener destroy_listener;
@@ -358,6 +363,8 @@
return;
}
+ output->page_flip_pending = 1;
+
/*
* Now, update all the sprite surfaces
*/
@@ -391,6 +398,9 @@
weston_log("vblank event request failed: %d: %s\n",
ret, strerror(errno));
}
+
+ s->output = output;
+ output->vblank_pending = 1;
}
return;
@@ -402,6 +412,10 @@
{
struct drm_sprite *s = (struct drm_sprite *)data;
struct drm_compositor *c = s->compositor;
+ struct drm_output *output = s->output;
+ uint32_t msecs;
+
+ output->vblank_pending = 0;
if (s->surface) {
weston_buffer_post_release(s->surface->buffer);
@@ -420,6 +434,11 @@
s->fb_id = s->pending_fb_id;
s->pending_fb_id = 0;
}
+
+ if (!output->page_flip_pending) {
+ msecs = sec * 1000 + usec / 1000;
+ weston_output_finish_frame(&output->base, msecs);
+ }
}
static void
@@ -429,6 +448,8 @@
struct drm_output *output = (struct drm_output *) data;
uint32_t msecs;
+ output->page_flip_pending = 0;
+
if (output->current) {
if (output->current->is_client_buffer)
gbm_bo_destroy(output->current->bo);
@@ -440,8 +461,10 @@
output->current = output->next;
output->next = NULL;
- msecs = sec * 1000 + usec / 1000;
- weston_output_finish_frame(&output->base, msecs);
+ if (!output->vblank_pending) {
+ msecs = sec * 1000 + usec / 1000;
+ weston_output_finish_frame(&output->base, msecs);
+ }
}
static int