diff options
author | Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com> | 2011-12-14 12:00:08 +0200 |
---|---|---|
committer | Robert Bragg <robert@linux.intel.com> | 2012-01-16 13:45:28 +0000 |
commit | 23ba9c32762a8754ae3c993087a40b5f5ff38919 (patch) | |
tree | 9ce8779d40572f68f6de92be91e9f3549523f582 /src | |
parent | 60c672551894c921ab1d5c8b19372120b0ffd3c2 (diff) |
egl_dri2: add triple buffering support to drm platform
Diffstat (limited to 'src')
-rw-r--r-- | src/egl/drivers/dri2/egl_dri2.h | 11 | ||||
-rw-r--r-- | 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 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; |