gl/egl: support direct dmabuf import with external-oes only formats

Allow creating EGL images from DMA buffers in formats that the driver
only supports for the external-oes texture target.

Pass the intended texture target to gst_egl_image_from_dmabuf_direct so
that _gst_egl_image_check_dmabuf_direct can decide whether to create an
EGL image for a format that can only be targeted at external-oes
textures by the driver. Allow creating GstGLMemoryEGL objects from these
DMA buffers.
This commit is contained in:
Philipp Zabel 2020-02-13 10:28:40 +01:00 committed by Nicolas Dufresne
parent 7da70e2b9f
commit 359e361881
3 changed files with 52 additions and 10 deletions

View file

@ -714,7 +714,8 @@ _drm_direct_fourcc_from_info (GstVideoInfo * info)
}
static gboolean
_gst_egl_image_check_dmabuf_direct (GstGLContext * context, int fourcc)
_gst_egl_image_check_dmabuf_direct (GstGLContext * context, int fourcc,
GstGLTextureTarget target)
{
EGLDisplay egl_display = EGL_DEFAULT_DISPLAY;
GstGLDisplayEGL *display_egl;
@ -800,7 +801,7 @@ _gst_egl_image_check_dmabuf_direct (GstGLContext * context, int fourcc)
GST_DEBUG ("driver only supports external import of fourcc %"
GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
}
ret = !external_only[i];
ret = !external_only[i] || (target == GST_GL_TEXTURE_TARGET_EXTERNAL_OES);
g_free (modifiers);
g_free (external_only);
return ret;
@ -814,11 +815,12 @@ _gst_egl_image_check_dmabuf_direct (GstGLContext * context, int fourcc)
}
/**
* gst_egl_image_from_dmabuf_direct:
* gst_egl_image_from_dmabuf_direct_target:
* @context: a #GstGLContext (must be an EGL context)
* @fd: Array of DMABuf file descriptors
* @offset: Array of offsets, relative to the DMABuf
* @in_info: the #GstVideoInfo
* @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
@ -831,10 +833,13 @@ _gst_egl_image_check_dmabuf_direct (GstGLContext * context, int fourcc)
* a single plane.
*
* Returns: a #GstEGLImage wrapping @dmabuf or %NULL on failure
*
* Since: 1.18
*/
GstEGLImage *
gst_egl_image_from_dmabuf_direct (GstGLContext * context,
gint * fd, gsize * offset, GstVideoInfo * in_info)
gst_egl_image_from_dmabuf_direct_target (GstGLContext * context,
gint * fd, gsize * offset, GstVideoInfo * in_info,
GstGLTextureTarget target)
{
EGLImageKHR img;
@ -856,7 +861,7 @@ gst_egl_image_from_dmabuf_direct (GstGLContext * context,
if (fourcc == -1)
return NULL;
if (!_gst_egl_image_check_dmabuf_direct (context, fourcc))
if (!_gst_egl_image_check_dmabuf_direct (context, fourcc, target))
return NULL;
with_modifiers = gst_gl_context_check_feature (context,
@ -980,6 +985,33 @@ gst_egl_image_from_dmabuf_direct (GstGLContext * context,
(GstEGLImageDestroyNotify) _destroy_egl_image);
}
/**
* gst_egl_image_from_dmabuf_direct:
* @context: a #GstGLContext (must be an EGL context)
* @fd: Array of DMABuf file descriptors
* @offset: Array of offsets, relative to the DMABuf
* @in_info: the #GstVideoInfo
*
* 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. The appropriate DRM format is picked, and the EGL image
* is created with this DRM format.
*
* 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: a #GstEGLImage wrapping @dmabuf or %NULL on failure
*/
GstEGLImage *
gst_egl_image_from_dmabuf_direct (GstGLContext * context,
gint * fd, gsize * offset, GstVideoInfo * in_info)
{
return gst_egl_image_from_dmabuf_direct_target (context, fd, offset, in_info,
GST_GL_TEXTURE_TARGET_2D);
}
gboolean
gst_egl_image_export_dmabuf (GstEGLImage * image, int *fd, gint * stride,
gsize * offset)

View file

@ -93,6 +93,12 @@ GstEGLImage * gst_egl_image_from_dmabuf_direct (GstGLContext *
gint *fd,
gsize *offset,
GstVideoInfo * in_info);
GST_GL_API
GstEGLImage * gst_egl_image_from_dmabuf_direct_target (GstGLContext * context,
gint *fd,
gsize *offset,
GstVideoInfo * in_info,
GstGLTextureTarget target);
GST_GL_API
gboolean gst_egl_image_export_dmabuf (GstEGLImage *image, int *fd, gint *stride, gsize *offset);

View file

@ -147,12 +147,14 @@ _gl_mem_egl_alloc (GstGLBaseMemoryAllocator * allocator,
mem = g_new0 (GstGLMemoryEGL, 1);
if (alloc_flags & GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_WRAP_GPU_HANDLE) {
if (params->target != GST_GL_TEXTURE_TARGET_2D) {
if (params->target != GST_GL_TEXTURE_TARGET_2D &&
params->target != GST_GL_TEXTURE_TARGET_EXTERNAL_OES) {
g_free (mem);
GST_CAT_ERROR (GST_CAT_GL_MEMORY, "GstGLMemoryEGL only supports wrapping "
"2D textures");
"2D and external-oes textures");
return NULL;
}
mem->mem.tex_target = params->target;
mem->image = gst_egl_image_ref (params->parent.gl_handle);
}
@ -197,9 +199,11 @@ _gl_mem_create (GstGLMemoryEGL * gl_mem, GError ** error)
return FALSE;
}
} else {
guint gl_target = gst_gl_texture_target_to_gl (gl_mem->mem.tex_target);
gl->ActiveTexture (GL_TEXTURE0 + gl_mem->mem.plane);
gl->BindTexture (GL_TEXTURE_2D, gl_mem->mem.tex_id);
gl->EGLImageTargetTexture2D (GL_TEXTURE_2D,
gl->BindTexture (gl_target, gl_mem->mem.tex_id);
gl->EGLImageTargetTexture2D (gl_target,
gst_egl_image_get_image (GST_EGL_IMAGE (gl_mem->image)));
}