[Mesa-dev] [PATCH 07/16] RFC: egl/x11: Support DRI3 v1.1
Jason Ekstrand
jason at jlekstrand.net
Sat Feb 10 00:24:50 UTC 2018
On Fri, Feb 9, 2018 at 3:43 PM, Jason Ekstrand <jason at jlekstrand.net> 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>
> ---
> src/egl/drivers/dri2/egl_dri2.c | 7 +
> src/egl/drivers/dri2/egl_dri2.h | 3 +
> src/egl/drivers/dri2/platform_x11_dri3.c | 104 ++++++++++--
> src/glx/dri3_glx.c | 10 +-
> src/loader/loader_dri3_helper.c | 272
> ++++++++++++++++++++++++++-----
> src/loader/loader_dri3_helper.h | 17 +-
> 6 files changed, 358 insertions(+), 55 deletions(-)
>
> diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_
> dri2.c
> index 34cdb9f..8147842 100644
> --- a/src/egl/drivers/dri2/egl_dri2.c
> +++ b/src/egl/drivers/dri2/egl_dri2.c
> @@ -885,6 +885,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 0f4e7a8..bff33df 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 6e40eaa..0532cd3 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);
> @@ -302,13 +309,77 @@ 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;
> + }
> +
> + dri2_img = malloc(sizeof *dri2_img);
> + if (!dri2_img) {
>
You need to free bp_reply
> + _eglError(EGL_BAD_ALLOC, "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);
>
You need to free dri2_img
> + 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);
> @@ -470,6 +541,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 f280a8c..931912f 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) &&
>
Should we check for some image functions as well? In particular,
createImageWithModifiers and queryDmaBufModifiers.
> + (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 2912bb6..80a4497 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>
> @@ -40,6 +41,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
>
The copy of drm_fourcc.h we have in mesa has this now.
> +
> /**
> * A cached blit context.
> */
> @@ -256,6 +261,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 +279,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;
> @@ -1040,8 +1047,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 +1075,80 @@ 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 >= 19 &&
> + draw->ext->image->queryDmaBufModifiers &&
> + draw->ext->image->createImageWithModifiers2) {
>
Ok, I guess we do some extra checks here. Maybe that's sufficient.
> + 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[2] = {NULL, NULL};
> + uint32_t counts[2] = {0, 0};
> + uint32_t n = 0;
> + int i;
> +
> + 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) {
+ counts[n] = mod_reply->num_drawable_modifiers;
> + modifiers[n] = malloc(counts[n] * sizeof(uint64_t));
> + if (!modifiers[n]) {
> + free(mod_reply);
> + goto no_image;
> + }
> +
> + memcpy(modifiers[n],
> + xcb_dri3_get_supported_modifiers_drawable_modifiers(
> mod_reply),
> + counts[n] * sizeof(uint64_t));
> + n++;
> + }
> +
> + if (mod_reply->num_screen_modifiers) {
> + counts[n] = mod_reply->num_screen_modifiers;
> + modifiers[n] = malloc(counts[n] * sizeof(uint64_t));
> + if (!modifiers[n]) {
> + free(modifiers[0]);
>
The use of the modifiers array all the way through with the n counter is
desceptively general. Since you have free(modifiers[0]) here no one can
just insert another modifiers list get in between even though it looks like
they can. I think it would be clearer if we just had separate
drawable_modifiers and screen_modifiers variables and put them into an
array right before the createImageWithModifiers.
> + free(mod_reply);
> + goto no_image;
> + }
> +
> + memcpy(modifiers[n],
> + xcb_dri3_get_supported_modifiers_screen_modifiers(
> mod_reply),
> + counts[n] * sizeof(uint64_t));
> + n++;
> + }
> +
> + free(mod_reply);
> +
> + buffer->image = draw->ext->image->createImageWithModifiers2(
> draw->dri_screen,
> +
> width, height,
> +
> format,
> +
> modifiers,
> +
> counts,
> + n,
> +
> buffer);
> + for (i = 0; i < n; i++)
> + free(modifiers[i]);
>
You don't relaly need the n here because free(NULL) is safe.
> + }
> +#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 +1176,72 @@ 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;
> + draw->ext->image->queryImage(pixmap_buffer,
> __DRI_IMAGE_ATTRIB_NUM_PLANES,
> + &num_planes);
> + if (num_planes <= 0)
> + num_planes = 1;
>
Do we want this based on num_planes <= 0 or the return value of
queryImage? I think either probably works.
>
> - 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;
> + }
> +
> + 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;
> + }
>
> - 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(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) {
> + 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
>
This #define is gross. I don't mind #ifs but when preprocessor and
language control flow aren't properly nested, you're just asking for
problems. Perhaps the best thing to do would be to leave the entire if
outside the #if and then do
#if ...
xcb_dri3_pixmap_from_buffers(...);
#else
unreachable("DRI3 v1.1 or greater is required for modifiers");
#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 +1263,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);
>
You could also do
while (i >= 0)
close(buffer_fds[i--]);
I don't know which is more readable. Meh.
> draw->ext->image->destroyImage(pixmap_b
uffer);
> no_linear_buffer:
> if (draw->is_different_gpu)
> @@ -1296,6 +1422,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 +1479,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 +1509,58 @@ 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)
>
Same comment about this #if.
> + 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);
> + 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
> + {
> + 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 4ce98b8..5689e27 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.5.0.400.gff86faf
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20180209/76d404d0/attachment-0001.html>
More information about the mesa-dev
mailing list