egl_dri2 wayland: Sync front buffer release
authorBenjamin Franzke <benjaminfranzke@googlemail.com>
Fri, 11 Feb 2011 01:23:14 +0000 (02:23 +0100)
committerKristian Høgsberg <krh@bitplanet.net>
Fri, 11 Feb 2011 04:07:01 +0000 (23:07 -0500)
src/egl/drivers/dri2/egl_dri2.h
src/egl/drivers/dri2/platform_wayland.c

index 1656a50c0131e971e30637c4d344bcfde19fd44c..ad262d21f0ff8b8c06fb67aef51a2ffff16e2d43 100644 (file)
@@ -126,6 +126,7 @@ struct dri2_egl_surface
    int                    dx;
    int                    dy;
    __DRIbuffer           *dri_buffers[__DRI_BUFFER_COUNT];
+   __DRIbuffer           *pending_buffer;
    EGLBoolean             block_swap_buffers;
 #endif
 };
index 9be9a8190382e4473dbf628da6d0fdab607846d3..64f8b1bccc790ddabe70098f1bd1bb318a210688 100644 (file)
 
 #include "egl_dri2.h"
 
+static void
+sync_callback(void *data)
+{
+   int *done = data;
+
+   *done = 1;
+}
+
+static void
+force_roundtrip(struct wl_display *display)
+{
+   int done = 0;
+
+   wl_display_sync_callback(display, sync_callback, &done);
+   wl_display_iterate(display, WL_DISPLAY_WRITABLE);
+   while (!done)
+      wl_display_iterate(display, WL_DISPLAY_READABLE);
+}
+
+
 /**
  * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
  */
@@ -66,6 +86,7 @@ dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
    for (i = 0; i < __DRI_BUFFER_COUNT; ++i)
       dri2_surf->dri_buffers[i] = NULL;
 
+   dri2_surf->pending_buffer = NULL;
    dri2_surf->block_swap_buffers = EGL_FALSE;
 
    switch (type) {
@@ -230,6 +251,49 @@ dri2_process_front_buffer(struct dri2_egl_surface *dri2_surf, unsigned format)
    }
 }
 
+static void
+dri2_release_pending_buffer(void *data)
+{
+   struct dri2_egl_surface *dri2_surf = data;
+   struct dri2_egl_display *dri2_dpy =
+      dri2_egl_display(dri2_surf->base.Resource.Display);
+
+   /* FIXME: print internal error */
+   if (!dri2_surf->pending_buffer)
+      return;
+   
+   dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
+                                 dri2_surf->pending_buffer);
+   dri2_surf->pending_buffer = NULL;
+}
+
+static void
+dri2_release_buffers(struct dri2_egl_surface *dri2_surf)
+{
+   struct dri2_egl_display *dri2_dpy =
+      dri2_egl_display(dri2_surf->base.Resource.Display);
+   int i;
+
+   for (i = 0; i < __DRI_BUFFER_COUNT; ++i) {
+      if (dri2_surf->dri_buffers[i]) {
+         switch (i) {
+         case __DRI_BUFFER_FRONT_LEFT:
+            if (dri2_surf->pending_buffer)
+               force_roundtrip(dri2_dpy->wl_dpy->display);
+            dri2_surf->pending_buffer = dri2_surf->dri_buffers[i];
+            wl_display_sync_callback(dri2_dpy->wl_dpy->display,
+                                     dri2_release_pending_buffer, dri2_surf);
+            break;
+         default:
+            dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
+                                          dri2_surf->dri_buffers[i]);
+            break;
+         }
+         dri2_surf->dri_buffers[i] = NULL;
+      }
+   }
+}
+
 static __DRIbuffer *
 dri2_get_buffers_with_format(__DRIdrawable * driDrawable,
                             int *width, int *height,
@@ -244,13 +308,8 @@ dri2_get_buffers_with_format(__DRIdrawable * driDrawable,
    if (dri2_surf->type == DRI2_WINDOW_SURFACE &&
        (dri2_surf->base.Width != dri2_surf->wl_win->width || 
         dri2_surf->base.Height != dri2_surf->wl_win->height)) {
-      for (i = 0; i < __DRI_BUFFER_COUNT; ++i) {
-         if (dri2_surf->dri_buffers[i]) {
-            dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
-                                         dri2_surf->dri_buffers[i]);
-            dri2_surf->dri_buffers[i] = NULL;
-         }
-      }
+
+      dri2_release_buffers(dri2_surf);
 
       dri2_surf->base.Width  = dri2_surf->wl_win->width;
       dri2_surf->base.Height = dri2_surf->wl_win->height;
@@ -523,25 +582,6 @@ dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp)
    return EGL_TRUE;
 }
 
-static void
-sync_callback(void *data)
-{
-   int *done = data;
-
-   *done = 1;
-}
-
-static void
-force_roundtrip(struct wl_display *display)
-{
-   int done = 0;
-
-   wl_display_sync_callback(display, sync_callback, &done);
-   wl_display_iterate(display, WL_DISPLAY_WRITABLE);
-   while (!done)
-      wl_display_iterate(display, WL_DISPLAY_READABLE);
-}
-
 EGLBoolean
 dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp)
 {