From 6f10e7c37a34570f61fa2db8fc1860553207b7e9 Mon Sep 17 00:00:00 2001 From: Varad Gautam Date: Tue, 30 May 2017 17:23:37 +0530 Subject: [PATCH] egl/dri2: Create EGLImages with dmabuf modifiers MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Allow creating EGLImages with dmabuf format modifiers when target is EGL_LINUX_DMA_BUF_EXT for EGL_EXT_image_dma_buf_import_modifiers. v2: - clear modifier assembling and error label name (Eric Engestrom) v3: - remove goto jumps within switch-case (Emil Velikov) - treat zero as valid modifier (Daniel Stone) - ensure same modifier across all dmabuf planes (Emil Velikov) v4: - allow modifiers to add extra planes (Louis-Francis Ratté-Boulianne) v5: - fix error checking, some cleanups (Jason Ekstrand) - pass single copy of the modifier to createImageFromDmaBufs2 Signed-off-by: Pekka Paalanen Signed-off-by: Varad Gautam Signed-off-by: Louis-Francis Ratté-Boulianne Reviewed-by: Eric Engestrom Reviewed-by: Daniel Stone Reviewed-by: Emil Velikov --- src/egl/drivers/dri2/egl_dri2.c | 108 ++++++++++++++++++++++++++++---- src/egl/main/eglimage.c | 48 ++++++++++++++ src/egl/main/eglimage.h | 2 + 3 files changed, 147 insertions(+), 11 deletions(-) diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index 8f0f1b323a7..177b5471284 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -87,6 +87,10 @@ #define DRM_FORMAT_GR1616 fourcc_code('G', 'R', '3', '2') /* [31:0] R:G 16:16 little endian */ #endif +#ifndef DRM_FORMAT_MOD_INVALID +#define DRM_FORMAT_MOD_INVALID ((1ULL<<56) - 1) +#endif + static void dri_set_background_context(void *loaderPrivate) { @@ -1987,6 +1991,37 @@ dri2_check_dma_buf_attribs(const _EGLImageAttribs *attrs) } } + /** + * If is EGL_LINUX_DMA_BUF_EXT, both or neither of the following + * attribute values may be given. + * + * This is referring to EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT and + * EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, and the same for other planes. + */ + for (i = 0; i < DMA_BUF_MAX_PLANES; ++i) { + if (attrs->DMABufPlaneModifiersLo[i].IsPresent != + attrs->DMABufPlaneModifiersHi[i].IsPresent) { + _eglError(EGL_BAD_PARAMETER, "modifier attribute lo or hi missing"); + return EGL_FALSE; + } + } + + /* Although the EGL_EXT_image_dma_buf_import_modifiers spec doesn't + * mandate it, we only accept the same modifier across all planes. */ + for (i = 1; i < DMA_BUF_MAX_PLANES; ++i) { + if (attrs->DMABufPlaneFds[i].IsPresent) { + if ((attrs->DMABufPlaneModifiersLo[0].IsPresent != + attrs->DMABufPlaneModifiersLo[i].IsPresent) || + (attrs->DMABufPlaneModifiersLo[0].Value != + attrs->DMABufPlaneModifiersLo[i].Value) || + (attrs->DMABufPlaneModifiersHi[0].Value != + attrs->DMABufPlaneModifiersHi[i].Value)) { + _eglError(EGL_BAD_PARAMETER, "modifier attributes not equal"); + return EGL_FALSE; + } + } + } + return EGL_TRUE; } @@ -2095,7 +2130,25 @@ dri2_check_dma_buf_format(const _EGLImageAttribs *attrs) for (i = plane_n; i < DMA_BUF_MAX_PLANES; ++i) { if (attrs->DMABufPlaneFds[i].IsPresent || attrs->DMABufPlaneOffsets[i].IsPresent || - attrs->DMABufPlanePitches[i].IsPresent) { + attrs->DMABufPlanePitches[i].IsPresent || + attrs->DMABufPlaneModifiersLo[i].IsPresent || + attrs->DMABufPlaneModifiersHi[i].IsPresent) { + + /** + * The modifiers extension spec says: + * + * "Modifiers may modify any attribute of a buffer import, including + * but not limited to adding extra planes to a format which + * otherwise does not have those planes. As an example, a modifier + * may add a plane for an external compression buffer to a + * single-plane format. The exact meaning and effect of any + * modifier is canonically defined by drm_fourcc.h, not as part of + * this extension." + */ + if (attrs->DMABufPlaneModifiersLo[i].IsPresent && + attrs->DMABufPlaneModifiersHi[i].IsPresent) + continue; + _eglError(EGL_BAD_ATTRIBUTE, "too many plane attributes"); return 0; } @@ -2128,6 +2181,8 @@ dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx, int fds[DMA_BUF_MAX_PLANES]; int pitches[DMA_BUF_MAX_PLANES]; int offsets[DMA_BUF_MAX_PLANES]; + uint64_t modifier; + bool has_modifier = false; unsigned error; /** @@ -2160,16 +2215,47 @@ dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx, offsets[i] = attrs.DMABufPlaneOffsets[i].Value; } - dri_image = - dri2_dpy->image->createImageFromDmaBufs(dri2_dpy->dri_screen, - attrs.Width, attrs.Height, attrs.DMABufFourCC.Value, - fds, num_fds, pitches, offsets, - attrs.DMABufYuvColorSpaceHint.Value, - attrs.DMABufSampleRangeHint.Value, - attrs.DMABufChromaHorizontalSiting.Value, - attrs.DMABufChromaVerticalSiting.Value, - &error, - NULL); + /* dri2_check_dma_buf_attribs ensures that the modifier, if available, + * will be present in attrs.DMABufPlaneModifiersLo[0] and + * attrs.DMABufPlaneModifiersHi[0] */ + if (attrs.DMABufPlaneModifiersLo[0].IsPresent) { + modifier = + ((uint64_t) attrs.DMABufPlaneModifiersHi[0].Value << 32) | + attrs.DMABufPlaneModifiersLo[0].Value; + has_modifier = true; + } else { + modifier = DRM_FORMAT_MOD_INVALID; + } + + if (has_modifier) { + if (dri2_dpy->image->base.version < 15 || + dri2_dpy->image->createImageFromDmaBufs2 == NULL) { + _eglError(EGL_BAD_MATCH, "unsupported dma_buf format modifier"); + return EGL_NO_IMAGE_KHR; + } + dri_image = + dri2_dpy->image->createImageFromDmaBufs2(dri2_dpy->dri_screen, + attrs.Width, attrs.Height, attrs.DMABufFourCC.Value, + modifier, fds, num_fds, pitches, offsets, + attrs.DMABufYuvColorSpaceHint.Value, + attrs.DMABufSampleRangeHint.Value, + attrs.DMABufChromaHorizontalSiting.Value, + attrs.DMABufChromaVerticalSiting.Value, + &error, + NULL); + } + else { + dri_image = + dri2_dpy->image->createImageFromDmaBufs(dri2_dpy->dri_screen, + attrs.Width, attrs.Height, attrs.DMABufFourCC.Value, + fds, num_fds, pitches, offsets, + attrs.DMABufYuvColorSpaceHint.Value, + attrs.DMABufSampleRangeHint.Value, + attrs.DMABufChromaHorizontalSiting.Value, + attrs.DMABufChromaVerticalSiting.Value, + &error, + NULL); + } dri2_create_image_khr_texture_error(error); if (!dri_image) diff --git a/src/egl/main/eglimage.c b/src/egl/main/eglimage.c index fed390a4982..c558f2f02b0 100644 --- a/src/egl/main/eglimage.c +++ b/src/egl/main/eglimage.c @@ -106,6 +106,18 @@ _eglParseImageAttribList(_EGLImageAttribs *attrs, _EGLDisplay *dpy, attrs->DMABufPlanePitches[0].Value = val; attrs->DMABufPlanePitches[0].IsPresent = EGL_TRUE; break; + case EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT: + if (!dpy->Extensions.EXT_image_dma_buf_import_modifiers) + err = EGL_BAD_PARAMETER; + attrs->DMABufPlaneModifiersLo[0].Value = val; + attrs->DMABufPlaneModifiersLo[0].IsPresent = EGL_TRUE; + break; + case EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT: + if (!dpy->Extensions.EXT_image_dma_buf_import_modifiers) + err = EGL_BAD_PARAMETER; + attrs->DMABufPlaneModifiersHi[0].Value = val; + attrs->DMABufPlaneModifiersHi[0].IsPresent = EGL_TRUE; + break; case EGL_DMA_BUF_PLANE1_FD_EXT: attrs->DMABufPlaneFds[1].Value = val; attrs->DMABufPlaneFds[1].IsPresent = EGL_TRUE; @@ -118,6 +130,18 @@ _eglParseImageAttribList(_EGLImageAttribs *attrs, _EGLDisplay *dpy, attrs->DMABufPlanePitches[1].Value = val; attrs->DMABufPlanePitches[1].IsPresent = EGL_TRUE; break; + case EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT: + if (!dpy->Extensions.EXT_image_dma_buf_import_modifiers) + err = EGL_BAD_PARAMETER; + attrs->DMABufPlaneModifiersLo[1].Value = val; + attrs->DMABufPlaneModifiersLo[1].IsPresent = EGL_TRUE; + break; + case EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT: + if (!dpy->Extensions.EXT_image_dma_buf_import_modifiers) + err = EGL_BAD_PARAMETER; + attrs->DMABufPlaneModifiersHi[1].Value = val; + attrs->DMABufPlaneModifiersHi[1].IsPresent = EGL_TRUE; + break; case EGL_DMA_BUF_PLANE2_FD_EXT: attrs->DMABufPlaneFds[2].Value = val; attrs->DMABufPlaneFds[2].IsPresent = EGL_TRUE; @@ -130,6 +154,18 @@ _eglParseImageAttribList(_EGLImageAttribs *attrs, _EGLDisplay *dpy, attrs->DMABufPlanePitches[2].Value = val; attrs->DMABufPlanePitches[2].IsPresent = EGL_TRUE; break; + case EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT: + if (!dpy->Extensions.EXT_image_dma_buf_import_modifiers) + err = EGL_BAD_PARAMETER; + attrs->DMABufPlaneModifiersLo[2].Value = val; + attrs->DMABufPlaneModifiersLo[2].IsPresent = EGL_TRUE; + break; + case EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT: + if (!dpy->Extensions.EXT_image_dma_buf_import_modifiers) + err = EGL_BAD_PARAMETER; + attrs->DMABufPlaneModifiersHi[2].Value = val; + attrs->DMABufPlaneModifiersHi[2].IsPresent = EGL_TRUE; + break; case EGL_DMA_BUF_PLANE3_FD_EXT: if (!dpy->Extensions.EXT_image_dma_buf_import_modifiers) err = EGL_BAD_PARAMETER; @@ -148,6 +184,18 @@ _eglParseImageAttribList(_EGLImageAttribs *attrs, _EGLDisplay *dpy, attrs->DMABufPlanePitches[3].Value = val; attrs->DMABufPlanePitches[3].IsPresent = EGL_TRUE; break; + case EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT: + if (!dpy->Extensions.EXT_image_dma_buf_import_modifiers) + err = EGL_BAD_PARAMETER; + attrs->DMABufPlaneModifiersLo[3].Value = val; + attrs->DMABufPlaneModifiersLo[3].IsPresent = EGL_TRUE; + break; + case EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT: + if (!dpy->Extensions.EXT_image_dma_buf_import_modifiers) + err = EGL_BAD_PARAMETER; + attrs->DMABufPlaneModifiersHi[3].Value = val; + attrs->DMABufPlaneModifiersHi[3].IsPresent = EGL_TRUE; + break; case EGL_YUV_COLOR_SPACE_HINT_EXT: if (val != EGL_ITU_REC601_EXT && val != EGL_ITU_REC709_EXT && val != EGL_ITU_REC2020_EXT) { diff --git a/src/egl/main/eglimage.h b/src/egl/main/eglimage.h index a909d9b5889..eb66280ff96 100644 --- a/src/egl/main/eglimage.h +++ b/src/egl/main/eglimage.h @@ -73,6 +73,8 @@ struct _egl_image_attribs struct _egl_image_attrib_int DMABufPlaneFds[DMA_BUF_MAX_PLANES]; struct _egl_image_attrib_int DMABufPlaneOffsets[DMA_BUF_MAX_PLANES]; struct _egl_image_attrib_int DMABufPlanePitches[DMA_BUF_MAX_PLANES]; + struct _egl_image_attrib_int DMABufPlaneModifiersLo[DMA_BUF_MAX_PLANES]; + struct _egl_image_attrib_int DMABufPlaneModifiersHi[DMA_BUF_MAX_PLANES]; struct _egl_image_attrib_int DMABufYuvColorSpaceHint; struct _egl_image_attrib_int DMABufSampleRangeHint; struct _egl_image_attrib_int DMABufChromaHorizontalSiting; -- 2.30.2