[PATCH v2 10/11] egl_dri2: add triple buffering support to drm platform
Ander Conselvan de Oliveira
ander.conselvan.de.oliveira at intel.com
Wed Jan 25 06:24:22 PST 2012
---
src/egl/drivers/dri2/egl_dri2.h | 11 +++++
src/egl/drivers/dri2/platform_drm.c | 82 ++++++++++++++++++++++++++++++++++-
2 files changed, 92 insertions(+), 1 deletions(-)
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index 20945c1..fc31364 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -145,6 +145,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;
@@ -179,8 +188,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..b16bc42 100644
--- a/src/egl/drivers/dri2/platform_drm.c
+++ b/src/egl/drivers/dri2/platform_drm.c
@@ -44,7 +44,25 @@ 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]++;
+ 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 == NULL)
+ return;
+
+ if (buffer == dri2_surf->third_buffer)
+ dri2_surf->drm_buffer_lock[DRM_BUFFER_THIRD]--;
+ else if (buffer->attachment == __DRI_BUFFER_FRONT_LEFT)
+ dri2_surf->drm_buffer_lock[DRM_BUFFER_FRONT]--;
+ else if (buffer->attachment == __DRI_BUFFER_BACK_LEFT)
+ dri2_surf->drm_buffer_lock[DRM_BUFFER_BACK]--;
+
}
static _EGLSurface *
@@ -73,6 +91,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 +102,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 +190,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 +261,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 +352,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