[RFC v2 03/13] glamor: Implement PixmapFromBuffers and BuffersFromPixmap

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


Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
---
 glamor/glamor.c               |  93 ++++++++++++++--
 glamor/glamor.h               |  64 ++++++++++-
 glamor/glamor_egl.c           | 146 +++++++++++++++++++++----
 glamor/glamor_egl.h           |  84 ++++++++++++++
 glamor/glamor_egl_ext.h       |  65 +++++++++++
 glamor/glamor_egl_stubs.c     |   7 +-
 glamor/glamor_priv.h          |  10 ++
 hw/xwayland/.gitignore        |   2 +
 hw/xwayland/Makefile.am       |   9 +-
 hw/xwayland/xwayland-glamor.c | 248 +++++++++++++++++++++++++++++++++---------
 hw/xwayland/xwayland.c        |   6 +-
 hw/xwayland/xwayland.h        |  10 +-
 12 files changed, 645 insertions(+), 99 deletions(-)
 create mode 100644 glamor/glamor_egl_ext.h

diff --git a/glamor/glamor.c b/glamor/glamor.c
index 91236e29c..3f91202db 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -114,6 +114,65 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex)
     glamor_pixmap_attach_fbo(pixmap, fbo);
 }
 
+_X_EXPORT void
+glamor_set_pixmap_dmabuf(PixmapPtr pixmap,
+                         int num_fds, int *fds,
+                         uint32_t *strides, uint32_t *offsets,
+                         uint32_t format, uint64_t modifier)
+{
+    glamor_pixmap_private *pixmap_priv;
+    glamor_pixmap_dmabuf *dmabuf;
+    int i;
+
+    pixmap_priv = glamor_get_pixmap_private(pixmap);
+
+    if (pixmap_priv->dmabuf) {
+        free(pixmap_priv->dmabuf);
+        pixmap_priv->dmabuf = NULL;
+    }
+
+    dmabuf = calloc(1, sizeof(glamor_pixmap_dmabuf));
+    if (dmabuf == NULL) {
+        ErrorF("XXX fail to create dmabuf struct.\n");
+        return;
+    }
+    dmabuf->num_fds = num_fds;
+    dmabuf->format = format;
+    dmabuf->modifier = modifier;
+    for (i = 0; i < num_fds; i++) {
+        dmabuf->fds[i] = fds[i];
+        dmabuf->strides[i] = strides[i];
+        dmabuf->offsets[i] = offsets[i];
+    }
+
+    pixmap_priv->dmabuf = dmabuf;
+}
+
+_X_EXPORT int
+glamor_dmabuf_from_pixmap(PixmapPtr pixmap, int *fds,
+                          uint32_t *strides, uint32_t *offsets,
+                          uint32_t *format, uint64_t *modifier)
+{
+    glamor_pixmap_private *pixmap_priv;
+    glamor_pixmap_dmabuf *dmabuf;
+    int i;
+
+    pixmap_priv = glamor_get_pixmap_private(pixmap);
+
+    if (!pixmap_priv->dmabuf)
+        return 0;
+
+    dmabuf = pixmap_priv->dmabuf;
+    *format = dmabuf->format;
+    *modifier = dmabuf->modifier;
+    for (i = 0; i < dmabuf->num_fds; i++) {
+        fds[i] = dmabuf->fds[i];
+        strides[i] = dmabuf->strides[i];
+        offsets[i] = dmabuf->offsets[i];
+    }
+    return dmabuf->num_fds;
+}
+
 uint32_t
 glamor_get_pixmap_texture(PixmapPtr pixmap)
 {
@@ -804,8 +863,9 @@ glamor_supports_pixmap_import_export(ScreenPtr screen)
 }
 
 _X_EXPORT int
-glamor_fd_from_pixmap(ScreenPtr screen,
-                      PixmapPtr pixmap, CARD16 *stride, CARD32 *size)
+glamor_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
+                       uint32_t *strides, uint32_t *offsets,
+                       uint32_t *format, uint64_t *modifier)
 {
     glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
     glamor_screen_private *glamor_priv =
@@ -818,10 +878,9 @@ glamor_fd_from_pixmap(ScreenPtr screen,
     case GLAMOR_TEXTURE_ONLY:
         if (!glamor_pixmap_ensure_fbo(pixmap, GL_RGBA, 0))
             return -1;
-        return glamor_egl_dri3_fd_name_from_tex(screen,
-                                                pixmap,
-                                                pixmap_priv->fbo->tex,
-                                                FALSE, stride, size);
+        return glamor_egl_fds_from_pixmap(screen, pixmap, fds,
+                                          strides, offsets,
+                                          format, modifier);
     default:
         break;
     }
@@ -834,6 +893,10 @@ glamor_shareable_fd_from_pixmap(ScreenPtr screen,
 {
     unsigned orig_usage_hint = pixmap->usage_hint;
     int ret;
+    int fds[4];
+    uint32_t strides[4], offsets[4];
+    uint32_t format;
+    uint64_t modifier;
 
     /*
      * The actual difference between a sharable and non sharable buffer
@@ -842,7 +905,17 @@ glamor_shareable_fd_from_pixmap(ScreenPtr screen,
      * 2 of those calls are also exported API, so we cannot just add a flag.
      */
     pixmap->usage_hint = CREATE_PIXMAP_USAGE_SHARED;
-    ret = glamor_fd_from_pixmap(screen, pixmap, stride, size);
+    ret = glamor_fds_from_pixmap(screen, pixmap, fds, strides, offsets,
+                                 &format, &modifier);
+
+    /* Pixmaps with multi-planes/modifier are not shareable */
+    if (ret > 1)
+        return -1;
+
+    ret = fds[0];
+    *stride = strides[0];
+    *size = pixmap->drawable.height * *stride;
+
     pixmap->usage_hint = orig_usage_hint;
 
     return ret;
@@ -858,10 +931,8 @@ glamor_name_from_pixmap(PixmapPtr pixmap, CARD16 *stride, CARD32 *size)
     case GLAMOR_TEXTURE_ONLY:
         if (!glamor_pixmap_ensure_fbo(pixmap, GL_RGBA, 0))
             return -1;
-        return glamor_egl_dri3_fd_name_from_tex(pixmap->drawable.pScreen,
-                                                pixmap,
-                                                pixmap_priv->fbo->tex,
-                                                TRUE, stride, size);
+        return glamor_egl_fd_name_from_pixmap(pixmap->drawable.pScreen,
+                                              pixmap, stride, size);
     default:
         break;
     }
diff --git a/glamor/glamor.h b/glamor/glamor.h
index 4ad28df17..f16f79c97 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -108,6 +108,18 @@ extern _X_EXPORT uint32_t glamor_get_pixmap_texture(PixmapPtr pixmap);
 extern _X_EXPORT void glamor_set_pixmap_texture(PixmapPtr pixmap,
                                                 unsigned int tex);
 
+extern _X_EXPORT void glamor_set_pixmap_dmabuf(PixmapPtr pixmap,
+                                               int num_fds, int *fds,
+                                               uint32_t *strides,
+                                               uint32_t *offsets,
+                                               uint32_t format,
+                                               uint64_t modifier);
+extern _X_EXPORT int glamor_dmabuf_from_pixmap(PixmapPtr pixmap, int *fds,
+                                               uint32_t *strides,
+                                               uint32_t *offsets,
+                                               uint32_t *format,
+                                               uint64_t *modifier);
+
 extern _X_EXPORT void glamor_set_pixmap_type(PixmapPtr pixmap,
                                              glamor_pixmap_type_t type);
 extern _X_EXPORT void glamor_block_handler(ScreenPtr screen);
@@ -138,14 +150,16 @@ 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 int glamor_egl_dri3_fd_name_from_tex(ScreenPtr, PixmapPtr,
-                                                      unsigned int, Bool,
-                                                      CARD16 *, CARD32 *);
+extern _X_EXPORT int glamor_egl_fds_from_pixmap(ScreenPtr, PixmapPtr, int *,
+                                                uint32_t *, uint32_t *,
+                                                uint32_t *, uint64_t *);
+extern _X_EXPORT int glamor_egl_fd_name_from_pixmap(ScreenPtr, PixmapPtr,
+                                                    CARD16 *, CARD32 *);
 
 extern _X_EXPORT struct gbm_device *glamor_egl_get_gbm_device(ScreenPtr screen);
 
 /* @glamor_supports_pixmap_import_export: Returns whether
- * glamor_fd_from_pixmap(), glamor_name_from_pixmap(), and
+ * glamor_fds_from_pixmap(), glamor_name_from_pixmap(), and
  * glamor_pixmap_from_fd() are supported.
  *
  * @screen: Current screen pointer.
@@ -165,7 +179,7 @@ extern _X_EXPORT Bool glamor_supports_pixmap_import_export(ScreenPtr screen);
  * @screen: Current screen pointer.
  * @pixmap: The pixmap from which we want the fd.
  * @stride, @size: Pointers to fill the stride and size of the
- * 		   buffer associated to the fd.
+ *                buffer associated to the fd.
  *
  * the pixmap and the buffer associated by the fd will share the same
  * content.
@@ -175,6 +189,23 @@ extern _X_EXPORT int glamor_fd_from_pixmap(ScreenPtr screen,
                                            PixmapPtr pixmap,
                                            CARD16 *stride, CARD32 *size);
 
+/* @glamor_fds_from_pixmap: Get a dma-buf fd from a pixmap.
+ *
+ * @screen: Current screen pointer.
+ * @pixmap: The pixmap from which we want the fd.
+ * @fds, @strides, @offsets: Pointers to fill info of each plane.
+ * @format, @modifier: Pointers to fill the format and modifier of the buffer.
+ *
+ * the pixmap and the buffer associated by the fds will share the same
+ * content.
+ * Returns the number of planes, -1 on error.
+ * */
+extern _X_EXPORT int glamor_fds_from_pixmap(ScreenPtr screen,
+                                            PixmapPtr pixmap,
+                                            int *fds,
+                                            uint32_t *strides, uint32_t *offsets,
+                                            uint32_t *format, uint64_t *modifier);
+
 /* @glamor_shareable_fd_from_pixmap: Get a dma-buf fd suitable for sharing
  *				     with other GPUs from a pixmap.
  *
@@ -245,6 +276,29 @@ extern _X_EXPORT PixmapPtr glamor_pixmap_from_fd(ScreenPtr screen,
                                                  CARD8 depth,
                                                  CARD8 bpp);
 
+/* @glamor_pixmap_from_fds: Creates a pixmap to wrap a dma-buf fds.
+ *
+ * @screen: Current screen pointer.
+ * @num_fds: Number of fds to import
+ * @fds: The dma-buf fds to import.
+ * @width: The width of the buffers.
+ * @height: The height of the buffers.
+ * @stride: The stride of the buffers.
+ * @format: The format of the buffers.
+ * @modifier: The modifier of the buffers.
+ *
+ * Returns a valid pixmap if the import succeeded, else NULL.
+ * */
+extern _X_EXPORT PixmapPtr glamor_pixmap_from_fds(ScreenPtr screen,
+                                                  CARD8 num_fds,
+                                                  int *fds,
+                                                  CARD16 width,
+                                                  CARD16 height,
+                                                  CARD32 *strides,
+                                                  CARD32 *offsets,
+                                                  CARD32 format,
+                                                  uint64_t modifier);
+
 /* @glamor_back_pixmap_from_fd: Backs an existing pixmap with a dma-buf fd.
  *
  * @pixmap: Pixmap to change backing for
diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index b0d3e9efe..d88d7cbcf 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -56,6 +56,8 @@ struct glamor_egl_screen_private {
     CloseScreenProcPtr CloseScreen;
     int fd;
     struct gbm_device *gbm;
+    int dmabuf_capable;
+    int modifiers_capable;
 
     CloseScreenProcPtr saved_close_screen;
     DestroyPixmapProcPtr saved_destroy_pixmap;
@@ -234,6 +236,43 @@ glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap,
     return ret;
 }
 
+static Bool
+glamor_egl_create_textured_pixmap_from_dmabuf(PixmapPtr pixmap,
+                                              CARD8 num_fds, int *fds,
+                                              CARD16 width, CARD16 height,
+                                              CARD32 *strides, CARD32 *offsets,
+                                              CARD32 format, uint64_t modifier)
+{
+    ScreenPtr screen = pixmap->drawable.pScreen;
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    struct glamor_screen_private *glamor_priv =
+        glamor_get_screen_private(screen);
+    struct glamor_egl_screen_private *glamor_egl;
+    EGLImageKHR image;
+    GLuint texture;
+
+    glamor_egl = glamor_egl_get_screen_private(scrn);
+    assert(glamor_egl->dmabuf_capable);
+
+    glamor_make_current(glamor_priv);
+
+    image = glamor_egl_create_image(glamor_egl->display, num_fds, fds,
+                                    width, height, strides, offsets,
+                                    format, modifier);
+    if (image == EGL_NO_IMAGE_KHR) {
+        glamor_set_pixmap_type(pixmap, GLAMOR_DRM_ONLY);
+        return FALSE;
+    }
+    glamor_create_texture_from_image(screen, image, &texture);
+    glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM);
+    glamor_set_pixmap_texture(pixmap, texture);
+    glamor_set_pixmap_dmabuf(pixmap, num_fds, fds, strides, offsets,
+                             format, modifier);
+    glamor_egl_set_pixmap_image(pixmap, image);
+
+    return TRUE;
+}
+
 static void
 glamor_get_name_from_bo(int gbm_fd, struct gbm_bo *bo, int *name)
 {
@@ -329,10 +368,45 @@ glamor_gbm_bo_from_pixmap(ScreenPtr screen, PixmapPtr pixmap)
 }
 
 int
-glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
-                                 PixmapPtr pixmap,
-                                 unsigned int tex,
-                                 Bool want_name, CARD16 *stride, CARD32 *size)
+glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
+                           uint32_t *strides, uint32_t *offsets,
+                           uint32_t *format, uint64_t *modifier)
+{
+#ifdef GLAMOR_HAS_GBM
+    struct gbm_bo *bo;
+    int ret;
+
+    if (!glamor_make_pixmap_exportable(pixmap))
+        return 0;
+
+    ret = glamor_dmabuf_from_pixmap(pixmap, fds, strides, offsets,
+                                    format, modifier);
+    if (ret)
+        return ret;
+
+    bo = glamor_gbm_bo_from_pixmap(screen, pixmap);
+    if (!bo)
+        return 0;
+
+    pixmap->devKind = gbm_bo_get_stride(bo);
+
+    fds[0] = gbm_bo_get_fd(bo);
+    strides[0] = pixmap->devKind;
+    offsets[0] = 0;
+    *modifier = gbm_bo_get_modifier(bo);
+    *format = gbm_bo_get_format(bo);
+
+    gbm_bo_destroy(bo);
+    return 1;
+#else
+    return 0;
+#endif
+}
+
+int
+glamor_egl_fd_name_from_pixmap(ScreenPtr screen,
+                               PixmapPtr pixmap,
+                               CARD16 *stride, CARD32 *size)
 {
     struct glamor_egl_screen_private *glamor_egl;
     struct gbm_bo *bo;
@@ -346,12 +420,7 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
 
     pixmap->devKind = gbm_bo_get_stride(bo);
 
-    if (want_name) {
-        glamor_get_name_from_bo(glamor_egl->fd, bo, &fd);
-    }
-    else {
-        fd = gbm_bo_get_fd(bo);
-    }
+    glamor_get_name_from_bo(glamor_egl->fd, bo, &fd);
     *stride = pixmap->devKind;
     *size = pixmap->devKind * gbm_bo_get_height(bo);
 
@@ -396,19 +465,38 @@ glamor_back_pixmap_from_fd(PixmapPtr pixmap,
 }
 
 _X_EXPORT PixmapPtr
-glamor_pixmap_from_fd(ScreenPtr screen,
-                      int fd,
-                      CARD16 width,
-                      CARD16 height,
-                      CARD16 stride, CARD8 depth, CARD8 bpp)
+glamor_pixmap_from_fds(ScreenPtr screen,
+                       CARD8 num_fds, int *fds,
+                       CARD16 width, CARD16 height,
+                       CARD32 *strides, CARD32 *offsets,
+                       CARD32 format, uint64_t modifier)
 {
     PixmapPtr pixmap;
-    Bool ret;
+    struct glamor_egl_screen_private *glamor_egl;
+    const struct drm_format_info *info;
+    Bool ret = FALSE;
+    int i;
+
+    glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen));
+
+    info = drm_format_get_info(format);
+
+    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?
+        ret = glamor_egl_create_textured_pixmap_from_dmabuf(pixmap, num_fds, fds,
+                                                            width, height,
+                                                            strides, offsets,
+                                                            format, modifier);
+    } else if (num_fds == 1) {
+        ret = glamor_back_pixmap_from_fd(pixmap, fds[0], width, height,
+                                         strides[0], info->depth, info->bpp);
+    }
 
-    pixmap = screen->CreatePixmap(screen, 0, 0, depth, 0);
-    ret = glamor_back_pixmap_from_fd(pixmap, fd, width, height,
-                                     stride, depth, bpp);
     if (ret == FALSE) {
+        for (i = 0; i < num_fds; i++)
+            close(fds[i]);
         screen->DestroyPixmap(pixmap);
         return NULL;
     }
@@ -423,6 +511,7 @@ glamor_egl_destroy_pixmap(PixmapPtr pixmap)
     struct glamor_egl_screen_private *glamor_egl =
         glamor_egl_get_screen_private(scrn);
     Bool ret;
+    int i;
 
     if (pixmap->refcnt == 1) {
         struct glamor_pixmap_private *pixmap_priv =
@@ -430,6 +519,12 @@ glamor_egl_destroy_pixmap(PixmapPtr pixmap)
 
         if (pixmap_priv->image)
             eglDestroyImageKHR(glamor_egl->display, pixmap_priv->image);
+
+        if (pixmap_priv->dmabuf) {
+            for (i = 0; i < pixmap_priv->dmabuf->num_fds; i++)
+                close(pixmap_priv->dmabuf->fds[i]);
+            free(pixmap_priv->dmabuf);
+        }
     }
 
     screen->DestroyPixmap = glamor_egl->saved_destroy_pixmap;
@@ -532,10 +627,10 @@ glamor_dri3_open_client(ClientPtr client,
 }
 
 static dri3_screen_info_rec glamor_dri3_info = {
-    .version = 1,
+    .version = 2,
     .open_client = glamor_dri3_open_client,
-    .pixmap_from_fd = glamor_pixmap_from_fd,
-    .fd_from_pixmap = glamor_fd_from_pixmap,
+    .pixmap_from_fds = glamor_pixmap_from_fds,
+    .fds_from_pixmap = glamor_egl_fds_from_pixmap,
 };
 #endif /* DRI3 */
 
@@ -734,6 +829,13 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd)
     xf86DrvMsg(scrn->scrnIndex, X_INFO, "glamor X acceleration enabled on %s\n",
                glGetString(GL_RENDERER));
 
+    if (epoxy_has_egl_extension(glamor_egl->display,
+                                "EXT_image_dma_buf_import"))
+        glamor_egl->dmabuf_capable = TRUE;
+    if (epoxy_has_egl_extension(glamor_egl->display,
+                                "EXT_image_dma_buf_import_modifiers"))
+        glamor_egl->modifiers_capable = TRUE;
+
     glamor_egl->saved_free_screen = scrn->FreeScreen;
     scrn->FreeScreen = glamor_egl_free_screen;
     return TRUE;
diff --git a/glamor/glamor_egl.h b/glamor/glamor_egl.h
index 6bb1185bf..71bd22bac 100644
--- a/glamor/glamor_egl.h
+++ b/glamor/glamor_egl.h
@@ -30,6 +30,7 @@
 #define MESA_EGL_NO_X11_HEADERS
 #include <epoxy/gl.h>
 #include <epoxy/egl.h>
+#include <glamor_egl_ext.h>
 
 /*
  * Create an EGLDisplay from a native display type. This is a little quirky
@@ -72,4 +73,87 @@ glamor_egl_get_display(EGLint type, void *native)
     return eglGetDisplay(native);
 }
 
+static inline EGLImageKHR
+glamor_egl_create_image(EGLDisplay egl_display,
+                        CARD8 num_fds, int *fds,
+                        CARD16 width, CARD16 height,
+                        CARD32 *strides, CARD32 *offsets,
+                        CARD32 format, uint64_t modifier)
+{
+    EGLint attribs[30];
+    int atti = 0;
+
+    attribs[atti++] = EGL_WIDTH;
+    attribs[atti++] = width;
+    attribs[atti++] = EGL_HEIGHT;
+    attribs[atti++] = height;
+    attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
+    attribs[atti++] = format;
+
+    if (num_fds > 0) {
+        attribs[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT;
+        attribs[atti++] = fds[0];
+        attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
+        attribs[atti++] = offsets[0];
+        attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
+        attribs[atti++] = strides[0];
+        if (modifier) {
+            attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
+            attribs[atti++] = modifier & 0xffffffff;
+            attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
+            attribs[atti++] = modifier >> 32;
+        }
+    }
+
+    if (num_fds > 1) {
+        attribs[atti++] = EGL_DMA_BUF_PLANE1_FD_EXT;
+        attribs[atti++] = fds[1];
+        attribs[atti++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT;
+        attribs[atti++] = offsets[1];
+        attribs[atti++] = EGL_DMA_BUF_PLANE1_PITCH_EXT;
+        attribs[atti++] = strides[1];
+        if (modifier) {
+            attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT;
+            attribs[atti++] = modifier & 0xffffffff;
+            attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT;
+            attribs[atti++] = modifier >> 32;
+        }
+    }
+
+    if (num_fds > 2) {
+        attribs[atti++] = EGL_DMA_BUF_PLANE2_FD_EXT;
+        attribs[atti++] = fds[2];
+        attribs[atti++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT;
+        attribs[atti++] = offsets[2];
+        attribs[atti++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
+        attribs[atti++] = strides[2];
+        if (modifier) {
+            attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT;
+            attribs[atti++] = modifier & 0xffffffff;
+            attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT;
+            attribs[atti++] = modifier >> 32;
+        }
+    }
+
+    if (num_fds > 3) {
+        attribs[atti++] = EGL_DMA_BUF_PLANE3_FD_EXT;
+        attribs[atti++] = fds[3];
+        attribs[atti++] = EGL_DMA_BUF_PLANE3_OFFSET_EXT;
+        attribs[atti++] = offsets[3];
+        attribs[atti++] = EGL_DMA_BUF_PLANE3_PITCH_EXT;
+        attribs[atti++] = strides[3];
+        if (modifier) {
+            attribs[atti++] = EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT;
+            attribs[atti++] = modifier & 0xffffffff;
+            attribs[atti++] = EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT;
+            attribs[atti++] = modifier >> 32;
+        }
+    }
+
+    attribs[atti++] = EGL_NONE;
+
+    return eglCreateImageKHR(egl_display, EGL_NO_CONTEXT,
+                             EGL_LINUX_DMA_BUF_EXT, NULL, attribs);
+}
+
 #endif
diff --git a/glamor/glamor_egl_ext.h b/glamor/glamor_egl_ext.h
new file mode 100644
index 000000000..436e52137
--- /dev/null
+++ b/glamor/glamor_egl_ext.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+/* Extensions used by Glamor, copied from Mesa's eglmesaext.h, */
+
+#ifndef GLAMOR_EGL_EXT_H
+#define GLAMOR_EGL_EXT_H
+
+/* Define needed tokens from EGL_EXT_image_dma_buf_import extension
+ * here to avoid having to add ifdefs everywhere.*/
+#ifndef EGL_EXT_image_dma_buf_import
+#define EGL_LINUX_DMA_BUF_EXT					0x3270
+#define EGL_LINUX_DRM_FOURCC_EXT				0x3271
+#define EGL_DMA_BUF_PLANE0_FD_EXT				0x3272
+#define EGL_DMA_BUF_PLANE0_OFFSET_EXT				0x3273
+#define EGL_DMA_BUF_PLANE0_PITCH_EXT				0x3274
+#define EGL_DMA_BUF_PLANE1_FD_EXT				0x3275
+#define EGL_DMA_BUF_PLANE1_OFFSET_EXT				0x3276
+#define EGL_DMA_BUF_PLANE1_PITCH_EXT				0x3277
+#define EGL_DMA_BUF_PLANE2_FD_EXT				0x3278
+#define EGL_DMA_BUF_PLANE2_OFFSET_EXT				0x3279
+#define EGL_DMA_BUF_PLANE2_PITCH_EXT				0x327A
+#endif
+
+/* Define tokens from EGL_EXT_image_dma_buf_import_modifiers */
+#ifndef EGL_EXT_image_dma_buf_import_modifiers
+#define EGL_EXT_image_dma_buf_import_modifiers 1
+#define EGL_DMA_BUF_PLANE3_FD_EXT         0x3440
+#define EGL_DMA_BUF_PLANE3_OFFSET_EXT     0x3441
+#define EGL_DMA_BUF_PLANE3_PITCH_EXT      0x3442
+#define EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT 0x3443
+#define EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT 0x3444
+#define EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT 0x3445
+#define EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT 0x3446
+#define EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT 0x3447
+#define EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT 0x3448
+#define EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT 0x3449
+#define EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT 0x344A
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDMABUFFORMATSEXTPROC) (EGLDisplay dpy, EGLint max_formats, EGLint *formats, EGLint *num_formats);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDMABUFMODIFIERSEXTPROC) (EGLDisplay dpy, EGLint format, EGLint max_modifiers, EGLuint64KHR *modifiers, EGLBoolean *external_only, EGLint *num_modifiers);
+#endif
+
+#endif /* GLAMOR_EGL_EXT_H */
diff --git a/glamor/glamor_egl_stubs.c b/glamor/glamor_egl_stubs.c
index 40f7fcc01..c6e13842b 100644
--- a/glamor/glamor_egl_stubs.c
+++ b/glamor/glamor_egl_stubs.c
@@ -36,10 +36,9 @@ glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
 }
 
 int
-glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
-                                 PixmapPtr pixmap,
-                                 unsigned int tex,
-                                 Bool want_name, CARD16 *stride, CARD32 *size)
+glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
+                           uint32_t *offsets, uint32_t *strides,
+                           uint32_t *format, uint64_t *modifier)
 {
     return 0;
 }
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 07a98efeb..3856ddd77 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -319,6 +319,15 @@ typedef struct glamor_pixmap_fbo {
     GLenum type; /**< GL type used to create the texture. */
 } glamor_pixmap_fbo;
 
+typedef struct glamor_pixmap_dmabuf {
+    int num_fds;
+    int fds[4];
+    uint32_t strides[4];
+    uint32_t offsets[4];
+    uint32_t format;
+    uint64_t modifier;
+} glamor_pixmap_dmabuf;
+
 typedef struct glamor_pixmap_clipped_regions {
     int block_idx;
     RegionPtr region;
@@ -341,6 +350,7 @@ typedef struct glamor_pixmap_private {
     Bool prepared;
 #ifdef GLAMOR_HAS_GBM
     EGLImageKHR image;
+    glamor_pixmap_dmabuf *dmabuf;
 #endif
     /** block width of this large pixmap. */
     int block_w;
diff --git a/hw/xwayland/.gitignore b/hw/xwayland/.gitignore
index 38ada56d1..c0320b555 100644
--- a/hw/xwayland/.gitignore
+++ b/hw/xwayland/.gitignore
@@ -5,3 +5,5 @@ pointer-constraints-unstable-v1-client-protocol.h
 pointer-constraints-unstable-v1-protocol.c
 relative-pointer-unstable-v1-client-protocol.h
 relative-pointer-unstable-v1-protocol.c
+linux-dmabuf-unstable-v1-client-protocol.h
+linux-dmabuf-unstable-v1-protocol.c
diff --git a/hw/xwayland/Makefile.am b/hw/xwayland/Makefile.am
index 7eda9be34..5a65de026 100644
--- a/hw/xwayland/Makefile.am
+++ b/hw/xwayland/Makefile.am
@@ -57,7 +57,9 @@ Xwayland_built_sources +=					\
 	pointer-constraints-unstable-v1-client-protocol.h	\
 	pointer-constraints-unstable-v1-protocol.c		\
 	tablet-unstable-v2-client-protocol.h			\
-	tablet-unstable-v2-protocol.c
+	tablet-unstable-v2-protocol.c				\
+	linux-dmabuf-unstable-v1-client-protocol.h		\
+	linux-dmabuf-unstable-v1-protocol.c
 
 nodist_Xwayland_SOURCES = $(Xwayland_built_sources)
 CLEANFILES = $(Xwayland_built_sources)
@@ -85,6 +87,11 @@ tablet-unstable-v2-protocol.c: $(WAYLAND_PROTOCOLS_DATADIR)/unstable/tablet/tabl
 tablet-unstable-v2-client-protocol.h: $(WAYLAND_PROTOCOLS_DATADIR)/unstable/tablet/tablet-unstable-v2.xml
 	$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
 
+linux-dmabuf-unstable-v1-protocol.c : $(WAYLAND_PROTOCOLS_DATADIR)/unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml
+	$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
+linux-dmabuf-unstable-v1-client-protocol.h : $(WAYLAND_PROTOCOLS_DATADIR)/unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml
+	$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
+
 %-protocol.c : %.xml
 	$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
 
diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c
index 87622839e..dbd119beb 100644
--- a/hw/xwayland/xwayland-glamor.c
+++ b/hw/xwayland/xwayland-glamor.c
@@ -45,6 +45,13 @@ struct xwl_pixmap {
     struct gbm_bo *bo;
     void *image;
     unsigned int texture;
+
+    int num_fds;
+    int fds[4];
+    uint32_t strides[4];
+    uint32_t offsets[4];
+    uint32_t format;
+    uint64_t modifier;
 };
 
 static void
@@ -59,7 +66,7 @@ xwl_glamor_egl_make_current(struct glamor_context *glamor_ctx)
 }
 
 static uint32_t
-drm_format_for_depth(int depth)
+wl_drm_format_for_depth(int depth)
 {
     switch (depth) {
     case 15:
@@ -104,7 +111,8 @@ glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
 }
 
 static PixmapPtr
-xwl_glamor_create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo, int depth)
+xwl_glamor_create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo, int depth,
+                                uint32_t format)
 {
     PixmapPtr pixmap;
     struct xwl_pixmap *xwl_pixmap;
@@ -130,6 +138,7 @@ xwl_glamor_create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo, int depth)
     }
 
     xwl_pixmap->bo = bo;
+    xwl_pixmap->format = format;
     xwl_pixmap->buffer = NULL;
     xwl_pixmap->image = eglCreateImageKHR(xwl_screen->egl_display,
                                           xwl_screen->egl_context,
@@ -152,30 +161,112 @@ xwl_glamor_create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo, int depth)
     return pixmap;
 }
 
+static PixmapPtr
+xwl_glamor_create_pixmap_for_dmabuf(ScreenPtr screen, CARD8 num_fds, int *fds,
+                                    CARD16 width, CARD16 height,
+                                    CARD32 *strides, CARD32 *offsets,
+                                    CARD32 format, uint64_t modifier)
+{
+    PixmapPtr pixmap;
+    struct xwl_pixmap *xwl_pixmap;
+    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+    const struct drm_format_info *info;
+    int i;
+
+    xwl_pixmap = malloc(sizeof *xwl_pixmap);
+    if (xwl_pixmap == NULL)
+        return NULL;
+
+    info = drm_format_get_info(format);
+    pixmap = glamor_create_pixmap(screen, width, height, info->depth,
+                                  GLAMOR_CREATE_PIXMAP_NO_TEXTURE);
+    if (pixmap == NULL) {
+        free(xwl_pixmap);
+        return NULL;
+    }
+
+    if (lastGLContext != xwl_screen->glamor_ctx) {
+        lastGLContext = xwl_screen->glamor_ctx;
+        xwl_glamor_egl_make_current(xwl_screen->glamor_ctx);
+    }
+
+    xwl_pixmap->bo = NULL;
+    xwl_pixmap->buffer = NULL;
+    xwl_pixmap->num_fds = num_fds;
+    for (i = 0; i < num_fds; i++) {
+       xwl_pixmap->fds[i] = fds[i];
+       xwl_pixmap->strides[i] = strides[i];
+       xwl_pixmap->offsets[i] = offsets[i];
+    }
+    xwl_pixmap->format = format;
+    xwl_pixmap->modifier = modifier;
+    xwl_pixmap->image = glamor_egl_create_image(xwl_screen->egl_display,
+                                                num_fds, fds,
+                                                width, height,
+                                                strides, offsets,
+                                                format, modifier);
+    glGenTextures(1, &xwl_pixmap->texture);
+    glBindTexture(GL_TEXTURE_2D, xwl_pixmap->texture);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, xwl_pixmap->image);
+    glBindTexture(GL_TEXTURE_2D, 0);
+
+    xwl_pixmap_set_private(pixmap, xwl_pixmap);
+
+    glamor_set_pixmap_texture(pixmap, xwl_pixmap->texture);
+    glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM);
+
+    return pixmap;
+}
+
 struct wl_buffer *
 xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap)
 {
     struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
     struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
-    int prime_fd;
 
     if (xwl_pixmap->buffer)
         return xwl_pixmap->buffer;
 
-    prime_fd = gbm_bo_get_fd(xwl_pixmap->bo);
-    if (prime_fd == -1)
-        return NULL;
-
-    xwl_pixmap->buffer =
-        wl_drm_create_prime_buffer(xwl_screen->drm, prime_fd,
-                                   pixmap->drawable.width,
-                                   pixmap->drawable.height,
-                                   drm_format_for_depth(pixmap->drawable.depth),
-                                   0, gbm_bo_get_stride(xwl_pixmap->bo),
-                                   0, 0,
-                                   0, 0);
-
-    close(prime_fd);
+    if (xwl_pixmap->bo) {
+        int prime_fd;
+
+        prime_fd = gbm_bo_get_fd(xwl_pixmap->bo);
+        if (prime_fd == -1)
+            return NULL;
+
+        xwl_pixmap->buffer =
+            wl_drm_create_prime_buffer(xwl_screen->drm, prime_fd,
+                                       pixmap->drawable.width,
+                                       pixmap->drawable.height,
+                                       wl_drm_format_for_depth(pixmap->drawable.depth),
+                                       0, gbm_bo_get_stride(xwl_pixmap->bo),
+                                       0, 0,
+                                       0, 0);
+
+        close(prime_fd);
+    } else if (xwl_pixmap->num_fds > 0) {
+        struct  zwp_linux_buffer_params_v1 *params;
+        int i;
+
+        params = zwp_linux_dmabuf_v1_create_params(xwl_screen->dmabuf);
+        for (i = 0; i < xwl_pixmap->num_fds; i++) {
+            zwp_linux_buffer_params_v1_add(params, xwl_pixmap->fds[i], i,
+                                           xwl_pixmap->offsets[i],
+                                           xwl_pixmap->strides[i],
+                                           xwl_pixmap->modifier >> 32,
+                                           xwl_pixmap->modifier & 0xffffffff);
+        }
+
+        xwl_pixmap->buffer =
+           zwp_linux_buffer_params_v1_create_immed(params,
+                                                   pixmap->drawable.width,
+                                                   pixmap->drawable.height,
+                                                   wl_drm_format_for_depth(pixmap->drawable.depth),
+                                                   0);
+    }
 
     return xwl_pixmap->buffer;
 }
@@ -196,7 +287,7 @@ xwl_glamor_create_pixmap(ScreenPtr screen,
                            GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
 
         if (bo)
-            return xwl_glamor_create_pixmap_for_bo(screen, bo, depth);
+            return xwl_glamor_create_pixmap_for_bo(screen, bo, depth, format);
     }
 
     return glamor_create_pixmap(screen, width, height, depth, hint);
@@ -213,7 +304,8 @@ xwl_glamor_destroy_pixmap(PixmapPtr pixmap)
             wl_buffer_destroy(xwl_pixmap->buffer);
 
         eglDestroyImageKHR(xwl_screen->egl_display, xwl_pixmap->image);
-        gbm_bo_destroy(xwl_pixmap->bo);
+        if (xwl_pixmap->bo)
+           gbm_bo_destroy(xwl_pixmap->bo);
         free(xwl_pixmap);
     }
 
@@ -331,6 +423,13 @@ xwl_drm_init_egl(struct xwl_screen *xwl_screen)
         return;
     }
 
+    if (epoxy_has_egl_extension(xwl_screen->egl_display,
+                                "EXT_image_dma_buf_import"))
+       xwl_screen->dmabuf_capable = TRUE;
+    if (epoxy_has_egl_extension(xwl_screen->egl_display,
+                                "EXT_image_dma_buf_import_modifiers"))
+       xwl_screen->modifiers_capable = TRUE;
+
     return;
 }
 
@@ -403,8 +502,8 @@ static const struct wl_drm_listener xwl_drm_listener = {
 };
 
 Bool
-xwl_screen_init_glamor(struct xwl_screen *xwl_screen,
-                       uint32_t id, uint32_t version)
+xwl_screen_set_drm_interface(struct xwl_screen *xwl_screen,
+                             uint32_t id, uint32_t version)
 {
     if (version < 2)
         return FALSE;
@@ -417,11 +516,23 @@ xwl_screen_init_glamor(struct xwl_screen *xwl_screen,
     return TRUE;
 }
 
+Bool
+xwl_screen_set_dmabuf_interface(struct xwl_screen *xwl_screen,
+                                uint32_t id, uint32_t version)
+{
+    if (version < 2)
+        return FALSE;
+
+    xwl_screen->dmabuf =
+        wl_registry_bind(xwl_screen->registry, id, &zwp_linux_dmabuf_v1_interface, 2);
+
+    return TRUE;
+}
+
 int
-glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
-                                 PixmapPtr pixmap,
-                                 unsigned int tex,
-                                 Bool want_name, CARD16 *stride, CARD32 *size)
+glamor_egl_fd_name_from_pixmap(ScreenPtr screen,
+                               PixmapPtr pixmap,
+                               CARD16 *stride, CARD32 *size)
 {
     return 0;
 }
@@ -522,58 +633,89 @@ xwl_dri3_open_client(ClientPtr client,
     return Success;
 }
 
-static PixmapPtr
-xwl_dri3_pixmap_from_fd(ScreenPtr screen, int fd,
-                        CARD16 width, CARD16 height, CARD16 stride,
-                        CARD8 depth, CARD8 bpp)
+_X_EXPORT PixmapPtr
+glamor_pixmap_from_fds(ScreenPtr screen,
+                         CARD8 num_fds, int *fds,
+                         CARD16 width, CARD16 height,
+                         CARD32 *strides, CARD32 *offsets,
+                         CARD32 format, uint64_t modifier)
 {
     struct xwl_screen *xwl_screen = xwl_screen_get(screen);
     struct gbm_import_fd_data data;
     struct gbm_bo *bo;
+    const struct drm_format_info *info;
     PixmapPtr pixmap;
 
-    if (width == 0 || height == 0 ||
-        depth < 15 || bpp != BitsPerPixel(depth) || stride < width * bpp / 8)
-        return NULL;
+    info = drm_format_get_info(format);
 
-    data.fd = fd;
-    data.width = width;
-    data.height = height;
-    data.stride = stride;
-    data.format = gbm_format_for_depth(depth);
-    bo = gbm_bo_import(xwl_screen->gbm, GBM_BO_IMPORT_FD, &data,
-                       GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
-    if (bo == NULL)
+    if (width == 0 || height == 0 || num_fds == 0 ||
+        info->depth < 15 || info->bpp != BitsPerPixel(info->depth) ||
+        strides[0] < width * info->bpp / 8) // XXX Does this condition still make sense?
         return NULL;
 
-    pixmap = xwl_glamor_create_pixmap_for_bo(screen, bo, depth);
-    if (pixmap == NULL) {
-        gbm_bo_destroy(bo);
-        return NULL;
+    if (xwl_screen->dmabuf_capable) {
+      pixmap = xwl_glamor_create_pixmap_for_dmabuf(screen, num_fds, fds,
+                                                   width, height,
+                                                   strides, offsets,
+                                                   format, modifier);
+    } else if (num_fds == 1) {
+       data.fd = fds[0];
+       data.width = width;
+       data.height = height;
+       data.stride = strides[0];
+       data.format = gbm_format_for_depth(info->depth);
+       bo = gbm_bo_import(xwl_screen->gbm, GBM_BO_IMPORT_FD, &data,
+             GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
+       if (bo == NULL)
+          return NULL;
+
+       pixmap = xwl_glamor_create_pixmap_for_bo(screen, bo, info->depth, format);
+       if (pixmap == NULL) {
+          gbm_bo_destroy(bo);
+          return NULL;
+       }
+    } else {
+       return NULL;
     }
 
     return pixmap;
 }
 
-static int
-xwl_dri3_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap,
-                        CARD16 *stride, CARD32 *size)
+_X_EXPORT int
+glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
+                           uint32_t *strides, uint32_t *offsets,
+                           uint32_t *format, uint64_t *modifier)
 {
     struct xwl_pixmap *xwl_pixmap;
+    int i;
 
     xwl_pixmap = xwl_pixmap_get(pixmap);
 
-    *stride = gbm_bo_get_stride(xwl_pixmap->bo);
-    *size = pixmap->drawable.width * *stride;
+    if (xwl_pixmap->bo) {
+        fds[0] = gbm_bo_get_fd(xwl_pixmap->bo);
+        strides[0] = gbm_bo_get_stride(xwl_pixmap->bo);
+        offsets[0] = 0;
+        *format = gbm_format_for_depth(pixmap->drawable.depth),
+        *modifier = 0;
+        return 1;
+    }
+
+    for (i = 0; i < xwl_pixmap->num_fds; i++) {
+       fds[i] = xwl_pixmap->fds[i];
+       strides[i] = xwl_pixmap->strides[i];
+       offsets[i] = xwl_pixmap->offsets[i];
+    }
+    *format = xwl_pixmap->format;
+    *modifier = xwl_pixmap->modifier;
 
-    return gbm_bo_get_fd(xwl_pixmap->bo);
+    return xwl_pixmap->num_fds;
 }
 
 static dri3_screen_info_rec xwl_dri3_info = {
-    .version = 1,
+    .version = 2,
     .open = NULL,
-    .pixmap_from_fd = xwl_dri3_pixmap_from_fd,
-    .fd_from_pixmap = xwl_dri3_fd_from_pixmap,
+    .pixmap_from_fds = glamor_pixmap_from_fds,
+    .fds_from_pixmap = glamor_fds_from_pixmap,
     .open_client = xwl_dri3_open_client,
 };
 
diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c
index 551443f93..67c00e7e0 100644
--- a/hw/xwayland/xwayland.c
+++ b/hw/xwayland/xwayland.c
@@ -678,7 +678,11 @@ registry_global(void *data, struct wl_registry *registry, uint32_t id,
 #ifdef GLAMOR_HAS_GBM
     else if (xwl_screen->glamor &&
              strcmp(interface, "wl_drm") == 0 && version >= 2) {
-        xwl_screen_init_glamor(xwl_screen, id, version);
+        xwl_screen_set_drm_interface(xwl_screen, id, version);
+    }
+    else if (xwl_screen->glamor &&
+             strcmp(interface, "zwp_linux_dmabuf_v1") == 0 && version >= 2) {
+        xwl_screen_set_dmabuf_interface(xwl_screen, id, version);
     }
 #endif
 }
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
index a05e0862c..784b14e8e 100644
--- a/hw/xwayland/xwayland.h
+++ b/hw/xwayland/xwayland.h
@@ -45,6 +45,7 @@
 #include "relative-pointer-unstable-v1-client-protocol.h"
 #include "pointer-constraints-unstable-v1-client-protocol.h"
 #include "tablet-unstable-v2-client-protocol.h"
+#include "linux-dmabuf-unstable-v1-client-protocol.h"
 
 struct xwl_screen {
     int width;
@@ -94,11 +95,14 @@ struct xwl_screen {
     int drm_fd;
     int fd_render_node;
     struct wl_drm *drm;
+    struct zwp_linux_dmabuf_v1 *dmabuf;
     uint32_t formats;
     uint32_t capabilities;
     void *egl_display, *egl_context;
     struct gbm_device *gbm;
     struct glamor_context *glamor_ctx;
+    int dmabuf_capable;
+    int modifiers_capable;
 
     Atom allow_commits_prop;
 };
@@ -315,8 +319,10 @@ struct wl_buffer *xwl_shm_pixmap_get_wl_buffer(PixmapPtr pixmap);
 
 Bool xwl_glamor_init(struct xwl_screen *xwl_screen);
 
-Bool xwl_screen_init_glamor(struct xwl_screen *xwl_screen,
-                         uint32_t id, uint32_t version);
+Bool xwl_screen_set_drm_interface(struct xwl_screen *xwl_screen,
+                                  uint32_t id, uint32_t version);
+Bool xwl_screen_set_dmabuf_interface(struct xwl_screen *xwl_screen,
+                                     uint32_t id, uint32_t version);
 struct wl_buffer *xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap);
 
 void xwl_screen_release_tablet_manager(struct xwl_screen *xwl_screen);
-- 
2.13.0



More information about the xorg-devel mailing list