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