summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRui Matos <tiagomatos@gmail.com>2015-02-18 15:24:14 +0100
committerRobert Bragg <robert.bragg@intel.com>2015-02-23 18:36:56 +0000
commit200c4032ac60112a7c27d14ad3ba1c768e6b970c (patch)
tree42d87548ef1a0a1830fbbe479929446cefb261b1
parentb5f5e908230b3536449534d6176c1fe225074e96 (diff)
kms-winsys: Defer setting new surfaces until swap buffers
We can't just destroy and replace the EGL and gbm surfaces while they are still in use i.e. while there is a pending flip. In fact, in that case, we were calling gbm_surface_destroy() on a surface that still had the front buffer locked and then, on the flip handler, gbm_surface_release_buffer() for a buffer that didn't belong to the new surface. Instead, we still allocate new surfaces when requested but they only replace the old ones on the next swap buffers when we're sure that the previous flip has been handled and buffers properly released.
-rw-r--r--cogl/winsys/cogl-winsys-egl-kms.c34
1 files changed, 26 insertions, 8 deletions
diff --git a/cogl/winsys/cogl-winsys-egl-kms.c b/cogl/winsys/cogl-winsys-egl-kms.c
index 86f57c08..dbedb0c7 100644
--- a/cogl/winsys/cogl-winsys-egl-kms.c
+++ b/cogl/winsys/cogl-winsys-egl-kms.c
@@ -110,6 +110,9 @@ typedef struct _CoglOnscreenKMS
struct gbm_bo *current_bo;
struct gbm_bo *next_bo;
CoglBool pending_swap_notify;
+
+ EGLSurface *pending_egl_surface;
+ struct gbm_surface *pending_surface;
} CoglOnscreenKMS;
static const char device_name[] = "/dev/dri/card0";
@@ -868,10 +871,27 @@ _cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
while (kms_onscreen->next_fb_id != 0)
handle_drm_event (kms_renderer);
+ if (kms_onscreen->pending_egl_surface)
+ {
+ eglDestroySurface (egl_renderer->edpy, egl_onscreen->egl_surface);
+ egl_onscreen->egl_surface = kms_onscreen->pending_egl_surface;
+ kms_onscreen->pending_egl_surface = NULL;
+
+ _cogl_framebuffer_winsys_update_size (COGL_FRAMEBUFFER (kms_display->onscreen),
+ kms_display->width, kms_display->height);
+ context->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_BIND;
+ }
parent_vtable->onscreen_swap_buffers_with_damage (onscreen,
rectangles,
n_rectangles);
+ if (kms_onscreen->pending_surface)
+ {
+ free_current_bo (onscreen);
+ gbm_surface_destroy (kms_onscreen->surface);
+ kms_onscreen->surface = kms_onscreen->pending_surface;
+ kms_onscreen->pending_surface = NULL;
+ }
/* Now we need to set the CRTC to whatever is the front buffer */
kms_onscreen->next_bo = gbm_surface_lock_front_buffer (kms_onscreen->surface);
@@ -1177,7 +1197,6 @@ cogl_kms_display_set_layout (CoglDisplay *display,
height != kms_display->height) &&
kms_display->onscreen)
{
- CoglContext *context = COGL_FRAMEBUFFER (kms_display->onscreen)->context;
CoglOnscreenEGL *egl_onscreen = kms_display->onscreen->winsys;
CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
struct gbm_surface *new_surface;
@@ -1213,14 +1232,13 @@ cogl_kms_display_set_layout (CoglDisplay *display,
return FALSE;
}
- eglDestroySurface (egl_renderer->edpy, egl_onscreen->egl_surface);
- gbm_surface_destroy (kms_onscreen->surface);
-
- kms_onscreen->surface = new_surface;
- egl_onscreen->egl_surface = new_egl_surface;
+ if (kms_onscreen->pending_egl_surface)
+ eglDestroySurface (egl_renderer->edpy, kms_onscreen->pending_egl_surface);
+ if (kms_onscreen->pending_surface)
+ gbm_surface_destroy (kms_onscreen->pending_surface);
- _cogl_framebuffer_winsys_update_size (COGL_FRAMEBUFFER (kms_display->onscreen), width, height);
- context->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_BIND;
+ kms_onscreen->pending_surface = new_surface;
+ kms_onscreen->pending_egl_surface = new_egl_surface;
}
kms_display->width = width;