[Mesa-dev] [PATCH 10/11] egl/x11: Support DRI3 v1.1

Jason Ekstrand jason at jlekstrand.net
Thu Feb 15 22:44:39 UTC 2018


On Thu, Feb 15, 2018 at 7:57 AM, Daniel Stone <daniels at collabora.com> wrote:

> From: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
>
> Add support for DRI3 v1.1, which allows pixmaps to be backed by
> multi-planar buffers, or those with format modifiers. This is both
> for allocating render buffers, as well as EGLImage imports from a
> native pixmap (EGL_NATIVE_PIXMAP_KHR).
>
> Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
> Reviewed-by: Eric Engestrom <eric.engestrom at imgtec.com>
> Reviewed-by: Emil Velikov <emil.velikov at collabora.com>
> Reviewed-by: Daniel Stone <daniels at collabora.com>
> Signed-off-by: Daniel Stone <daniels at collabora.com>
> ---
>  src/egl/drivers/dri2/egl_dri2.c          |   7 +
>  src/egl/drivers/dri2/egl_dri2.h          |   3 +
>  src/egl/drivers/dri2/platform_x11_dri3.c | 105 +++++++++--
>  src/glx/dri3_glx.c                       |  10 +-
>  src/loader/loader_dri3_helper.c          | 306
> +++++++++++++++++++++++++++----
>  src/loader/loader_dri3_helper.h          |  17 +-
>  6 files changed, 393 insertions(+), 55 deletions(-)
>
> diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_
> dri2.c
> index 17b646e7ede..9a7e43bafb6 100644
> --- a/src/egl/drivers/dri2/egl_dri2.c
> +++ b/src/egl/drivers/dri2/egl_dri2.c
> @@ -881,6 +881,13 @@ dri2_setup_extensions(_EGLDisplay *disp)
>     if (!dri2_bind_extensions(dri2_dpy, mandatory_core_extensions,
> extensions, false))
>        return EGL_FALSE;
>
> +#ifdef HAVE_DRI3
> +   dri2_dpy->multibuffers_available =
> +      (dri2_dpy->dri3_major_version > 1 || (dri2_dpy->dri3_major_version
> == 1 &&
> +                                            dri2_dpy->dri3_minor_version
> >= 1)) &&
> +      (dri2_dpy->image && dri2_dpy->image->base.version >= 15);
> +#endif
> +
>     dri2_bind_extensions(dri2_dpy, optional_core_extensions, extensions,
> true);
>     return EGL_TRUE;
>  }
> diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_
> dri2.h
> index d36d02c3c49..00c4768d421 100644
> --- a/src/egl/drivers/dri2/egl_dri2.h
> +++ b/src/egl/drivers/dri2/egl_dri2.h
> @@ -199,6 +199,9 @@ struct dri2_egl_display
>     xcb_screen_t             *screen;
>     bool                     swap_available;
>  #ifdef HAVE_DRI3
> +   bool                     multibuffers_available;
> +   int                      dri3_major_version;
> +   int                      dri3_minor_version;
>     struct loader_dri3_extensions loader_dri3_ext;
>  #endif
>  #endif
> diff --git a/src/egl/drivers/dri2/platform_x11_dri3.c
> b/src/egl/drivers/dri2/platform_x11_dri3.c
> index 6ead4d0a222..15c349eb828 100644
> --- a/src/egl/drivers/dri2/platform_x11_dri3.c
> +++ b/src/egl/drivers/dri2/platform_x11_dri3.c
> @@ -39,6 +39,23 @@
>  #include "loader.h"
>  #include "loader_dri3_helper.h"
>
> +static uint32_t
> +dri3_format_for_depth(uint32_t depth)
> +{
> +   switch (depth) {
> +   case 16:
> +      return __DRI_IMAGE_FORMAT_RGB565;
> +   case 24:
> +      return __DRI_IMAGE_FORMAT_XRGB8888;
> +   case 30:
> +      return __DRI_IMAGE_FORMAT_XRGB2101010;
> +   case 32:
> +      return __DRI_IMAGE_FORMAT_ARGB8888;
> +   default:
> +      return __DRI_IMAGE_FORMAT_NONE;
> +   }
> +}
> +
>  static struct dri3_egl_surface *
>  loader_drawable_to_egl_surface(struct loader_dri3_drawable *draw) {
>     size_t offset = offsetof(struct dri3_egl_surface, loader_drawable);
> @@ -156,7 +173,9 @@ dri3_create_surface(_EGLDriver *drv, _EGLDisplay
> *disp, EGLint type,
>
>     if (loader_dri3_drawable_init(dri2_dpy->conn, drawable,
>                                   dri2_dpy->dri_screen,
> -                                 dri2_dpy->is_different_gpu, dri_config,
> +                                 dri2_dpy->is_different_gpu,
> +                                 dri2_dpy->multibuffers_available,
> +                                 dri_config,
>                                   &dri2_dpy->loader_dri3_ext,
>                                   &egl_dri3_vtable,
>                                   &dri3_surf->loader_drawable)) {
> @@ -262,20 +281,8 @@ dri3_create_image_khr_pixmap(_EGLDisplay *disp,
> _EGLContext *ctx,
>        return NULL;
>     }
>
> -   switch (bp_reply->depth) {
> -   case 16:
> -      format = __DRI_IMAGE_FORMAT_RGB565;
> -      break;
> -   case 24:
> -      format = __DRI_IMAGE_FORMAT_XRGB8888;
> -      break;
> -   case 30:
> -      format = __DRI_IMAGE_FORMAT_XRGB2101010;
> -      break;
> -   case 32:
> -      format = __DRI_IMAGE_FORMAT_ARGB8888;
> -      break;
> -   default:
> +   format = dri3_format_for_depth(bp_reply->depth);
> +   if (format == __DRI_IMAGE_FORMAT_NONE) {
>        _eglError(EGL_BAD_PARAMETER,
>                  "dri3_create_image_khr: unsupported pixmap depth");
>        free(bp_reply);
> @@ -303,13 +310,78 @@ dri3_create_image_khr_pixmap(_EGLDisplay *disp,
> _EGLContext *ctx,
>     return &dri2_img->base;
>  }
>
> +#if XCB_DRI3_MAJOR_VERSION > 1 || (XCB_DRI3_MAJOR_VERSION == 1 &&
> XCB_DRI3_MINOR_VERSION >= 1)
> +static _EGLImage *
> +dri3_create_image_khr_pixmap_from_buffers(_EGLDisplay *disp, _EGLContext
> *ctx,
> +                                          EGLClientBuffer buffer,
> +                                          const EGLint *attr_list)
> +{
> +   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
> +   struct dri2_egl_image *dri2_img;
> +   xcb_dri3_buffers_from_pixmap_cookie_t bp_cookie;
> +   xcb_dri3_buffers_from_pixmap_reply_t  *bp_reply;
> +   xcb_drawable_t drawable;
> +   unsigned int format;
> +
> +   drawable = (xcb_drawable_t) (uintptr_t) buffer;
> +   bp_cookie = xcb_dri3_buffers_from_pixmap(dri2_dpy->conn, drawable);
> +   bp_reply = xcb_dri3_buffers_from_pixmap_reply(dri2_dpy->conn,
> +                                                 bp_cookie, NULL);
> +
> +   if (!bp_reply) {
> +      _eglError(EGL_BAD_ATTRIBUTE, "dri3_create_image_khr");
> +      return EGL_NO_IMAGE_KHR;
> +   }
> +
> +   format = dri3_format_for_depth(bp_reply->depth);
> +   if (format == __DRI_IMAGE_FORMAT_NONE) {
> +      _eglError(EGL_BAD_PARAMETER,
> +                "dri3_create_image_khr: unsupported pixmap depth");
> +      free(bp_reply);
> +      return EGL_NO_IMAGE_KHR;
> +   }
> +
> +   dri2_img = malloc(sizeof *dri2_img);
> +   if (!dri2_img) {
> +      _eglError(EGL_BAD_ALLOC, "dri3_create_image_khr");
> +      free(bp_reply);
> +      return EGL_NO_IMAGE_KHR;
> +   }
> +
> +   _eglInitImage(&dri2_img->base, disp);
> +
> +   dri2_img->dri_image = loader_dri3_create_image_from_
> buffers(dri2_dpy->conn,
> +                                                               bp_reply,
> +                                                               format,
> +
>  dri2_dpy->dri_screen,
> +
>  dri2_dpy->image,
> +                                                               dri2_img);
> +   free(bp_reply);
> +
> +   if (!dri2_img->dri_image) {
> +      _eglError(EGL_BAD_ATTRIBUTE, "dri3_create_image_khr");
> +      free(dri2_img);
> +      return EGL_NO_IMAGE_KHR;
> +   }
> +
> +   return &dri2_img->base;
> +}
> +#endif
> +
>  static _EGLImage *
>  dri3_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
>                        _EGLContext *ctx, EGLenum target,
>                        EGLClientBuffer buffer, const EGLint *attr_list)
>  {
> +   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
> +
>     switch (target) {
>     case EGL_NATIVE_PIXMAP_KHR:
> +#if XCB_DRI3_MAJOR_VERSION > 1 || (XCB_DRI3_MAJOR_VERSION == 1 &&
> XCB_DRI3_MINOR_VERSION >= 1)
> +      if (dri2_dpy->multibuffers_available)
> +         return dri3_create_image_khr_pixmap_from_buffers(disp, ctx,
> buffer,
> +                                                          attr_list);
> +#endif
>        return dri3_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
>     default:
>        return dri2_create_image_khr(drv, disp, ctx, target, buffer,
> attr_list);
> @@ -471,6 +543,9 @@ dri3_x11_connect(struct dri2_egl_display *dri2_dpy)
>        free(error);
>        return EGL_FALSE;
>     }
> +
> +   dri2_dpy->dri3_major_version = dri3_query->major_version;
> +   dri2_dpy->dri3_minor_version = dri3_query->minor_version;
>     free(dri3_query);
>
>     present_query =
> diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c
> index f280a8cef77..931912f9430 100644
> --- a/src/glx/dri3_glx.c
> +++ b/src/glx/dri3_glx.c
> @@ -346,7 +346,10 @@ dri3_create_drawable(struct glx_screen *base, XID
> xDrawable,
>  {
>     struct dri3_drawable *pdraw;
>     struct dri3_screen *psc = (struct dri3_screen *) base;
> +   const struct dri3_display *const pdp = (struct dri3_display *)
> +      base->display->dri3Display;
>     __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
> +   bool has_multibuffer = false;
>
>     pdraw = calloc(1, sizeof(*pdraw));
>     if (!pdraw)
> @@ -357,11 +360,16 @@ dri3_create_drawable(struct glx_screen *base, XID
> xDrawable,
>     pdraw->base.drawable = drawable;
>     pdraw->base.psc = &psc->base;
>
> +   if ((psc->image && psc->image->base.version >= 15) &&
> +       (pdp->dri3Major > 1 || (pdp->dri3Major == 1 && pdp->dri3Minor >=
> 1)))
> +      has_multibuffer = true;
> +
>     (void) __glXInitialize(psc->base.dpy);
>
>     if (loader_dri3_drawable_init(XGetXCBConnection(base->dpy),
>                                   xDrawable, psc->driScreen,
> -                                 psc->is_different_gpu, config->driConfig,
> +                                 psc->is_different_gpu, has_multibuffer,
> +                                 config->driConfig,
>                                   &psc->loader_dri3_ext, &glx_dri3_vtable,
>                                   &pdraw->loader_drawable)) {
>        free(pdraw);
> diff --git a/src/loader/loader_dri3_helper.c b/src/loader/loader_dri3_
> helper.c
> index 2912bb6749b..038216c2637 100644
> --- a/src/loader/loader_dri3_helper.c
> +++ b/src/loader/loader_dri3_helper.c
> @@ -24,6 +24,7 @@
>  #include <fcntl.h>
>  #include <stdlib.h>
>  #include <unistd.h>
> +#include <string.h>
>
>  #include <X11/xshmfence.h>
>  #include <xcb/xcb.h>
> @@ -256,6 +257,7 @@ loader_dri3_drawable_init(xcb_connection_t *conn,
>                            xcb_drawable_t drawable,
>                            __DRIscreen *dri_screen,
>                            bool is_different_gpu,
> +                          bool multiplanes_available,
>                            const __DRIconfig *dri_config,
>                            struct loader_dri3_extensions *ext,
>                            const struct loader_dri3_vtable *vtable,
> @@ -273,6 +275,7 @@ loader_dri3_drawable_init(xcb_connection_t *conn,
>     draw->drawable = drawable;
>     draw->dri_screen = dri_screen;
>     draw->is_different_gpu = is_different_gpu;
> +   draw->multiplanes_available = multiplanes_available;
>
>     draw->have_back = 0;
>     draw->have_fake_front = 0;
> @@ -1024,6 +1027,42 @@ image_format_to_fourcc(int format)
>     return 0;
>  }
>
> +static bool
> +has_supported_modifier(struct loader_dri3_drawable *draw, unsigned int
> format,
> +                       uint64_t *modifiers, uint32_t count)
> +{
> +   uint64_t *supported_modifiers;
> +   int32_t supported_modifiers_count;
> +   int i, j;
> +
> +   if (!draw->ext->image->queryDmaBufModifiers(draw->dri_screen,
> +                                               format, 0, NULL, NULL,
> +
>  &supported_modifiers_count) ||
> +       supported_modifiers_count == 0)
> +      return false;
> +
> +   supported_modifiers = malloc(supported_modifiers_count *
> sizeof(uint64_t));
> +   if (!supported_modifiers)
> +      return false;
> +
> +   draw->ext->image->queryDmaBufModifiers(draw->dri_screen, format,
> +                                          supported_modifiers_count,
> +                                          supported_modifiers, NULL,
> +                                          &supported_modifiers_count);
> +
> +   for (i = 0; i < supported_modifiers_count; i++) {
> +      for (j = 0; j < count; j++) {
> +         if (supported_modifiers[i] == modifiers[j]) {
> +            free(supported_modifiers);
> +            return true;
> +         }
> +      }
> +   }
> +
> +   free(supported_modifiers);
> +   return false;
>

We could make the cleanup path a bit nicer if we did something like this:

bool found = false;
for (...) {
   if (...) {
      found = true;
      break;
   }
}

free(...);
return found;

That would mean we only have one free.  I don't really care all that much
though as the current code is correct.


> +}
> +
>  /** loader_dri3_alloc_render_buffer
>   *
>   * Use the driver createImage function to construct a __DRIimage, then
> @@ -1040,8 +1079,10 @@ dri3_alloc_render_buffer(struct
> loader_dri3_drawable *draw, unsigned int format,
>     xcb_pixmap_t pixmap;
>     xcb_sync_fence_t sync_fence;
>     struct xshmfence *shm_fence;
> -   int buffer_fd, fence_fd;
> -   int stride;
> +   int buffer_fds[4], fence_fd;
> +   int num_planes = 0;
> +   int i, mod;
> +   int ret;
>
>     /* Create an xshmfence object and
>      * prepare to send that to the X server
> @@ -1066,13 +1107,81 @@ dri3_alloc_render_buffer(struct
> loader_dri3_drawable *draw, unsigned int format,
>        goto no_image;
>
>     if (!draw->is_different_gpu) {
> -      buffer->image = draw->ext->image->createImage(draw->dri_screen,
> -                                                    width, height,
> -                                                    format,
> -                                                    __DRI_IMAGE_USE_SHARE
> |
> -
> __DRI_IMAGE_USE_SCANOUT |
> -
> __DRI_IMAGE_USE_BACKBUFFER,
> -                                                    buffer);
> +#if XCB_DRI3_MAJOR_VERSION > 1 || (XCB_DRI3_MAJOR_VERSION == 1 &&
> XCB_DRI3_MINOR_VERSION >= 1)
> +      if (draw->multiplanes_available &&
> +          draw->ext->image->base.version >= 15 &&
> +          draw->ext->image->queryDmaBufModifiers &&
> +          draw->ext->image->createImageWithModifiers) {
> +         xcb_dri3_get_supported_modifiers_cookie_t mod_cookie;
> +         xcb_dri3_get_supported_modifiers_reply_t *mod_reply;
> +         xcb_generic_error_t *error = NULL;
> +         uint64_t *modifiers = NULL;
> +         uint32_t count = 0;
> +
> +         mod_cookie = xcb_dri3_get_supported_modifiers(draw->conn,
> +                                                       draw->drawable,
> +                                                       depth, buffer->cpp
> * 8);
> +         mod_reply = xcb_dri3_get_supported_modifiers_reply(draw->conn,
> +                                                            mod_cookie,
> +                                                            &error);
> +         if (!mod_reply)
> +            goto no_image;
> +
> +         if (mod_reply->num_drawable_modifiers) {
> +            count = mod_reply->num_drawable_modifiers;
> +            modifiers = malloc(count * sizeof(uint64_t));
> +            if (!modifiers) {
> +               free(mod_reply);
> +               goto no_image;
> +            }
> +
> +            memcpy(modifiers,
> +                   xcb_dri3_get_supported_modifiers_drawable_modifiers(
> mod_reply),
> +                   count * sizeof(uint64_t));
>

Dumb question, but why do we need to memcpy?  Can't we just pass these
directly into createImageWithModifiers so long as we don't free mod_reply
until after it returns?


> +
> +            if (!has_supported_modifier(draw,
> image_format_to_fourcc(format),
> +                                        modifiers, count)) {
> +               free(modifiers);
> +               count = 0;
> +               modifiers = NULL;
> +            }
> +         }
> +
> +         if (mod_reply->num_screen_modifiers && modifiers == NULL) {
> +            count = mod_reply->num_screen_modifiers;
> +            modifiers = malloc(count * sizeof(uint64_t));
> +            if (!modifiers) {
> +               free(modifiers);
> +               free(mod_reply);
> +               goto no_image;
> +            }
> +
> +            memcpy(modifiers,
> +                   xcb_dri3_get_supported_modifiers_screen_modifiers(
> mod_reply),
> +                   count * sizeof(uint64_t));
> +         }
> +
> +         free(mod_reply);
> +
> +         buffer->image = draw->ext->image->createImageWithModifiers(draw-
> >dri_screen,
> +
> width, height,
> +
> format,
> +
> modifiers,
> +                                                                    count,
> +
> buffer);
> +         free(modifiers);
> +      }
> +#endif
> +
> +      if (!buffer->image)
> +         buffer->image = draw->ext->image->createImage(draw->dri_screen,
> +                                                       width, height,
> +                                                       format,
> +
>  __DRI_IMAGE_USE_SHARE |
> +
>  __DRI_IMAGE_USE_SCANOUT |
> +
>  __DRI_IMAGE_USE_BACKBUFFER,
> +                                                       buffer);
> +
>        pixmap_buffer = buffer->image;
>
>        if (!buffer->image)
> @@ -1100,25 +1209,71 @@ dri3_alloc_render_buffer(struct
> loader_dri3_drawable *draw, unsigned int format,
>           goto no_linear_buffer;
>     }
>
> -   /* X wants the stride, so ask the image for it
> +   /* X want some information about the planes, so ask the image for it
>      */
> -   if (!draw->ext->image->queryImage(pixmap_buffer,
> __DRI_IMAGE_ATTRIB_STRIDE,
> -                                     &stride))
> -      goto no_buffer_attrib;
> +   if (!draw->ext->image->queryImage(pixmap_buffer,
> __DRI_IMAGE_ATTRIB_NUM_PLANES,
> +                                     &num_planes))
> +      num_planes = 1;
>
> -   buffer->pitch = stride;
> +   for (i = 0; i < num_planes; i++) {
> +      __DRIimage *image = draw->ext->image->fromPlanar(pixmap_buffer, i,
> NULL);
>
> -   if (!draw->ext->image->queryImage(pixmap_buffer,
> __DRI_IMAGE_ATTRIB_FD,
> -                                     &buffer_fd))
> -      goto no_buffer_attrib;
> +      if (!image) {
> +         assert(i == 0);
> +         image = pixmap_buffer;
> +      }
>
> -   xcb_dri3_pixmap_from_buffer(draw->conn,
> -                               (pixmap = xcb_generate_id(draw->conn)),
> -                               draw->drawable,
> -                               buffer->size,
> -                               width, height, buffer->pitch,
> -                               depth, buffer->cpp * 8,
> -                               buffer_fd);
> +      ret = draw->ext->image->queryImage(image, __DRI_IMAGE_ATTRIB_FD,
> +                                         &buffer_fds[i]);
> +      ret &= draw->ext->image->queryImage(image,
> __DRI_IMAGE_ATTRIB_STRIDE,
> +                                          &buffer->strides[i]);
> +      ret &= draw->ext->image->queryImage(image,
> __DRI_IMAGE_ATTRIB_OFFSET,
> +                                          &buffer->offsets[i]);
> +      if (image != pixmap_buffer)
> +         draw->ext->image->destroyImage(image);
> +
> +      if (!ret)
> +         goto no_buffer_attrib;
> +   }
> +
> +   ret = draw->ext->image->queryImage(pixmap_buffer,
> +                                     __DRI_IMAGE_ATTRIB_MODIFIER_UPPER,
> &mod);
> +   buffer->modifier = (uint64_t) mod << 32;
> +   ret &= draw->ext->image->queryImage(pixmap_buffer,
> +                                       __DRI_IMAGE_ATTRIB_MODIFIER_LOWER,
> &mod);
> +   buffer->modifier |= (uint64_t)(mod & 0xffffffff);
> +
> +   if (!ret)
> +      buffer->modifier = DRM_FORMAT_MOD_INVALID;
> +
> +   pixmap = xcb_generate_id(draw->conn);
> +#if XCB_DRI3_MAJOR_VERSION > 1 || (XCB_DRI3_MAJOR_VERSION == 1 &&
> XCB_DRI3_MINOR_VERSION >= 1)
> +   if (draw->multiplanes_available &&
> +       buffer->modifier != DRM_FORMAT_MOD_INVALID) {
>

I made a similar comment on the Wayland one but buffer->modifier != INVALID
should imply multiplanes_available.  We should make multiplanes_available
an assert.


> +      xcb_dri3_pixmap_from_buffers(draw->conn,
> +                                   pixmap,
> +                                   draw->drawable,
> +                                   num_planes,
> +                                   width, height,
> +                                   buffer->strides[0], buffer->offsets[0],
> +                                   buffer->strides[1], buffer->offsets[1],
> +                                   buffer->strides[2], buffer->offsets[2],
> +                                   buffer->strides[3], buffer->offsets[3],
> +                                   depth, buffer->cpp * 8,
> +                                   buffer->modifier,
> +                                   buffer_fds);
> +   }
> +   else
> +#endif
> +   {
> +      xcb_dri3_pixmap_from_buffer(draw->conn,
> +                                  pixmap,
> +                                  draw->drawable,
> +                                  buffer->size,
> +                                  width, height, buffer->strides[0],
> +                                  depth, buffer->cpp * 8,
> +                                  buffer_fds[0]);
> +   }
>
>     xcb_dri3_fence_from_fd(draw->conn,
>                            pixmap,
> @@ -1140,6 +1295,9 @@ dri3_alloc_render_buffer(struct
> loader_dri3_drawable *draw, unsigned int format,
>     return buffer;
>
>  no_buffer_attrib:
> +   do {
> +      close(buffer_fds[i]);
> +   } while (--i >= 0);
>     draw->ext->image->destroyImage(pixmap_buffer);
>  no_linear_buffer:
>     if (draw->is_different_gpu)
> @@ -1296,6 +1454,50 @@ loader_dri3_create_image(xcb_connection_t *c,
>     return ret;
>  }
>
> +#if XCB_DRI3_MAJOR_VERSION > 1 || (XCB_DRI3_MAJOR_VERSION == 1 &&
> XCB_DRI3_MINOR_VERSION >= 1)
> +__DRIimage *
> +loader_dri3_create_image_from_buffers(xcb_connection_t *c,
> +                                      xcb_dri3_buffers_from_pixmap_reply_t
> *bp_reply,
> +                                      unsigned int format,
> +                                      __DRIscreen *dri_screen,
> +                                      const __DRIimageExtension *image,
> +                                      void *loaderPrivate)
> +{
> +   __DRIimage                           *ret;
> +   int                                  *fds;
> +   uint32_t                             *strides_in, *offsets_in;
> +   int                                   strides[4], offsets[4];
> +   unsigned                              error;
> +   int                                   i;
> +
> +   if (bp_reply->nfd > 4)
> +      return NULL;
> +
> +   fds = xcb_dri3_buffers_from_pixmap_reply_fds(c, bp_reply);
> +   strides_in = xcb_dri3_buffers_from_pixmap_strides(bp_reply);
> +   offsets_in = xcb_dri3_buffers_from_pixmap_offsets(bp_reply);
> +   for (i = 0; i < bp_reply->nfd; i++) {
> +      strides[i] = strides_in[i];
> +      offsets[i] = offsets_in[i];
> +   }
> +
> +   ret = image->createImageFromDmaBufs2(dri_screen,
> +                                        bp_reply->width,
> +                                        bp_reply->height,
> +                                        image_format_to_fourcc(format),
> +                                        bp_reply->modifier,
> +                                        fds, bp_reply->nfd,
> +                                        strides, offsets,
> +                                        0, 0, 0, 0, /* UNDEFINED */
> +                                        &error, loaderPrivate);
> +
> +   for (i = 0; i < bp_reply->nfd; i++)
> +      close(fds[i]);
> +
> +   return ret;
> +}
> +#endif
> +
>  /** dri3_get_pixmap_buffer
>   *
>   * Get the DRM object for a pixmap from the X server and
> @@ -1309,10 +1511,10 @@ dri3_get_pixmap_buffer(__DRIdrawable
> *driDrawable, unsigned int format,
>     int                                  buf_id =
> loader_dri3_pixmap_buf_id(buffer_type);
>     struct loader_dri3_buffer            *buffer = draw->buffers[buf_id];
>     xcb_drawable_t                       pixmap;
> -   xcb_dri3_buffer_from_pixmap_cookie_t bp_cookie;
> -   xcb_dri3_buffer_from_pixmap_reply_t  *bp_reply;
>     xcb_sync_fence_t                     sync_fence;
>     struct xshmfence                     *shm_fence;
> +   int                                  width;
> +   int                                  height;
>     int                                  fence_fd;
>
>     if (buffer)
> @@ -1339,32 +1541,60 @@ dri3_get_pixmap_buffer(__DRIdrawable
> *driDrawable, unsigned int format,
>                            false,
>                            fence_fd);
>
> -   bp_cookie = xcb_dri3_buffer_from_pixmap(draw->conn, pixmap);
> -   bp_reply = xcb_dri3_buffer_from_pixmap_reply(draw->conn, bp_cookie,
> NULL);
> -   if (!bp_reply)
> -      goto no_image;
> +#if XCB_DRI3_MAJOR_VERSION > 1 || (XCB_DRI3_MAJOR_VERSION == 1 &&
> XCB_DRI3_MINOR_VERSION >= 1)
> +   if (draw->multiplanes_available &&
> +       draw->ext->image->base.version >= 15 &&
> +       draw->ext->image->createImageFromDmaBufs2) {
> +      xcb_dri3_buffers_from_pixmap_cookie_t bps_cookie;
> +      xcb_dri3_buffers_from_pixmap_reply_t *bps_reply;
> +
> +      bps_cookie = xcb_dri3_buffers_from_pixmap(draw->conn, pixmap);
> +      bps_reply = xcb_dri3_buffers_from_pixmap_reply(draw->conn,
> bps_cookie,
> +                                                     NULL);
> +      if (!bps_reply)
> +         goto no_image;
> +      buffer->image =
> +         loader_dri3_create_image_from_buffers(draw->conn, bps_reply,
> format,
> +                                               draw->dri_screen,
> +                                               draw->ext->image,
> +                                               buffer);
> +      width = bps_reply->width;
> +      height = bps_reply->height;
> +      free(bps_reply);
> +   } else
> +#endif
>

I really don't like mising preprocessor and C control-flow like this.  I
made a suggestion on the previous version.  If there's nothing better to
do, then I can live with it.


> +   {
> +      xcb_dri3_buffer_from_pixmap_cookie_t bp_cookie;
> +      xcb_dri3_buffer_from_pixmap_reply_t *bp_reply;
> +
> +      bp_cookie = xcb_dri3_buffer_from_pixmap(draw->conn, pixmap);
> +      bp_reply = xcb_dri3_buffer_from_pixmap_reply(draw->conn,
> bp_cookie, NULL);
> +      if (!bp_reply)
> +         goto no_image;
> +
> +      buffer->image = loader_dri3_create_image(draw->conn, bp_reply,
> format,
> +                                               draw->dri_screen,
> +                                               draw->ext->image, buffer);
> +      width = bp_reply->width;
> +      height = bp_reply->height;
> +      free(bp_reply);
> +   }
>
> -   buffer->image = loader_dri3_create_image(draw->conn, bp_reply, format,
> -                                            draw->dri_screen,
> draw->ext->image,
> -                                            buffer);
>     if (!buffer->image)
>        goto no_image;
>
>     buffer->pixmap = pixmap;
>     buffer->own_pixmap = false;
> -   buffer->width = bp_reply->width;
> -   buffer->height = bp_reply->height;
> +   buffer->width = width;
> +   buffer->height = height;
>     buffer->shm_fence = shm_fence;
>     buffer->sync_fence = sync_fence;
>
>     draw->buffers[buf_id] = buffer;
>
> -   free(bp_reply);
> -
>     return buffer;
>
>  no_image:
> -   free(bp_reply);
>     xcb_sync_destroy_fence(draw->conn, sync_fence);
>     xshmfence_unmap_shm(shm_fence);
>  no_fence:
> diff --git a/src/loader/loader_dri3_helper.h b/src/loader/loader_dri3_
> helper.h
> index 4ce98b8c59f..5689e2707c5 100644
> --- a/src/loader/loader_dri3_helper.h
> +++ b/src/loader/loader_dri3_helper.h
> @@ -62,8 +62,11 @@ struct loader_dri3_buffer {
>     bool         busy;           /* Set on swap, cleared on IdleNotify */
>     bool         own_pixmap;     /* We allocated the pixmap ID, free on
> destroy */
>
> +   uint32_t     num_planes;
>     uint32_t     size;
> -   uint32_t     pitch;
> +   int          strides[4];
> +   int          offsets[4];
> +   uint64_t     modifier;
>     uint32_t     cpp;
>     uint32_t     flags;
>     uint32_t     width, height;
> @@ -120,6 +123,7 @@ struct loader_dri3_drawable {
>     /* Information about the GPU owning the buffer */
>     __DRIscreen *dri_screen;
>     bool is_different_gpu;
> +   bool multiplanes_available;
>
>     /* Present extension capabilities
>      */
> @@ -179,6 +183,7 @@ loader_dri3_drawable_init(xcb_connection_t *conn,
>                            xcb_drawable_t drawable,
>                            __DRIscreen *dri_screen,
>                            bool is_different_gpu,
> +                          bool is_multiplanes_available,
>                            const __DRIconfig *dri_config,
>                            struct loader_dri3_extensions *ext,
>                            const struct loader_dri3_vtable *vtable,
> @@ -236,6 +241,16 @@ loader_dri3_create_image(xcb_connection_t *c,
>                           const __DRIimageExtension *image,
>                           void *loaderPrivate);
>
> +#if XCB_DRI3_MAJOR_VERSION > 1 || (XCB_DRI3_MAJOR_VERSION == 1 &&
> XCB_DRI3_MINOR_VERSION >= 1)
> +__DRIimage *
> +loader_dri3_create_image_from_buffers(xcb_connection_t *c,
> +                                      xcb_dri3_buffers_from_pixmap_reply_t
> *bp_reply,
> +                                      unsigned int format,
> +                                      __DRIscreen *dri_screen,
> +                                      const __DRIimageExtension *image,
> +                                      void *loaderPrivate);
> +#endif
> +
>  int
>  loader_dri3_get_buffers(__DRIdrawable *driDrawable,
>                          unsigned int format,
> --
> 2.14.3
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20180215/72c76b93/attachment-0001.html>


More information about the mesa-dev mailing list