summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnder Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>2011-12-14 12:00:08 +0200
committerRobert Bragg <robert@linux.intel.com>2012-01-16 13:45:28 +0000
commit23ba9c32762a8754ae3c993087a40b5f5ff38919 (patch)
tree9ce8779d40572f68f6de92be91e9f3549523f582
parent60c672551894c921ab1d5c8b19372120b0ffd3c2 (diff)
egl_dri2: add triple buffering support to drm platform
-rw-r--r--src/egl/drivers/dri2/egl_dri2.h11
-rw-r--r--src/egl/drivers/dri2/platform_drm.c79
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 20945c10a0..fc31364833 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 06fdd8501e..4212cea74b 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;