diff --git a/girs/GstGL-1.0.gir b/girs/GstGL-1.0.gir
index 8282637e5d..e9fd842c10 100644
--- a/girs/GstGL-1.0.gir
+++ b/girs/GstGL-1.0.gir
@@ -3507,6 +3507,9 @@ extension.
only include formats with linear modifier
+
+ include emulated formats
+
#GstGLFilter helps to implement simple OpenGL filter elements taking a
diff --git a/subprojects/gst-plugins-base/ext/gl/gstgldownloadelement.c b/subprojects/gst-plugins-base/ext/gl/gstgldownloadelement.c
index 6c0e91c63c..00e63c9a1a 100644
--- a/subprojects/gst-plugins-base/ext/gl/gstgldownloadelement.c
+++ b/subprojects/gst-plugins-base/ext/gl/gstgldownloadelement.c
@@ -958,7 +958,7 @@ _convert_dma_drm (GstGLContext * context, GstStructure * s)
GValue newfmtval = G_VALUE_INIT;
if (context && gst_gl_dma_buf_transform_drm_formats_to_gst_formats (context,
- drmval, 0, &newfmtval)) {
+ drmval, GST_GL_DRM_FORMAT_INCLUDE_EMULATED, &newfmtval)) {
gst_structure_set_value (s, "format", &newfmtval);
gst_structure_remove_field (s, "drm-format");
g_value_unset (&newfmtval);
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 c3ee82afdb..1dc4e9064c 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
@@ -489,10 +489,9 @@ gst_egl_image_from_texture (GstGLContext * context, GstGLMemory * gl_mem,
* target.
*/
static int
-_drm_rgba_fourcc_from_info (const GstVideoInfo * info, int plane,
+_drm_rgba_fourcc_from_format (GstVideoFormat format, int plane,
GstGLFormat * out_format)
{
- GstVideoFormat format = GST_VIDEO_INFO_FORMAT (info);
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
const gint rgba_fourcc = DRM_FORMAT_ABGR8888;
const gint rgb_fourcc = DRM_FORMAT_BGR888;
@@ -657,7 +656,8 @@ gst_egl_image_from_dmabuf (GstGLContext * context,
gboolean with_modifiers;
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_format (GST_VIDEO_INFO_FORMAT (in_info), plane,
+ &format);
GST_DEBUG ("fourcc %.4s (%d) plane %d (%dx%d)",
(char *) &fourcc, fourcc, plane,
GST_VIDEO_INFO_COMP_WIDTH (in_info, comp[0]),
@@ -1096,4 +1096,69 @@ gst_egl_image_export_dmabuf (GstEGLImage * image, int *fd, gint * stride,
return TRUE;
}
+/**
+ * gst_egl_image_can_emulate:
+ * @context: a #GstGLContext (must be an EGL context)
+ * @format: a #GstVideoFormat
+ *
+ * Checks if the given @context can emulate @format using a limited subset of
+ * RGB texture formats. Such @format is then suitable for importing using
+ * gst_egl_image_from_dmabuf() even when GL supports the video format as
+ * external-only or not at all.
+ *
+ * Returns: #TRUE if @format can be emulated
+ */
+gboolean
+gst_egl_image_can_emulate (GstGLContext * context, GstVideoFormat format)
+{
+ const GstVideoFormatInfo *info;
+ guint i;
+ GstGLFormat out_format;
+
+ info = gst_video_format_get_info (format);
+
+ for (i = 0; i != GST_VIDEO_FORMAT_INFO_N_PLANES (info); ++i) {
+ int fourcc;
+
+ fourcc = _drm_rgba_fourcc_from_format (format, i, &out_format);
+ if (fourcc == -1) {
+ return FALSE;
+ }
+
+ if (GST_VIDEO_FORMAT_INFO_IS_YUV (info)) {
+ /* For YUV formats we only support linear modifier. */
+ if (!gst_gl_context_egl_format_supports_modifier (context, fourcc,
+ DRM_FORMAT_MOD_LINEAR, FALSE)) {
+ return FALSE;
+ }
+ } else if (GST_VIDEO_FORMAT_INFO_IS_RGB (info)) {
+ /* For RGB formats any DMA format that is not external-only will do. */
+ const GArray *dma_modifiers;
+ guint j;
+
+ if (!gst_gl_context_egl_get_format_modifiers (context, fourcc,
+ &dma_modifiers)) {
+ return FALSE;
+ }
+
+ for (j = 0; j < dma_modifiers->len; ++j) {
+ GstGLDmaModifier *mod =
+ &g_array_index (dma_modifiers, GstGLDmaModifier, j);
+
+ if (!mod->external_only) {
+ break;
+ }
+ }
+
+ if (j == dma_modifiers->len) {
+ return FALSE;
+ }
+ } else {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
#endif /* GST_GL_HAVE_DMABUF */
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 b34607d40c..c69d65a768 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
@@ -111,6 +111,10 @@ GstEGLImage * gst_egl_image_from_dmabuf_direct_target_with_dma_drm
GstGLTextureTarget target);
GST_GL_API
gboolean gst_egl_image_export_dmabuf (GstEGLImage *image, int *fd, gint *stride, gsize *offset);
+
+GST_GL_API
+gboolean gst_egl_image_can_emulate (GstGLContext * context,
+ GstVideoFormat format);
#endif
/**
diff --git a/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.c b/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.c
index cae5942e1e..71a3c93081 100644
--- a/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.c
+++ b/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.c
@@ -47,13 +47,13 @@
#if GST_GL_HAVE_PLATFORM_EGL
#include "egl/gstglcontext_egl.h"
-#endif
-
+#include "egl/gsteglimage.h"
#if GST_GL_HAVE_DMABUF
#ifdef HAVE_LIBDRM
#include
#endif
#endif
+#endif
#define USING_OPENGL(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0))
#define USING_OPENGL3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 1))
@@ -934,6 +934,7 @@ _append_drm_formats_from_video_format (GstGLContext * context,
GstVideoFormat format, GstGLDrmFormatFlags flags, GPtrArray * drm_formats)
{
gint32 i, fourcc;
+ gint32 num_added = 0;
const GArray *dma_modifiers = NULL;
char *drm_format;
@@ -964,6 +965,14 @@ _append_drm_formats_from_video_format (GstGLContext * context,
drm_format = gst_video_dma_drm_fourcc_to_string (fourcc, mod->modifier);
g_ptr_array_add (drm_formats, drm_format);
+ ++num_added;
+ }
+
+ if (num_added == 0 && (flags & GST_GL_DRM_FORMAT_INCLUDE_EMULATED) &&
+ gst_egl_image_can_emulate (context, format)) {
+ drm_format =
+ gst_video_dma_drm_fourcc_to_string (fourcc, DRM_FORMAT_MOD_LINEAR);
+ g_ptr_array_add (drm_formats, drm_format);
}
}
#endif
@@ -1071,7 +1080,9 @@ _get_video_format_from_drm_format (GstGLContext * context,
return GST_VIDEO_FORMAT_UNKNOWN;
if (!gst_gl_context_egl_format_supports_modifier (context, fourcc, modifier,
- flags & GST_GL_DRM_FORMAT_INCLUDE_EXTERNAL))
+ flags & GST_GL_DRM_FORMAT_INCLUDE_EXTERNAL) &&
+ !(flags & GST_GL_DRM_FORMAT_INCLUDE_EMULATED &&
+ gst_egl_image_can_emulate (context, gst_format)))
return GST_VIDEO_FORMAT_UNKNOWN;
return gst_format;
diff --git a/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.h b/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.h
index 9258cdc64f..78d4091c1e 100644
--- a/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.h
+++ b/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.h
@@ -71,6 +71,7 @@ void gst_gl_multiply_matrix4 (const gfloat * a, const gfloat * b, gfloat * resul
* GstGLDrmFormatFlags:
* @GST_GL_DRM_FORMAT_INCLUDE_EXTERNAL: include external-only formats (Since: 1.26)
* @GST_GL_DRM_FORMAT_LINEAR_ONLY: only include formats with linear modifier (Since: 1.26)
+ * @GST_GL_DRM_FORMAT_INCLUDE_EMULATED: include emulated formats (Since: 1.26)
*
* Since: 1.26
*/
@@ -92,6 +93,14 @@ typedef enum
* Since: 1.26
*/
GST_GL_DRM_FORMAT_LINEAR_ONLY = 1 << 1,
+ /**
+ * GST_GL_DRM_FORMAT_INCLUDE_EMULATED:
+ *
+ * include emulated formats
+ *
+ * Since: 1.26
+ */
+ GST_GL_DRM_FORMAT_INCLUDE_EMULATED = 1 << 2,
} GstGLDrmFormatFlags;
GST_GL_API