[RFC v2 04/13] glamor: Implement GetSupportedFormats and GetSupportedModifiers

Louis-Francis Ratté-Boulianne lfrb at collabora.com
Fri Jul 14 04:47:51 UTC 2017


Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
---
 dri3/dri3.c                   |  92 ++++++++++++++++++++++++++++++++
 dri3/dri3.h                   |  12 +++++
 glamor/glamor.h               |  10 ++++
 glamor/glamor_egl.c           |  69 ++++++++++++++++++++++++
 hw/xwayland/xwayland-glamor.c | 119 +++++++++++++++++++++++++++++++++++++-----
 hw/xwayland/xwayland.h        |   9 +++-
 6 files changed, 297 insertions(+), 14 deletions(-)

diff --git a/dri3/dri3.c b/dri3/dri3.c
index d042b8b7d..221200cf0 100644
--- a/dri3/dri3.c
+++ b/dri3/dri3.c
@@ -26,6 +26,8 @@
 
 #include "dri3_priv.h"
 
+#include <drm_fourcc.h>
+
 static int dri3_request;
 DevPrivateKeyRec dri3_screen_private_key;
 
@@ -99,3 +101,93 @@ dri3_extension_init(void)
 bail:
     FatalError("Cannot initialize DRI3 extension");
 }
+
+const struct drm_format_info *
+drm_format_get_info(uint32_t format)
+{
+    static const struct drm_format_info formats[] = {
+        { .format = DRM_FORMAT_C8,          .depth = 8,  .bpp = 8  },
+        { .format = DRM_FORMAT_RGB332,      .depth = 8,  .bpp = 8  },
+        { .format = DRM_FORMAT_BGR233,      .depth = 8,  .bpp = 8  },
+        { .format = DRM_FORMAT_XRGB4444,    .depth = 12, .bpp = 16 },
+        { .format = DRM_FORMAT_XBGR4444,    .depth = 12, .bpp = 16 },
+        { .format = DRM_FORMAT_RGBX4444,    .depth = 12, .bpp = 16 },
+        { .format = DRM_FORMAT_BGRX4444,    .depth = 12, .bpp = 16 },
+        { .format = DRM_FORMAT_ARGB4444,    .depth = 16, .bpp = 16 },
+        { .format = DRM_FORMAT_ABGR4444,    .depth = 16, .bpp = 16 },
+        { .format = DRM_FORMAT_RGBA4444,    .depth = 16, .bpp = 16 },
+        { .format = DRM_FORMAT_BGRA4444,    .depth = 16, .bpp = 16 },
+        { .format = DRM_FORMAT_XRGB1555,    .depth = 15, .bpp = 16 },
+        { .format = DRM_FORMAT_XBGR1555,    .depth = 15, .bpp = 16 },
+        { .format = DRM_FORMAT_RGBX5551,    .depth = 15, .bpp = 16 },
+        { .format = DRM_FORMAT_BGRX5551,    .depth = 15, .bpp = 16 },
+        { .format = DRM_FORMAT_ARGB1555,    .depth = 16, .bpp = 16 },
+        { .format = DRM_FORMAT_ABGR1555,    .depth = 16, .bpp = 16 },
+        { .format = DRM_FORMAT_RGBA5551,    .depth = 16, .bpp = 16 },
+        { .format = DRM_FORMAT_BGRA5551,    .depth = 16, .bpp = 16 },
+        { .format = DRM_FORMAT_RGB565,      .depth = 16, .bpp = 16 },
+        { .format = DRM_FORMAT_BGR565,      .depth = 16, .bpp = 16 },
+        { .format = DRM_FORMAT_RGB888,      .depth = 24, .bpp = 24 },
+        { .format = DRM_FORMAT_BGR888,      .depth = 24, .bpp = 24 },
+        { .format = DRM_FORMAT_XRGB8888,    .depth = 24, .bpp = 32 },
+        { .format = DRM_FORMAT_XBGR8888,    .depth = 24, .bpp = 32 },
+        { .format = DRM_FORMAT_RGBX8888,    .depth = 24, .bpp = 32 },
+        { .format = DRM_FORMAT_BGRX8888,    .depth = 24, .bpp = 32 },
+        { .format = DRM_FORMAT_XRGB2101010, .depth = 30, .bpp = 32 },
+        { .format = DRM_FORMAT_XBGR2101010, .depth = 30, .bpp = 32 },
+        { .format = DRM_FORMAT_RGBX1010102, .depth = 30, .bpp = 32 },
+        { .format = DRM_FORMAT_BGRX1010102, .depth = 30, .bpp = 32 },
+        { .format = DRM_FORMAT_ARGB2101010, .depth = 30, .bpp = 32 },
+        { .format = DRM_FORMAT_ABGR2101010, .depth = 30, .bpp = 32 },
+        { .format = DRM_FORMAT_RGBA1010102, .depth = 30, .bpp = 32 },
+        { .format = DRM_FORMAT_BGRA1010102, .depth = 30, .bpp = 32 },
+        { .format = DRM_FORMAT_ARGB8888,    .depth = 32, .bpp = 32 },
+        { .format = DRM_FORMAT_ABGR8888,    .depth = 32, .bpp = 32 },
+        { .format = DRM_FORMAT_RGBA8888,    .depth = 32, .bpp = 32 },
+        { .format = DRM_FORMAT_BGRA8888,    .depth = 32, .bpp = 32 },
+    };
+
+    unsigned int i;
+
+    for (i = 0; i < ARRAY_SIZE(formats); ++i) {
+        if (formats[i].format == format)
+            return &formats[i];
+    }
+
+    return NULL;
+}
+
+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;
+}
diff --git a/dri3/dri3.h b/dri3/dri3.h
index 67589c70c..93fdeacf5 100644
--- a/dri3/dri3.h
+++ b/dri3/dri3.h
@@ -103,6 +103,18 @@ dri3_screen_init(ScreenPtr screen, dri3_screen_info_ptr info);
 extern _X_EXPORT int
 dri3_send_open_reply(ClientPtr client, int fd);
 
+struct drm_format_info {
+    uint32_t format;
+    uint32_t depth;
+    uint32_t bpp;
+};
+
+extern _X_EXPORT const struct drm_format_info *
+drm_format_get_info(uint32_t format);
+
+extern _X_EXPORT uint32_t
+drm_format_for_depth(uint32_t bpp, uint32_t depth);
+
 #endif
 
 #endif /* _DRI3_H_ */
diff --git a/glamor/glamor.h b/glamor/glamor.h
index f16f79c97..044480597 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -318,6 +318,16 @@ extern _X_EXPORT Bool glamor_back_pixmap_from_fd(PixmapPtr pixmap,
                                                  CARD16 stride,
                                                  CARD8 depth,
                                                  CARD8 bpp);
+
+extern _X_EXPORT Bool glamor_get_formats(ScreenPtr screen,
+                                         CARD32 *num_formats,
+                                         CARD32 **formats);
+
+extern _X_EXPORT Bool glamor_get_modifiers(ScreenPtr screen,
+                                           CARD32 format,
+                                           CARD32 *num_modifiers,
+                                           uint64_t **modifiers);
+
 #ifdef GLAMOR_FOR_XORG
 
 #define GLAMOR_EGL_MODULE_NAME  "glamoregl"
diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index d88d7cbcf..8bd050308 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -503,6 +503,75 @@ glamor_pixmap_from_fds(ScreenPtr screen,
     return pixmap;
 }
 
+_X_EXPORT Bool
+glamor_get_formats(ScreenPtr screen,
+                   CARD32 *num_formats, CARD32 **formats)
+{
+    struct glamor_egl_screen_private *glamor_egl;
+    EGLint num;
+
+    glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen));
+
+    if (!glamor_egl->modifiers_capable)
+        return FALSE;
+
+    if (!eglQueryDmaBufFormatsEXT(glamor_egl->display, 0, NULL, &num)) {
+        *num_formats = 0;
+        return FALSE;
+    }
+
+    *formats = calloc(num, sizeof(CARD32));
+    if (*formats == NULL) {
+        *num_formats = 0;
+        return FALSE;
+    }
+
+    if (!eglQueryDmaBufFormatsEXT(glamor_egl->display, num,
+                                  (EGLint *) *formats, &num)) {
+        *num_formats = 0;
+        free(*formats);
+        return FALSE;
+    }
+
+    *num_formats = num;
+    return TRUE;
+}
+
+_X_EXPORT Bool
+glamor_get_modifiers(ScreenPtr screen, CARD32 format,
+                     CARD32 *num_modifiers, uint64_t **modifiers)
+{
+    struct glamor_egl_screen_private *glamor_egl;
+    EGLint num;
+
+    glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen));
+
+    if (!glamor_egl->modifiers_capable)
+        return FALSE;
+
+    if (!eglQueryDmaBufModifiersEXT(glamor_egl->display, format, 0, NULL,
+                                    NULL, &num)) {
+        *num_modifiers = 0;
+        return FALSE;
+    }
+
+    *modifiers = calloc(num, sizeof(uint64_t));
+    if (*modifiers == NULL) {
+        *num_modifiers = 0;
+        return FALSE;
+    }
+
+    if (!eglQueryDmaBufModifiersEXT(glamor_egl->display, format, num,
+                                    (EGLuint64KHR *) *modifiers, NULL, &num)) {
+        *num_modifiers = 0;
+        free(*modifiers);
+        return FALSE;
+    }
+
+    *num_modifiers = num;
+    return TRUE;
+}
+
 static Bool
 glamor_egl_destroy_pixmap(PixmapPtr pixmap)
 {
diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c
index dbd119beb..78fe11103 100644
--- a/hw/xwayland/xwayland-glamor.c
+++ b/hw/xwayland/xwayland-glamor.c
@@ -462,19 +462,6 @@ xwl_drm_handle_device(void *data, struct wl_drm *drm, const char *device)
 static void
 xwl_drm_handle_format(void *data, struct wl_drm *drm, uint32_t format)
 {
-   struct xwl_screen *xwl_screen = data;
-
-   switch (format) {
-   case WL_DRM_FORMAT_ARGB8888:
-      xwl_screen->formats |= XWL_FORMAT_ARGB8888;
-      break;
-   case WL_DRM_FORMAT_XRGB8888:
-      xwl_screen->formats |= XWL_FORMAT_XRGB8888;
-      break;
-   case WL_DRM_FORMAT_RGB565:
-      xwl_screen->formats |= XWL_FORMAT_RGB565;
-      break;
-   }
 }
 
 static void
@@ -501,6 +488,54 @@ static const struct wl_drm_listener xwl_drm_listener = {
     xwl_drm_handle_capabilities
 };
 
+static void
+xwl_dmabuf_handle_format(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
+                         uint32_t format)
+{
+}
+
+static void
+xwl_dmabuf_handle_modifier(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
+                           uint32_t format, uint32_t modifier_hi,
+                           uint32_t modifier_lo)
+{
+   struct xwl_screen *xwl_screen = data;
+    struct xwl_format *xwl_format = NULL;
+    int i;
+
+    for (i = 0; i < xwl_screen->num_formats; i++) {
+        if (xwl_screen->formats[i].format == format) {
+            xwl_format = &xwl_screen->formats[i];
+            break;
+        }
+    }
+
+    if (xwl_format == NULL) {
+       xwl_screen->num_formats++;
+       xwl_screen->formats = realloc(xwl_screen->formats,
+                                     xwl_screen->num_formats * sizeof(*xwl_format));
+       if (!xwl_screen->formats)
+          return;
+       xwl_format = &xwl_screen->formats[xwl_screen->num_formats - 1];
+       xwl_format->format = format;
+       xwl_format->num_modifiers = 0;
+       xwl_format->modifiers = NULL;
+    }
+
+    xwl_format->num_modifiers++;
+    xwl_format->modifiers = realloc(xwl_format->modifiers,
+                                    xwl_format->num_modifiers * sizeof(uint64_t));
+    if (!xwl_format->modifiers)
+       return;
+    xwl_format->modifiers[xwl_format->num_modifiers - 1]  = (uint64_t) modifier_lo;
+    xwl_format->modifiers[xwl_format->num_modifiers - 1] |= (uint64_t) modifier_hi << 32;
+}
+
+static const struct zwp_linux_dmabuf_v1_listener xwl_dmabuf_listener = {
+    .format   = xwl_dmabuf_handle_format,
+    .modifier = xwl_dmabuf_handle_modifier
+};
+
 Bool
 xwl_screen_set_drm_interface(struct xwl_screen *xwl_screen,
                              uint32_t id, uint32_t version)
@@ -525,6 +560,7 @@ xwl_screen_set_dmabuf_interface(struct xwl_screen *xwl_screen,
 
     xwl_screen->dmabuf =
         wl_registry_bind(xwl_screen->registry, id, &zwp_linux_dmabuf_v1_interface, 2);
+    zwp_linux_dmabuf_v1_add_listener(xwl_screen->dmabuf, &xwl_dmabuf_listener, xwl_screen);
 
     return TRUE;
 }
@@ -711,12 +747,69 @@ glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
     return xwl_pixmap->num_fds;
 }
 
+_X_EXPORT Bool
+glamor_get_formats(ScreenPtr screen,
+                   CARD32 *num_formats, CARD32 **formats)
+{
+    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+    int i;
+
+    if (!xwl_screen->modifiers_capable || !xwl_screen->dmabuf)
+        return FALSE;
+
+    *formats = calloc(xwl_screen->num_formats, sizeof(CARD32));
+    if (*formats == NULL) {
+        *num_formats = 0;
+        return FALSE;
+    }
+
+    for (i = 0; i < xwl_screen->num_formats; i++)
+       (*formats)[i] = xwl_screen->formats[i].format;
+    *num_formats = xwl_screen->num_formats;
+
+    return TRUE;
+}
+
+_X_EXPORT Bool
+glamor_get_modifiers(ScreenPtr screen, CARD32 format,
+                     CARD32 *num_modifiers, uint64_t **modifiers)
+{
+    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+    struct xwl_format *xwl_format = NULL;
+    int i;
+
+    if (!xwl_screen->modifiers_capable || !xwl_screen->dmabuf)
+        return FALSE;
+
+    for (i = 0; i < xwl_screen->num_formats; i++) {
+       if (xwl_screen->formats[i].format == format) {
+          xwl_format = &xwl_screen->formats[i];
+          break;
+       }
+    }
+
+    *modifiers = calloc(xwl_format->num_modifiers, sizeof(uint64_t));
+    if (*modifiers == NULL) {
+        *num_modifiers = 0;
+        return FALSE;
+    }
+
+    for (i = 0; i < xwl_format->num_modifiers; i++)
+       (*modifiers)[i] = xwl_format->modifiers[i];
+    *num_modifiers = xwl_format->num_modifiers;
+
+    return TRUE;
+}
+
+
 static dri3_screen_info_rec xwl_dri3_info = {
     .version = 2,
     .open = NULL,
     .pixmap_from_fds = glamor_pixmap_from_fds,
     .fds_from_pixmap = glamor_fds_from_pixmap,
     .open_client = xwl_dri3_open_client,
+    .get_formats = glamor_get_formats,
+    .get_modifiers = glamor_get_modifiers,
 };
 
 Bool
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
index 784b14e8e..25fac5d6f 100644
--- a/hw/xwayland/xwayland.h
+++ b/hw/xwayland/xwayland.h
@@ -47,6 +47,12 @@
 #include "tablet-unstable-v2-client-protocol.h"
 #include "linux-dmabuf-unstable-v1-client-protocol.h"
 
+struct xwl_format {
+    uint32_t format;
+    int num_modifiers;
+    uint64_t *modifiers;
+};
+
 struct xwl_screen {
     int width;
     int height;
@@ -96,7 +102,8 @@ struct xwl_screen {
     int fd_render_node;
     struct wl_drm *drm;
     struct zwp_linux_dmabuf_v1 *dmabuf;
-    uint32_t formats;
+    uint32_t num_formats;
+    struct xwl_format *formats;
     uint32_t capabilities;
     void *egl_display, *egl_context;
     struct gbm_device *gbm;
-- 
2.13.0



More information about the xorg-devel mailing list