[PATCH xserver 10/11] glamor: Delay making pixmaps shareable until we need to.

Eric Anholt eric at anholt.net
Fri Nov 6 12:52:04 PST 2015


If a pixmap isn't getting exported as a dmabuf, then we don't need to
go the GBM route 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.

Signed-off-by: Eric Anholt <eric at anholt.net>
---
 glamor/glamor.c               |   2 +
 glamor/glamor.h               |   5 -
 glamor/glamor_egl.c           | 211 ++++++++++++++++++------------------------
 glamor/glamor_egl_stubs.c     |   6 --
 glamor/glamor_fbo.c           |  35 +++----
 glamor/glamor_priv.h          |   2 +
 hw/xwayland/xwayland-glamor.c |   6 --
 7 files changed, 109 insertions(+), 158 deletions(-)

diff --git a/glamor/glamor.c b/glamor/glamor.c
index ec5f81b..663399c 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -168,6 +168,8 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
 
     pixmap_priv = glamor_get_pixmap_private(pixmap);
 
+    pixmap_priv->usage_shared = (usage == CREATE_PIXMAP_USAGE_SHARED);
+
     format = gl_iformat_for_pixmap(pixmap);
 
     pitch = (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3;
diff --git a/glamor/glamor.h b/glamor/glamor.h
index 12dff8e..a4e0655 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 e68af18..8638063 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)
 {
@@ -334,6 +291,7 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride)
     return ret;
 }
 
+#ifdef GLAMOR_HAS_GBM
 Bool
 glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap,
                                               struct gbm_bo *bo)
@@ -342,6 +300,8 @@ glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap,
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
     struct glamor_screen_private *glamor_priv =
         glamor_get_screen_private(screen);
+    struct glamor_pixmap_private *pixmap_priv =
+        glamor_get_pixmap_private(pixmap);
     struct glamor_egl_screen_private *glamor_egl;
     EGLImageKHR image;
     GLuint texture;
@@ -362,13 +322,15 @@ glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap,
     glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM);
     glamor_set_pixmap_texture(pixmap, texture);
     glamor_egl_set_pixmap_image(pixmap, image);
+    if (pixmap_priv->gbm)
+        gbm_bo_destroy(pixmap_priv->gbm);
+    pixmap_priv->gbm = bo;
     ret = TRUE;
 
  done:
     return ret;
 }
 
-#ifdef GLAMOR_HAS_GBM
 static void
 glamor_get_name_from_bo(int gbm_fd, struct gbm_bo *bo, int *name)
 {
@@ -380,79 +342,83 @@ 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->gbm)
+        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_priv->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;
     }
 
-    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);
+
+    /* Now, swap the tex/gbm/EGLImage/etc. of the exported pixmap into
+     * the original pixmap struct.
+     */
+    glamor_egl_exchange_buffers(pixmap, exported);
 
-    pixmap->devKind = gbm_bo_get_stride(bo);
+    screen->DestroyPixmap(exported);
 
-    return bo;
-}
+    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 =
-        glamor_get_pixmap_private(pixmap);
-
-    pixmap_priv = glamor_get_pixmap_private(pixmap);
-    if (!glamor_priv->dri3_enabled)
-        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
+    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
+    glamor_make_pixmap_exportable(pixmap);
+    return pixmap_priv->gbm;
 }
 
 int
@@ -462,30 +428,26 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
                                  Bool want_name, CARD16 *stride, CARD32 *size)
 {
 #ifdef GLAMOR_HAS_GBM
+     struct glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap);
     struct glamor_egl_screen_private *glamor_egl;
-    struct gbm_bo *bo;
     int fd = -1;
 
     glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen));
 
-    bo = _get_gbm_bo_from_pixmap(screen, pixmap, tex);
-    if (!bo)
+    if (!glamor_make_pixmap_exportable(pixmap))
         goto failure;
 
-    pixmap->devKind = gbm_bo_get_stride(bo);
-
     if (want_name) {
         if (glamor_egl->has_gem)
-            glamor_get_name_from_bo(glamor_egl->fd, bo, &fd);
+            glamor_get_name_from_bo(glamor_egl->fd, priv->gbm, &fd);
     }
     else {
-        fd = gbm_bo_get_fd(bo);
+        fd = gbm_bo_get_fd(priv->gbm);
     }
-    *stride = pixmap->devKind;
-    *size = pixmap->devKind * gbm_bo_get_height(bo);
+    *stride = gbm_bo_get_stride(priv->gbm);
+    *size = *stride * gbm_bo_get_height(priv->gbm);
 
-    gbm_bo_destroy(bo);
- failure:
+failure:
     return fd;
 #else
     return -1;
@@ -504,7 +466,6 @@ 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 };
 
     glamor_egl = glamor_egl_get_screen_private(scrn);
@@ -526,12 +487,12 @@ glamor_back_pixmap_from_fd(PixmapPtr pixmap,
 
     screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, stride, NULL);
 
-    ret = glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo);
-    gbm_bo_destroy(bo);
+    if (!glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo)) {
+        gbm_bo_destroy(bo);
+        return FALSE;
+    }
 
-    if (ret)
-        return TRUE;
-    return FALSE;
+    return TRUE;
 #else
     return FALSE;
 #endif
@@ -576,6 +537,13 @@ glamor_egl_destroy_pixmap(PixmapPtr pixmap)
 
         if (pixmap_priv->image)
             eglDestroyImageKHR(glamor_egl->display, pixmap_priv->image);
+
+#ifdef GLAMOR_HAS_GBM
+        if (pixmap_priv->gbm) {
+            gbm_bo_destroy(pixmap_priv->gbm);
+            pixmap_priv->gbm = NULL;
+        }
+#endif
     }
 
     screen->DestroyPixmap = glamor_egl->saved_destroy_pixmap;
@@ -589,7 +557,8 @@ glamor_egl_destroy_pixmap(PixmapPtr pixmap)
 _X_EXPORT void
 glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr back)
 {
-    EGLImageKHR temp;
+    EGLImageKHR temp_image;
+    struct gbm_bo *temp_bo;
     struct glamor_pixmap_private *front_priv =
         glamor_get_pixmap_private(front);
     struct glamor_pixmap_private *back_priv =
@@ -597,9 +566,13 @@ glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr back)
 
     glamor_pixmap_exchange_fbos(front, back);
 
-    temp = back_priv->image;
+    temp_image = back_priv->image;
     back_priv->image = front_priv->image;
-    front_priv->image = temp;
+    front_priv->image = temp_image;
+
+    temp_bo = back_priv->gbm;
+    back_priv->gbm = front_priv->gbm;
+    front_priv->gbm = temp_bo;
 
     glamor_set_pixmap_type(front, GLAMOR_TEXTURE_DRM);
     glamor_set_pixmap_type(back, GLAMOR_TEXTURE_DRM);
diff --git a/glamor/glamor_egl_stubs.c b/glamor/glamor_egl_stubs.c
index 35944c8..40f7fcc 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 262033f..c29b00e 100644
--- a/glamor/glamor_fbo.c
+++ b/glamor/glamor_fbo.c
@@ -329,27 +329,18 @@ 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);
-        glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0,
-                     format, GL_UNSIGNED_BYTE, NULL);
-    }
+    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);
+    glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0,
+                 format, GL_UNSIGNED_BYTE, NULL);
+
     return tex;
 }
 
@@ -367,7 +358,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);
     fbo = glamor_create_fbo_from_tex(glamor_priv, w, h, format, tex, flag);
 
     return fbo;
@@ -530,7 +521,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/glamor/glamor_priv.h b/glamor/glamor_priv.h
index f3950f1..df6a02a 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -353,8 +353,10 @@ typedef struct glamor_pixmap_private {
     GLuint pbo;
     RegionRec prepare_region;
     Bool prepared;
+    Bool usage_shared;
 #if GLAMOR_HAS_GBM
     EGLImageKHR image;
+    struct gbm_bo *gbm;
 #endif
     /** block width of this large pixmap. */
     int block_w;
diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c
index dedefdc..ebaf05a 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;
-- 
2.6.2



More information about the xorg-devel mailing list