diff --git a/girs/GstGL-1.0.gir b/girs/GstGL-1.0.gir
index afe3f976d3..8282637e5d 100644
--- a/girs/GstGL-1.0.gir
+++ b/girs/GstGL-1.0.gir
@@ -3500,6 +3500,14 @@ extension.</doc>
         <doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstgldisplay.h">any display type</doc>
       </member>
     </bitfield>
+    <bitfield name="GLDrmFormatFlags" version="1.26" glib:type-name="GstGLDrmFormatFlags" glib:get-type="gst_gl_drm_format_flags_get_type" c:type="GstGLDrmFormatFlags">
+      <member name="include_external" value="1" c:identifier="GST_GL_DRM_FORMAT_INCLUDE_EXTERNAL" version="1.26" glib:nick="include-external" glib:name="GST_GL_DRM_FORMAT_INCLUDE_EXTERNAL">
+        <doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.h">include external-only formats</doc>
+      </member>
+      <member name="linear_only" value="2" c:identifier="GST_GL_DRM_FORMAT_LINEAR_ONLY" version="1.26" glib:nick="linear-only" glib:name="GST_GL_DRM_FORMAT_LINEAR_ONLY">
+        <doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.h">only include formats with linear modifier</doc>
+      </member>
+    </bitfield>
     <class name="GLFilter" c:symbol-prefix="gl_filter" c:type="GstGLFilter" parent="GLBaseFilter" glib:type-name="GstGLFilter" glib:get-type="gst_gl_filter_get_type" glib:type-struct="GLFilterClass">
       <doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglfilter.c">#GstGLFilter helps to implement simple OpenGL filter elements taking a
 single input and producing a single output with a #GstGLFramebuffer</doc>
@@ -10910,6 +10918,62 @@ multiple times.  This must be called before any other #GstGLBuffer operation.</d
         </parameter>
       </parameters>
     </function-macro>
+    <function name="gl_dma_buf_transform_drm_formats_to_gst_formats" c:identifier="gst_gl_dma_buf_transform_drm_formats_to_gst_formats" version="1.26">
+      <doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.c">Given the DRM formats in @src #GValue, collect corresponding GST formats to
+@dst #GValue. This function returns %FALSE if  the context is not an EGL
+context.</doc>
+      <source-position filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.h"/>
+      <return-value transfer-ownership="none">
+        <doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.c">whether any valid GST video formats were found and stored in @dst</doc>
+        <type name="gboolean" c:type="gboolean"/>
+      </return-value>
+      <parameters>
+        <parameter name="context" transfer-ownership="none">
+          <doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.c">a #GstContext</doc>
+          <type name="GLContext" c:type="GstGLContext*"/>
+        </parameter>
+        <parameter name="src" transfer-ownership="none">
+          <doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.c">value of "drm-format" field in #GstCaps as #GValue</doc>
+          <type name="GObject.Value" c:type="const GValue*"/>
+        </parameter>
+        <parameter name="flags" transfer-ownership="none">
+          <doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.c">transformation flags</doc>
+          <type name="GLDrmFormatFlags" c:type="GstGLDrmFormatFlags"/>
+        </parameter>
+        <parameter name="dst" direction="inout" caller-allocates="0" transfer-ownership="full">
+          <doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.c">empty destination #GValue</doc>
+          <type name="GObject.Value" c:type="GValue*"/>
+        </parameter>
+      </parameters>
+    </function>
+    <function name="gl_dma_buf_transform_gst_formats_to_drm_formats" c:identifier="gst_gl_dma_buf_transform_gst_formats_to_drm_formats" version="1.26">
+      <doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.c">Given the video formats in @src #GValue, collect corresponding drm formats
+supported by @context into @dst #GValue. This function returns %FALSE if
+the context is not an EGL context.</doc>
+      <source-position filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.h"/>
+      <return-value transfer-ownership="none">
+        <doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.c">whether any valid drm formats were found and stored in @dst</doc>
+        <type name="gboolean" c:type="gboolean"/>
+      </return-value>
+      <parameters>
+        <parameter name="context" transfer-ownership="none">
+          <doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.c">a #GstContext</doc>
+          <type name="GLContext" c:type="GstGLContext*"/>
+        </parameter>
+        <parameter name="src" transfer-ownership="none">
+          <doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.c">value of "format" field in #GstCaps as #GValue</doc>
+          <type name="GObject.Value" c:type="const GValue*"/>
+        </parameter>
+        <parameter name="flags" transfer-ownership="none">
+          <doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.c">transformation flags</doc>
+          <type name="GLDrmFormatFlags" c:type="GstGLDrmFormatFlags"/>
+        </parameter>
+        <parameter name="dst" direction="inout" caller-allocates="0" transfer-ownership="full">
+          <doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.c">empty destination #GValue</doc>
+          <type name="GObject.Value" c:type="GValue*"/>
+        </parameter>
+      </parameters>
+    </function>
     <function name="gl_element_propagate_display_context" c:identifier="gst_gl_element_propagate_display_context">
       <source-position filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.h"/>
       <return-value transfer-ownership="none">
diff --git a/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglupload.c b/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglupload.c
index e35674f10d..3898e9f390 100644
--- a/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglupload.c
+++ b/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglupload.c
@@ -717,12 +717,6 @@ static const UploadMethod _gl_memory_upload = {
 
 #if GST_GL_HAVE_DMABUF
 
-typedef enum
-{
-  GST_GL_DRM_FORMAT_INCLUDE_EXTERNAL = 1 << 1,
-  GST_GL_DRM_FORMAT_LINEAR_ONLY = 2 << 1,
-} GstGLDrmFormatFlags;
-
 typedef struct _GstEGLImageCacheEntry
 {
   GstEGLImage *eglimage[GST_VIDEO_MAX_PLANES];
@@ -873,107 +867,6 @@ _dma_buf_upload_new (GstGLUpload * upload)
   return dmabuf;
 }
 
-/* Append all drm format strings to drm_formats array. */
-static void
-_append_drm_formats_from_video_format (GstGLContext * context,
-    GstVideoFormat format, GstGLDrmFormatFlags flags,
-    GPtrArray * drm_formats)
-{
-  gint32 i, fourcc;
-  const GArray *dma_modifiers = NULL;
-  char *drm_format;
-
-  fourcc = gst_video_dma_drm_fourcc_from_format (format);
-  if (fourcc == DRM_FORMAT_INVALID)
-    return;
-
-  if (!gst_gl_context_egl_get_format_modifiers (context, fourcc,
-          &dma_modifiers))
-    return;
-
-  /* No modifier info, lets warn and move on */
-  if (!dma_modifiers) {
-    GST_WARNING_OBJECT (context, "Undefined modifiers list for %"
-        GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
-    return;
-  }
-
-  for (i = 0; i < dma_modifiers->len; i++) {
-    GstGLDmaModifier *mod = &g_array_index (dma_modifiers, GstGLDmaModifier, i);
-
-    if (!(flags & GST_GL_DRM_FORMAT_INCLUDE_EXTERNAL) && mod->external_only)
-      continue;
-
-    if (flags & GST_GL_DRM_FORMAT_LINEAR_ONLY && mod->modifier != DRM_FORMAT_MOD_LINEAR)
-      continue;
-
-    drm_format = gst_video_dma_drm_fourcc_to_string (fourcc, mod->modifier);
-    g_ptr_array_add (drm_formats, drm_format);
-  }
-}
-
-/* Given the video formats in src GValue, collecting all the according
-   drm formats to dst GValue. Return FALSE if no valid drm formats found. */
-static gboolean
-_dma_buf_transform_gst_formats_to_drm_formats (GstGLContext * context,
-    const GValue * video_value, GstGLDrmFormatFlags flags,
-    GValue * drm_value)
-{
-  GstVideoFormat gst_format;
-  GPtrArray *all_drm_formats = NULL;
-  guint i;
-
-  all_drm_formats = g_ptr_array_new ();
-
-  if (G_VALUE_HOLDS_STRING (video_value)) {
-    gst_format =
-        gst_video_format_from_string (g_value_get_string (video_value));
-    if (gst_format != GST_VIDEO_FORMAT_UNKNOWN) {
-      _append_drm_formats_from_video_format (context, gst_format,
-          flags, all_drm_formats);
-    }
-  } else if (GST_VALUE_HOLDS_LIST (video_value)) {
-    guint num_values = gst_value_list_get_size (video_value);
-
-    for (i = 0; i < num_values; i++) {
-      const GValue *val = gst_value_list_get_value (video_value, i);
-
-      gst_format = gst_video_format_from_string (g_value_get_string (val));
-      if (gst_format == GST_VIDEO_FORMAT_UNKNOWN)
-        continue;
-
-      _append_drm_formats_from_video_format (context, gst_format,
-          flags, all_drm_formats);
-    }
-  }
-
-  if (all_drm_formats->len == 0) {
-    g_ptr_array_unref (all_drm_formats);
-    return FALSE;
-  }
-
-  if (all_drm_formats->len == 1) {
-    g_value_init (drm_value, G_TYPE_STRING);
-    g_value_take_string (drm_value, g_ptr_array_index (all_drm_formats, 0));
-  } else {
-    GValue item = G_VALUE_INIT;
-
-    gst_value_list_init (drm_value, all_drm_formats->len);
-
-    for (i = 0; i < all_drm_formats->len; i++) {
-      g_value_init (&item, G_TYPE_STRING);
-      g_value_take_string (&item, g_ptr_array_index (all_drm_formats, i));
-      gst_value_list_append_value (drm_value, &item);
-      g_value_unset (&item);
-    }
-  }
-
-  /* The strings are already token by the GValue, no need to free. */
-  g_ptr_array_unref (all_drm_formats);
-
-  return TRUE;
-}
-
 static gboolean
 _check_modifier (GstGLContext * context, guint32 fourcc,
     guint64 modifier, gboolean include_external)
@@ -1019,93 +912,6 @@ _set_default_formats_list (GstStructure * structure)
   gst_structure_take_value (structure, "format", &formats);
 }
 
-static GstVideoFormat
-_get_video_format_from_drm_format (GstGLContext * context,
-    const gchar * drm_format, GstGLDrmFormatFlags flags)
-{
-  GstVideoFormat gst_format;
-  guint32 fourcc;
-  guint64 modifier;
-
-  fourcc = gst_video_dma_drm_fourcc_from_string (drm_format, &modifier);
-  if (fourcc == DRM_FORMAT_INVALID)
-    return GST_VIDEO_FORMAT_UNKNOWN;
-
-  if (flags & GST_GL_DRM_FORMAT_LINEAR_ONLY && modifier != DRM_FORMAT_MOD_LINEAR)
-    return GST_VIDEO_FORMAT_UNKNOWN;
-
-  gst_format = gst_video_dma_drm_fourcc_to_format (fourcc);
-  if (gst_format == GST_VIDEO_FORMAT_UNKNOWN)
-    return GST_VIDEO_FORMAT_UNKNOWN;
-
-  if (!_check_modifier (context, fourcc, modifier, flags & GST_GL_DRM_FORMAT_INCLUDE_EXTERNAL))
-    return GST_VIDEO_FORMAT_UNKNOWN;
-
-  return gst_format;
-}
-
-/* Given the drm formats in src GValue, collecting all the according
-   gst formats to dst GValue. Return FALSE if no valid drm formats found. */
-static gboolean
-_dma_buf_transform_drm_formats_to_gst_formats (GstGLContext * context,
-    const GValue * drm_value, GstGLDrmFormatFlags flags,
-    GValue * video_value)
-{
-  GstVideoFormat gst_format;
-  GArray *all_formats = NULL;
-  guint i;
-
-  all_formats = g_array_new (FALSE, FALSE, sizeof (GstVideoFormat));
-
-  if (G_VALUE_HOLDS_STRING (drm_value)) {
-    gst_format = _get_video_format_from_drm_format (context,
-        g_value_get_string (drm_value), flags);
-
-    if (gst_format != GST_VIDEO_FORMAT_UNKNOWN)
-      g_array_append_val (all_formats, gst_format);
-  } else if (GST_VALUE_HOLDS_LIST (drm_value)) {
-    guint num_values = gst_value_list_get_size (drm_value);
-
-    for (i = 0; i < num_values; i++) {
-      const GValue *val = gst_value_list_get_value (drm_value, i);
-
-      gst_format = _get_video_format_from_drm_format (context,
-          g_value_get_string (val), flags);
-      if (gst_format == GST_VIDEO_FORMAT_UNKNOWN)
-        continue;
-
-      g_array_append_val (all_formats, gst_format);
-    }
-  }
-
-  if (all_formats->len == 0) {
-    g_array_unref (all_formats);
-    return FALSE;
-  }
-
-  if (all_formats->len == 1) {
-    g_value_init (video_value, G_TYPE_STRING);
-    gst_format = g_array_index (all_formats, GstVideoFormat, 0);
-    g_value_set_string (video_value, gst_video_format_to_string (gst_format));
-  } else {
-    GValue item = G_VALUE_INIT;
-
-    gst_value_list_init (video_value, all_formats->len);
-
-    for (i = 0; i < all_formats->len; i++) {
-      g_value_init (&item, G_TYPE_STRING);
-      gst_format = g_array_index (all_formats, GstVideoFormat, i);
-      g_value_set_string (&item, gst_video_format_to_string (gst_format));
-      gst_value_list_append_value (video_value, &item);
-      g_value_unset (&item);
-    }
-  }
-
-  g_array_unref (all_formats);
-
-  return TRUE;
-}
-
 static gboolean
 _dma_buf_convert_format_field_in_structure (GstGLContext * context,
     GstStructure * structure, GstPadDirection direction,
@@ -1132,7 +938,7 @@ _dma_buf_convert_format_field_in_structure (GstGLContext * context,
       val = gst_structure_get_value (structure, "format");
     }
 
-    if (_dma_buf_transform_gst_formats_to_drm_formats (context,
+    if (gst_gl_dma_buf_transform_gst_formats_to_drm_formats (context,
             val, flags, &drm_formats)) {
       gst_structure_take_value (structure, "drm-format", &drm_formats);
     } else {
@@ -1157,7 +963,7 @@ _dma_buf_convert_format_field_in_structure (GstGLContext * context,
       return TRUE;
     }
 
-    if (_dma_buf_transform_drm_formats_to_gst_formats (context,
+    if (gst_gl_dma_buf_transform_drm_formats_to_gst_formats (context,
             val, flags, &gst_formats)) {
       gst_structure_take_value (structure, "format", &gst_formats);
     } else {
@@ -1192,7 +998,8 @@ _dma_buf_check_formats_in_structure (GstGLContext * context,
     if (fourcc == DRM_FORMAT_INVALID)
       return FALSE;
 
-    if (!_check_modifier (context, fourcc,
+    if (context &&
+        !gst_gl_context_egl_format_supports_modifier (context, fourcc,
             DRM_FORMAT_MOD_LINEAR, include_external))
       return FALSE;
 
@@ -1214,7 +1021,8 @@ _dma_buf_check_formats_in_structure (GstGLContext * context,
       if (fourcc == DRM_FORMAT_INVALID)
         continue;
 
-      if (!_check_modifier (context, fourcc,
+      if (context &&
+          !gst_gl_context_egl_format_supports_modifier (context, fourcc,
               DRM_FORMAT_MOD_LINEAR, include_external))
         continue;
 
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 e1bec0fe13..cae5942e1e 100644
--- a/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.c
+++ b/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.c
@@ -45,6 +45,16 @@
 #include <gst/gl/wayland/gstgldisplay_wayland.h>
 #endif
 
+#if GST_GL_HAVE_PLATFORM_EGL
+#include "egl/gstglcontext_egl.h"
+#endif
+
+#if GST_GL_HAVE_DMABUF
+#ifdef HAVE_LIBDRM
+#include <drm_fourcc.h>
+#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))
 #define USING_GLES(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES, 1, 0))
@@ -916,3 +926,236 @@ void gst_gl_set_affine_transformation_meta_from_ndc
   gst_gl_multiply_matrix4 (to_ndc_matrix, matrix, tmp);
   gst_gl_multiply_matrix4 (tmp, from_ndc_matrix, meta->matrix);
 }
+
+#ifdef HAVE_LIBDRM
+/* Append all drm format strings to drm_formats array. */
+static void
+_append_drm_formats_from_video_format (GstGLContext * context,
+    GstVideoFormat format, GstGLDrmFormatFlags flags, GPtrArray * drm_formats)
+{
+  gint32 i, fourcc;
+  const GArray *dma_modifiers = NULL;
+  char *drm_format;
+
+  fourcc = gst_video_dma_drm_fourcc_from_format (format);
+  if (fourcc == DRM_FORMAT_INVALID)
+    return;
+
+  if (!gst_gl_context_egl_get_format_modifiers (context, fourcc,
+          &dma_modifiers))
+    return;
+
+  /* No modifier info, lets warn and move on */
+  if (!dma_modifiers) {
+    GST_WARNING_OBJECT (context, "Undefined modifiers list for %"
+        GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
+    return;
+  }
+
+  for (i = 0; i < dma_modifiers->len; i++) {
+    GstGLDmaModifier *mod = &g_array_index (dma_modifiers, GstGLDmaModifier, i);
+
+    if (!(flags & GST_GL_DRM_FORMAT_INCLUDE_EXTERNAL) && mod->external_only)
+      continue;
+
+    if (flags & GST_GL_DRM_FORMAT_LINEAR_ONLY &&
+        mod->modifier != DRM_FORMAT_MOD_LINEAR)
+      continue;
+
+    drm_format = gst_video_dma_drm_fourcc_to_string (fourcc, mod->modifier);
+    g_ptr_array_add (drm_formats, drm_format);
+  }
+}
+#endif
+
+/**
+ * gst_gl_dma_buf_transform_gst_formats_to_drm_formats:
+ * @context: (transfer none): a #GstContext
+ * @src: value of "format" field in #GstCaps as #GValue
+ * @flags: transformation flags
+ * @dst: (inout): empty destination #GValue
+ *
+ * Given the video formats in @src #GValue, collect corresponding drm formats
+ * supported by @context into @dst #GValue. This function returns %FALSE if
+ * the context is not an EGL context.
+ *
+ * Returns: whether any valid drm formats were found and stored in @dst
+ *
+ * Since: 1.26
+ */
+gboolean
+gst_gl_dma_buf_transform_gst_formats_to_drm_formats (GstGLContext * context,
+    const GValue * src, GstGLDrmFormatFlags flags, GValue * dst)
+{
+#ifdef HAVE_LIBDRM
+  GstVideoFormat gst_format;
+  GPtrArray *all_drm_formats = NULL;
+  guint i;
+
+  /* This is only supported with EGL */
+  if (!GST_IS_GL_CONTEXT_EGL (context))
+    return FALSE;
+
+  all_drm_formats = g_ptr_array_new ();
+
+  if (G_VALUE_HOLDS_STRING (src)) {
+    gst_format = gst_video_format_from_string (g_value_get_string (src));
+    if (gst_format != GST_VIDEO_FORMAT_UNKNOWN) {
+      _append_drm_formats_from_video_format (context, gst_format,
+          flags, all_drm_formats);
+    }
+  } else if (GST_VALUE_HOLDS_LIST (src)) {
+    guint num_values = gst_value_list_get_size (src);
+
+    for (i = 0; i < num_values; i++) {
+      const GValue *val = gst_value_list_get_value (src, i);
+
+      gst_format = gst_video_format_from_string (g_value_get_string (val));
+      if (gst_format == GST_VIDEO_FORMAT_UNKNOWN)
+        continue;
+
+      _append_drm_formats_from_video_format (context, gst_format,
+          flags, all_drm_formats);
+    }
+  }
+
+  if (all_drm_formats->len == 0) {
+    g_ptr_array_unref (all_drm_formats);
+    return FALSE;
+  }
+
+  if (all_drm_formats->len == 1) {
+    g_value_init (dst, G_TYPE_STRING);
+    g_value_take_string (dst, g_ptr_array_index (all_drm_formats, 0));
+  } else {
+    GValue item = G_VALUE_INIT;
+
+    gst_value_list_init (dst, all_drm_formats->len);
+
+    for (i = 0; i < all_drm_formats->len; i++) {
+      g_value_init (&item, G_TYPE_STRING);
+      g_value_take_string (&item, g_ptr_array_index (all_drm_formats, i));
+      gst_value_list_append_value (dst, &item);
+      g_value_unset (&item);
+    }
+  }
+
+  /* The strings are already taken by the GValue, no need to free. */
+  g_ptr_array_unref (all_drm_formats);
+
+  return TRUE;
+#else
+  return FALSE;
+#endif
+}
+
+#ifdef HAVE_LIBDRM
+static GstVideoFormat
+_get_video_format_from_drm_format (GstGLContext * context,
+    const gchar * drm_format, GstGLDrmFormatFlags flags)
+{
+  GstVideoFormat gst_format;
+  guint32 fourcc;
+  guint64 modifier;
+
+  fourcc = gst_video_dma_drm_fourcc_from_string (drm_format, &modifier);
+  if (fourcc == DRM_FORMAT_INVALID)
+    return GST_VIDEO_FORMAT_UNKNOWN;
+
+  if (flags & GST_GL_DRM_FORMAT_LINEAR_ONLY &&
+      modifier != DRM_FORMAT_MOD_LINEAR)
+    return GST_VIDEO_FORMAT_UNKNOWN;
+
+  gst_format = gst_video_dma_drm_fourcc_to_format (fourcc);
+  if (gst_format == GST_VIDEO_FORMAT_UNKNOWN)
+    return GST_VIDEO_FORMAT_UNKNOWN;
+
+  if (!gst_gl_context_egl_format_supports_modifier (context, fourcc, modifier,
+      flags & GST_GL_DRM_FORMAT_INCLUDE_EXTERNAL))
+    return GST_VIDEO_FORMAT_UNKNOWN;
+
+  return gst_format;
+}
+#endif
+
+/**
+ * gst_gl_dma_buf_transform_drm_formats_to_gst_formats:
+ * @context: (transfer none): a #GstContext
+ * @src: value of "drm-format" field in #GstCaps as #GValue
+ * @flags: transformation flags
+ * @dst: (inout): empty destination #GValue
+ *
+ * Given the DRM formats in @src #GValue, collect corresponding GST formats to
+ * @dst #GValue. This function returns %FALSE if  the context is not an EGL
+ * context.
+ *
+ * Returns: whether any valid GST video formats were found and stored in @dst
+ *
+ * Since: 1.26
+ */
+gboolean
+gst_gl_dma_buf_transform_drm_formats_to_gst_formats (GstGLContext * context,
+    const GValue * src, GstGLDrmFormatFlags flags, GValue * dst)
+{
+#ifdef HAVE_LIBDRM
+  GstVideoFormat gst_format;
+  GArray *all_formats = NULL;
+  guint i;
+
+  /* This is only supported with EGL */
+  if (!GST_IS_GL_CONTEXT_EGL (context))
+    return FALSE;
+
+  all_formats = g_array_new (FALSE, FALSE, sizeof (GstVideoFormat));
+
+  if (G_VALUE_HOLDS_STRING (src)) {
+    gst_format = _get_video_format_from_drm_format (context,
+        g_value_get_string (src), flags);
+
+    if (gst_format != GST_VIDEO_FORMAT_UNKNOWN)
+      g_array_append_val (all_formats, gst_format);
+  } else if (GST_VALUE_HOLDS_LIST (src)) {
+    guint num_values = gst_value_list_get_size (src);
+
+    for (i = 0; i < num_values; i++) {
+      const GValue *val = gst_value_list_get_value (src, i);
+
+      gst_format = _get_video_format_from_drm_format (context,
+          g_value_get_string (val), flags);
+      if (gst_format == GST_VIDEO_FORMAT_UNKNOWN)
+        continue;
+
+      g_array_append_val (all_formats, gst_format);
+    }
+  }
+
+  if (all_formats->len == 0) {
+    g_array_unref (all_formats);
+    return FALSE;
+  }
+
+  if (all_formats->len == 1) {
+    g_value_init (dst, G_TYPE_STRING);
+    gst_format = g_array_index (all_formats, GstVideoFormat, 0);
+    g_value_set_string (dst, gst_video_format_to_string (gst_format));
+  } else {
+    GValue item = G_VALUE_INIT;
+
+    gst_value_list_init (dst, all_formats->len);
+
+    for (i = 0; i < all_formats->len; i++) {
+      g_value_init (&item, G_TYPE_STRING);
+      gst_format = g_array_index (all_formats, GstVideoFormat, i);
+      g_value_set_string (&item, gst_video_format_to_string (gst_format));
+      gst_value_list_append_value (dst, &item);
+      g_value_unset (&item);
+    }
+  }
+
+  g_array_unref (all_formats);
+
+  return TRUE;
+#else
+  return FALSE;
+#endif
+}
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 b27145489f..9258cdc64f 100644
--- a/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.h
+++ b/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglutils.h
@@ -67,6 +67,40 @@ void gst_gl_set_affine_transformation_meta_from_ndc (GstVideoAffineTransformatio
 GST_GL_API
 void gst_gl_multiply_matrix4 (const gfloat * a, const gfloat * b, gfloat * result);
 
+/**
+ * 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)
+ *
+ * Since: 1.26
+ */
+typedef enum
+{
+  /**
+   * GST_GL_DRM_FORMAT_INCLUDE_EXTERNAL:
+   *
+   * include external-only formats
+   *
+   * Since: 1.26
+   */
+  GST_GL_DRM_FORMAT_INCLUDE_EXTERNAL = 1 << 0,
+ /**
+  * GST_GL_DRM_FORMAT_LINEAR_ONLY:
+  *
+  * only include formats with linear modifier
+  *
+  * Since: 1.26
+  */
+  GST_GL_DRM_FORMAT_LINEAR_ONLY = 1 << 1,
+} GstGLDrmFormatFlags;
+
+GST_GL_API
+gboolean gst_gl_dma_buf_transform_gst_formats_to_drm_formats (GstGLContext * context,
+    const GValue * src, GstGLDrmFormatFlags flags, GValue * dst);
+
+GST_GL_API
+gboolean gst_gl_dma_buf_transform_drm_formats_to_gst_formats (GstGLContext * context,
+    const GValue * src, GstGLDrmFormatFlags flags, GValue * dst);
 
 G_END_DECLS