From: Louis-Francis Ratté-Boulianne <[email protected]> Use EGL extension EXT_image_dma_buf_modifiers to query supported DMA-BUF formats and modifiers to return to DRI3 clients. The information is cached to avoid having to fetch it again for each new client.
Signed-off-by: Louis-Francis Ratté-Boulianne <[email protected]> Signed-off-by: Daniel Stone <[email protected]> --- dri3/dri3.h | 12 +++++ dri3/dri3_priv.h | 18 +++++++ dri3/dri3_request.c | 13 +++-- dri3/dri3_screen.c | 121 ++++++++++++++++++++++++++++++++++++++++++ glamor/glamor_egl.c | 84 +++++++++++++++++++++++++++++ hw/xwayland/xwayland-glamor.c | 79 +++++++++++++++++++++++++++ hw/xwayland/xwayland.h | 1 + 7 files changed, 325 insertions(+), 3 deletions(-) diff --git a/dri3/dri3.h b/dri3/dri3.h index 7562352ff..40b8474c0 100644 --- a/dri3/dri3.h +++ b/dri3/dri3.h @@ -52,12 +52,24 @@ typedef int (*dri3_fd_from_pixmap_proc) (ScreenPtr screen, CARD16 *stride, CARD32 *size); +typedef int (*dri3_get_formats_proc) (ScreenPtr screen, + CARD32 *num_formats, + CARD32 **formats); + +typedef int (*dri3_get_modifiers_proc) (ScreenPtr screen, + CARD32 format, + CARD32 *num_modifiers, + uint64_t **modifiers); + + typedef struct dri3_screen_info { uint32_t version; dri3_open_proc open; dri3_pixmap_from_fd_proc pixmap_from_fd; dri3_fd_from_pixmap_proc fd_from_pixmap; + dri3_get_formats_proc get_formats; + dri3_get_modifiers_proc get_modifiers; /* Version 1 */ dri3_open_client_proc open_client; diff --git a/dri3/dri3_priv.h b/dri3/dri3_priv.h index e61ef226c..c767f373e 100644 --- a/dri3/dri3_priv.h +++ b/dri3/dri3_priv.h @@ -34,11 +34,22 @@ extern DevPrivateKeyRec dri3_screen_private_key; +typedef struct dri3_dmabuf_format { + CARD32 format; + CARD32 num_modifiers; + CARD32 *modifiers_hi; + CARD32 *modifiers_lo; +} dri3_dmabuf_format_rec, *dri3_dmabuf_format_ptr; + typedef struct dri3_screen_priv { CloseScreenProcPtr CloseScreen; ConfigNotifyProcPtr ConfigNotify; DestroyWindowProcPtr DestroyWindow; + Bool formats_cached; + CARD32 num_formats; + dri3_dmabuf_format_ptr formats; + dri3_screen_info_ptr info; } dri3_screen_priv_rec, *dri3_screen_priv_ptr; @@ -75,4 +86,11 @@ dri3_pixmap_from_fd(PixmapPtr *ppixmap, ScreenPtr screen, int fd, int dri3_fd_from_pixmap(int *pfd, PixmapPtr pixmap, CARD16 *stride, CARD32 *size); +int +dri3_get_supported_formats(ScreenPtr screen, CARD32 *num_formats, CARD32 **formats); + +int +dri3_get_supported_modifiers(ScreenPtr screen, CARD32 format, CARD32 *num_modifiers, + CARD32 **modifiers_hi, CARD32 **modifiers_lo); + #endif /* _DRI3PRIV_H_ */ diff --git a/dri3/dri3_request.c b/dri3/dri3_request.c index 336175d92..35f1c2533 100644 --- a/dri3/dri3_request.c +++ b/dri3/dri3_request.c @@ -310,9 +310,9 @@ proc_dri3_get_supported_formats(ClientPtr client) DrawablePtr drawable; ScreenPtr pScreen; CARD32 *formats = NULL; - int nformats = 0; + CARD32 nformats = 0; + CARD32 i; int status; - int i; REQUEST_SIZE_MATCH(xDRI3GetSupportedFormatsReq); @@ -322,6 +322,8 @@ proc_dri3_get_supported_formats(ClientPtr client) return status; pScreen = drawable->pScreen; + dri3_get_supported_formats(pScreen, &nformats, &formats); + rep.numFormats = nformats; rep.length = bytes_to_int32(rep.numFormats * sizeof(CARD32)); @@ -336,6 +338,8 @@ proc_dri3_get_supported_formats(ClientPtr client) WriteToClient(client, sizeof(rep), &rep); WriteToClient(client, nformats * sizeof(CARD32), formats); + free(formats); + return Success; } @@ -351,7 +355,7 @@ proc_dri3_get_supported_modifiers(ClientPtr client) ScreenPtr pScreen; CARD32 *modifiers_hi = NULL; CARD32 *modifiers_lo = NULL; - int nmodifiers = 0; + CARD32 nmodifiers = 0; int status; int i; @@ -363,6 +367,9 @@ proc_dri3_get_supported_modifiers(ClientPtr client) return status; pScreen = drawable->pScreen; + dri3_get_supported_modifiers(pScreen, stuff->format, &nmodifiers, + &modifiers_hi, &modifiers_lo); + rep.numModifiers = nmodifiers; rep.length = bytes_to_int32(2 * rep.numModifiers * sizeof(CARD32)); diff --git a/dri3/dri3_screen.c b/dri3/dri3_screen.c index 6c0c60cbf..4d4f77bcf 100644 --- a/dri3/dri3_screen.c +++ b/dri3/dri3_screen.c @@ -96,3 +96,124 @@ dri3_fd_from_pixmap(int *pfd, PixmapPtr pixmap, CARD16 *stride, CARD32 *size) return Success; } +static int +cache_formats_and_modifiers(ScreenPtr screen) +{ + dri3_screen_priv_ptr ds = dri3_screen_priv(screen); + dri3_screen_info_ptr info = ds->info; + CARD32 *formats = NULL; + uint64_t *modifiers = NULL; + int i, j; + + if (ds->formats_cached) + return Success; + + if (!info || !info->get_formats || !info->get_modifiers) + return BadImplementation; + + (*info->get_formats) (screen, &ds->num_formats, &formats); + ds->formats = calloc(ds->num_formats, sizeof(dri3_dmabuf_format_rec)); + if (!ds->formats) + return BadAlloc; + + for (i = 0; i < ds->num_formats; i++) { + dri3_dmabuf_format_ptr iter = &ds->formats[i]; + + iter->format = formats[i]; + (*info->get_modifiers) (screen, formats[i], + &iter->num_modifiers, + &modifiers); + + iter->modifiers_hi = malloc(iter->num_modifiers * sizeof(CARD32)); + if (iter->modifiers_hi == NULL) + goto error; + iter->modifiers_lo = malloc(iter->num_modifiers * sizeof(CARD32)); + if (iter->modifiers_lo == NULL) + goto error; + + for (j = 0; j < iter->num_modifiers; j++) { + iter->modifiers_hi[j] = modifiers[j] >> 32; + iter->modifiers_lo[j] = modifiers[j] & 0xffffffff; + } + goto done; + +error: + iter->num_modifiers = 0; + free(iter->modifiers_hi); + free(iter->modifiers_lo); +done: + free(modifiers); + } + free(formats); + ds->formats_cached = TRUE; + + return Success; +} + +int +dri3_get_supported_formats(ScreenPtr screen, CARD32 *num_formats, + CARD32 **formats) +{ + dri3_screen_priv_ptr ds = dri3_screen_priv(screen); + int i; + int ret; + + ret = cache_formats_and_modifiers(screen); + if (ret != Success) + return ret; + + *formats = malloc(ds->num_formats * sizeof(CARD32)); + if (!*formats) { + *num_formats = 0; + return BadAlloc; + } + + *num_formats = ds->num_formats; + for (i = 0; i < ds->num_formats; i++) + *formats[i] = ds->formats[i].format; + + return Success; +} + +int +dri3_get_supported_modifiers(ScreenPtr screen, + CARD32 format, CARD32 *num_modifiers, + CARD32 **modifiers_hi, CARD32 **modifiers_lo) +{ + dri3_screen_priv_ptr ds = dri3_screen_priv(screen); + int i; + int ret; + + ret = cache_formats_and_modifiers(screen); + if (ret != Success) + return ret; + + // XXX We don't really need a copy, but without it we're kind of asymetric + // with the get_formats API... + for (i = 0; i < ds->num_formats; i++) { + if (ds->formats[i].format == format) { + *modifiers_hi = malloc(ds->formats[i].num_modifiers * sizeof(CARD32)); + if (!*modifiers_hi) { + *num_modifiers = 0; + return BadAlloc; + } + *modifiers_lo = malloc(ds->formats[i].num_modifiers * sizeof(CARD32)); + if (!*modifiers_lo) { + *num_modifiers = 0; + free(*modifiers_hi); + *modifiers_hi = NULL; + return BadAlloc; + } + + *num_modifiers = ds->formats[i].num_modifiers; + memcpy(*modifiers_hi, ds->formats[i].modifiers_hi, + ds->formats[i].num_modifiers * sizeof(CARD32)); + memcpy(*modifiers_lo, ds->formats[i].modifiers_lo, + ds->formats[i].num_modifiers * sizeof(CARD32)); + + return Success; + } + } + + return BadMatch; +} diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index b0d3e9efe..91b34a4bb 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -56,6 +56,7 @@ struct glamor_egl_screen_private { CloseScreenProcPtr CloseScreen; int fd; struct gbm_device *gbm; + int modifiers_capable; CloseScreenProcPtr saved_close_screen; DestroyPixmapProcPtr saved_destroy_pixmap; @@ -416,6 +417,83 @@ glamor_pixmap_from_fd(ScreenPtr screen, } static Bool +glamor_get_formats(ScreenPtr screen, + CARD32 *num_formats, CARD32 **formats) +{ +#ifndef EGL_EXT_image_dma_buf_import_modifiers + return FALSE; +#else + struct glamor_egl_screen_private *glamor_egl; + EGLint num; + + glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen)); + + if (!glamor_egl->modifiers_capable) + return FALSE; + + if (!eglQueryDmaBufFormatsEXT(glamor_egl->display, 0, NULL, &num)) { + *num_formats = 0; + return FALSE; + } + + *formats = calloc(num, sizeof(CARD32)); + if (*formats == NULL) { + *num_formats = 0; + return FALSE; + } + + if (!eglQueryDmaBufFormatsEXT(glamor_egl->display, num, + (EGLint *) *formats, &num)) { + *num_formats = 0; + free(*formats); + return FALSE; + } + + *num_formats = num; + return TRUE; +#endif +} + +static Bool +glamor_get_modifiers(ScreenPtr screen, CARD32 format, + CARD32 *num_modifiers, uint64_t **modifiers) +{ +#ifndef EGL_EXT_image_dma_buf_import_modifiers + return FALSE; +#else + struct glamor_egl_screen_private *glamor_egl; + EGLint num; + + glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen)); + + if (!glamor_egl->modifiers_capable) + return FALSE; + + if (!eglQueryDmaBufModifiersEXT(glamor_egl->display, format, 0, NULL, + NULL, &num)) { + *num_modifiers = 0; + return FALSE; + } + + *modifiers = calloc(num, sizeof(uint64_t)); + if (*modifiers == NULL) { + *num_modifiers = 0; + return FALSE; + } + + if (!eglQueryDmaBufModifiersEXT(glamor_egl->display, format, num, + (EGLuint64KHR *) *modifiers, NULL, &num)) { + *num_modifiers = 0; + free(*modifiers); + return FALSE; + } + + *num_modifiers = num; + return TRUE; +#endif +} + +static Bool glamor_egl_destroy_pixmap(PixmapPtr pixmap) { ScreenPtr screen = pixmap->drawable.pScreen; @@ -536,6 +614,8 @@ static dri3_screen_info_rec glamor_dri3_info = { .open_client = glamor_dri3_open_client, .pixmap_from_fd = glamor_pixmap_from_fd, .fd_from_pixmap = glamor_fd_from_pixmap, + .get_formats = glamor_get_formats, + .get_modifiers = glamor_get_modifiers, }; #endif /* DRI3 */ @@ -734,6 +814,10 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) xf86DrvMsg(scrn->scrnIndex, X_INFO, "glamor X acceleration enabled on %s\n", glGetString(GL_RENDERER)); + if (epoxy_has_egl_extension(glamor_egl->display, + "EXT_image_dma_buf_import_modifiers")) + glamor_egl->modifiers_capable = TRUE; + glamor_egl->saved_free_screen = scrn->FreeScreen; scrn->FreeScreen = glamor_egl_free_screen; return TRUE; diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c index 87622839e..0273f5f16 100644 --- a/hw/xwayland/xwayland-glamor.c +++ b/hw/xwayland/xwayland-glamor.c @@ -331,6 +331,10 @@ xwl_drm_init_egl(struct xwl_screen *xwl_screen) return; } + if (epoxy_has_egl_extension(xwl_screen->egl_display, + "EXT_image_dma_buf_import_modifiers")) + xwl_screen->modifiers_capable = TRUE; + return; } @@ -569,12 +573,87 @@ xwl_dri3_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, return gbm_bo_get_fd(xwl_pixmap->bo); } +static int +xwl_dri3_get_formats(ScreenPtr screen, + CARD32 *num_formats, CARD32 **formats) +{ +#ifndef EGL_EXT_image_dma_buf_import_modifiers + return FALSE; +#else + struct xwl_screen *xwl_screen = xwl_screen_get(screen); + EGLint num; + + if (!xwl_screen->modifiers_capable) + return FALSE; + + if (!eglQueryDmaBufFormatsEXT(xwl_screen->egl_display, 0, NULL, &num)) { + *num_formats = 0; + return FALSE; + } + + *formats = calloc(num, sizeof(CARD32)); + if (*formats == NULL) { + *num_formats = 0; + return FALSE; + } + + if (!eglQueryDmaBufFormatsEXT(xwl_screen->egl_display, num, (EGLint *) *formats, &num)) { + *num_formats = 0; + free(*formats); + return FALSE; + } + + *num_formats = num; + return TRUE; +#endif +} + +static int +xwl_dri3_get_modifiers(ScreenPtr screen, CARD32 format, + CARD32 *num_modifiers, uint64_t **modifiers) +{ +#ifndef EGL_EXT_image_dma_buf_import_modifiers + return FALSE; +#else + struct xwl_screen *xwl_screen = xwl_screen_get(screen); + EGLint num; + + if (!xwl_screen->modifiers_capable) + return FALSE; + + if (!eglQueryDmaBufModifiersEXT(xwl_screen->egl_display, format, 0, NULL, + NULL, &num)) { + *num_modifiers = 0; + return FALSE; + } + + *modifiers = calloc(num, sizeof(uint64_t)); + if (*modifiers == NULL) { + *num_modifiers = 0; + return FALSE; + } + + if (!eglQueryDmaBufModifiersEXT(xwl_screen->egl_display, format, num, + *modifiers, NULL, &num)) { + *num_modifiers = 0; + free(*modifiers); + return FALSE; + } + + *num_modifiers = num; + return TRUE; +#endif +} + + static dri3_screen_info_rec xwl_dri3_info = { .version = 1, .open = NULL, .pixmap_from_fd = xwl_dri3_pixmap_from_fd, .fd_from_pixmap = xwl_dri3_fd_from_pixmap, .open_client = xwl_dri3_open_client, + .get_formats = xwl_dri3_get_formats, + .get_modifiers = xwl_dri3_get_modifiers, }; Bool diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h index a05e0862c..30f7de026 100644 --- a/hw/xwayland/xwayland.h +++ b/hw/xwayland/xwayland.h @@ -99,6 +99,7 @@ struct xwl_screen { void *egl_display, *egl_context; struct gbm_device *gbm; struct glamor_context *glamor_ctx; + int modifiers_capable; Atom allow_commits_prop; }; -- 2.13.0 _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: https://lists.x.org/mailman/listinfo/xorg-devel
