[RFC 9/9] egl_dri2: add triple buffering support to drm platform

Ander Conselvan de Oliveira conselvan2 at gmail.com
Wed Dec 14 02:00:08 PST 2011


From: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira at intel.com>

---
 src/egl/drivers/dri2/egl_dri2.h     |   11 +++++
 src/egl/drivers/dri2/platform_drm.c |   79 ++++++++++++++++++++++++++++++++++-
 2 files changed, 89 insertions(+), 1 deletions(-)

diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index 206902b..f75c278 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -143,6 +143,15 @@ enum wayland_buffer_type {
 };
 #endif
 
+#ifdef HAVE_DRM_PLATFORM
+enum drm_buffer_type {
+   DRM_BUFFER_FRONT,
+   DRM_BUFFER_BACK,
+   DRM_BUFFER_THIRD,
+   DRM_BUFFER_COUNT
+};
+#endif
+
 struct dri2_egl_surface
 {
    _EGLSurface          base;
@@ -177,8 +186,10 @@ struct dri2_egl_surface
 
 #ifdef HAVE_DRM_PLATFORM
    struct gbm_dri_surface *gbm_surf;
+   int                    drm_buffer_lock[DRM_BUFFER_COUNT];
 #ifndef HAVE_WAYLAND_PLATFORM
    __DRIbuffer           *dri_buffers[__DRI_BUFFER_COUNT];
+   __DRIbuffer           *third_buffer;
 #endif
 #endif
 
diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c
index 06fdd85..4212cea 100644
--- a/src/egl/drivers/dri2/platform_drm.c
+++ b/src/egl/drivers/dri2/platform_drm.c
@@ -44,7 +44,22 @@ get_front_buffer(struct gbm_dri_surface *surf, void *data)
 
    (void) surf;
 
-   return &dri2_surf->buffers[__DRI_BUFFER_FRONT_LEFT];
+   dri2_surf->drm_buffer_lock[DRM_BUFFER_FRONT] = 1;
+   return dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT];
+}
+
+static void
+release_buffer(struct gbm_dri_surface *surf, __DRIbuffer *buffer, void *data)
+{
+   struct dri2_egl_surface *dri2_surf = data;
+
+   if (buffer == dri2_surf->third_buffer)
+      dri2_surf->drm_buffer_lock[DRM_BUFFER_THIRD] = 0;
+   else if (buffer->attachment == __DRI_BUFFER_FRONT_LEFT)
+      dri2_surf->drm_buffer_lock[DRM_BUFFER_FRONT] = 0;
+   else if (buffer->attachment == __DRI_BUFFER_BACK_LEFT)
+      dri2_surf->drm_buffer_lock[DRM_BUFFER_BACK] = 0;
+
 }
 
 static _EGLSurface *
@@ -73,6 +88,8 @@ 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->third_buffer = NULL;
+
    switch (type) {
    case EGL_WINDOW_BIT:
       surf = gbm_dri_surface((struct gbm_surface *) window);
@@ -82,6 +99,7 @@ dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
       dri2_surf->base.Height = surf->base.height;
 
       surf->get_front_buffer = get_front_buffer;
+      surf->release_buffer = release_buffer;
       surf->dri_private = dri2_surf;
 
       break;
@@ -169,6 +187,61 @@ pointer_swap(const void **p1, const void **p2)
    *p2 = tmp;
 }
 
+static void
+destroy_third_buffer(struct dri2_egl_surface *dri2_surf)
+{
+   struct dri2_egl_display *dri2_dpy =
+      dri2_egl_display(dri2_surf->base.Resource.Display);
+
+   if (dri2_surf->third_buffer == NULL)
+      return;
+
+   dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
+                                 dri2_surf->third_buffer);
+   dri2_surf->third_buffer = NULL;
+   dri2_surf->drm_buffer_lock[DRM_BUFFER_THIRD] = 0;
+}
+
+static void
+swap_drm_buffers(struct dri2_egl_surface *dri2_surf,
+                 enum drm_buffer_type a, enum drm_buffer_type b)
+{
+   int tmp;
+
+   tmp = dri2_surf->drm_buffer_lock[a];
+   dri2_surf->drm_buffer_lock[a] = dri2_surf->drm_buffer_lock[b];
+   dri2_surf->drm_buffer_lock[b] = tmp;
+}
+
+static void
+swap_back_and_third(struct dri2_egl_surface *dri2_surf)
+{
+   if (dri2_surf->drm_buffer_lock[DRM_BUFFER_THIRD])
+      destroy_third_buffer(dri2_surf);
+
+   pointer_swap((const void **) &dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT],
+                (const void **) &dri2_surf->third_buffer);
+
+   swap_drm_buffers(dri2_surf, DRM_BUFFER_BACK, DRM_BUFFER_THIRD);
+}
+
+static void
+dri2_prior_buffer_creation(struct dri2_egl_surface *dri2_surf,
+                           unsigned int type)
+{
+   switch (type) {
+   case __DRI_BUFFER_BACK_LEFT:
+         if (dri2_surf->drm_buffer_lock[DRM_BUFFER_BACK])
+            swap_back_and_third(dri2_surf);
+         else if (dri2_surf->third_buffer)
+            destroy_third_buffer(dri2_surf);
+         break;
+   default:
+         break;
+
+   }
+}
+
 static __DRIbuffer *
 dri2_get_buffers_with_format(__DRIdrawable * driDrawable,
 			     int *width, int *height,
@@ -185,6 +258,8 @@ dri2_get_buffers_with_format(__DRIdrawable * driDrawable,
       assert(attachments[i] < __DRI_BUFFER_COUNT);
       assert(dri2_surf->buffer_count < 5);
 
+      dri2_prior_buffer_creation(dri2_surf, attachments[i]);
+
       if (dri2_surf->dri_buffers[attachments[i]] == NULL) {
 
          dri2_surf->dri_buffers[attachments[i]] =
@@ -274,6 +349,8 @@ dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
          __DRI_BUFFER_FRONT_LEFT;
       dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]->attachment =
         __DRI_BUFFER_BACK_LEFT;
+
+      swap_drm_buffers(dri2_surf, DRM_BUFFER_FRONT, DRM_BUFFER_BACK);
    }
 
    _EGLContext *ctx;
-- 
1.7.4.1



More information about the wayland-devel mailing list