gl/egl: support direct dmabuf import with external-oes only formats
authorPhilipp Zabel <p.zabel@pengutronix.de>
Thu, 13 Feb 2020 09:28:40 +0000 (10:28 +0100)
committerNicolas Dufresne <nicolas@ndufresne.ca>
Mon, 2 Mar 2020 11:07:26 +0000 (11:07 +0000)
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.

gst-libs/gst/gl/egl/gsteglimage.c
gst-libs/gst/gl/egl/gsteglimage.h
gst-libs/gst/gl/egl/gstglmemoryegl.c

index 43904be..246904f 100644 (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)
index 776a6b0..6aa56a4 100644 (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);
index 341c79e..84b07c9 100644 (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)));
   }