diff --git a/girs/GstGL-1.0.gir b/girs/GstGL-1.0.gir
index 4cfec0bdab..df41d496d3 100644
--- a/girs/GstGL-1.0.gir
+++ b/girs/GstGL-1.0.gir
@@ -11213,6 +11213,31 @@ NDC coordinates in @matrix.
+
+ Given @swizzle, produce @inversion such that:
+
+@swizzle[@inversion[i]] == identity[i] where:
+- identity = {0, 1, 2,...}
+- unset fields are marked by -1
+
+
+
+
+
+
+ input swizzle
+
+
+
+
+
+ resulting inversion
+
+
+
+
+
+
@@ -11365,6 +11390,35 @@ NDC coordinates in @matrix.
+
+ Calculates the swizzle indices for @video_format and @gl_format in order to
+access a texture such that accessing a texel from a texture through the swizzle
+index produces values in the order (R, G, B, A) or (Y, U, V, A).
+
+For multi-planer formats, the swizzle index uses the same component order (RGBA/YUVA)
+and should be applied after combining multiple planes into a single rgba/yuva value.
+e.g. sampling from a NV12 format would have Y from one texture and UV from
+another texture into a (Y, U, V) value. Add an Aplha component and then
+perform swizzling. Sampling from NV21 would produce (Y, V, U) which is then
+swizzled to (Y, U, V).
+
+
+ whether valid swizzle indices could be found
+
+
+
+
+ the #GstVideoFormat in use
+
+
+
+ the returned swizzle indices
+
+
+
+
+
+
the quark used for #GstGLWindow in #GError's
diff --git a/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglcolorconvert.c b/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglcolorconvert.c
index 358ce7fae8..03be2844d2 100644
--- a/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglcolorconvert.c
+++ b/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglcolorconvert.c
@@ -1624,65 +1624,11 @@ _index_to_shader_swizzle (int idx)
}
}
-static void
-get_rgb_format_gl_swizzle_order (GstVideoFormat format,
- gint swizzle[GST_VIDEO_MAX_COMPONENTS])
-{
- const GstVideoFormatInfo *finfo = gst_video_format_get_info (format);
- int c_i = 0, i;
-
- g_return_if_fail (finfo->flags & GST_VIDEO_FORMAT_FLAG_RGB
- || format == GST_VIDEO_FORMAT_AYUV || format == GST_VIDEO_FORMAT_VUYA);
-
- for (i = 0; i < finfo->n_components; i++) {
- swizzle[c_i++] = finfo->poffset[i];
- }
-
- /* special case spaced RGB formats as the space does not contain a poffset
- * value and we need all four components to be valid in order to swizzle
- * correctly */
- if (format == GST_VIDEO_FORMAT_xRGB || format == GST_VIDEO_FORMAT_xBGR) {
- swizzle[c_i++] = 0;
- } else if (format == GST_VIDEO_FORMAT_RGBx || format == GST_VIDEO_FORMAT_BGRx) {
- swizzle[c_i++] = 3;
- } else {
- for (i = finfo->n_components; i < GST_VIDEO_MAX_COMPONENTS; i++) {
- swizzle[c_i++] = -1;
- }
- }
-}
-
static void
video_format_to_gl_reorder (GstVideoFormat v_format, gint * reorder,
gboolean input)
{
switch (v_format) {
- case GST_VIDEO_FORMAT_RGBA:
- case GST_VIDEO_FORMAT_RGBx:
- case GST_VIDEO_FORMAT_BGRA:
- case GST_VIDEO_FORMAT_BGRx:
- case GST_VIDEO_FORMAT_ARGB:
- case GST_VIDEO_FORMAT_xRGB:
- case GST_VIDEO_FORMAT_ABGR:
- case GST_VIDEO_FORMAT_xBGR:
- case GST_VIDEO_FORMAT_AYUV:
- case GST_VIDEO_FORMAT_VUYA:
- get_rgb_format_gl_swizzle_order (v_format, reorder);
- break;
- case GST_VIDEO_FORMAT_BGR:
- case GST_VIDEO_FORMAT_BGRP:
- reorder[0] = 2;
- reorder[1] = 1;
- reorder[2] = 0;
- reorder[3] = 3;
- break;
- case GST_VIDEO_FORMAT_RGB:
- case GST_VIDEO_FORMAT_RGBP:
- reorder[0] = 0;
- reorder[1] = 1;
- reorder[2] = 2;
- reorder[3] = 3;
- break;
case GST_VIDEO_FORMAT_UYVY:
reorder[0] = 1;
reorder[1] = 0;
@@ -1698,55 +1644,9 @@ video_format_to_gl_reorder (GstVideoFormat v_format, gint * reorder,
reorder[2] = 0;
reorder[3] = input ? 3 : 2;
break;
- case GST_VIDEO_FORMAT_AV12:
- case GST_VIDEO_FORMAT_NV12:
- case GST_VIDEO_FORMAT_NV16:
- case GST_VIDEO_FORMAT_P010_10LE:
- case GST_VIDEO_FORMAT_P010_10BE:
- case GST_VIDEO_FORMAT_P012_LE:
- case GST_VIDEO_FORMAT_P012_BE:
- case GST_VIDEO_FORMAT_P016_LE:
- case GST_VIDEO_FORMAT_P016_BE:
- case GST_VIDEO_FORMAT_NV12_16L32S:
- case GST_VIDEO_FORMAT_NV12_4L4:
- reorder[0] = 0;
- reorder[1] = 1;
- reorder[2] = 2;
- reorder[3] = 3;
- break;
- case GST_VIDEO_FORMAT_NV21:
- case GST_VIDEO_FORMAT_NV61:
- reorder[0] = 0;
- reorder[1] = 2;
- reorder[2] = 1;
- reorder[3] = 3;
- break;
- case GST_VIDEO_FORMAT_Y410:
- case GST_VIDEO_FORMAT_Y412_LE:
- case GST_VIDEO_FORMAT_Y412_BE:
- reorder[0] = 1;
- reorder[1] = 0;
- reorder[2] = 2;
- reorder[3] = 0;
- break;
- case GST_VIDEO_FORMAT_I420:
- case GST_VIDEO_FORMAT_Y444:
- case GST_VIDEO_FORMAT_Y42B:
- case GST_VIDEO_FORMAT_Y41B:
- case GST_VIDEO_FORMAT_A420:
- reorder[0] = 0;
- reorder[1] = 1;
- reorder[2] = 2;
- reorder[3] = 3;
- break;
- case GST_VIDEO_FORMAT_YV12:
- reorder[0] = 0;
- reorder[1] = 2;
- reorder[2] = 1;
- reorder[3] = 3;
- break;
default:
- g_assert_not_reached ();
+ if (!gst_gl_video_format_swizzle (v_format, reorder))
+ g_assert_not_reached ();
break;
}
@@ -1754,30 +1654,6 @@ video_format_to_gl_reorder (GstVideoFormat v_format, gint * reorder,
reorder[3]);
}
-/* given a swizzle index, produce an index such that:
- *
- * swizzle[idx[i]] == identity[i] where:
- * - swizzle is the original swizzle
- * - idx is the result
- * - identity = {0, 1, 2,...}
- * - unset fields are marked by -1
- */
-static void
-swizzle_identity_order (gint * swizzle, gint * idx)
-{
- int i;
-
- for (i = 0; i < GST_VIDEO_MAX_COMPONENTS; i++) {
- idx[i] = -1;
- }
-
- for (i = 0; i < GST_VIDEO_MAX_COMPONENTS; i++) {
- if (swizzle[i] >= 0 && swizzle[i] < 4 && idx[swizzle[i]] == -1) {
- idx[swizzle[i]] = i;
- }
- }
-}
-
static void
calculate_reorder_indexes (GstVideoFormat in_format,
GstVideoFormat out_format,
@@ -1797,7 +1673,7 @@ calculate_reorder_indexes (GstVideoFormat in_format,
for (i = 0; i < GST_VIDEO_MAX_COMPONENTS; i++)
ret_out[i] = out_reorder[i];
} else {
- swizzle_identity_order (out_reorder, ret_out);
+ gst_gl_swizzle_invert (out_reorder, ret_out);
}
for (i = 0; i < GST_VIDEO_MAX_COMPONENTS; i++)
diff --git a/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglformat.c b/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglformat.c
index 4c7548bc4f..0614a9bcbd 100644
--- a/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglformat.c
+++ b/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglformat.c
@@ -456,6 +456,144 @@ gst_gl_format_n_components (GstGLFormat gl_format)
}
}
+static void
+get_single_planar_format_gl_swizzle_order (GstVideoFormat format,
+ gint swizzle[GST_VIDEO_MAX_COMPONENTS])
+{
+ const GstVideoFormatInfo *finfo = gst_video_format_get_info (format);
+ int c_i = 0, i;
+
+ g_return_if_fail (finfo->flags & GST_VIDEO_FORMAT_FLAG_RGB
+ || format == GST_VIDEO_FORMAT_AYUV || format == GST_VIDEO_FORMAT_VUYA);
+
+ for (i = 0; i < finfo->n_components; i++) {
+ swizzle[c_i++] = finfo->poffset[i];
+ }
+
+ /* special case spaced RGB formats as the space does not contain a poffset
+ * value and we need all four components to be valid in order to swizzle
+ * correctly */
+ if (format == GST_VIDEO_FORMAT_xRGB || format == GST_VIDEO_FORMAT_xBGR) {
+ swizzle[c_i++] = 0;
+ } else if (format == GST_VIDEO_FORMAT_RGBx || format == GST_VIDEO_FORMAT_BGRx
+ || format == GST_VIDEO_FORMAT_RGB || format == GST_VIDEO_FORMAT_BGR) {
+ swizzle[c_i++] = 3;
+ } else {
+ for (i = finfo->n_components; i < GST_VIDEO_MAX_COMPONENTS; i++) {
+ swizzle[c_i++] = -1;
+ }
+ }
+}
+
+/**
+ * gst_gl_video_format_swizzle:
+ * @video_format: the #GstVideoFormat in use
+ * @swizzle: (out) (array fixed-size=4): the returned swizzle indices
+ *
+ * Calculates the swizzle indices for @video_format and @gl_format in order to
+ * access a texture such that accessing a texel from a texture through the swizzle
+ * index produces values in the order (R, G, B, A) or (Y, U, V, A).
+ *
+ * For multi-planer formats, the swizzle index uses the same component order (RGBA/YUVA)
+ * and should be applied after combining multiple planes into a single rgba/yuva value.
+ * e.g. sampling from a NV12 format would have Y from one texture and UV from
+ * another texture into a (Y, U, V) value. Add an Aplha component and then
+ * perform swizzling. Sampling from NV21 would produce (Y, V, U) which is then
+ * swizzled to (Y, U, V).
+ *
+ * Returns: whether valid swizzle indices could be found
+ *
+ * Since: 1.24
+ */
+gboolean
+gst_gl_video_format_swizzle (GstVideoFormat video_format, int *swizzle)
+{
+ const GstVideoFormatInfo *finfo = gst_video_format_get_info (video_format);
+
+ if (finfo->n_planes == 1) {
+ get_single_planar_format_gl_swizzle_order (video_format, swizzle);
+ return TRUE;
+ }
+
+ switch (video_format) {
+ case GST_VIDEO_FORMAT_BGRP:
+ get_single_planar_format_gl_swizzle_order (GST_VIDEO_FORMAT_BGR, swizzle);
+ return TRUE;
+ case GST_VIDEO_FORMAT_RGBP:
+ get_single_planar_format_gl_swizzle_order (GST_VIDEO_FORMAT_RGB, swizzle);
+ return TRUE;
+ case GST_VIDEO_FORMAT_AV12:
+ case GST_VIDEO_FORMAT_NV12:
+ case GST_VIDEO_FORMAT_NV16:
+ case GST_VIDEO_FORMAT_P010_10LE:
+ case GST_VIDEO_FORMAT_P010_10BE:
+ case GST_VIDEO_FORMAT_P012_LE:
+ case GST_VIDEO_FORMAT_P012_BE:
+ case GST_VIDEO_FORMAT_P016_LE:
+ case GST_VIDEO_FORMAT_P016_BE:
+ case GST_VIDEO_FORMAT_NV12_16L32S:
+ case GST_VIDEO_FORMAT_NV12_4L4:
+ case GST_VIDEO_FORMAT_I420:
+ case GST_VIDEO_FORMAT_Y444:
+ case GST_VIDEO_FORMAT_Y42B:
+ case GST_VIDEO_FORMAT_Y41B:
+ case GST_VIDEO_FORMAT_A420:
+ swizzle[0] = 0;
+ swizzle[1] = 1;
+ swizzle[2] = 2;
+ swizzle[3] = 3;
+ return TRUE;
+ case GST_VIDEO_FORMAT_NV21:
+ case GST_VIDEO_FORMAT_NV61:
+ case GST_VIDEO_FORMAT_YV12:
+ swizzle[0] = 0;
+ swizzle[1] = 2;
+ swizzle[2] = 1;
+ swizzle[3] = 3;
+ return TRUE;
+ case GST_VIDEO_FORMAT_Y410:
+ case GST_VIDEO_FORMAT_Y412_LE:
+ case GST_VIDEO_FORMAT_Y412_BE:
+ swizzle[0] = 1;
+ swizzle[1] = 0;
+ swizzle[2] = 2;
+ swizzle[3] = 3;
+ return TRUE;
+ /* TODO: deal with YUY2 variants */
+ default:
+ return FALSE;
+ }
+}
+
+/**
+ * gst_gl_swizzle_invert:
+ * @swizzle: (array fixed-size=4): input swizzle
+ * @inversion: (out) (array fixed-size=4): resulting inversion
+ *
+ * Given @swizzle, produce @inversion such that:
+ *
+ * @swizzle[@inversion[i]] == identity[i] where:
+ * - identity = {0, 1, 2,...}
+ * - unset fields are marked by -1
+ *
+ * Since: 1.24
+ */
+void
+gst_gl_swizzle_invert (gint * swizzle, gint * inversion)
+{
+ int i;
+
+ for (i = 0; i < GST_VIDEO_MAX_COMPONENTS; i++) {
+ inversion[i] = -1;
+ }
+
+ for (i = 0; i < GST_VIDEO_MAX_COMPONENTS; i++) {
+ if (swizzle[i] >= 0 && swizzle[i] < 4 && inversion[swizzle[i]] == -1) {
+ inversion[swizzle[i]] = i;
+ }
+ }
+}
+
/**
* gst_gl_format_is_supported:
* @context: a #GstGLContext
diff --git a/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglformat.h b/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglformat.h
index c85061dee3..6beb93ee75 100644
--- a/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglformat.h
+++ b/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglformat.h
@@ -151,11 +151,18 @@ void gst_gl_format_type_from_sized_gl_format (GstGLFormat
GstGLFormat * unsized_format,
guint * gl_type);
+GST_GL_API
+gboolean gst_gl_video_format_swizzle (GstVideoFormat video_format,
+ int * swizzle);
+
GST_GL_API
gboolean gst_gl_format_is_supported (GstGLContext * context,
GstGLFormat format);
GST_GL_API
guint gst_gl_format_n_components (GstGLFormat gl_format);
+GST_GL_API
+void gst_gl_swizzle_invert (gint * swizzle,
+ gint * inversion);
GST_GL_API
GstGLTextureTarget gst_gl_texture_target_from_string (const gchar * str);