diff options
author | Eric Anholt <eric@anholt.net> | 2015-06-18 11:14:41 -0700 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2015-12-11 19:33:53 -0800 |
commit | 8b00f18b5a1c376706cc8dbd82ae20c83022010d (patch) | |
tree | 99dd47eda1525a392a45820564096f41b2b12ee8 | |
parent | de1228d1f50eac72930943f5ac7b58d92d23b679 (diff) |
glamor: Delay making pixmaps shareable until we need to.
If a pixmap isn't getting exported as a dmabuf, then we don't need to
make an EGLImage/GBM bo for it. This should reduce normal pixmap
allocation overhead, and also lets the driver choose non-scanout
formats which may be much higher performance.
On Raspberry Pi, where scanout isn't usable as a texture source, this
improves x11perf -copypixwin100 from about 4300/sec to 5780/sec under
xcompmgr -a, because we no longer need to upload our x11perf window to
a tiled temporary in order to render it to the screen.
v2: Just use pixmap->usage_hint instead of a new field. Drop the
changes that started storing gbm_bos in the pixmap priv due to
lifetime issues.
v3: Fix a missing gbm_bo_destroy() on the pixmap-from-fd success path.
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
(cherry picked from commit 51984dddfcc7133ed3c1f20d03514aa98c9a7831)
-rw-r--r-- | glamor/glamor.h | 5 | ||||
-rw-r--r-- | glamor/glamor_egl.c | 169 | ||||
-rw-r--r-- | glamor/glamor_egl_stubs.c | 6 | ||||
-rw-r--r-- | glamor/glamor_fbo.c | 39 | ||||
-rw-r--r-- | hw/xwayland/xwayland-glamor.c | 6 |
5 files changed, 82 insertions, 143 deletions
diff --git a/glamor/glamor.h b/glamor/glamor.h index 12dff8e4b..a4e065576 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -140,11 +140,6 @@ extern _X_EXPORT void glamor_pixmap_exchange_fbos(PixmapPtr front, /* The DDX is not supposed to call these three functions */ extern _X_EXPORT void glamor_enable_dri3(ScreenPtr screen); -extern _X_EXPORT unsigned int glamor_egl_create_argb8888_based_texture(ScreenPtr - screen, - int w, - int h, - Bool linear); extern _X_EXPORT int glamor_egl_dri3_fd_name_from_tex(ScreenPtr, PixmapPtr, unsigned int, Bool, CARD16 *, CARD32 *); diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index e68af18dd..ea0443de6 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -187,49 +187,6 @@ glamor_egl_get_gbm_device(ScreenPtr screen) #endif } -unsigned int -glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h, Bool linear) -{ - ScrnInfoPtr scrn = xf86ScreenToScrn(screen); - struct glamor_egl_screen_private *glamor_egl; - EGLImageKHR image; - GLuint texture; - -#ifdef GLAMOR_HAS_GBM - struct gbm_bo *bo; - EGLNativePixmapType native_pixmap; - - glamor_egl = glamor_egl_get_screen_private(scrn); - bo = gbm_bo_create(glamor_egl->gbm, w, h, GBM_FORMAT_ARGB8888, -#ifdef GLAMOR_HAS_GBM_LINEAR - (linear ? GBM_BO_USE_LINEAR : 0) | -#endif - GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT); - if (!bo) - return 0; - - /* If the following assignment raises an error or a warning - * then that means EGLNativePixmapType is not struct gbm_bo * - * on your platform: This code won't work and you should not - * compile with dri3 support enabled */ - native_pixmap = bo; - - image = eglCreateImageKHR(glamor_egl->display, - EGL_NO_CONTEXT, - EGL_NATIVE_PIXMAP_KHR, - native_pixmap, NULL); - gbm_bo_destroy(bo); - if (image == EGL_NO_IMAGE_KHR) - return 0; - glamor_create_texture_from_image(screen, image, &texture); - eglDestroyImageKHR(glamor_egl->display, image); - - return texture; -#else - return 0; /* this path should never happen */ -#endif -} - Bool glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int stride) { @@ -380,79 +337,92 @@ glamor_get_name_from_bo(int gbm_fd, struct gbm_bo *bo, int *name) } #endif -#ifdef GLAMOR_HAS_GBM -static void * -_get_gbm_bo_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, unsigned int tex) +static Bool +glamor_make_pixmap_exportable(PixmapPtr pixmap) { +#ifdef GLAMOR_HAS_GBM + ScreenPtr screen = pixmap->drawable.pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + struct glamor_egl_screen_private *glamor_egl = + glamor_egl_get_screen_private(scrn); struct glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - struct glamor_screen_private *glamor_priv = - glamor_get_screen_private(screen); - struct glamor_egl_screen_private *glamor_egl; - EGLImageKHR image; + unsigned width = pixmap->drawable.width; + unsigned height = pixmap->drawable.height; struct gbm_bo *bo; + PixmapPtr exported; + GCPtr scratch_gc; - EGLint attribs[] = { - EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, - EGL_GL_TEXTURE_LEVEL_KHR, 0, - EGL_NONE - }; + if (pixmap_priv->image) + return TRUE; - glamor_egl = glamor_egl_get_screen_private(scrn); + if (pixmap->drawable.bitsPerPixel != 32) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Failed to make %dbpp pixmap exportable\n", + pixmap->drawable.bitsPerPixel); + return FALSE; + } - glamor_make_current(glamor_priv); + bo = gbm_bo_create(glamor_egl->gbm, width, height, + GBM_FORMAT_ARGB8888, +#ifdef GLAMOR_HAS_GBM_LINEAR + (pixmap->usage_hint == CREATE_PIXMAP_USAGE_SHARED ? + GBM_BO_USE_LINEAR : 0) | +#endif + GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT); + if (!bo) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Failed to make %dx%dx%dbpp GBM bo\n", + width, height, pixmap->drawable.bitsPerPixel); + return FALSE; + } - image = pixmap_priv->image; - if (!image) { - image = eglCreateImageKHR(glamor_egl->display, - glamor_egl->context, - EGL_GL_TEXTURE_2D_KHR, - (EGLClientBuffer) (uintptr_t) - tex, attribs); - if (image == EGL_NO_IMAGE_KHR) - return NULL; - - glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM); - glamor_egl_set_pixmap_image(pixmap, image); + exported = screen->CreatePixmap(screen, 0, 0, pixmap->drawable.depth, 0); + screen->ModifyPixmapHeader(exported, width, height, 0, 0, + gbm_bo_get_stride(bo), NULL); + if (!glamor_egl_create_textured_pixmap_from_gbm_bo(exported, bo)) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Failed to make %dx%dx%dbpp pixmap from GBM bo\n", + width, height, pixmap->drawable.bitsPerPixel); + screen->DestroyPixmap(exported); + gbm_bo_destroy(bo); + return FALSE; } + gbm_bo_destroy(bo); - bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_EGL_IMAGE, image, 0); - if (!bo) - return NULL; + scratch_gc = GetScratchGC(pixmap->drawable.depth, screen); + ValidateGC(&pixmap->drawable, scratch_gc); + scratch_gc->ops->CopyArea(&pixmap->drawable, &exported->drawable, + scratch_gc, + 0, 0, width, height, 0, 0); + FreeScratchGC(scratch_gc); - pixmap->devKind = gbm_bo_get_stride(bo); + /* Now, swap the tex/gbm/EGLImage/etc. of the exported pixmap into + * the original pixmap struct. + */ + glamor_egl_exchange_buffers(pixmap, exported); - return bo; -} + screen->DestroyPixmap(exported); + + return TRUE; +#else + return FALSE; #endif +} struct gbm_bo * glamor_gbm_bo_from_pixmap(ScreenPtr screen, PixmapPtr pixmap) { -#ifdef GLAMOR_HAS_GBM - glamor_screen_private *glamor_priv = - glamor_get_screen_private(pixmap->drawable.pScreen); - glamor_pixmap_private *pixmap_priv = + struct glamor_egl_screen_private *glamor_egl = + glamor_egl_get_screen_private(xf86ScreenToScrn(screen)); + struct glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - pixmap_priv = glamor_get_pixmap_private(pixmap); - if (!glamor_priv->dri3_enabled) + if (!glamor_make_pixmap_exportable(pixmap)) return NULL; - switch (pixmap_priv->type) { - case GLAMOR_TEXTURE_DRM: - case GLAMOR_TEXTURE_ONLY: - if (!glamor_pixmap_ensure_fbo(pixmap, GL_RGBA, 0)) - return NULL; - return _get_gbm_bo_from_pixmap(screen, pixmap, - pixmap_priv->fbo->tex); - default: - break; - } - return NULL; -#else - return NULL; -#endif + + return gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_EGL_IMAGE, + pixmap_priv->image, 0); } int @@ -468,7 +438,7 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen, glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen)); - bo = _get_gbm_bo_from_pixmap(screen, pixmap, tex); + bo = glamor_gbm_bo_from_pixmap(screen, pixmap); if (!bo) goto failure; @@ -504,8 +474,8 @@ glamor_back_pixmap_from_fd(PixmapPtr pixmap, ScrnInfoPtr scrn = xf86ScreenToScrn(screen); struct glamor_egl_screen_private *glamor_egl; struct gbm_bo *bo; - Bool ret = FALSE; struct gbm_import_fd_data import_data = { 0 }; + Bool ret; glamor_egl = glamor_egl_get_screen_private(scrn); @@ -528,10 +498,7 @@ glamor_back_pixmap_from_fd(PixmapPtr pixmap, ret = glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo); gbm_bo_destroy(bo); - - if (ret) - return TRUE; - return FALSE; + return ret; #else return FALSE; #endif diff --git a/glamor/glamor_egl_stubs.c b/glamor/glamor_egl_stubs.c index 35944c849..40f7fcc01 100644 --- a/glamor/glamor_egl_stubs.c +++ b/glamor/glamor_egl_stubs.c @@ -43,9 +43,3 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen, { return 0; } - -unsigned int -glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h, Bool linear) -{ - return 0; -} diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index 545f89fcd..b1b584d21 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -329,30 +329,19 @@ glamor_destroy_fbo(glamor_screen_private *glamor_priv, static int _glamor_create_tex(glamor_screen_private *glamor_priv, - int w, int h, GLenum format, Bool linear) + int w, int h, GLenum format) { - unsigned int tex = 0; - - /* With dri3, we want to allocate ARGB8888 pixmaps only. - * Depending on the implementation, GL_RGBA might not - * give us ARGB8888. We ask glamor_egl to use get - * an ARGB8888 based texture for us. */ - if (glamor_priv->dri3_enabled && format == GL_RGBA) { - tex = glamor_egl_create_argb8888_based_texture(glamor_priv->screen, - w, h, linear); - } - if (!tex) { - glamor_make_current(glamor_priv); - glGenTextures(1, &tex); - glBindTexture(GL_TEXTURE_2D, tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - glamor_priv->suppress_gl_out_of_memory_logging = true; - glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, - format, GL_UNSIGNED_BYTE, NULL); - glamor_priv->suppress_gl_out_of_memory_logging = false; - } + unsigned int tex; + + glamor_make_current(glamor_priv); + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glamor_priv->suppress_gl_out_of_memory_logging = true; + glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, + format, GL_UNSIGNED_BYTE, NULL); + glamor_priv->suppress_gl_out_of_memory_logging = false; if (glGetError() == GL_OUT_OF_MEMORY) { if (!glamor_priv->logged_any_fbo_allocation_failure) { @@ -383,7 +372,7 @@ glamor_create_fbo(glamor_screen_private *glamor_priv, if (fbo) return fbo; new_fbo: - tex = _glamor_create_tex(glamor_priv, w, h, format, flag == CREATE_PIXMAP_USAGE_SHARED); + tex = _glamor_create_tex(glamor_priv, w, h, format); if (!tex) return NULL; fbo = glamor_create_fbo_from_tex(glamor_priv, w, h, format, tex, flag); @@ -548,7 +537,7 @@ glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag) if (!pixmap_priv->fbo->tex) pixmap_priv->fbo->tex = _glamor_create_tex(glamor_priv, pixmap->drawable.width, - pixmap->drawable.height, format, FALSE); + pixmap->drawable.height, format); if (flag != GLAMOR_CREATE_FBO_NO_FBO && pixmap_priv->fbo->fb == 0) if (glamor_pixmap_ensure_fb(glamor_priv, pixmap_priv->fbo) != 0) diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c index dedefdc2c..ebaf05aae 100644 --- a/hw/xwayland/xwayland-glamor.c +++ b/hw/xwayland/xwayland-glamor.c @@ -409,12 +409,6 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen, return 0; } -unsigned int -glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h, Bool linear) -{ - return 0; -} - struct xwl_auth_state { int fd; ClientPtr client; |