diff --git a/subprojects/gst-plugins-base/gst-libs/gst/gl/egl/gsteglimage.c b/subprojects/gst-plugins-base/gst-libs/gst/gl/egl/gsteglimage.c index 7675e76334..1e137938d6 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/gl/egl/gsteglimage.c +++ b/subprojects/gst-plugins-base/gst-libs/gst/gl/egl/gsteglimage.c @@ -635,7 +635,7 @@ get_egl_stride (const GstVideoInfo * info, gint plane) * is passed as RGBA data. Shaders later take this "RGBA" data and * convert it from its true format (described by in_info) to actual * RGBA output. For example, with I420, three EGL images are created, - * one for each plane, each EGL image with a single-channel R format. + * one for each @plane, each EGL image with a single-channel R format. * With NV12, two EGL images are created, one with R format, one * with RG format etc. * @@ -644,14 +644,51 @@ get_egl_stride (const GstVideoInfo * info, gint plane) GstEGLImage * gst_egl_image_from_dmabuf (GstGLContext * context, gint dmabuf, const GstVideoInfo * in_info, gint plane, gsize offset) +{ + GstVideoInfoDmaDrm in_info_dma; + + if (!gst_video_info_dma_drm_from_video_info (&in_info_dma, in_info, + DRM_FORMAT_MOD_LINEAR)) + return FALSE; + + return gst_egl_image_from_dmabuf_with_dma_drm (context, dmabuf, + &in_info_dma, plane, offset); +} + +/** + * gst_egl_image_from_dmabuf_with_dma_drm: + * @context: a #GstGLContext (must be an EGL context) + * @dmabuf: the DMA-Buf file descriptor + * @in_info_dma: the #GstVideoInfoDmaDrm in @dmabuf + * @plane: the plane in @in_info to create and #GstEGLImage for + * @offset: the byte-offset in the data + * + * Creates an EGL image that imports the dmabuf FD. The dmabuf data + * is passed as RGBA data. Shaders later take this "RGBA" data and + * convert it from its true format (described by in_info) to actual + * RGBA output. For example, with I420, three EGL images are created, + * one for each @plane, each EGL image with a single-channel R format. + * With NV12, two EGL images are created, one with R format, one + * with RG format etc. User can specify the modifier in @in_info_dma + * for non-linear dmabuf. + * + * Returns: (nullable): a #GstEGLImage wrapping @dmabuf or %NULL on failure + * + * Since: 1.24 + */ +GstEGLImage * +gst_egl_image_from_dmabuf_with_dma_drm (GstGLContext * context, gint dmabuf, + const GstVideoInfoDmaDrm * in_info_dma, gint plane, gsize offset) { gint comp[GST_VIDEO_MAX_COMPONENTS]; GstGLFormat format = 0; - guintptr attribs[13]; + const GstVideoInfo *in_info = &in_info_dma->vinfo; + guintptr attribs[17]; EGLImageKHR img; gint atti = 0; gint fourcc; gint i; + gboolean with_modifiers; gst_video_format_info_component (in_info->finfo, plane, comp); fourcc = _drm_rgba_fourcc_from_info (in_info, plane, &format); @@ -660,6 +697,9 @@ gst_egl_image_from_dmabuf (GstGLContext * context, GST_VIDEO_INFO_COMP_WIDTH (in_info, comp[0]), GST_VIDEO_INFO_COMP_HEIGHT (in_info, comp[0])); + with_modifiers = gst_gl_context_check_feature (context, + "EGL_EXT_image_dma_buf_import_modifiers"); + attribs[atti++] = EGL_WIDTH; attribs[atti++] = GST_VIDEO_INFO_COMP_WIDTH (in_info, comp[0]); attribs[atti++] = EGL_HEIGHT; @@ -672,8 +712,16 @@ gst_egl_image_from_dmabuf (GstGLContext * context, attribs[atti++] = offset; attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT; attribs[atti++] = get_egl_stride (in_info, plane); + + if (with_modifiers && in_info_dma->drm_modifier != DRM_FORMAT_MOD_INVALID) { + attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT; + attribs[atti++] = in_info_dma->drm_modifier & 0xffffffff; + attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT; + attribs[atti++] = (in_info_dma->drm_modifier >> 32) & 0xffffffff; + } + attribs[atti] = EGL_NONE; - g_assert (atti == G_N_ELEMENTS (attribs) - 1); + g_assert (atti <= G_N_ELEMENTS (attribs) - 1); for (i = 0; i < atti; i++) GST_LOG ("attr %i: %" G_GINTPTR_FORMAT, i, attribs[i]); @@ -724,6 +772,8 @@ gst_egl_image_check_dmabuf_direct (GstGLContext * context, * a supported texture format for the given @target. * * Returns: %TRUE if the format is supported. + * + * Since: 1.24 */ gboolean gst_egl_image_check_dmabuf_direct_with_dma_drm (GstGLContext * context, @@ -785,7 +835,7 @@ gst_egl_image_check_dmabuf_direct_with_dma_drm (GstGLContext * context, * @target: GL texture target this GstEGLImage is intended for * * Creates an EGL image that imports the dmabuf FD. The dmabuf data - * is passed directly as the format described in in_info. This is + * is passed directly as the format described in @in_info. This is * useful if the hardware is capable of performing color space conversions * internally. The appropriate DRM format is picked, and the EGL image * is created with this DRM format. @@ -803,10 +853,45 @@ gst_egl_image_from_dmabuf_direct_target (GstGLContext * context, gint * fd, const gsize * offset, const GstVideoInfo * in_info, GstGLTextureTarget target) { + GstVideoInfoDmaDrm in_info_dma; + if (!gst_video_info_dma_drm_from_video_info (&in_info_dma, in_info, + DRM_FORMAT_MOD_LINEAR)) + return NULL; + + return gst_egl_image_from_dmabuf_direct_target_with_dma_drm (context, fd, + offset, &in_info_dma, target); +} + +/** + * gst_egl_image_from_dmabuf_direct_target_with_dma_drm: + * @context: a #GstGLContext (must be an EGL context) + * @fd: Array of DMABuf file descriptors + * @offset: Array of offsets, relative to the DMABuf + * @in_info_dma: the #GstVideoInfoDmaDrm + * @target: GL texture target this GstEGLImage is intended for + * + * Creates an EGL image that imports the dmabuf FD. The dmabuf data is passed + * directly as the format described in @in_info. This is useful if the hardware + * is capable of performing color space conversions internally. + * + * Another notable difference to gst_egl_image_from_dmabuf() is that this + * function creates one EGL image for all planes, not one for a single plane. + * + * Returns: (nullable): a #GstEGLImage wrapping @dmabuf or %NULL on failure + * + * Since: 1.24 + */ +GstEGLImage * +gst_egl_image_from_dmabuf_direct_target_with_dma_drm (GstGLContext * context, + gint * fd, const gsize * offset, const GstVideoInfoDmaDrm * in_info_dma, + GstGLTextureTarget target) +{ EGLImageKHR img; + const GstVideoInfo *in_info = &in_info_dma->vinfo; guint n_planes = GST_VIDEO_INFO_N_PLANES (in_info); guint32 fourcc; + guint64 modifier; gint i; gboolean with_modifiers; @@ -819,14 +904,18 @@ gst_egl_image_from_dmabuf_direct_target (GstGLContext * context, guintptr attribs[41]; /* 6 + 10 * 3 + 4 + 1 */ gint atti = 0; - if (!gst_egl_image_check_dmabuf_direct (context, in_info, target)) + if (!gst_egl_image_check_dmabuf_direct_with_dma_drm (context, in_info_dma, + target)) return NULL; - fourcc = - gst_video_dma_drm_fourcc_from_format (GST_VIDEO_INFO_FORMAT (in_info)); + fourcc = in_info_dma->drm_fourcc; + modifier = in_info_dma->drm_modifier; with_modifiers = gst_gl_context_check_feature (context, "EGL_EXT_image_dma_buf_import_modifiers"); + if (!with_modifiers && modifier != DRM_FORMAT_MOD_LINEAR) + return NULL; + /* EGL DMABuf importation supports a maximum of 3 planes */ if (G_UNLIKELY (n_planes > 3)) return NULL; @@ -846,11 +935,11 @@ gst_egl_image_from_dmabuf_direct_target (GstGLContext * context, attribs[atti++] = offset[0]; attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT; attribs[atti++] = get_egl_stride (in_info, 0); - if (with_modifiers) { + if (with_modifiers && modifier != DRM_FORMAT_MOD_INVALID) { attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT; - attribs[atti++] = DRM_FORMAT_MOD_LINEAR & 0xffffffff; + attribs[atti++] = modifier & 0xffffffff; attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT; - attribs[atti++] = (DRM_FORMAT_MOD_LINEAR >> 32) & 0xffffffff; + attribs[atti++] = (modifier >> 32) & 0xffffffff; } } @@ -862,11 +951,11 @@ gst_egl_image_from_dmabuf_direct_target (GstGLContext * context, attribs[atti++] = offset[1]; attribs[atti++] = EGL_DMA_BUF_PLANE1_PITCH_EXT; attribs[atti++] = get_egl_stride (in_info, 1); - if (with_modifiers) { + if (with_modifiers && modifier != DRM_FORMAT_MOD_INVALID) { attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT; - attribs[atti++] = DRM_FORMAT_MOD_LINEAR & 0xffffffff; + attribs[atti++] = modifier & 0xffffffff; attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT; - attribs[atti++] = (DRM_FORMAT_MOD_LINEAR >> 32) & 0xffffffff; + attribs[atti++] = (modifier >> 32) & 0xffffffff; } } @@ -878,11 +967,11 @@ gst_egl_image_from_dmabuf_direct_target (GstGLContext * context, attribs[atti++] = offset[2]; attribs[atti++] = EGL_DMA_BUF_PLANE2_PITCH_EXT; attribs[atti++] = get_egl_stride (in_info, 2); - if (with_modifiers) { + if (with_modifiers && modifier != DRM_FORMAT_MOD_INVALID) { attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT; - attribs[atti++] = DRM_FORMAT_MOD_LINEAR & 0xffffffff; + attribs[atti++] = modifier & 0xffffffff; attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT; - attribs[atti++] = (DRM_FORMAT_MOD_LINEAR >> 32) & 0xffffffff; + attribs[atti++] = (modifier >> 32) & 0xffffffff; } } diff --git a/subprojects/gst-plugins-base/gst-libs/gst/gl/egl/gsteglimage.h b/subprojects/gst-plugins-base/gst-libs/gst/gl/egl/gsteglimage.h index f90fa82a39..5b8cb5f54c 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/gl/egl/gsteglimage.h +++ b/subprojects/gst-plugins-base/gst-libs/gst/gl/egl/gsteglimage.h @@ -89,6 +89,12 @@ GstEGLImage * gst_egl_image_from_dmabuf (GstGLContext * gint plane, gsize offset); GST_GL_API +GstEGLImage * gst_egl_image_from_dmabuf_with_dma_drm (GstGLContext * context, + gint dmabuf, + const GstVideoInfoDmaDrm * in_info_dma, + gint plane, + gsize offset); +GST_GL_API GstEGLImage * gst_egl_image_from_dmabuf_direct (GstGLContext * context, gint *fd, const gsize *offset, @@ -101,6 +107,13 @@ GstEGLImage * gst_egl_image_from_dmabuf_direct_target (GstGLContext * GstGLTextureTarget target); GST_GL_API +GstEGLImage * gst_egl_image_from_dmabuf_direct_target_with_dma_drm + (GstGLContext * context, + gint * fd, + const gsize * offset, + const GstVideoInfoDmaDrm * in_info_dma, + GstGLTextureTarget target); +GST_GL_API gboolean gst_egl_image_export_dmabuf (GstEGLImage *image, int *fd, gint *stride, gsize *offset); #endif