[RFC xserver 08/16] Glamor: Use gbm_bo_create_with_modifiers for internal pixmap allocation

Daniel Stone daniels at collabora.com
Thu Jun 8 18:43:34 UTC 2017


From: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>

Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Signed-off-by: Daniel Stone <daniels at collabora.com>
---
 configure.ac                  |   4 ++
 glamor/glamor_egl.c           | 112 ++++++++++++++++++++++++++++++++++++++----
 hw/xwayland/xwayland-glamor.c |  23 +++++++++
 include/dix-config.h.in       |   3 ++
 4 files changed, 133 insertions(+), 9 deletions(-)

diff --git a/configure.ac b/configure.ac
index fbee76211..7587f311e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2095,6 +2095,10 @@ if test "x$GLAMOR" = xyes; then
 			[AC_DEFINE(GLAMOR_HAS_GBM_LINEAR, 1, [Have GBM_BO_USE_LINEAR])], [],
 			[#include <stdlib.h>
 			 #include <gbm.h>])
+		dnl 17.1.0 is required for gbm_bo_create_with_modifiers
+		PKG_CHECK_EXISTS(gbm >= 17.1.0,
+				 [AC_DEFINE(GBM_BO_WITH_MODIFIERS, 1, [Have gbm_bo_create_with_modifiers])],
+				 [])
 	else
 		if test "x$XORG" = xyes; then
 			AC_MSG_ERROR([Glamor for Xorg requires $LIBGBM])
diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index 392c9a39c..68bc8b0bd 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -363,6 +363,45 @@ glamor_get_name_from_bo(int gbm_fd, struct gbm_bo *bo, int *name)
         *name = -1;
 }
 
+static uint32_t
+drm_format_for_depth(uint32_t bpp, uint32_t depth)
+{
+    uint32_t fmt;
+
+    switch (bpp) {
+        case 8:
+            fmt = DRM_FORMAT_C8;
+            break;
+        case 16:
+            if (depth == 15)
+                fmt = DRM_FORMAT_XRGB1555;
+            else
+                fmt = DRM_FORMAT_RGB565;
+            break;
+        case 24:
+            fmt = DRM_FORMAT_RGB888;
+            break;
+        case 32:
+            if (depth == 24)
+                fmt = DRM_FORMAT_XRGB8888;
+            else if (depth == 30)
+                fmt = DRM_FORMAT_XRGB2101010;
+            else
+                fmt = DRM_FORMAT_ARGB8888;
+            break;
+        default:
+            // XXX error
+            fmt = DRM_FORMAT_XRGB8888;
+            break;
+    }
+
+    return fmt;
+}
+
+static Bool
+glamor_get_modifiers(ScreenPtr screen, CARD32 format,
+                     CARD32 *num_modifiers, uint64_t **modifiers);
+
 static Bool
 glamor_make_pixmap_exportable(PixmapPtr pixmap)
 {
@@ -374,9 +413,11 @@ glamor_make_pixmap_exportable(PixmapPtr pixmap)
         glamor_get_pixmap_private(pixmap);
     unsigned width = pixmap->drawable.width;
     unsigned height = pixmap->drawable.height;
+    uint64_t modifier = 0;
     struct gbm_bo *bo;
     PixmapPtr exported;
     GCPtr scratch_gc;
+    bool ret = FALSE;
 
     if (pixmap_priv->image)
         return TRUE;
@@ -388,13 +429,31 @@ glamor_make_pixmap_exportable(PixmapPtr pixmap)
         return FALSE;
     }
 
-    bo = gbm_bo_create(glamor_egl->gbm, width, height,
-                       GBM_FORMAT_ARGB8888,
+#ifdef GBM_BO_WITH_MODIFIERS
+    if (glamor_egl->modifiers_capable) {
+        uint32_t num_modifiers;
+        uint64_t *modifiers = NULL;
+
+        glamor_get_modifiers(screen, DRM_FORMAT_ARGB8888,
+                             &num_modifiers, &modifiers);
+        bo = gbm_bo_create_with_modifiers(glamor_egl->gbm, width, height,
+                                          GBM_FORMAT_ARGB8888,
+                                          modifiers, num_modifiers);
+        modifier = gbm_bo_get_modifier(bo);
+        free(modifiers);
+    }
+    else
+#endif
+    {
+        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) |
+                (pixmap->usage_hint == CREATE_PIXMAP_USAGE_SHARED ?
+                 GBM_BO_USE_LINEAR : 0) |
 #endif
-                       GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT);
+                GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT);
+    }
+
     if (!bo) {
         xf86DrvMsg(scrn->scrnIndex, X_ERROR,
                    "Failed to make %dx%dx%dbpp GBM bo\n",
@@ -405,15 +464,45 @@ glamor_make_pixmap_exportable(PixmapPtr pixmap)
     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)) {
+
+    if (modifier) {
+#ifdef GBM_BO_WITH_MODIFIERS
+        // XXX Check if multi planes is supported
+        int i, num_fds, fds[4];
+        uint32_t strides[4], offsets[4];
+        uint32_t format;
+
+        format = drm_format_for_depth(pixmap->drawable.bitsPerPixel,
+                                      pixmap->drawable.depth);
+        num_fds = gbm_bo_get_plane_count(bo);
+        for (i = 0; i < num_fds; i++) {
+            fds[i] = gbm_bo_get_fd(bo); // All planes use same fd
+            strides[i] = gbm_bo_get_stride_for_plane(bo, i);
+            offsets[i] = gbm_bo_get_offset(bo, i);
+        }
+        ret = glamor_egl_create_textured_pixmap_from_dmabuf(exported,
+                                                            num_fds, fds,
+                                                            width, height,
+                                                            strides, offsets,
+                                                            format, modifier);
+        if (!ret) {
+            for (i = 0; i < num_fds; i++)
+                close(fds[i]);
+        }
+#endif
+    } else {
+        ret = glamor_egl_create_textured_pixmap_from_gbm_bo(exported, bo);
+    }
+
+    gbm_bo_destroy(bo);
+
+    if (!ret) {
         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);
 
     scratch_gc = GetScratchGC(pixmap->drawable.depth, screen);
     ValidateGC(&pixmap->drawable, scratch_gc);
@@ -564,7 +653,7 @@ glamor_pixmap_from_fds(ScreenPtr screen,
     pixmap = screen->CreatePixmap(screen, 0, 0, info->depth, 0);
 
     if (glamor_egl->dmabuf_capable) {
-        screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, strides[0], NULL); // XXX what is the stride used for?
+        screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, strides[0], NULL);
         ret = glamor_egl_create_textured_pixmap_from_dmabuf(pixmap, num_fds, fds,
                                                             width, height,
                                                             strides, offsets,
@@ -696,6 +785,7 @@ _X_EXPORT void
 glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr back)
 {
     EGLImageKHR temp;
+    struct glamor_pixmap_dmabuf *tmp_dmabuf;
     struct glamor_pixmap_private *front_priv =
         glamor_get_pixmap_private(front);
     struct glamor_pixmap_private *back_priv =
@@ -707,6 +797,10 @@ glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr back)
     back_priv->image = front_priv->image;
     front_priv->image = temp;
 
+    tmp_dmabuf = back_priv->dmabuf;
+    back_priv->dmabuf = front_priv->dmabuf;
+    front_priv->dmabuf = tmp_dmabuf;
+
     glamor_set_pixmap_type(front, GLAMOR_TEXTURE_DRM);
     glamor_set_pixmap_type(back, GLAMOR_TEXTURE_DRM);
 }
diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c
index 139e38052..de9769028 100644
--- a/hw/xwayland/xwayland-glamor.c
+++ b/hw/xwayland/xwayland-glamor.c
@@ -334,12 +334,17 @@ xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap)
     return xwl_pixmap->buffer;
 }
 
+static int
+xwl_dri3_get_modifiers(ScreenPtr screen, CARD32 format,
+                       CARD32 *num_modifiers, uint64_t **modifiers);
+
 static PixmapPtr
 xwl_glamor_create_pixmap(ScreenPtr screen,
                          int width, int height, int depth, unsigned int hint)
 {
     struct xwl_screen *xwl_screen = xwl_screen_get(screen);
     struct gbm_bo *bo;
+    uint32_t format;
 
     if (width > 0 && height > 0 && depth >= 15 &&
         (hint == 0 ||
@@ -348,6 +353,24 @@ xwl_glamor_create_pixmap(ScreenPtr screen,
         bo = gbm_bo_create(xwl_screen->gbm, width, height,
                            gbm_format_for_depth(depth),
                            GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
+        format = gbm_format_for_depth(depth);
+
+#ifdef GBM_BO_WITH_MODIFIERS
+        if (xwl_screen->modifiers_capable) {
+            uint32_t num_modifiers;
+            uint64_t *modifiers = NULL;
+
+            xwl_dri3_get_modifiers(screen, format, &num_modifiers, &modifiers);
+            bo = gbm_bo_create_with_modifiers(xwl_screen->gbm, width, height,
+                                              format, modifiers, num_modifiers);
+            free(modifiers);
+        }
+        else
+#endif
+        {
+            bo = gbm_bo_create(xwl_screen->gbm, width, height, format,
+                               GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
+        }
 
         if (bo)
             return xwl_glamor_create_pixmap_for_bo(screen, bo, depth, format);
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index ad1ab20a6..57aee61fd 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -497,6 +497,9 @@
 /* Build glamor/gbm has linear support */
 #undef GLAMOR_HAS_GBM_LINEAR
 
+/* GBM has modifiers support */
+#undef GBM_BO_WITH_MODIFIERS
+
 /* Build glamor use new drmGetDeviceNameFromFD2 */
 #undef GLAMOR_HAS_DRM_NAME_FROM_FD_2
 
-- 
2.13.0



More information about the xorg-devel mailing list