[Mesa-dev] [RFC 01/22] RFC: egl/x11: Support DRI3 v1.1

Emil Velikov emil.l.velikov at gmail.com
Tue Jun 20 14:19:08 UTC 2017


Hi Daniel,

Top-level comments

Build POV:
- Having the XCB_DRI3_.*_VERSION compile guards is Ok for now. But
let's drop those as get a xcb release.
We dont want to be in cases where Mesa is built w/o DRI3 1.1 support
and one spends time debugging why "nothing works".

Couple of ideas/questions from the protocol POV:
- Do we want to send color_space, sample_range, horiz_siting or
vert_siting information over the wire?
- Considering we know the number of planes, one could simply pass a
pointer to the strides/offsets, instead of passing each one explicitly
(re: xcb_dri3_pixmap_from_buffers)


Everything else is quite minor, although there's quite a few nitpicks.

On 8 June 2017 at 19:43, 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: Daniel Stone <daniels at collabora.com>
> ---
>  src/egl/drivers/dri2/egl_dri2.c          |   3 +
>  src/egl/drivers/dri2/egl_dri2.h          |   1 +
>  src/egl/drivers/dri2/platform_x11_dri3.c |  62 +++++++-
>  src/glx/dri3_glx.c                       |  10 +-
>  src/loader/loader_dri3_helper.c          | 250 +++++++++++++++++++++++++------
>  src/loader/loader_dri3_helper.h          |  16 +-
>  6 files changed, 293 insertions(+), 49 deletions(-)
>
> diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
> index 7175e827c9..5b0799fcc4 100644
> --- a/src/egl/drivers/dri2/egl_dri2.c
> +++ b/src/egl/drivers/dri2/egl_dri2.c
> @@ -804,6 +804,9 @@ dri2_setup_extensions(_EGLDisplay *disp)
>     if (!dri2_bind_extensions(dri2_dpy, mandatory_core_extensions, extensions, false))
>        return EGL_FALSE;
>
> +   dri2_dpy->multibuffers_available &=
> +      (dri2_dpy->image && dri2_dpy->image->base.version >= 15);
> +
Store dri3major/minor and set the variable at once (like we do for
egl/dri2 and in glx) or try Eric's suggestions?

>     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 a71b4489cd..a1a676d867 100644
> --- a/src/egl/drivers/dri2/egl_dri2.h
> +++ b/src/egl/drivers/dri2/egl_dri2.h
> @@ -194,6 +194,7 @@ struct dri2_egl_display
>     xcb_screen_t             *screen;
>     int                      swap_available;
>  #ifdef HAVE_DRI3
> +   int                      multibuffers_available;
Please make this bool. Eric has just addressed all the other
int-pretending-to-be-bool variables.

>     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 041da3208d..0db2d7872a 100644
> --- a/src/egl/drivers/dri2/platform_x11_dri3.c
> +++ b/src/egl/drivers/dri2/platform_x11_dri3.c
> @@ -198,7 +198,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)) {
> @@ -344,15 +346,71 @@ dri3_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
>     return &dri2_img->base;
>  }
>
> +#if XCB_DRI3_MAJOR_VERSION > 1 || XCB_DRI3_MINOR_VERSION >= 1
While we will nuke these before 2.1 comes about, let's be more
explicit and check for "major || (major && minor)".
The run-time checks are more important and should be updated as well.

> +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;
> +
> +   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_ALLOC, "xcb_dri3_buffer_from_pixmap");
> +      return NULL;
Error message and return value differs with the cases below - please
unify. Leaning slightly towards the below examples.

> +   }
> +
> +   dri2_img = malloc(sizeof *dri2_img);
> +   if (!dri2_img) {
> +      _eglError(EGL_BAD_ALLOC, "dri3_create_image_khr");
> +      return EGL_NO_IMAGE_KHR;
> +   }
> +
> +   if (!_eglInitImage(&dri2_img->base, disp)) {
Unrelated: I could swear I nuked the return type of _eglInitImage().
Patches coming in a second.

> +      free(dri2_img);
> +      return EGL_NO_IMAGE_KHR;
> +   }
> +
> +   dri2_img->dri_image = loader_dri3_create_image_from_buffers(dri2_dpy->conn,
> +                                                               bp_reply,
> +                                                               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)
>  {
>     (void) drv;
> +   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
Compiler will flag as set-but-unused variable, but shouldn't be too annoying.

>
>     switch (target) {
>     case EGL_NATIVE_PIXMAP_KHR:
> +#if 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);
> @@ -504,6 +562,8 @@ dri3_x11_connect(struct dri2_egl_display *dri2_dpy)
>        free(error);
>        return EGL_FALSE;
>     }
> +   dri2_dpy->multibuffers_available = dri3_query->major_version > 1 ||
> +                                      dri3_query->minor_version >= 1;

As mentioned above this should be major || (major && minor)


>     free(dri3_query);
>
>     present_query =
> diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c
> index 509160697f..4b599ef897 100644
> --- a/src/glx/dri3_glx.c
> +++ b/src/glx/dri3_glx.c
> @@ -374,7 +374,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;
> +   int has_multibuffer = 0;
Please use bool + false/true.

>
>     pdraw = calloc(1, sizeof(*pdraw));
>     if (!pdraw)
> @@ -385,11 +388,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->dri3Minor >= 1))
Ditto - ... major > 1 || (major == 1 && minor >= 1)

> +      has_multibuffer = 1;
> +
>     (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 493a7f5218..3908512b9f 100644
> --- a/src/loader/loader_dri3_helper.c
> +++ b/src/loader/loader_dri3_helper.c
> @@ -40,6 +40,10 @@
>  #define DRI_CONF_VBLANK_DEF_INTERVAL_1 2
>  #define DRI_CONF_VBLANK_ALWAYS_SYNC 3
>
> +#ifndef DRM_FORMAT_MOD_INVALID
> +#define DRM_FORMAT_MOD_INVALID ((1ULL<<56) - 1)
> +#endif
> +
>  static inline void
>  dri3_fence_reset(xcb_connection_t *c, struct loader_dri3_buffer *buffer)
>  {
> @@ -128,6 +132,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,
> @@ -145,6 +150,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;
> @@ -814,6 +820,27 @@ dri3_cpp_for_format(uint32_t format) {
>     }
>  }
>
> +/* the DRIimage createImage function takes __DRI_IMAGE_FORMAT codes, while
> + * the createImageFromFds call takes __DRI_IMAGE_FOURCC codes. To avoid
> + * complete confusion, just deal in __DRI_IMAGE_FORMAT codes for now and
> + * translate to __DRI_IMAGE_FOURCC codes in the call to createImageFromFds
> + */
> +static int
> +image_format_to_fourcc(int format)
> +{
> +
> +   /* Convert from __DRI_IMAGE_FORMAT to __DRI_IMAGE_FOURCC (sigh) */
> +   switch (format) {
> +   case __DRI_IMAGE_FORMAT_SARGB8: return __DRI_IMAGE_FOURCC_SARGB8888;
> +   case __DRI_IMAGE_FORMAT_RGB565: return __DRI_IMAGE_FOURCC_RGB565;
> +   case __DRI_IMAGE_FORMAT_XRGB8888: return __DRI_IMAGE_FOURCC_XRGB8888;
> +   case __DRI_IMAGE_FORMAT_ARGB8888: return __DRI_IMAGE_FOURCC_ARGB8888;
> +   case __DRI_IMAGE_FORMAT_ABGR8888: return __DRI_IMAGE_FOURCC_ABGR8888;
> +   case __DRI_IMAGE_FORMAT_XBGR8888: return __DRI_IMAGE_FOURCC_XBGR8888;
> +   }
> +   return 0;
> +}
> +
Keep code motion as separate commit, pretty please.

>  /** loader_dri3_alloc_render_buffer
>   *
>   * Use the driver createImage function to construct a __DRIimage, then
> @@ -830,8 +857,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;
> +   uint32_t fourcc_format;
> +   int num_planes = 0;
> +   int i, mod;
>
>     /* Create an xshmfence object and
>      * prepare to send that to the X server
> @@ -855,14 +884,67 @@ dri3_alloc_render_buffer(struct loader_dri3_drawable *draw, unsigned int format,
>     if (!buffer->cpp)
>        goto no_image;
>
> +   fourcc_format = image_format_to_fourcc(format);
> +   if (!fourcc_format)
> +      goto no_image;
Should be called only in the multiplanes_available case.

> +
>     if (!draw->is_different_gpu) {
> -      buffer->image = draw->ext->image->createImage(draw->dri_screen,
We're about to have 10+ cases of "draw->ext->image" - introduce a
(short) local variable?


> -                                                    width, height,
> -                                                    format,
> -                                                    __DRI_IMAGE_USE_SHARE |
> -                                                    __DRI_IMAGE_USE_SCANOUT |
> -                                                    __DRI_IMAGE_USE_BACKBUFFER,
> -                                                    buffer);
> +#if 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) {
Wondering if we should nuke the >= 15 piece (here or in the callers)
or keep it everywhere for clarity.

> +         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 *mod_parts;
> +         int i, count;
num_modifiers is uint32_t - please change the count declaration to be the same.

> +
> +         mod_cookie = xcb_dri3_get_supported_modifiers(draw->conn,
> +                                                       draw->drawable,
> +                                                       fourcc_format);
> +         mod_reply = xcb_dri3_get_supported_modifiers_reply(draw->conn,
> +                                                            mod_cookie,
> +                                                            &error);
> +         if (!mod_reply)
> +            goto no_image;
> +
> +         count = mod_reply->num_modifiers;
> +         if (count) {
> +            modifiers = malloc(count * sizeof(uint64_t));
> +            if (!modifiers) {
> +               free(mod_reply);
> +               goto no_image;
> +            }
> +
> +            mod_parts = xcb_dri3_get_supported_modifiers_modifiers(mod_reply);
I take it this function cannot fail, or we simply don't bother with
such cases elsewhere?

> +            for (i = 0; i < count; i++) {
> +               modifiers[i] = (uint64_t) mod_parts[i * 2] << 32;
> +               modifiers[i] |= (uint64_t) mod_parts[i * 2 + 1] & 0xffffff;
> +            }
> +         }
> +
> +         free(mod_reply);
> +
> +         buffer->image = draw->ext->image->createImageWithModifiers(draw->dri_screen,
> +                                                                    width, height,
> +                                                                    format,
> +                                                                    modifiers, count,
> +                                                                    buffer);
> +         free(modifiers);
> +      }
> +#endif
> +
> +      if (!buffer->image)
Does not align with all the error paths above. There we bail out, yet
here we fall-back to the old extension.
Perhaps change the former to come here? One could even more that whole
hunk into a separate function.

> +         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)
> @@ -890,25 +972,82 @@ 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;
> -
> -   buffer->pitch = stride;
> +   draw->ext->image->queryImage(pixmap_buffer, __DRI_IMAGE_ATTRIB_NUM_PLANES,
> +                                &num_planes);
> +   if (num_planes <= 0)
> +      num_planes = 1;
> +
> +   for (i = 0; i < num_planes; i++) {
> +      __DRIimage *image = draw->ext->image->fromPlanar(pixmap_buffer, i, NULL);
> +      int ret;
> +      if (!image)
> +         image = pixmap_buffer;

> +      ret = draw->ext->image->queryImage(image, __DRI_IMAGE_ATTRIB_FD,
> +                                         &buffer_fds[i]);
> +      if (!ret) {
> +         if (image != pixmap_buffer)
> +            draw->ext->image->destroyImage(image);
> +         goto no_buffer_attrib;
> +      }
> +      ret = draw->ext->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE,
> +                                         &buffer->strides[i]);
> +      if (!ret) {
> +         if (image != pixmap_buffer)
> +            draw->ext->image->destroyImage(image);
> +         goto no_buffer_attrib;
> +      }
Bikeshed, yet it should make the code shorter/easier to read.

    ret = queryImage(... _FD, &foo);
    ret &= queryImage(... _STRIDE, &bar);
    if !ret {
        if (image != pixmap_buffer)
            destroyImage(image);
        goto no_buffer_attrib;
    }



> +      ret = draw->ext->image->queryImage(image, __DRI_IMAGE_ATTRIB_OFFSET,
> +                                         &buffer->offsets[i]);
> +      if (!ret)
> +         buffer->offsets[i] = 0;
> +      if (image != pixmap_buffer)
> +         draw->ext->image->destroyImage(image);
> +   }
>
> -   if (!draw->ext->image->queryImage(pixmap_buffer, __DRI_IMAGE_ATTRIB_FD,
> -                                     &buffer_fd))
> -      goto no_buffer_attrib;

> +   if (!draw->ext->image->queryImage(pixmap_buffer,
> +                                     __DRI_IMAGE_ATTRIB_MODIFIER_UPPER,
> +                                     &mod)) {
> +      buffer->modifier = DRM_FORMAT_MOD_INVALID;
> +   } else {
> +      buffer->modifier = (uint64_t) mod << 32;
> +      if (!draw->ext->image->queryImage(pixmap_buffer,
> +                                        __DRI_IMAGE_ATTRIB_MODIFIER_LOWER,
> +                                        &mod)) {
> +         buffer->modifier = DRM_FORMAT_MOD_INVALID;
> +      } else {
> +         buffer->modifier |= (uint64_t)(mod & 0xffffffff);
> +      }
Moar bikeshed:

   ret = query(... UPPER, &mod);
   modifier = (uint64_t) mod << 32;
   ret &= query(... LOWER, &mod);
   modifier = (uint64_t) (mod & 0xffffffff);
   if !ret
      modifier = INVALID;


> +   }
>
> -   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);
> +#if XCB_DRI3_MAJOR_VERSION > 1 || XCB_DRI3_MINOR_VERSION >= 1
> +   if (draw->multiplanes_available) {
This else looks a bit odd. If we fail to manage multiple buffers
above, multiplanes_available will still be true, yet we could have a
DRIImage.
We should track that (modify multiplanes_available/other) and act
accordingly here.

> +      xcb_dri3_pixmap_from_buffers(draw->conn,
> +                                   (pixmap = xcb_generate_id(draw->conn)),
Move the xcb_generate_id() call a few lines above.

> +                                   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],
num_planes

> +                                   fourcc_format,
> +                                   buffer->modifier >> 32,
> +                                   buffer->modifier & 0xffffffff,
> +                                   buffer_fds);
> +   }
> +   else
> +#endif
> +   {
> +      xcb_dri3_pixmap_from_buffer(draw->conn,
> +                                  (pixmap = xcb_generate_id(draw->conn)),
... and simply use "pixmap" here.

> +                                  draw->drawable,
> +                                  buffer->size,
> +                                  width, height, buffer->strides[0],
> +                                  depth, buffer->cpp * 8,
> +                                  buffer_fds[0]);
> +   }
>
>     xcb_dri3_fence_from_fd(draw->conn,
>                            pixmap,
> @@ -930,6 +1069,8 @@ dri3_alloc_render_buffer(struct loader_dri3_drawable *draw, unsigned int format,
>     return buffer;
>
>  no_buffer_attrib:
> +   while (--i >= 0)
> +      close(buffer_fds[i]);
I think Eric is spot on here - it seems like we leak an fd.

>     draw->ext->image->destroyImage(pixmap_buffer);
>  no_linear_buffer:
>     if (draw->is_different_gpu)
> @@ -1037,27 +1178,6 @@ dri3_update_drawable(__DRIdrawable *driDrawable,
>     return true;
>  }
>
> -/* the DRIimage createImage function takes __DRI_IMAGE_FORMAT codes, while
> - * the createImageFromFds call takes __DRI_IMAGE_FOURCC codes. To avoid
> - * complete confusion, just deal in __DRI_IMAGE_FORMAT codes for now and
> - * translate to __DRI_IMAGE_FOURCC codes in the call to createImageFromFds
> - */
> -static int
> -image_format_to_fourcc(int format)
> -{
> -
> -   /* Convert from __DRI_IMAGE_FORMAT to __DRI_IMAGE_FOURCC (sigh) */
> -   switch (format) {
> -   case __DRI_IMAGE_FORMAT_SARGB8: return __DRI_IMAGE_FOURCC_SARGB8888;
> -   case __DRI_IMAGE_FORMAT_RGB565: return __DRI_IMAGE_FOURCC_RGB565;
> -   case __DRI_IMAGE_FORMAT_XRGB8888: return __DRI_IMAGE_FOURCC_XRGB8888;
> -   case __DRI_IMAGE_FORMAT_ARGB8888: return __DRI_IMAGE_FOURCC_ARGB8888;
> -   case __DRI_IMAGE_FORMAT_ABGR8888: return __DRI_IMAGE_FOURCC_ABGR8888;
> -   case __DRI_IMAGE_FORMAT_XBGR8888: return __DRI_IMAGE_FOURCC_XBGR8888;
> -   }
> -   return 0;
> -}
> -
>  __DRIimage *
>  loader_dri3_create_image(xcb_connection_t *c,
>                           xcb_dri3_buffer_from_pixmap_reply_t *bp_reply,
> @@ -1099,6 +1219,44 @@ loader_dri3_create_image(xcb_connection_t *c,
>     return ret;
>  }
>
> +#if 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,
> +                                      __DRIscreen *dri_screen,
> +                                      const __DRIimageExtension *image,
> +                                      void *loaderPrivate)
> +{
> +   int                                  *fds;
> +   uint32_t                             *strides_in, *offsets_in;
> +   int                                   strides[4], offsets[4];
> +   uint64_t                              modifier;
> +   unsigned                              error;
> +   int                                   i;
> +
> +   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++) {
Assert/error/clamp when xcb goes crazy and bp_reply->nfd >= 4?

> +      strides[i] = strides_in[i];
> +      offsets[i] = offsets_in[i];
In hindsight making the DRI interface use uint32_t might have been a
good idea ;-)

> +   }
> +
> +   modifier = (uint64_t) bp_reply->modifier_hi << 32;
> +   modifier |= ((uint64_t) bp_reply->modifier_lo) & 0xffffffff;
> +
> +   return image->createImageFromDmaBufs2(dri_screen,
> +                                         bp_reply->width,
> +                                         bp_reply->height,
> +                                         bp_reply->format,
> +                                         modifier,
> +                                         fds, bp_reply->nfd,
> +                                         strides, offsets,

> +                                         0, 0, 0, 0, /* UNDEFINED */
Question: Should we extend the protocol to provide this information?


> +                                         &error, loaderPrivate);
> +}
> +#endif
> +
>  /** dri3_get_pixmap_buffer
>   *
>   * Get the DRM object for a pixmap from the X server and
> diff --git a/src/loader/loader_dri3_helper.h b/src/loader/loader_dri3_helper.h
> index a865e46355..6bac25e607 100644
> --- a/src/loader/loader_dri3_helper.h
> +++ b/src/loader/loader_dri3_helper.h
> @@ -61,8 +61,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;
> @@ -125,6 +128,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
>      */
> @@ -174,6 +178,7 @@ loader_dri3_drawable_init(xcb_connection_t *conn,
>                            xcb_drawable_t drawable,
>                            __DRIscreen *dri_screen,
>                            bool is_different_gpu,
> +                          bool is_multiplanes_available,
s/is_multiplanes_available/multiplanes_available/ maybe?
FWIW we could/should update the is_different_gpu at a later stage.

Thanks
Emil


More information about the mesa-dev mailing list