From 213285f2b8c6578e01783a77d954ccc3ec313663 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 17 Feb 2012 16:56:05 +0800 Subject: [PATCH] For DRI swap buffers. This commit added two APIs to support the DRI swap buffer. one is glamor_egl_exchange_buffers() which can swap two pixmaps' underlying KHRimages/fbos/texs. The DDX layer should exchange the DRM bos to make them consistent to each other. Another API is glamor_egl_create_textured_screen_ext(), which extent one more parameters to track the DDX layer's back pixmap pointer. This is for the triple buffer support. When using triple buffer, the DDX layer will keep a back pixmap rather then the front pixmap and the pixmap used by the DRI2 client. And during the closing screen stage, we have to dereference all the back pixmap's glamor resources. Thus we have to extent this API to register it when create new screen. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 34 ++++++++++++++++++++++--- glamor/glamor.h | 24 +++++++++++++++++- glamor/glamor_egl.c | 59 +++++++++++++++++++++++++++++++++++++++++--- glamor/glamor_fbo.c | 19 ++++++++++++++ glamor/glamor_priv.h | 12 ++------- 5 files changed, 129 insertions(+), 19 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 86de1154b..0d9ba2814 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -106,7 +106,7 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex) } void -glamor_set_screen_pixmap(PixmapPtr screen_pixmap) +glamor_set_screen_pixmap(PixmapPtr screen_pixmap, PixmapPtr *back_pixmap) { glamor_pixmap_private *pixmap_priv; glamor_screen_private *glamor_priv; @@ -117,6 +117,8 @@ glamor_set_screen_pixmap(PixmapPtr screen_pixmap) pixmap_priv->fbo->width = screen_pixmap->drawable.width; pixmap_priv->fbo->height = screen_pixmap->drawable.height; + + glamor_priv->back_pixmap = back_pixmap; } PixmapPtr @@ -420,6 +422,29 @@ glamor_release_screen_priv(ScreenPtr screen) glamor_set_screen_private(screen, NULL); } +_X_EXPORT void +glamor_set_pixmap_private(PixmapPtr pixmap, glamor_pixmap_private *priv) +{ + glamor_pixmap_private *old_priv; + glamor_pixmap_fbo *fbo; + + old_priv = dixGetPrivate(&pixmap->devPrivates, glamor_pixmap_private_key); + + if (priv) { + assert(old_priv == NULL); + } else { + if (old_priv == NULL) + return; + fbo = glamor_pixmap_detach_fbo(old_priv); + glamor_purge_fbo(fbo); + free(old_priv); + } + + dixSetPrivate(&pixmap->devPrivates, + glamor_pixmap_private_key, + priv); +} + Bool glamor_close_screen(int idx, ScreenPtr screen) { @@ -458,9 +483,10 @@ glamor_close_screen(int idx, ScreenPtr screen) } #endif screen_pixmap = screen->GetScreenPixmap(screen); - screen_pixmap_priv = glamor_get_pixmap_private(screen_pixmap); - fbo = glamor_pixmap_detach_fbo(screen_pixmap_priv); - glamor_purge_fbo(fbo); + glamor_set_pixmap_private(screen_pixmap, NULL); + if (glamor_priv->back_pixmap && *glamor_priv->back_pixmap) + glamor_set_pixmap_private(*glamor_priv->back_pixmap, NULL); + glamor_release_screen_priv(screen); return screen->CloseScreen(idx, screen); diff --git a/glamor/glamor.h b/glamor/glamor.h index d3437d381..4a4e9bdcb 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -120,7 +120,7 @@ extern _X_EXPORT Bool glamor_close_screen(int idx, ScreenPtr screen); /* Let glamor to know the screen's fbo. The low level * driver should already assign a tex * to this pixmap through the set_pixmap_texture. */ -extern _X_EXPORT void glamor_set_screen_pixmap(PixmapPtr screen_pixmap); +extern _X_EXPORT void glamor_set_screen_pixmap(PixmapPtr screen_pixmap, PixmapPtr *back_pixmap); /* @glamor_glyphs_init: Initialize glyphs internal data structures. * @@ -146,6 +146,16 @@ extern _X_EXPORT void glamor_egl_screen_init(ScreenPtr screen); extern _X_EXPORT void glamor_egl_make_current(ScreenPtr screen); extern _X_EXPORT void glamor_egl_restore_context(ScreenPtr screen); +/* @glamor_egl_exchange_buffers: Exchange the underlying buffers(KHR image,fbo). + * + * @front: front pixmap. + * @back: back pixmap. + * + * Used by the DRI2 page flip. This function will exchange the KHR images and + * fbos of the two pixmaps. + * */ +extern _X_EXPORT void glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr back); + #ifdef GLAMOR_FOR_XORG #define GLAMOR_EGL_MODULE_NAME "glamoregl" @@ -183,6 +193,18 @@ extern _X_EXPORT Bool glamor_egl_init_textured_pixmap(ScreenPtr screen); extern _X_EXPORT Bool glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int stride); + +/* @glamor_egl_create_textured_screen_ext: + * + * extent one parameter to track the pointer of the DDX layer's back pixmap. + * We need this pointer during the closing screen stage. As before back to + * the DDX's close screen, we have to free all the glamor related resources. + */ +extern _X_EXPORT Bool glamor_egl_create_textured_screen_ext(ScreenPtr screen, + int handle, + int stride, + PixmapPtr *back_pixmap); + /* * @glamor_egl_create_textured_pixmap: Try to create a textured pixmap from * a BO handle. diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index ecbc186fa..081b363ab 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -85,6 +85,7 @@ struct glamor_egl_screen_private { CloseScreenProcPtr CloseScreen; int fd; EGLImageKHR front_image; + PixmapPtr *back_pixmap; int cpp; #ifdef GLAMOR_HAS_GBM struct gbm_device *gbm; @@ -233,7 +234,24 @@ glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int stride) glamor_egl->front_image = dixLookupPrivate(&screen_pixmap->devPrivates, glamor_egl_pixmap_private_key); - glamor_set_screen_pixmap(screen_pixmap); + glamor_set_screen_pixmap(screen_pixmap, glamor_egl->back_pixmap); + return TRUE; +} + +Bool +glamor_egl_create_textured_screen_ext(ScreenPtr screen, + int handle, + int stride, + PixmapPtr *back_pixmap) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + struct glamor_egl_screen_private *glamor_egl; + + glamor_egl = glamor_egl_get_screen_private(scrn); + + glamor_egl->back_pixmap = back_pixmap; + if (!glamor_egl_create_textured_screen(screen, handle, stride)) + return FALSE; return TRUE; } @@ -280,9 +298,10 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride) ((stride * 8 + 7) / pixmap->drawable.bitsPerPixel), name, pixmap->drawable.depth); - if (image == EGL_NO_IMAGE_KHR) + if (image == EGL_NO_IMAGE_KHR) { + glamor_set_pixmap_type(pixmap, GLAMOR_DRM_ONLY); goto done; - + } glamor_create_texture_from_image(glamor_egl, image, &texture); glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM); glamor_set_pixmap_texture(pixmap, texture); @@ -315,6 +334,28 @@ _glamor_egl_destroy_pixmap_image(PixmapPtr pixmap) } } +extern void glamor_pixmap_exchange_fbos(PixmapPtr front, PixmapPtr back); + +_X_EXPORT void +glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr back) +{ + ScrnInfoPtr scrn = xf86Screens[front->drawable.pScreen->myNum]; + struct glamor_egl_screen_private *glamor_egl = + glamor_egl_get_screen_private(scrn); + EGLImageKHR old_front_image; + EGLImageKHR new_front_image; + + glamor_pixmap_exchange_fbos(front, back); + new_front_image = dixLookupPrivate(&back->devPrivates, glamor_egl_pixmap_private_key); + old_front_image = dixLookupPrivate(&front->devPrivates, glamor_egl_pixmap_private_key); + dixSetPrivate(&front->devPrivates, glamor_egl_pixmap_private_key, new_front_image); + dixSetPrivate(&back->devPrivates, glamor_egl_pixmap_private_key, old_front_image); + glamor_set_pixmap_type(front, GLAMOR_TEXTURE_DRM); + glamor_set_pixmap_type(back, GLAMOR_TEXTURE_DRM); + glamor_egl->front_image = new_front_image; + +} + void glamor_egl_destroy_textured_pixmap(PixmapPtr pixmap) { @@ -329,13 +370,24 @@ glamor_egl_close_screen(int idx, ScreenPtr screen) ScrnInfoPtr scrn; struct glamor_egl_screen_private *glamor_egl; PixmapPtr screen_pixmap; + EGLImageKHR back_image; scrn = xf86Screens[screen->myNum]; glamor_egl = glamor_egl_get_screen_private(scrn); screen_pixmap = screen->GetScreenPixmap(screen); + glamor_egl->egl_destroy_image_khr(glamor_egl->display, glamor_egl->front_image); dixSetPrivate(&screen_pixmap->devPrivates, glamor_egl_pixmap_private_key, NULL); glamor_egl->front_image = NULL; + if (glamor_egl->back_pixmap && *glamor_egl->back_pixmap) { + back_image = dixLookupPrivate(&(*glamor_egl->back_pixmap)->devPrivates, + glamor_egl_pixmap_private_key); + if (back_image != NULL && back_image != EGL_NO_IMAGE_KHR) { + glamor_egl->egl_destroy_image_khr(glamor_egl->display, back_image); + dixSetPrivate(&(*glamor_egl->back_pixmap)->devPrivates, + glamor_egl_pixmap_private_key, NULL); + } + } screen->CloseScreen = glamor_egl->saved_close_screen; @@ -383,7 +435,6 @@ glamor_egl_free_screen(int scrnIndex, int flags) ScrnInfoPtr scrn = xf86Screens[scrnIndex]; struct glamor_egl_screen_private *glamor_egl; - ErrorF("free egl screen resources\n"); glamor_egl = glamor_egl_get_screen_private(scrn); if (glamor_egl != NULL) { diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index ec1a5b067..b4e4af71e 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -427,3 +427,22 @@ glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo) break; } } +/* + * XXX how to handle those pending OPs. + * By default, pending OP is disabled. Maybe we will give up the pending + * OP latter. + * + * */ + +_X_EXPORT void +glamor_pixmap_exchange_fbos(PixmapPtr front, PixmapPtr back) +{ + glamor_pixmap_private *front_priv, *back_priv; + glamor_pixmap_fbo *temp_fbo; + + front_priv = glamor_get_pixmap_private(front); + back_priv = glamor_get_pixmap_private(back); + temp_fbo = front_priv->fbo; + front_priv->fbo = back_priv->fbo; + back_priv->fbo = temp_fbo; +} diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 0d3aa82c3..b9670a398 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -212,6 +212,7 @@ typedef struct glamor_screen_private { GLint put_image_xybitmap_fg_uniform_location; GLint put_image_xybitmap_bg_uniform_location; + PixmapPtr *back_pixmap; int screen_fbo; struct glamor_saved_procs saved_procs; char delayed_fallback_string[GLAMOR_DELAYED_STRING_MAX + 1]; @@ -344,16 +345,7 @@ glamor_get_pixmap_private(PixmapPtr pixmap) glamor_pixmap_private_key); } -static inline void -glamor_set_pixmap_private(PixmapPtr pixmap, glamor_pixmap_private *priv) -{ - dixSetPrivate(&pixmap->devPrivates, - glamor_pixmap_private_key, - priv); -} - - - +void glamor_set_pixmap_private(PixmapPtr pixmap, glamor_pixmap_private *priv); /** * Returns TRUE if the given planemask covers all the significant bits in the