[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