mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-22 16:26:39 +00:00
gl: EGL image methods to import dmabufs with modifiers
This patch adds gst_egl_image_from_dmabuf_direct_target_with_dma_drm() and add gst_egl_image_from_dmabuf_with_dma_drm() functions New function gst_egl_image_from_dmabuf_direct_target_with_dma_drm(), where gst_egl_image_from_dmabuf_direct_target() is a specialization of the first. And gst_egl_image_from_dmabuf() is a specialization of new function gst_egl_image_from_dmabuf_with_dma_drm() Co-authored-by: Victor Jaquez <vjaquez@igalia.com> Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4680>
This commit is contained in:
parent
9f7f54174a
commit
1a2d136438
2 changed files with 118 additions and 16 deletions
|
@ -635,7 +635,7 @@ get_egl_stride (const GstVideoInfo * info, gint plane)
|
||||||
* is passed as RGBA data. Shaders later take this "RGBA" data and
|
* is passed as RGBA data. Shaders later take this "RGBA" data and
|
||||||
* convert it from its true format (described by in_info) to actual
|
* convert it from its true format (described by in_info) to actual
|
||||||
* RGBA output. For example, with I420, three EGL images are created,
|
* 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 NV12, two EGL images are created, one with R format, one
|
||||||
* with RG format etc.
|
* with RG format etc.
|
||||||
*
|
*
|
||||||
|
@ -644,14 +644,51 @@ get_egl_stride (const GstVideoInfo * info, gint plane)
|
||||||
GstEGLImage *
|
GstEGLImage *
|
||||||
gst_egl_image_from_dmabuf (GstGLContext * context,
|
gst_egl_image_from_dmabuf (GstGLContext * context,
|
||||||
gint dmabuf, const GstVideoInfo * in_info, gint plane, gsize offset)
|
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];
|
gint comp[GST_VIDEO_MAX_COMPONENTS];
|
||||||
GstGLFormat format = 0;
|
GstGLFormat format = 0;
|
||||||
guintptr attribs[13];
|
const GstVideoInfo *in_info = &in_info_dma->vinfo;
|
||||||
|
guintptr attribs[17];
|
||||||
EGLImageKHR img;
|
EGLImageKHR img;
|
||||||
gint atti = 0;
|
gint atti = 0;
|
||||||
gint fourcc;
|
gint fourcc;
|
||||||
gint i;
|
gint i;
|
||||||
|
gboolean with_modifiers;
|
||||||
|
|
||||||
gst_video_format_info_component (in_info->finfo, plane, comp);
|
gst_video_format_info_component (in_info->finfo, plane, comp);
|
||||||
fourcc = _drm_rgba_fourcc_from_info (in_info, plane, &format);
|
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_WIDTH (in_info, comp[0]),
|
||||||
GST_VIDEO_INFO_COMP_HEIGHT (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++] = EGL_WIDTH;
|
||||||
attribs[atti++] = GST_VIDEO_INFO_COMP_WIDTH (in_info, comp[0]);
|
attribs[atti++] = GST_VIDEO_INFO_COMP_WIDTH (in_info, comp[0]);
|
||||||
attribs[atti++] = EGL_HEIGHT;
|
attribs[atti++] = EGL_HEIGHT;
|
||||||
|
@ -672,8 +712,16 @@ gst_egl_image_from_dmabuf (GstGLContext * context,
|
||||||
attribs[atti++] = offset;
|
attribs[atti++] = offset;
|
||||||
attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
|
attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
|
||||||
attribs[atti++] = get_egl_stride (in_info, plane);
|
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;
|
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++)
|
for (i = 0; i < atti; i++)
|
||||||
GST_LOG ("attr %i: %" G_GINTPTR_FORMAT, i, attribs[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.
|
* a supported texture format for the given @target.
|
||||||
*
|
*
|
||||||
* Returns: %TRUE if the format is supported.
|
* Returns: %TRUE if the format is supported.
|
||||||
|
*
|
||||||
|
* Since: 1.24
|
||||||
*/
|
*/
|
||||||
gboolean
|
gboolean
|
||||||
gst_egl_image_check_dmabuf_direct_with_dma_drm (GstGLContext * context,
|
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
|
* @target: GL texture target this GstEGLImage is intended for
|
||||||
*
|
*
|
||||||
* Creates an EGL image that imports the dmabuf FD. The dmabuf data
|
* 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
|
* useful if the hardware is capable of performing color space conversions
|
||||||
* internally. The appropriate DRM format is picked, and the EGL image
|
* internally. The appropriate DRM format is picked, and the EGL image
|
||||||
* is created with this DRM format.
|
* 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,
|
gint * fd, const gsize * offset, const GstVideoInfo * in_info,
|
||||||
GstGLTextureTarget target)
|
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;
|
EGLImageKHR img;
|
||||||
|
const GstVideoInfo *in_info = &in_info_dma->vinfo;
|
||||||
guint n_planes = GST_VIDEO_INFO_N_PLANES (in_info);
|
guint n_planes = GST_VIDEO_INFO_N_PLANES (in_info);
|
||||||
guint32 fourcc;
|
guint32 fourcc;
|
||||||
|
guint64 modifier;
|
||||||
gint i;
|
gint i;
|
||||||
gboolean with_modifiers;
|
gboolean with_modifiers;
|
||||||
|
|
||||||
|
@ -819,14 +904,18 @@ gst_egl_image_from_dmabuf_direct_target (GstGLContext * context,
|
||||||
guintptr attribs[41]; /* 6 + 10 * 3 + 4 + 1 */
|
guintptr attribs[41]; /* 6 + 10 * 3 + 4 + 1 */
|
||||||
gint atti = 0;
|
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;
|
return NULL;
|
||||||
|
|
||||||
fourcc =
|
fourcc = in_info_dma->drm_fourcc;
|
||||||
gst_video_dma_drm_fourcc_from_format (GST_VIDEO_INFO_FORMAT (in_info));
|
modifier = in_info_dma->drm_modifier;
|
||||||
with_modifiers = gst_gl_context_check_feature (context,
|
with_modifiers = gst_gl_context_check_feature (context,
|
||||||
"EGL_EXT_image_dma_buf_import_modifiers");
|
"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 */
|
/* EGL DMABuf importation supports a maximum of 3 planes */
|
||||||
if (G_UNLIKELY (n_planes > 3))
|
if (G_UNLIKELY (n_planes > 3))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -846,11 +935,11 @@ gst_egl_image_from_dmabuf_direct_target (GstGLContext * context,
|
||||||
attribs[atti++] = offset[0];
|
attribs[atti++] = offset[0];
|
||||||
attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
|
attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
|
||||||
attribs[atti++] = get_egl_stride (in_info, 0);
|
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++] = 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++] = 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++] = offset[1];
|
||||||
attribs[atti++] = EGL_DMA_BUF_PLANE1_PITCH_EXT;
|
attribs[atti++] = EGL_DMA_BUF_PLANE1_PITCH_EXT;
|
||||||
attribs[atti++] = get_egl_stride (in_info, 1);
|
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++] = 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++] = 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++] = offset[2];
|
||||||
attribs[atti++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
|
attribs[atti++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
|
||||||
attribs[atti++] = get_egl_stride (in_info, 2);
|
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++] = 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++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT;
|
||||||
attribs[atti++] = (DRM_FORMAT_MOD_LINEAR >> 32) & 0xffffffff;
|
attribs[atti++] = (modifier >> 32) & 0xffffffff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,12 @@ GstEGLImage * gst_egl_image_from_dmabuf (GstGLContext *
|
||||||
gint plane,
|
gint plane,
|
||||||
gsize offset);
|
gsize offset);
|
||||||
GST_GL_API
|
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,
|
GstEGLImage * gst_egl_image_from_dmabuf_direct (GstGLContext * context,
|
||||||
gint *fd,
|
gint *fd,
|
||||||
const gsize *offset,
|
const gsize *offset,
|
||||||
|
@ -101,6 +107,13 @@ GstEGLImage * gst_egl_image_from_dmabuf_direct_target (GstGLContext *
|
||||||
GstGLTextureTarget target);
|
GstGLTextureTarget target);
|
||||||
|
|
||||||
GST_GL_API
|
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);
|
gboolean gst_egl_image_export_dmabuf (GstEGLImage *image, int *fd, gint *stride, gsize *offset);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue