summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2015-06-18 11:14:41 -0700
committerEric Anholt <eric@anholt.net>2015-12-11 19:33:53 -0800
commit8b00f18b5a1c376706cc8dbd82ae20c83022010d (patch)
tree99dd47eda1525a392a45820564096f41b2b12ee8
parentde1228d1f50eac72930943f5ac7b58d92d23b679 (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.h5
-rw-r--r--glamor/glamor_egl.c169
-rw-r--r--glamor/glamor_egl_stubs.c6
-rw-r--r--glamor/glamor_fbo.c39
-rw-r--r--hw/xwayland/xwayland-glamor.c6
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;