xserver: Branch 'master' - 7 commits

Adam Jackson ajax at kemper.freedesktop.org
Wed Apr 4 17:47:28 UTC 2018


 dri3/dri3_priv.h                                 |    3 
 dri3/dri3_request.c                              |   16 +---
 dri3/dri3_screen.c                               |   40 ++++++++++++
 glamor/glamor.h                                  |    3 
 glamor/glamor_egl.c                              |   75 ++++++++++++++++++-----
 glamor/glamor_priv.h                             |    1 
 hw/xfree86/drivers/modesetting/drmmode_display.c |    8 +-
 hw/xfree86/drivers/modesetting/drmmode_display.h |    1 
 8 files changed, 117 insertions(+), 30 deletions(-)

New commits:
commit 23c67987a337beb91292f8e318d566941453baa3
Author: Daniel Stone <daniels at collabora.com>
Date:   Wed Apr 4 16:16:38 2018 +0100

    glamor: Add fd_from_pixmap hook
    
    Add a fd_from_pixmap (singular) hook to go with fds_from_pixmap, which
    will ensure that the pixmap is allocated without modifiers and is thus
    exportable to non-modifier-aware clients.
    
    This makes it possible to run a compositing manager on an old GLX/EGL
    stack on top of an X server which allocates internal buffer storage
    using exotic modifiers from modifier-aware GBM/EGL/KMS.
    
    Signed-off-by: Daniel Stone <daniels at collabora.com>
    Reported-by: Adam Jackson <ajax at redhat.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index 2dffbb8dc..5a47dbd91 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -402,6 +402,32 @@ glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
 #endif
 }
 
+static int
+glamor_egl_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap,
+                          CARD16 *stride, CARD32 *size)
+{
+#ifdef GLAMOR_HAS_GBM
+    struct gbm_bo *bo;
+    int fd;
+
+    if (!glamor_make_pixmap_exportable(pixmap, FALSE))
+        return -1;
+
+    bo = glamor_gbm_bo_from_pixmap(screen, pixmap);
+    if (!bo)
+        return -1;
+
+    fd = gbm_bo_get_fd(bo);
+    *stride = gbm_bo_get_stride(bo);
+    *size = *stride * gbm_bo_get_height(bo);
+    gbm_bo_destroy(bo);
+
+    return fd;
+#else
+    return -1;
+#endif
+}
+
 int
 glamor_egl_fd_name_from_pixmap(ScreenPtr screen,
                                PixmapPtr pixmap,
@@ -775,6 +801,7 @@ static dri3_screen_info_rec glamor_dri3_info = {
     .version = 2,
     .open_client = glamor_dri3_open_client,
     .pixmap_from_fds = glamor_pixmap_from_fds,
+    .fd_from_pixmap = glamor_egl_fd_from_pixmap,
     .fds_from_pixmap = glamor_egl_fds_from_pixmap,
     .get_formats = glamor_get_formats,
     .get_modifiers = glamor_get_modifiers,
commit 9c407f0a1b40128fc65b19b6a499f1d4dae6f702
Author: Daniel Stone <daniels at collabora.com>
Date:   Wed Apr 4 16:16:37 2018 +0100

    glamor: Fall back to non-modifier allocations
    
    If we try to allocate with particular modifiers but it fails, try to
    fall back to non-modifier allocations.
    
    Signed-off-by: Daniel Stone <daniels at collabora.com>
    Reported-by: Adam Jackson <ajax at redhat.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index a1e0bc3c9..2dffbb8dc 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -261,7 +261,7 @@ glamor_make_pixmap_exportable(PixmapPtr pixmap, Bool modifiers_ok)
     unsigned width = pixmap->drawable.width;
     unsigned height = pixmap->drawable.height;
     uint32_t format;
-    struct gbm_bo *bo;
+    struct gbm_bo *bo = NULL;
     Bool used_modifiers = FALSE;
     PixmapPtr exported;
     GCPtr scratch_gc;
@@ -295,8 +295,9 @@ glamor_make_pixmap_exportable(PixmapPtr pixmap, Bool modifiers_ok)
             used_modifiers = TRUE;
         free(modifiers);
     }
-    else
 #endif
+
+    if (!bo)
     {
         bo = gbm_bo_create(glamor_egl->gbm, width, height, format,
 #ifdef GLAMOR_HAS_GBM_LINEAR
commit 86b2d8740a330deafe8a9bbf0402705a43efbb42
Author: Daniel Stone <daniels at collabora.com>
Date:   Wed Apr 4 16:16:36 2018 +0100

    glamor: Reallocate pixmap storage without modifiers if necessary
    
    If we need a pixmap's storage to be exported to a context in which we
    aren't aware of modifiers, reallocate the buffer again without
    modifiers.
    
    This makes it possible to run a compositing manager on an old GLX/EGL
    stack on top of an X server which allocates internal buffer storage
    using exotic modifiers from modifier-aware GBM/EGL/KMS.
    
    Signed-off-by: Daniel Stone <daniels at collabora.com>
    Reported-by: Adam Jackson <ajax at redhat.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index dd6a9a2df..a1e0bc3c9 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -250,7 +250,7 @@ glamor_get_name_from_bo(int gbm_fd, struct gbm_bo *bo, int *name)
 }
 
 static Bool
-glamor_make_pixmap_exportable(PixmapPtr pixmap)
+glamor_make_pixmap_exportable(PixmapPtr pixmap, Bool modifiers_ok)
 {
     ScreenPtr screen = pixmap->drawable.pScreen;
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
@@ -266,7 +266,8 @@ glamor_make_pixmap_exportable(PixmapPtr pixmap)
     PixmapPtr exported;
     GCPtr scratch_gc;
 
-    if (pixmap_priv->image)
+    if (pixmap_priv->image &&
+        (modifiers_ok || !pixmap_priv->used_modifiers))
         return TRUE;
 
     if (pixmap->drawable.bitsPerPixel != 32) {
@@ -282,7 +283,7 @@ glamor_make_pixmap_exportable(PixmapPtr pixmap)
         format = GBM_FORMAT_ARGB8888;
 
 #ifdef GBM_BO_WITH_MODIFIERS
-    if (glamor_egl->dmabuf_capable) {
+    if (modifiers_ok && glamor_egl->dmabuf_capable) {
         uint32_t num_modifiers;
         uint64_t *modifiers = NULL;
 
@@ -370,7 +371,7 @@ glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
     int i;
 #endif
 
-    if (!glamor_make_pixmap_exportable(pixmap))
+    if (!glamor_make_pixmap_exportable(pixmap, TRUE))
         return 0;
 
     bo = glamor_gbm_bo_from_pixmap(screen, pixmap);
@@ -411,7 +412,7 @@ glamor_egl_fd_name_from_pixmap(ScreenPtr screen,
 
     glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen));
 
-    if (!glamor_make_pixmap_exportable(pixmap))
+    if (!glamor_make_pixmap_exportable(pixmap, FALSE))
         goto failure;
 
     bo = glamor_gbm_bo_from_pixmap(screen, pixmap);
commit aab5c46ccbe769830cae383330fd62c074a0d2f7
Author: Daniel Stone <daniels at collabora.com>
Date:   Wed Apr 4 16:16:35 2018 +0100

    glamor: Push make_exportable into callers
    
    Rather than calling make_exportable from the get_bo entrypoint, make
    sure that someone has already explicitly requested the pixmap be
    exportable.
    
    This is technically an ABI break in that it changes observable
    behaviour, but no driver other than modesetting has ever used get_bo.
    
    Signed-off-by: Daniel Stone <daniels at collabora.com>
    Reported-by: Adam Jackson <ajax at redhat.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index 0e771b6d2..dd6a9a2df 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -351,7 +351,7 @@ glamor_gbm_bo_from_pixmap(ScreenPtr screen, PixmapPtr pixmap)
     struct glamor_pixmap_private *pixmap_priv =
         glamor_get_pixmap_private(pixmap);
 
-    if (!glamor_make_pixmap_exportable(pixmap))
+    if (!pixmap_priv->image)
         return NULL;
 
     return gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_EGL_IMAGE,
@@ -411,6 +411,9 @@ glamor_egl_fd_name_from_pixmap(ScreenPtr screen,
 
     glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen));
 
+    if (!glamor_make_pixmap_exportable(pixmap))
+        goto failure;
+
     bo = glamor_gbm_bo_from_pixmap(screen, pixmap);
     if (!bo)
         goto failure;
commit 1b9fa3b64ca420eb54b5e5f28074c326e1fbe825
Author: Daniel Stone <daniels at collabora.com>
Date:   Wed Apr 4 16:16:34 2018 +0100

    glamor: Track if BO allocation used modifiers
    
    Keep track of whether or not we fed modifiers into GBM when we allocated
    a BO. We'll use this later inside Glamor, to reallocate buffer storage
    if we allocate buffer storage using modifiers, and a non-modifier-aware
    client requests an export of that pixmap.
    
    This makes it possible to run a compositing manager on an old GLX/EGL
    stack on top of an X server which allocates internal buffer storage
    using exotic modifiers from modifier-aware GBM/EGL/KMS.
    
    Signed-off-by: Daniel Stone <daniels at collabora.com>
    Reported-by: Adam Jackson <ajax at redhat.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor.h b/glamor/glamor.h
index 7b5676226..b0b23d3a3 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -391,7 +391,8 @@ extern _X_EXPORT Bool glamor_egl_create_textured_pixmap(PixmapPtr pixmap,
  */
 extern _X_EXPORT Bool
  glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap,
-                                               struct gbm_bo *bo);
+                                               struct gbm_bo *bo,
+                                               Bool used_modifiers);
 
 #endif
 
diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index f82fa519b..0e771b6d2 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -150,7 +150,8 @@ glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int stride)
 }
 
 static void
-glamor_egl_set_pixmap_image(PixmapPtr pixmap, EGLImageKHR image)
+glamor_egl_set_pixmap_image(PixmapPtr pixmap, EGLImageKHR image,
+                            Bool used_modifiers)
 {
     struct glamor_pixmap_private *pixmap_priv =
         glamor_get_pixmap_private(pixmap);
@@ -165,6 +166,7 @@ glamor_egl_set_pixmap_image(PixmapPtr pixmap, EGLImageKHR image)
         eglDestroyImageKHR(glamor_egl->display, old);
     }
     pixmap_priv->image = image;
+    pixmap_priv->used_modifiers = used_modifiers;
 }
 
 Bool
@@ -204,7 +206,8 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride)
 
 Bool
 glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap,
-                                              struct gbm_bo *bo)
+                                              struct gbm_bo *bo,
+                                              Bool used_modifiers)
 {
     ScreenPtr screen = pixmap->drawable.pScreen;
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
@@ -229,7 +232,7 @@ glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap,
     glamor_create_texture_from_image(screen, image, &texture);
     glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM);
     glamor_set_pixmap_texture(pixmap, texture);
-    glamor_egl_set_pixmap_image(pixmap, image);
+    glamor_egl_set_pixmap_image(pixmap, image, used_modifiers);
     ret = TRUE;
 
  done:
@@ -259,6 +262,7 @@ glamor_make_pixmap_exportable(PixmapPtr pixmap)
     unsigned height = pixmap->drawable.height;
     uint32_t format;
     struct gbm_bo *bo;
+    Bool used_modifiers = FALSE;
     PixmapPtr exported;
     GCPtr scratch_gc;
 
@@ -286,6 +290,8 @@ glamor_make_pixmap_exportable(PixmapPtr pixmap)
 
         bo = gbm_bo_create_with_modifiers(glamor_egl->gbm, width, height,
                                           format, modifiers, num_modifiers);
+        if (bo)
+            used_modifiers = TRUE;
         free(modifiers);
     }
     else
@@ -309,7 +315,8 @@ 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 (!glamor_egl_create_textured_pixmap_from_gbm_bo(exported, bo,
+                                                       used_modifiers)) {
         xf86DrvMsg(scrn->scrnIndex, X_ERROR,
                    "Failed to make %dx%dx%dbpp pixmap from GBM bo\n",
                    width, height, pixmap->drawable.bitsPerPixel);
@@ -452,7 +459,7 @@ 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);
+    ret = glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo, FALSE);
     gbm_bo_destroy(bo);
     return ret;
 }
@@ -509,7 +516,7 @@ glamor_pixmap_from_fds(ScreenPtr screen,
         bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_FD_MODIFIER, &import_data, 0);
         if (bo) {
             screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, strides[0], NULL);
-            ret = glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo);
+            ret = glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo, TRUE);
             gbm_bo_destroy(bo);
         }
     } else
@@ -667,7 +674,8 @@ glamor_egl_destroy_pixmap(PixmapPtr pixmap)
 _X_EXPORT void
 glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr back)
 {
-    EGLImageKHR temp;
+    EGLImageKHR temp_img;
+    Bool temp_mod;
     struct glamor_pixmap_private *front_priv =
         glamor_get_pixmap_private(front);
     struct glamor_pixmap_private *back_priv =
@@ -675,9 +683,12 @@ glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr back)
 
     glamor_pixmap_exchange_fbos(front, back);
 
-    temp = back_priv->image;
+    temp_img = back_priv->image;
+    temp_mod = back_priv->used_modifiers;
     back_priv->image = front_priv->image;
-    front_priv->image = temp;
+    back_priv->used_modifiers = front_priv->used_modifiers;
+    front_priv->image = temp_img;
+    front_priv->used_modifiers = temp_mod;
 
     glamor_set_pixmap_type(front, GLAMOR_TEXTURE_DRM);
     glamor_set_pixmap_type(back, GLAMOR_TEXTURE_DRM);
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 3fff6396c..7d9a7d4fb 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -341,6 +341,7 @@ typedef struct glamor_pixmap_private {
     Bool prepared;
 #ifdef GLAMOR_HAS_GBM
     EGLImageKHR image;
+    Bool used_modifiers;
 #endif
     /** block width of this large pixmap. */
     int block_w;
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index 4fe59d22e..930a2716f 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -2822,7 +2822,8 @@ drmmode_set_pixmap_bo(drmmode_ptr drmmode, PixmapPtr pixmap, drmmode_bo *bo)
     if (!drmmode->glamor)
         return TRUE;
 
-    if (!glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo->gbm)) {
+    if (!glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo->gbm,
+                                                       bo->used_modifiers)) {
         xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed to create pixmap\n");
         return FALSE;
     }
commit 0e9504e10c4363e24a83f1a82e6a4b9f5fd8f846
Author: Daniel Stone <daniels at collabora.com>
Date:   Wed Apr 4 16:16:33 2018 +0100

    drmmode: Track if BO allocation used modifiers
    
    Keep track of whether or not we fed modifiers into GBM when we allocated
    a BO. We'll use this later inside Glamor, to reallocate buffer storage
    if we allocate buffer storage using modifiers, and a non-modifier-aware
    client requests an export of that pixmap.
    
    This makes it possible to run a compositing manager on an old GLX/EGL
    stack on top of an X server which allocates internal buffer storage
    using exotic modifiers from modifier-aware GBM/EGL/KMS.
    
    Signed-off-by: Daniel Stone <daniels at collabora.com>
    Reported-by: Adam Jackson <ajax at redhat.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index e23893883..4fe59d22e 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -752,13 +752,16 @@ drmmode_create_bo(drmmode_ptr drmmode, drmmode_bo *bo,
                                                    format, modifiers,
                                                    num_modifiers);
             free(modifiers);
-            if (bo->gbm)
+            if (bo->gbm) {
+                bo->used_modifiers = TRUE;
                 return TRUE;
+            }
         }
 #endif
 
         bo->gbm = gbm_bo_create(drmmode->gbm, width, height, format,
                                 GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT);
+        bo->used_modifiers = FALSE;
         return bo->gbm != NULL;
     }
 #endif
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h
index d2dc7c225..1086b5ceb 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.h
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.h
@@ -75,6 +75,7 @@ typedef struct {
     uint32_t height;
     struct dumb_bo *dumb;
 #ifdef GLAMOR_HAS_GBM
+    Bool used_modifiers;
     struct gbm_bo *gbm;
 #endif
 } drmmode_bo;
commit 75bba3aedcb04132a4fe2806680cd38a8f2bd206
Author: Daniel Stone <daniels at collabora.com>
Date:   Wed Apr 4 16:16:32 2018 +0100

    dri3: Use single-FD screen call for single-FD request
    
    When importing client buffers into Pixmaps, we can use the fds_to_pixmap
    hook for both single-FD and multi-FD client requests without any harm.
    
    For the other direction of exporting Pixmap buffers to client FDs,
    create a new helper which calls the old pixmap_to_fd hook if available.
    This allows the implementation to ensure that the Pixmap storage is
    accessible to clients not aware of multiple planes or modifiers, e.g. by
    reallocating and copying.
    
    This makes it possible to run a compositing manager on an old GLX/EGL
    stack on top of an X server which allocates internal buffer storage
    using exotic modifiers from modifier-aware GBM/EGL/KMS.
    
    Signed-off-by: Daniel Stone <daniels at collabora.com>
    Reported-by: Adam Jackson <ajax at redhat.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/dri3/dri3_priv.h b/dri3/dri3_priv.h
index 8447680ba..d86f06be0 100644
--- a/dri3/dri3_priv.h
+++ b/dri3/dri3_priv.h
@@ -84,6 +84,9 @@ dri3_pixmap_from_fds(PixmapPtr *ppixmap, ScreenPtr screen, CARD8 num_fds, int *f
                      CARD8 depth, CARD8 bpp, CARD64 modifier);
 
 int
+dri3_fd_from_pixmap(PixmapPtr pixmap, CARD16 *stride, CARD32 *size);
+
+int
 dri3_fds_from_pixmap(PixmapPtr pixmap, int *fds,
                      CARD32 *strides, CARD32 *offsets,
                      CARD64 *modifier);
diff --git a/dri3/dri3_request.c b/dri3/dri3_request.c
index fc258711b..2d3deb282 100644
--- a/dri3/dri3_request.c
+++ b/dri3/dri3_request.c
@@ -212,10 +212,7 @@ proc_dri3_buffer_from_pixmap(ClientPtr client)
         .length = 0,
     };
     int rc;
-    int num_fds;
-    int fds[4];
-    uint32_t strides[4], offsets[4];
-    uint64_t modifier;
+    int fd;
     PixmapPtr pixmap;
 
     REQUEST_SIZE_MATCH(xDRI3BufferFromPixmapReq);
@@ -231,13 +228,10 @@ proc_dri3_buffer_from_pixmap(ClientPtr client)
     rep.depth = pixmap->drawable.depth;
     rep.bpp = pixmap->drawable.bitsPerPixel;
 
-    num_fds = dri3_fds_from_pixmap(pixmap, fds, strides, offsets, &modifier);
-    if (num_fds != 1)
+    fd = dri3_fd_from_pixmap(pixmap, &rep.stride, &rep.size);
+    if (fd == -1)
         return BadPixmap;
 
-    rep.stride = (CARD16) strides[0];
-    rep.size = rep.stride * rep.height;
-
     if (client->swapped) {
         swaps(&rep.sequenceNumber);
         swapl(&rep.length);
@@ -246,8 +240,8 @@ proc_dri3_buffer_from_pixmap(ClientPtr client)
         swaps(&rep.height);
         swaps(&rep.stride);
     }
-    if (WriteFdToClient(client, fds[0], TRUE) < 0) {
-        close(fds[0]);
+    if (WriteFdToClient(client, fd, TRUE) < 0) {
+        close(fd);
         return BadAlloc;
     }
 
diff --git a/dri3/dri3_screen.c b/dri3/dri3_screen.c
index df40f8281..41595f412 100644
--- a/dri3/dri3_screen.c
+++ b/dri3/dri3_screen.c
@@ -30,6 +30,7 @@
 #include <misyncshm.h>
 #include <randrstr.h>
 #include <drm_fourcc.h>
+#include <unistd.h>
 
 static inline Bool has_open(dri3_screen_info_ptr info) {
     if (info == NULL)
@@ -124,6 +125,45 @@ dri3_fds_from_pixmap(PixmapPtr pixmap, int *fds,
     }
 }
 
+int
+dri3_fd_from_pixmap(PixmapPtr pixmap, CARD16 *stride, CARD32 *size)
+{
+    ScreenPtr                   screen = pixmap->drawable.pScreen;
+    dri3_screen_priv_ptr        ds = dri3_screen_priv(screen);
+    dri3_screen_info_ptr        info = ds->info;
+    CARD32                      strides[4];
+    CARD32                      offsets[4];
+    CARD64                      modifier;
+    int                         fds[4];
+    int                         num_fds;
+
+    if (!info)
+        return -1;
+
+    /* Preferentially use the old interface, allowing the implementation to
+     * ensure the buffer is in a single-plane format which doesn't need
+     * modifiers. */
+    if (info->fd_from_pixmap != NULL)
+        return (*info->fd_from_pixmap)(screen, pixmap, stride, size);
+
+    if (info->version < 2 || info->fds_from_pixmap == NULL)
+        return -1;
+
+    /* If using the new interface, make sure that it's a single plane starting
+     * at 0 within the BO. We don't check the modifier, as the client may
+     * have an auxiliary mechanism for determining the modifier itself. */
+    num_fds = info->fds_from_pixmap(screen, pixmap, fds, strides, offsets,
+                                    &modifier);
+    if (num_fds != 1 || offsets[0] != 0) {
+        int i;
+        for (i = 0; i < num_fds; i++)
+            close(fds[i]);
+        return -1;
+    }
+
+    return fds[0];
+}
+
 static int
 cache_formats_and_modifiers(ScreenPtr screen)
 {


More information about the xorg-commit mailing list