<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Wed, Feb 21, 2018 at 6:05 AM, Daniel Stone <span dir="ltr"><<a href="mailto:daniels@collabora.com" target="_blank">daniels@collabora.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">From: Louis-Francis Ratté-Boulianne <<a href="mailto:lfrb@collabora.com">lfrb@collabora.com</a>><br>
<br>
Add support for DRI3 v1.1, which allows pixmaps to be backed by<br>
multi-planar buffers, or those with format modifiers. This is both<br>
for allocating render buffers, as well as EGLImage imports from a<br>
native pixmap (EGL_NATIVE_PIXMAP_KHR).<br>
<br>
Signed-off-by: Louis-Francis Ratté-Boulianne <<a href="mailto:lfrb@collabora.com">lfrb@collabora.com</a>><br>
Reviewed-by: Eric Engestrom <<a href="mailto:eric.engestrom@imgtec.com">eric.engestrom@imgtec.com</a>><br>
Reviewed-by: Emil Velikov <<a href="mailto:emil.velikov@collabora.com">emil.velikov@collabora.com</a>><br>
Reviewed-by: Daniel Stone <<a href="mailto:daniels@collabora.com">daniels@collabora.com</a>><br>
Signed-off-by: Daniel Stone <<a href="mailto:daniels@collabora.com">daniels@collabora.com</a>><br>
---<br>
 src/egl/drivers/dri2/egl_dri2.<wbr>c          |   7 +<br>
 src/egl/drivers/dri2/egl_dri2.<wbr>h          |   3 +<br>
 src/egl/drivers/dri2/platform_<wbr>x11_dri3.c | 105 ++++++++--<br>
 src/glx/dri3_glx.c                       |  10 +-<br>
 src/loader/loader_dri3_helper.<wbr>c          | 319 ++++++++++++++++++++++++++----<wbr>-<br>
 src/loader/loader_dri3_helper.<wbr>h          |  17 +-<br>
 src/loader/meson.build                   |   2 +-<br>
 7 files changed, 400 insertions(+), 63 deletions(-)<br>
<br>
diff --git a/src/egl/drivers/dri2/egl_<wbr>dri2.c b/src/egl/drivers/dri2/egl_<wbr>dri2.c<br>
index 17b646e7ede..9a7e43bafb6 100644<br>
--- a/src/egl/drivers/dri2/egl_<wbr>dri2.c<br>
+++ b/src/egl/drivers/dri2/egl_<wbr>dri2.c<br>
@@ -881,6 +881,13 @@ dri2_setup_extensions(_<wbr>EGLDisplay *disp)<br>
    if (!dri2_bind_extensions(dri2_<wbr>dpy, mandatory_core_extensions, extensions, false))<br>
       return EGL_FALSE;<br>
<br>
+#ifdef HAVE_DRI3<br>
+   dri2_dpy->multibuffers_<wbr>available =<br>
+      (dri2_dpy->dri3_major_version > 1 || (dri2_dpy->dri3_major_version == 1 &&<br>
+                                            dri2_dpy->dri3_minor_version >= 1)) &&<br>
+      (dri2_dpy->image && dri2_dpy->image->base.version >= 15);<br>
+#endif<br>
+<br>
    dri2_bind_extensions(dri2_dpy, optional_core_extensions, extensions, true);<br>
    return EGL_TRUE;<br>
 }<br>
diff --git a/src/egl/drivers/dri2/egl_<wbr>dri2.h b/src/egl/drivers/dri2/egl_<wbr>dri2.h<br>
index d36d02c3c49..00c4768d421 100644<br>
--- a/src/egl/drivers/dri2/egl_<wbr>dri2.h<br>
+++ b/src/egl/drivers/dri2/egl_<wbr>dri2.h<br>
@@ -199,6 +199,9 @@ struct dri2_egl_display<br>
    xcb_screen_t             *screen;<br>
    bool                     swap_available;<br>
 #ifdef HAVE_DRI3<br>
+   bool                     multibuffers_available;<br>
+   int                      dri3_major_version;<br>
+   int                      dri3_minor_version;<br>
    struct loader_dri3_extensions loader_dri3_ext;<br>
 #endif<br>
 #endif<br>
diff --git a/src/egl/drivers/dri2/<wbr>platform_x11_dri3.c b/src/egl/drivers/dri2/<wbr>platform_x11_dri3.c<br>
index 2073c592dc9..aee6b0cfdcc 100644<br>
--- a/src/egl/drivers/dri2/<wbr>platform_x11_dri3.c<br>
+++ b/src/egl/drivers/dri2/<wbr>platform_x11_dri3.c<br>
@@ -39,6 +39,23 @@<br>
 #include "loader.h"<br>
 #include "loader_dri3_helper.h"<br>
<br>
+static uint32_t<br>
+dri3_format_for_depth(uint32_<wbr>t depth)<br>
+{<br>
+   switch (depth) {<br>
+   case 16:<br>
+      return __DRI_IMAGE_FORMAT_RGB565;<br>
+   case 24:<br>
+      return __DRI_IMAGE_FORMAT_XRGB8888;<br>
+   case 30:<br>
+      return __DRI_IMAGE_FORMAT_<wbr>XRGB2101010;<br>
+   case 32:<br>
+      return __DRI_IMAGE_FORMAT_ARGB8888;<br>
+   default:<br>
+      return __DRI_IMAGE_FORMAT_NONE;<br>
+   }<br>
+}<br>
+<br>
 static struct dri3_egl_surface *<br>
 loader_drawable_to_egl_<wbr>surface(struct loader_dri3_drawable *draw) {<br>
    size_t offset = offsetof(struct dri3_egl_surface, loader_drawable);<br>
@@ -168,7 +185,9 @@ dri3_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,<br>
<br>
    if (loader_dri3_drawable_init(<wbr>dri2_dpy->conn, drawable,<br>
                                  dri2_dpy->dri_screen,<br>
-                                 dri2_dpy->is_different_gpu, dri_config,<br>
+                                 dri2_dpy->is_different_gpu,<br>
+                                 dri2_dpy->multibuffers_<wbr>available,<br>
+                                 dri_config,<br>
                                  &dri2_dpy->loader_dri3_ext,<br>
                                  &egl_dri3_vtable,<br>
                                  &dri3_surf->loader_drawable)) {<br>
@@ -274,20 +293,8 @@ dri3_create_image_khr_pixmap(_<wbr>EGLDisplay *disp, _EGLContext *ctx,<br>
       return NULL;<br>
    }<br>
<br>
-   switch (bp_reply->depth) {<br>
-   case 16:<br>
-      format = __DRI_IMAGE_FORMAT_RGB565;<br>
-      break;<br>
-   case 24:<br>
-      format = __DRI_IMAGE_FORMAT_XRGB8888;<br>
-      break;<br>
-   case 30:<br>
-      format = __DRI_IMAGE_FORMAT_<wbr>XRGB2101010;<br>
-      break;<br>
-   case 32:<br>
-      format = __DRI_IMAGE_FORMAT_ARGB8888;<br>
-      break;<br>
-   default:<br>
+   format = dri3_format_for_depth(bp_<wbr>reply->depth);<br>
+   if (format == __DRI_IMAGE_FORMAT_NONE) {<br>
       _eglError(EGL_BAD_PARAMETER,<br>
                 "dri3_create_image_khr: unsupported pixmap depth");<br>
       free(bp_reply);<br>
@@ -315,13 +322,78 @@ dri3_create_image_khr_pixmap(_<wbr>EGLDisplay *disp, _EGLContext *ctx,<br>
    return &dri2_img->base;<br>
 }<br>
<br>
+#if XCB_DRI3_MAJOR_VERSION > 1 || (XCB_DRI3_MAJOR_VERSION == 1 && XCB_DRI3_MINOR_VERSION >= 1)<br>
+static _EGLImage *<br>
+dri3_create_image_khr_pixmap_<wbr>from_buffers(_EGLDisplay *disp, _EGLContext *ctx,<br>
+                                          EGLClientBuffer buffer,<br>
+                                          const EGLint *attr_list)<br>
+{<br>
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);<br>
+   struct dri2_egl_image *dri2_img;<br>
+   xcb_dri3_buffers_from_pixmap_<wbr>cookie_t bp_cookie;<br>
+   xcb_dri3_buffers_from_pixmap_<wbr>reply_t  *bp_reply;<br>
+   xcb_drawable_t drawable;<br>
+   unsigned int format;<br>
+<br>
+   drawable = (xcb_drawable_t) (uintptr_t) buffer;<br>
+   bp_cookie = xcb_dri3_buffers_from_pixmap(<wbr>dri2_dpy->conn, drawable);<br>
+   bp_reply = xcb_dri3_buffers_from_pixmap_<wbr>reply(dri2_dpy->conn,<br>
+                                                 bp_cookie, NULL);<br>
+<br>
+   if (!bp_reply) {<br>
+      _eglError(EGL_BAD_ATTRIBUTE, "dri3_create_image_khr");<br>
+      return EGL_NO_IMAGE_KHR;<br>
+   }<br>
+<br>
+   format = dri3_format_for_depth(bp_<wbr>reply->depth);<br>
+   if (format == __DRI_IMAGE_FORMAT_NONE) {<br>
+      _eglError(EGL_BAD_PARAMETER,<br>
+                "dri3_create_image_khr: unsupported pixmap depth");<br>
+      free(bp_reply);<br>
+      return EGL_NO_IMAGE_KHR;<br>
+   }<br>
+<br>
+   dri2_img = malloc(sizeof *dri2_img);<br>
+   if (!dri2_img) {<br>
+      _eglError(EGL_BAD_ALLOC, "dri3_create_image_khr");<br>
+      free(bp_reply);<br>
+      return EGL_NO_IMAGE_KHR;<br>
+   }<br>
+<br>
+   _eglInitImage(&dri2_img->base, disp);<br>
+<br>
+   dri2_img->dri_image = loader_dri3_create_image_from_<wbr>buffers(dri2_dpy->conn,<br>
+                                                               bp_reply,<br>
+                                                               format,<br>
+                                                               dri2_dpy->dri_screen,<br>
+                                                               dri2_dpy->image,<br>
+                                                               dri2_img);<br>
+   free(bp_reply);<br>
+<br>
+   if (!dri2_img->dri_image) {<br>
+      _eglError(EGL_BAD_ATTRIBUTE, "dri3_create_image_khr");<br>
+      free(dri2_img);<br>
+      return EGL_NO_IMAGE_KHR;<br>
+   }<br>
+<br>
+   return &dri2_img->base;<br>
+}<br>
+#endif<br>
+<br>
 static _EGLImage *<br>
 dri3_create_image_khr(_<wbr>EGLDriver *drv, _EGLDisplay *disp,<br>
                       _EGLContext *ctx, EGLenum target,<br>
                       EGLClientBuffer buffer, const EGLint *attr_list)<br>
 {<br>
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);<br>
+<br>
    switch (target) {<br>
    case EGL_NATIVE_PIXMAP_KHR:<br>
+#if XCB_DRI3_MAJOR_VERSION > 1 || (XCB_DRI3_MAJOR_VERSION == 1 && XCB_DRI3_MINOR_VERSION >= 1)<br>
+      if (dri2_dpy->multibuffers_<wbr>available)<br>
+         return dri3_create_image_khr_pixmap_<wbr>from_buffers(disp, ctx, buffer,<br>
+                                                          attr_list);<br>
+#endif<br>
       return dri3_create_image_khr_pixmap(<wbr>disp, ctx, buffer, attr_list);<br>
    default:<br>
       return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);<br>
@@ -483,6 +555,9 @@ dri3_x11_connect(struct dri2_egl_display *dri2_dpy)<br>
       free(error);<br>
       return EGL_FALSE;<br>
    }<br>
+<br>
+   dri2_dpy->dri3_major_version = dri3_query->major_version;<br>
+   dri2_dpy->dri3_minor_version = dri3_query->minor_version;<br>
    free(dri3_query);<br>
<br>
    present_query =<br>
diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c<br>
index 016f91b1963..933d5b5e181 100644<br>
--- a/src/glx/dri3_glx.c<br>
+++ b/src/glx/dri3_glx.c<br>
@@ -357,7 +357,10 @@ dri3_create_drawable(struct glx_screen *base, XID xDrawable,<br>
 {<br>
    struct dri3_drawable *pdraw;<br>
    struct dri3_screen *psc = (struct dri3_screen *) base;<br>
+   const struct dri3_display *const pdp = (struct dri3_display *)<br>
+      base->display->dri3Display;<br>
    __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;<br>
+   bool has_multibuffer = false;<br>
<br>
    pdraw = calloc(1, sizeof(*pdraw));<br>
    if (!pdraw)<br>
@@ -368,11 +371,16 @@ dri3_create_drawable(struct glx_screen *base, XID xDrawable,<br>
    pdraw->base.drawable = drawable;<br>
    pdraw->base.psc = &psc->base;<br>
<br>
+   if ((psc->image && psc->image->base.version >= 15) &&<br>
+       (pdp->dri3Major > 1 || (pdp->dri3Major == 1 && pdp->dri3Minor >= 1)))<br>
+      has_multibuffer = true;<br>
+<br>
    (void) __glXInitialize(psc->base.dpy)<wbr>;<br>
<br>
    if (loader_dri3_drawable_init(<wbr>XGetXCBConnection(base->dpy),<br>
                                  xDrawable, psc->driScreen,<br>
-                                 psc->is_different_gpu, config->driConfig,<br>
+                                 psc->is_different_gpu, has_multibuffer,<br>
+                                 config->driConfig,<br>
                                  &psc->loader_dri3_ext, &glx_dri3_vtable,<br>
                                  &pdraw->loader_drawable)) {<br>
       free(pdraw);<br>
diff --git a/src/loader/loader_dri3_<wbr>helper.c b/src/loader/loader_dri3_<wbr>helper.c<br>
index 426966a786a..fdb3e72f3b0 100644<br>
--- a/src/loader/loader_dri3_<wbr>helper.c<br>
+++ b/src/loader/loader_dri3_<wbr>helper.c<br>
@@ -24,6 +24,7 @@<br>
 #include <fcntl.h><br>
 #include <stdlib.h><br>
 #include <unistd.h><br>
+#include <string.h><br>
<br>
 #include <X11/xshmfence.h><br>
 #include <xcb/xcb.h><br>
@@ -34,6 +35,7 @@<br>
<br>
 #include "loader_dri3_helper.h"<br>
 #include "util/macros.h"<br>
+#include "drm_fourcc.h"<br>
<br>
 /* From xmlpool/options.h, user exposed so should be stable */<br>
 #define DRI_CONF_VBLANK_NEVER 0<br>
@@ -257,6 +259,7 @@ loader_dri3_drawable_init(xcb_<wbr>connection_t *conn,<br>
                           xcb_drawable_t drawable,<br>
                           __DRIscreen *dri_screen,<br>
                           bool is_different_gpu,<br>
+                          bool multiplanes_available,<br>
                           const __DRIconfig *dri_config,<br>
                           struct loader_dri3_extensions *ext,<br>
                           const struct loader_dri3_vtable *vtable,<br>
@@ -274,6 +277,7 @@ loader_dri3_drawable_init(xcb_<wbr>connection_t *conn,<br>
    draw->drawable = drawable;<br>
    draw->dri_screen = dri_screen;<br>
    draw->is_different_gpu = is_different_gpu;<br>
+   draw->multiplanes_available = multiplanes_available;<br>
<br>
    draw->have_back = 0;<br>
    draw->have_fake_front = 0;<br>
@@ -1023,6 +1027,41 @@ image_format_to_fourcc(int format)<br>
    return 0;<br>
 }<br>
<br>
+static bool<br>
+has_supported_modifier(struct loader_dri3_drawable *draw, unsigned int format,<br>
+                       uint64_t *modifiers, uint32_t count)<br>
+{<br>
+   uint64_t *supported_modifiers;<br>
+   int32_t supported_modifiers_count;<br>
+   bool found = false;<br>
+   int i, j;<br>
+<br>
+   if (!draw->ext->image-><wbr>queryDmaBufModifiers(draw-><wbr>dri_screen,<br>
+                                               format, 0, NULL, NULL,<br>
+                                               &supported_modifiers_count) ||<br>
+       supported_modifiers_count == 0)<br>
+      return false;<br>
+<br>
+   supported_modifiers = malloc(supported_modifiers_<wbr>count * sizeof(uint64_t));<br>
+   if (!supported_modifiers)<br>
+      return false;<br>
+<br>
+   draw->ext->image-><wbr>queryDmaBufModifiers(draw-><wbr>dri_screen, format,<br>
+                                          supported_modifiers_count,<br>
+                                          supported_modifiers, NULL,<br>
+                                          &supported_modifiers_count);<br>
+<br>
+   for (i = 0; !found && i < supported_modifiers_count; i++) {<br>
+      for (j = 0; !found && j < count; j++) {<br>
+         if (supported_modifiers[i] == modifiers[j])<br>
+            found = true;<br>
+      }<br>
+   }<br>
+<br>
+   free(supported_modifiers);<br>
+   return found;<br>
+}<br>
+<br>
 /** loader_dri3_alloc_render_<wbr>buffer<br>
  *<br>
  * Use the driver createImage function to construct a __DRIimage, then<br>
@@ -1039,8 +1078,10 @@ dri3_alloc_render_buffer(<wbr>struct loader_dri3_drawable *draw, unsigned int format,<br>
    xcb_pixmap_t pixmap;<br>
    xcb_sync_fence_t sync_fence;<br>
    struct xshmfence *shm_fence;<br>
-   int buffer_fd, fence_fd;<br>
-   int stride;<br>
+   int buffer_fds[4], fence_fd;<br>
+   int num_planes = 0;<br>
+   int i, mod;<br>
+   int ret;<br>
<br>
    /* Create an xshmfence object and<br>
     * prepare to send that to the X server<br>
@@ -1065,13 +1106,81 @@ dri3_alloc_render_buffer(<wbr>struct loader_dri3_drawable *draw, unsigned int format,<br>
       goto no_image;<br>
<br>
    if (!draw->is_different_gpu) {<br>
-      buffer->image = draw->ext->image->createImage(<wbr>draw->dri_screen,<br>
-                                                    width, height,<br>
-                                                    format,<br>
-                                                    __DRI_IMAGE_USE_SHARE |<br>
-                                                    __DRI_IMAGE_USE_SCANOUT |<br>
-                                                    __DRI_IMAGE_USE_BACKBUFFER,<br>
-                                                    buffer);<br>
+#if XCB_DRI3_MAJOR_VERSION > 1 || (XCB_DRI3_MAJOR_VERSION == 1 && XCB_DRI3_MINOR_VERSION >= 1)<br>
+      if (draw->multiplanes_available &&<br>
+          draw->ext->image->base.version >= 15 &&<br>
+          draw->ext->image-><wbr>queryDmaBufModifiers &&<br>
+          draw->ext->image-><wbr>createImageWithModifiers) {<br>
+         xcb_dri3_get_supported_<wbr>modifiers_cookie_t mod_cookie;<br>
+         xcb_dri3_get_supported_<wbr>modifiers_reply_t *mod_reply;<br>
+         xcb_generic_error_t *error = NULL;<br>
+         uint64_t *modifiers = NULL;<br>
+         uint32_t count = 0;<br>
+<br>
+         mod_cookie = xcb_dri3_get_supported_<wbr>modifiers(draw->conn,<br>
+                                                       draw->drawable,<br>
+                                                       depth, buffer->cpp * 8);<br>
+         mod_reply = xcb_dri3_get_supported_<wbr>modifiers_reply(draw->conn,<br>
+                                                            mod_cookie,<br>
+                                                            &error);<br>
+         if (!mod_reply)<br>
+            goto no_image;<br>
+<br>
+         if (mod_reply->num_drawable_<wbr>modifiers) {<br>
+            count = mod_reply->num_drawable_<wbr>modifiers;<br>
+            modifiers = malloc(count * sizeof(uint64_t));<br>
+            if (!modifiers) {<br>
+               free(mod_reply);<br>
+               goto no_image;<br>
+            }<br>
+<br>
+            memcpy(modifiers,<br>
+                   xcb_dri3_get_supported_<wbr>modifiers_drawable_modifiers(<wbr>mod_reply),<br>
+                   count * sizeof(uint64_t));<br>
+<br>
+            if (!has_supported_modifier(draw, image_format_to_fourcc(format)<wbr>,<br>
+                                        modifiers, count)) {<br>
+               free(modifiers);<br>
+               count = 0;<br>
+               modifiers = NULL;<br>
+            }<br>
+         }<br>
+<br>
+         if (mod_reply->num_screen_<wbr>modifiers && modifiers == NULL) {<br>
+            count = mod_reply->num_screen_<wbr>modifiers;<br>
+            modifiers = malloc(count * sizeof(uint64_t));<br>
+            if (!modifiers) {<br>
+               free(modifiers);<br>
+               free(mod_reply);<br>
+               goto no_image;<br>
+            }<br>
+<br>
+            memcpy(modifiers,<br>
+                   xcb_dri3_get_supported_<wbr>modifiers_screen_modifiers(<wbr>mod_reply),<br>
+                   count * sizeof(uint64_t));<br></blockquote><div><br></div><div>You really don't need all the memcpy action in this one given that modifiers is freed right below. :)  I've got a squash-in for you in my tree.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+         }<br>
+<br>
+         free(mod_reply);<br>
+<br>
+         buffer->image = draw->ext->image-><wbr>createImageWithModifiers(draw-<wbr>>dri_screen,<br>
+                                                                    width, height,<br>
+                                                                    format,<br>
+                                                                    modifiers,<br>
+                                                                    count,<br>
+                                                                    buffer);<br>
+         free(modifiers);<br>
+      }<br>
+#endif<br>
+<br>
+      if (!buffer->image)<br>
+         buffer->image = draw->ext->image->createImage(<wbr>draw->dri_screen,<br>
+                                                       width, height,<br>
+                                                       format,<br>
+                                                       __DRI_IMAGE_USE_SHARE |<br>
+                                                       __DRI_IMAGE_USE_SCANOUT |<br>
+                                                       __DRI_IMAGE_USE_BACKBUFFER,<br>
+                                                       buffer);<br>
+<br>
       pixmap_buffer = buffer->image;<br>
<br>
       if (!buffer->image)<br>
@@ -1099,25 +1208,71 @@ dri3_alloc_render_buffer(<wbr>struct loader_dri3_drawable *draw, unsigned int format,<br>
          goto no_linear_buffer;<br>
    }<br>
<br>
-   /* X wants the stride, so ask the image for it<br>
+   /* X want some information about the planes, so ask the image for it<br>
     */<br>
-   if (!draw->ext->image-><wbr>queryImage(pixmap_buffer, __DRI_IMAGE_ATTRIB_STRIDE,<br>
-                                     &stride))<br>
-      goto no_buffer_attrib;<br>
+   if (!draw->ext->image-><wbr>queryImage(pixmap_buffer, __DRI_IMAGE_ATTRIB_NUM_PLANES,<br>
+                                     &num_planes))<br>
+      num_planes = 1;<br>
<br>
-   buffer->pitch = stride;<br>
+   for (i = 0; i < num_planes; i++) {<br>
+      __DRIimage *image = draw->ext->image->fromPlanar(<wbr>pixmap_buffer, i, NULL);<br>
<br>
-   if (!draw->ext->image-><wbr>queryImage(pixmap_buffer, __DRI_IMAGE_ATTRIB_FD,<br>
-                                     &buffer_fd))<br>
-      goto no_buffer_attrib;<br>
+      if (!image) {<br>
+         assert(i == 0);<br>
+         image = pixmap_buffer;<br>
+      }<br>
<br>
-   xcb_dri3_pixmap_from_buffer(<wbr>draw->conn,<br>
-                               (pixmap = xcb_generate_id(draw->conn)),<br>
-                               draw->drawable,<br>
-                               buffer->size,<br>
-                               width, height, buffer->pitch,<br>
-                               depth, buffer->cpp * 8,<br>
-                               buffer_fd);<br>
+      ret = draw->ext->image->queryImage(<wbr>image, __DRI_IMAGE_ATTRIB_FD,<br>
+                                         &buffer_fds[i]);<br>
+      ret &= draw->ext->image->queryImage(<wbr>image, __DRI_IMAGE_ATTRIB_STRIDE,<br>
+                                          &buffer->strides[i]);<br>
+      ret &= draw->ext->image->queryImage(<wbr>image, __DRI_IMAGE_ATTRIB_OFFSET,<br>
+                                          &buffer->offsets[i]);<br>
+      if (image != pixmap_buffer)<br>
+         draw->ext->image-><wbr>destroyImage(image);<br>
+<br>
+      if (!ret)<br>
+         goto no_buffer_attrib;<br>
+   }<br>
+<br>
+   ret = draw->ext->image->queryImage(<wbr>pixmap_buffer,<br>
+                                     __DRI_IMAGE_ATTRIB_MODIFIER_<wbr>UPPER, &mod);<br>
+   buffer->modifier = (uint64_t) mod << 32;<br>
+   ret &= draw->ext->image->queryImage(<wbr>pixmap_buffer,<br>
+                                       __DRI_IMAGE_ATTRIB_MODIFIER_<wbr>LOWER, &mod);<br>
+   buffer->modifier |= (uint64_t)(mod & 0xffffffff);<br>
+<br>
+   if (!ret)<br>
+      buffer->modifier = DRM_FORMAT_MOD_INVALID;<br>
+<br>
+   pixmap = xcb_generate_id(draw->conn);<br>
+#if XCB_DRI3_MAJOR_VERSION > 1 || (XCB_DRI3_MAJOR_VERSION == 1 && XCB_DRI3_MINOR_VERSION >= 1)<br>
+   if (draw->multiplanes_available &&<br>
+       buffer->modifier != DRM_FORMAT_MOD_INVALID) {<br>
+      xcb_dri3_pixmap_from_buffers(<wbr>draw->conn,<br>
+                                   pixmap,<br>
+                                   draw->drawable,<br>
+                                   num_planes,<br>
+                                   width, height,<br>
+                                   buffer->strides[0], buffer->offsets[0],<br>
+                                   buffer->strides[1], buffer->offsets[1],<br>
+                                   buffer->strides[2], buffer->offsets[2],<br>
+                                   buffer->strides[3], buffer->offsets[3],<br>
+                                   depth, buffer->cpp * 8,<br>
+                                   buffer->modifier,<br>
+                                   buffer_fds);<br>
+   }<br>
+   else<br>
+#endif<br>
+   {<br>
+      xcb_dri3_pixmap_from_buffer(<wbr>draw->conn,<br>
+                                  pixmap,<br>
+                                  draw->drawable,<br>
+                                  buffer->size,<br>
+                                  width, height, buffer->strides[0],<br>
+                                  depth, buffer->cpp * 8,<br>
+                                  buffer_fds[0]);<br>
+   }<br>
<br>
    xcb_dri3_fence_from_fd(draw-><wbr>conn,<br>
                           pixmap,<br>
@@ -1139,6 +1294,9 @@ dri3_alloc_render_buffer(<wbr>struct loader_dri3_drawable *draw, unsigned int format,<br>
    return buffer;<br>
<br>
 no_buffer_attrib:<br>
+   do {<br>
+      close(buffer_fds[i]);<br>
+   } while (--i >= 0);<br>
    draw->ext->image-><wbr>destroyImage(pixmap_buffer);<br>
 no_linear_buffer:<br>
    if (draw->is_different_gpu)<br>
@@ -1295,6 +1453,50 @@ loader_dri3_create_image(xcb_<wbr>connection_t *c,<br>
    return ret;<br>
 }<br>
<br>
+#if XCB_DRI3_MAJOR_VERSION > 1 || (XCB_DRI3_MAJOR_VERSION == 1 && XCB_DRI3_MINOR_VERSION >= 1)<br>
+__DRIimage *<br>
+loader_dri3_create_image_<wbr>from_buffers(xcb_connection_t *c,<br>
+                                      xcb_dri3_buffers_from_pixmap_<wbr>reply_t *bp_reply,<br>
+                                      unsigned int format,<br>
+                                      __DRIscreen *dri_screen,<br>
+                                      const __DRIimageExtension *image,<br>
+                                      void *loaderPrivate)<br>
+{<br>
+   __DRIimage                           *ret;<br>
+   int                                  *fds;<br>
+   uint32_t                             *strides_in, *offsets_in;<br>
+   int                                   strides[4], offsets[4];<br>
+   unsigned                              error;<br>
+   int                                   i;<br>
+<br>
+   if (bp_reply->nfd > 4)<br>
+      return NULL;<br>
+<br>
+   fds = xcb_dri3_buffers_from_pixmap_<wbr>reply_fds(c, bp_reply);<br>
+   strides_in = xcb_dri3_buffers_from_pixmap_<wbr>strides(bp_reply);<br>
+   offsets_in = xcb_dri3_buffers_from_pixmap_<wbr>offsets(bp_reply);<br>
+   for (i = 0; i < bp_reply->nfd; i++) {<br>
+      strides[i] = strides_in[i];<br>
+      offsets[i] = offsets_in[i];<br>
+   }<br>
+<br>
+   ret = image-><wbr>createImageFromDmaBufs2(dri_<wbr>screen,<br>
+                                        bp_reply->width,<br>
+                                        bp_reply->height,<br>
+                                        image_format_to_fourcc(format)<wbr>,<br>
+                                        bp_reply->modifier,<br>
+                                        fds, bp_reply->nfd,<br>
+                                        strides, offsets,<br>
+                                        0, 0, 0, 0, /* UNDEFINED */<br>
+                                        &error, loaderPrivate);<br>
+<br>
+   for (i = 0; i < bp_reply->nfd; i++)<br>
+      close(fds[i]);<br>
+<br>
+   return ret;<br>
+}<br>
+#endif<br>
+<br>
 /** dri3_get_pixmap_buffer<br>
  *<br>
  * Get the DRM object for a pixmap from the X server and<br>
@@ -1308,10 +1510,10 @@ dri3_get_pixmap_buffer(__<wbr>DRIdrawable *driDrawable, unsigned int format,<br>
    int                                  buf_id = loader_dri3_pixmap_buf_id(<wbr>buffer_type);<br>
    struct loader_dri3_buffer            *buffer = draw->buffers[buf_id];<br>
    xcb_drawable_t                       pixmap;<br>
-   xcb_dri3_buffer_from_pixmap_<wbr>cookie_t bp_cookie;<br>
-   xcb_dri3_buffer_from_pixmap_<wbr>reply_t  *bp_reply;<br>
    xcb_sync_fence_t                     sync_fence;<br>
    struct xshmfence                     *shm_fence;<br>
+   int                                  width;<br>
+   int                                  height;<br>
    int                                  fence_fd;<br>
    __DRIscreen                          *cur_screen;<br>
<br>
@@ -1333,17 +1535,6 @@ dri3_get_pixmap_buffer(__<wbr>DRIdrawable *driDrawable, unsigned int format,<br>
       goto no_fence;<br>
    }<br>
<br>
-   xcb_dri3_fence_from_fd(draw-><wbr>conn,<br>
-                          pixmap,<br>
-                          (sync_fence = xcb_generate_id(draw->conn)),<br>
-                          false,<br>
-                          fence_fd);<br>
-<br>
-   bp_cookie = xcb_dri3_buffer_from_pixmap(<wbr>draw->conn, pixmap);<br>
-   bp_reply = xcb_dri3_buffer_from_pixmap_<wbr>reply(draw->conn, bp_cookie, NULL);<br>
-   if (!bp_reply)<br>
-      goto no_image;<br>
-<br>
    /* Get the currently-bound screen or revert to using the drawable's screen if<br>
     * no contexts are currently bound. The latter case is at least necessary for<br>
     * obs-studio, when using Window Capture (Xcomposite) as a Source.<br>
@@ -1353,27 +1544,65 @@ dri3_get_pixmap_buffer(__<wbr>DRIdrawable *driDrawable, unsigned int format,<br>
        cur_screen = draw->dri_screen;<br>
    }<br>
<br>
-   buffer->image = loader_dri3_create_image(draw-<wbr>>conn, bp_reply, format,<br>
-                                            cur_screen, draw->ext->image,<br>
-                                            buffer);<br>
+   xcb_dri3_fence_from_fd(draw-><wbr>conn,<br>
+                          pixmap,<br>
+                          (sync_fence = xcb_generate_id(draw->conn)),<br>
+                          false,<br>
+                          fence_fd);<br>
+<br>
+#if XCB_DRI3_MAJOR_VERSION > 1 || (XCB_DRI3_MAJOR_VERSION == 1 && XCB_DRI3_MINOR_VERSION >= 1)<br>
+   if (draw->multiplanes_available &&<br>
+       draw->ext->image->base.version >= 15 &&<br>
+       draw->ext->image-><wbr>createImageFromDmaBufs2) {<br>
+      xcb_dri3_buffers_from_pixmap_<wbr>cookie_t bps_cookie;<br>
+      xcb_dri3_buffers_from_pixmap_<wbr>reply_t *bps_reply;<br>
+<br>
+      bps_cookie = xcb_dri3_buffers_from_pixmap(<wbr>draw->conn, pixmap);<br>
+      bps_reply = xcb_dri3_buffers_from_pixmap_<wbr>reply(draw->conn, bps_cookie,<br>
+                                                     NULL);<br>
+      if (!bps_reply)<br>
+         goto no_image;<br>
+      buffer->image =<br>
+         loader_dri3_create_image_from_<wbr>buffers(draw->conn, bps_reply, format,<br>
+                                               cur_screen, draw->ext->image,<br>
+                                               buffer);<br>
+      width = bps_reply->width;<br>
+      height = bps_reply->height;<br>
+      free(bps_reply);<br>
+   } else<br>
+#endif<br>
+   {<br>
+      xcb_dri3_buffer_from_pixmap_<wbr>cookie_t bp_cookie;<br>
+      xcb_dri3_buffer_from_pixmap_<wbr>reply_t *bp_reply;<br>
+<br>
+      bp_cookie = xcb_dri3_buffer_from_pixmap(<wbr>draw->conn, pixmap);<br>
+      bp_reply = xcb_dri3_buffer_from_pixmap_<wbr>reply(draw->conn, bp_cookie, NULL);<br>
+      if (!bp_reply)<br>
+         goto no_image;<br>
+<br>
+      buffer->image = loader_dri3_create_image(draw-<wbr>>conn, bp_reply, format,<br>
+                                               cur_screen, draw->ext->image,<br>
+                                               buffer);<br>
+      width = bp_reply->width;<br>
+      height = bp_reply->height;<br>
+      free(bp_reply);<br>
+   }<br>
+<br>
    if (!buffer->image)<br>
       goto no_image;<br>
<br>
    buffer->pixmap = pixmap;<br>
    buffer->own_pixmap = false;<br>
-   buffer->width = bp_reply->width;<br>
-   buffer->height = bp_reply->height;<br>
+   buffer->width = width;<br>
+   buffer->height = height;<br>
    buffer->shm_fence = shm_fence;<br>
    buffer->sync_fence = sync_fence;<br>
<br>
    draw->buffers[buf_id] = buffer;<br>
<br>
-   free(bp_reply);<br>
-<br>
    return buffer;<br>
<br>
 no_image:<br>
-   free(bp_reply);<br>
    xcb_sync_destroy_fence(draw-><wbr>conn, sync_fence);<br>
    xshmfence_unmap_shm(shm_fence)<wbr>;<br>
 no_fence:<br>
diff --git a/src/loader/loader_dri3_<wbr>helper.h b/src/loader/loader_dri3_<wbr>helper.h<br>
index 5caf214b372..def70426431 100644<br>
--- a/src/loader/loader_dri3_<wbr>helper.h<br>
+++ b/src/loader/loader_dri3_<wbr>helper.h<br>
@@ -62,8 +62,11 @@ struct loader_dri3_buffer {<br>
    bool         busy;           /* Set on swap, cleared on IdleNotify */<br>
    bool         own_pixmap;     /* We allocated the pixmap ID, free on destroy */<br>
<br>
+   uint32_t     num_planes;<br>
    uint32_t     size;<br>
-   uint32_t     pitch;<br>
+   int          strides[4];<br>
+   int          offsets[4];<br>
+   uint64_t     modifier;<br>
    uint32_t     cpp;<br>
    uint32_t     flags;<br>
    uint32_t     width, height;<br>
@@ -120,6 +123,7 @@ struct loader_dri3_drawable {<br>
    /* Information about the GPU owning the buffer */<br>
    __DRIscreen *dri_screen;<br>
    bool is_different_gpu;<br>
+   bool multiplanes_available;<br>
<br>
    /* Present extension capabilities<br>
     */<br>
@@ -180,6 +184,7 @@ loader_dri3_drawable_init(xcb_<wbr>connection_t *conn,<br>
                           xcb_drawable_t drawable,<br>
                           __DRIscreen *dri_screen,<br>
                           bool is_different_gpu,<br>
+                          bool is_multiplanes_available,<br>
                           const __DRIconfig *dri_config,<br>
                           struct loader_dri3_extensions *ext,<br>
                           const struct loader_dri3_vtable *vtable,<br>
@@ -237,6 +242,16 @@ loader_dri3_create_image(xcb_<wbr>connection_t *c,<br>
                          const __DRIimageExtension *image,<br>
                          void *loaderPrivate);<br>
<br>
+#if XCB_DRI3_MAJOR_VERSION > 1 || (XCB_DRI3_MAJOR_VERSION == 1 && XCB_DRI3_MINOR_VERSION >= 1)<br>
+__DRIimage *<br>
+loader_dri3_create_image_<wbr>from_buffers(xcb_connection_t *c,<br>
+                                      xcb_dri3_buffers_from_pixmap_<wbr>reply_t *bp_reply,<br>
+                                      unsigned int format,<br>
+                                      __DRIscreen *dri_screen,<br>
+                                      const __DRIimageExtension *image,<br>
+                                      void *loaderPrivate);<br>
+#endif<br>
+<br>
 int<br>
 loader_dri3_get_buffers(__<wbr>DRIdrawable *driDrawable,<br>
                         unsigned int format,<br>
diff --git a/src/loader/meson.build b/src/loader/meson.build<br>
index 2693970182f..76fcae2cb44 100644<br>
--- a/src/loader/meson.build<br>
+++ b/src/loader/meson.build<br>
@@ -25,7 +25,7 @@ if with_platform_x11 and with_dri3<br>
     'loader_dri3_helper',<br>
     ['loader_dri3_helper.c', 'loader_dri3_helper.h'],<br>
     c_args : c_vis_args,<br>
-    include_directories : [inc_include, inc_src],<br>
+    include_directories : [inc_include, inc_src, inc_drm_uapi],<br>
     dependencies : [<br>
       dep_libdrm, dep_xcb_dri3, dep_xcb_present, dep_xcb_sync, dep_xshmfence,<br>
     ],<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.14.3<br>
<br>
______________________________<wbr>_________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br></div></div>