[mutter/wip/nielsdg/meta-multi-texture-wip: 3/7] multi-texture: Add API to have color conversion




commit 17f2960262e68ece3da64b9e49d0cb8826d011e9
Author: Niels De Graef <niels degraef barco com>
Date:   Wed Oct 23 14:58:37 2019 +0200

    multi-texture: Add API to have color conversion
    
    Some pixel formats need to be converted to RGB first before they can be
    composited onto the RGBA framebuffer. Since we have absolutely no
    intention of doing this on the CPU (killing any kind of performance on
    video), we write shaders to do this for us. MetaShapedTexture is then
    extended to use this on its base pipeline.

 src/compositor/meta-multi-texture-format.c | 163 +++++++++++++++++++++++++++++
 src/compositor/meta-shaped-texture.c       |  52 +++++++--
 src/meta/meta-multi-texture-format.h       |   9 ++
 3 files changed, 213 insertions(+), 11 deletions(-)
---
diff --git a/src/compositor/meta-multi-texture-format.c b/src/compositor/meta-multi-texture-format.c
index e838bb1822..4e19111d32 100644
--- a/src/compositor/meta-multi-texture-format.c
+++ b/src/compositor/meta-multi-texture-format.c
@@ -36,6 +36,56 @@
 #include <stdlib.h>
 #include <string.h>
 
+#define _YUV_TO_RGB(res, y, u, v)                                \
+    "vec4 " res ";\n"                                             \
+    res ".r = (" y ") + 1.59765625 * (" v ");\n"                  \
+    res ".g = (" y ") - 0.390625 * (" u ") - 0.8125 * (" v ");\n" \
+    res ".b = (" y ") + 2.015625 * (" u ");\n"                    \
+    res ".a = 1.0;\n"
+
+/* Shader for a single YUV plane */
+#define YUV_TO_RGB_FUNC "meta_yuv_to_rgba"
+static const char yuv_to_rgb_shader[] =
+    "vec4\n"
+    YUV_TO_RGB_FUNC " (vec2 UV)\n"
+    "{\n"
+    "  vec4 orig_color = texture2D(cogl_sampler0, UV);\n"
+    "  float y = 1.16438356 * (orig_color.r - 0.0625);\n"
+    "  float u = orig_color.g - 0.5;\n"
+    "  float v = orig_color.b - 0.5;\n"
+       _YUV_TO_RGB ("color", "y", "u", "v")
+    "  return color;\n"
+    "}\n";
+
+/* Shader for 1 Y-plane and 1 UV-plane */
+#define Y_UV_TO_RGB_FUNC "meta_y_uv_to_rgba"
+static const char y_uv_to_rgb_shader[] =
+    "vec4\n"
+    Y_UV_TO_RGB_FUNC "(vec2 UV)\n"
+    "{\n"
+    "  float y = 1.1640625 * (texture2D (cogl_sampler0, UV).x - 0.0625);\n"
+    "  vec2 uv = texture2D (cogl_sampler1, UV).rg;\n"
+    "  uv -= 0.5;\n"
+    "  float u = uv.x;\n"
+    "  float v = uv.y;\n"
+       _YUV_TO_RGB ("color", "y", "u", "v")
+    "  return color;\n"
+    "}\n";
+
+/* Shader for 1 Y-plane, 1 U-plane and 1 V-plane */
+#define Y_U_V_TO_RGB_FUNC "meta_y_u_v_to_rgba"
+static const char y_u_v_to_rgb_shader[] =
+    "vec4\n"
+    Y_U_V_TO_RGB_FUNC "(vec2 UV)\n"
+    "{\n"
+    "  float y = 1.16438356 * (texture2D(cogl_sampler0, UV).x - 0.0625);\n"
+    "  float u = texture2D(cogl_sampler1, UV).x - 0.5;\n"
+    "  float v = texture2D(cogl_sampler2, UV).x - 0.5;\n"
+       _YUV_TO_RGB ("color", "y", "u", "v")
+    "  return color;\n"
+    "}\n";
+
+
 typedef struct _MetaMultiTextureFormatInfo
 {
   MetaMultiTextureFormat multi_format;
@@ -46,6 +96,10 @@ typedef struct _MetaMultiTextureFormatInfo
   uint8_t hsub[COGL_PIXEL_FORMAT_MAX_PLANES];       /* horizontal subsampling                */
   uint8_t vsub[COGL_PIXEL_FORMAT_MAX_PLANES];       /* vertical subsampling                  */
   CoglPixelFormat subformats[COGL_PIXEL_FORMAT_MAX_PLANES]; /* influences how we deal with it on a GL level 
*/
+
+  /* Shaders */
+  const char *rgb_shaderfunc;  /* Shader name to convert to RGBA (or NULL) */
+  const char *rgb_shader;      /* Shader to convert to RGBA (or NULL)      */
 } MetaMultiTextureFormatInfo;
 
 /* NOTE: The actual enum values are used as the index, so you don't need to
@@ -58,6 +112,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1 },
     .vsub = { 1 },
     .subformats = { COGL_PIXEL_FORMAT_ANY },
+    .rgb_shaderfunc = NULL,
+    .rgb_shader = NULL,
   },
   /* Packed YUV */
   { /* YUYV */
@@ -66,6 +122,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1 },
     .vsub = { 1 },
     .subformats = { COGL_PIXEL_FORMAT_ARGB_8888 },
+    .rgb_shaderfunc = YUV_TO_RGB_FUNC,
+    .rgb_shader = yuv_to_rgb_shader,
   },
   { /* YVYU */
     .n_planes = 1,
@@ -73,6 +131,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1 },
     .vsub = { 1 },
     .subformats = { COGL_PIXEL_FORMAT_ARGB_8888 },
+    .rgb_shaderfunc = YUV_TO_RGB_FUNC,
+    .rgb_shader = yuv_to_rgb_shader,
   },
   { /* UYVY */
     .n_planes = 1,
@@ -80,6 +140,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1 },
     .vsub = { 1 },
     .subformats = { COGL_PIXEL_FORMAT_ARGB_8888 },
+    .rgb_shaderfunc = YUV_TO_RGB_FUNC,
+    .rgb_shader = yuv_to_rgb_shader,
   },
   { /* VYUY */
     .n_planes = 1,
@@ -87,6 +149,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1 },
     .vsub = { 1 },
     .subformats = { COGL_PIXEL_FORMAT_ARGB_8888 },
+    .rgb_shaderfunc = YUV_TO_RGB_FUNC,
+    .rgb_shader = yuv_to_rgb_shader,
   },
   { /* AYUV */
     .n_planes = 1,
@@ -94,6 +158,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1 },
     .vsub = { 1 },
     .subformats = { COGL_PIXEL_FORMAT_ARGB_8888 },
+    .rgb_shaderfunc = YUV_TO_RGB_FUNC,
+    .rgb_shader = yuv_to_rgb_shader,
   },
   /* 2 plane RGB + A */
   { /* XRGB8888_A8 */
@@ -102,6 +168,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1, 1 },
     .vsub = { 1, 1 },
     .subformats = { COGL_PIXEL_FORMAT_ARGB_8888, COGL_PIXEL_FORMAT_A_8 },
+    .rgb_shaderfunc = NULL,
+    .rgb_shader = NULL,
   },
   { /* XBGR8888_A8 */
     .n_planes = 2,
@@ -109,6 +177,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1, 1 },
     .vsub = { 1, 1 },
     .subformats = { COGL_PIXEL_FORMAT_ABGR_8888, COGL_PIXEL_FORMAT_A_8 },
+    .rgb_shaderfunc = NULL,
+    .rgb_shader = NULL,
   },
   { /* RGBX8888_A8 */
     .n_planes = 2,
@@ -116,6 +186,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1, 1 },
     .vsub = { 1, 1 },
     .subformats = { COGL_PIXEL_FORMAT_RGBA_8888, COGL_PIXEL_FORMAT_A_8 },
+    .rgb_shaderfunc = NULL,
+    .rgb_shader = NULL,
   },
   { /* BGRX8888_A8 */
     .n_planes = 2,
@@ -123,6 +195,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1, 1 },
     .vsub = { 1, 1 },
     .subformats = { COGL_PIXEL_FORMAT_BGRA_8888, COGL_PIXEL_FORMAT_A_8 },
+    .rgb_shaderfunc = NULL,
+    .rgb_shader = NULL,
   },
   { /* RGB888_A8 */
     .n_planes = 2,
@@ -130,6 +204,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1, 1 },
     .vsub = { 1, 1 },
     .subformats = { COGL_PIXEL_FORMAT_RGB_888, COGL_PIXEL_FORMAT_A_8 },
+    .rgb_shaderfunc = NULL,
+    .rgb_shader = NULL,
   },
   { /* BGR888_A8 */
     .n_planes = 2,
@@ -137,6 +213,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1, 1 },
     .vsub = { 1, 1 },
     .subformats = { COGL_PIXEL_FORMAT_BGR_888, COGL_PIXEL_FORMAT_A_8 },
+    .rgb_shaderfunc = NULL,
+    .rgb_shader = NULL,
   },
   { /* RGB565_A8 */
     .n_planes = 2,
@@ -144,6 +222,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1, 1 },
     .vsub = { 1, 1 },
     .subformats = { COGL_PIXEL_FORMAT_RGB_565, COGL_PIXEL_FORMAT_A_8 },
+    .rgb_shaderfunc = NULL,
+    .rgb_shader = NULL,
   },
   { /* BGR565_A8 */
     .n_planes = 2,
@@ -151,6 +231,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1, 1 },
     .vsub = { 1, 1 },
     .subformats = { COGL_PIXEL_FORMAT_RGB_565, COGL_PIXEL_FORMAT_A_8 },
+    .rgb_shaderfunc = NULL,
+    .rgb_shader = NULL,
   },
   /* 2 plane YUV */
   { /* NV12 */
@@ -159,6 +241,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1, 2 },
     .vsub = { 1, 2 },
     .subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_RG_88 },
+    .rgb_shaderfunc = Y_UV_TO_RGB_FUNC,
+    .rgb_shader = y_uv_to_rgb_shader,
   },
   { /* NV21 */
     .n_planes = 2,
@@ -166,6 +250,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1, 2 },
     .vsub = { 1, 2 },
     .subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_RG_88 },
+    .rgb_shaderfunc = Y_UV_TO_RGB_FUNC,
+    .rgb_shader = y_uv_to_rgb_shader,
   },
   { /* NV16 */
     .n_planes = 2,
@@ -173,6 +259,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1, 2 },
     .vsub = { 1, 1 },
     .subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_RG_88 },
+    .rgb_shaderfunc = Y_UV_TO_RGB_FUNC,
+    .rgb_shader = y_uv_to_rgb_shader,
   },
   { /* NV61 */
     .n_planes = 2,
@@ -180,6 +268,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1, 2 },
     .vsub = { 1, 1 },
     .subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_RG_88 },
+    .rgb_shaderfunc = Y_UV_TO_RGB_FUNC,
+    .rgb_shader = y_uv_to_rgb_shader,
   },
   { /* NV24 */
     .n_planes = 2,
@@ -187,6 +277,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1, 1 },
     .vsub = { 1, 1 },
     .subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_RG_88 },
+    .rgb_shaderfunc = Y_UV_TO_RGB_FUNC,
+    .rgb_shader = y_uv_to_rgb_shader,
   },
   { /* NV42 */
     .n_planes = 2,
@@ -194,6 +286,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1, 1 },
     .vsub = { 1, 1 },
     .subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_RG_88 },
+    .rgb_shaderfunc = Y_UV_TO_RGB_FUNC,
+    .rgb_shader = y_uv_to_rgb_shader,
   },
   /* 3 plane YUV */
   { /* YUV410 */
@@ -202,6 +296,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1, 4, 4 },
     .vsub = { 1, 4, 4 },
     .subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8 },
+    .rgb_shaderfunc = Y_U_V_TO_RGB_FUNC,
+    .rgb_shader = y_u_v_to_rgb_shader,
   },
   { /* YVU410 */
     .n_planes = 3,
@@ -209,6 +305,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1, 4, 4 },
     .vsub = { 1, 4, 4 },
     .subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8 },
+    .rgb_shaderfunc = Y_U_V_TO_RGB_FUNC,
+    .rgb_shader = y_u_v_to_rgb_shader,
   },
   { /* YUV411 */
     .n_planes = 3,
@@ -216,6 +314,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1, 4, 4 },
     .vsub = { 1, 1, 1 },
     .subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8 },
+    .rgb_shaderfunc = Y_U_V_TO_RGB_FUNC,
+    .rgb_shader = y_u_v_to_rgb_shader,
   },
   { /* YVU411 */
     .n_planes = 3,
@@ -223,6 +323,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1, 4, 4 },
     .vsub = { 1, 1, 1 },
     .subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8 },
+    .rgb_shaderfunc = Y_U_V_TO_RGB_FUNC,
+    .rgb_shader = y_u_v_to_rgb_shader,
   },
   { /* YUV420 */
     .n_planes = 3,
@@ -230,6 +332,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1, 2, 2 },
     .vsub = { 1, 2, 2 },
     .subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8 },
+    .rgb_shaderfunc = Y_U_V_TO_RGB_FUNC,
+    .rgb_shader = y_u_v_to_rgb_shader,
   },
   { /* YVU420 */
     .n_planes = 3,
@@ -237,6 +341,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1, 2, 2 },
     .vsub = { 1, 2, 2 },
     .subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8 },
+    .rgb_shaderfunc = Y_U_V_TO_RGB_FUNC,
+    .rgb_shader = y_u_v_to_rgb_shader,
   },
   { /* YUV422 */
     .n_planes = 3,
@@ -244,6 +350,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1, 2, 2 },
     .vsub = { 1, 1, 1 },
     .subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8 },
+    .rgb_shaderfunc = Y_U_V_TO_RGB_FUNC,
+    .rgb_shader = y_u_v_to_rgb_shader,
   },
   { /* YVU422 */
     .n_planes = 3,
@@ -251,6 +359,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1, 2, 2 },
     .vsub = { 1, 1, 1 },
     .subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8 },
+    .rgb_shaderfunc = Y_U_V_TO_RGB_FUNC,
+    .rgb_shader = y_u_v_to_rgb_shader,
   },
   { /* YUV444 */
     .n_planes = 3,
@@ -258,6 +368,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1, 1, 1 },
     .vsub = { 1, 1, 1 },
     .subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8 },
+    .rgb_shaderfunc = Y_U_V_TO_RGB_FUNC,
+    .rgb_shader = y_u_v_to_rgb_shader,
   },
   { /* YVU444 */
     .n_planes = 3,
@@ -265,6 +377,8 @@ static MetaMultiTextureFormatInfo multi_format_table[] = {
     .hsub = { 1, 1, 1 },
     .vsub = { 1, 1, 1 },
     .subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8 },
+    .rgb_shaderfunc = Y_U_V_TO_RGB_FUNC,
+    .rgb_shader = y_u_v_to_rgb_shader,
   },
 };
 
@@ -315,3 +429,52 @@ meta_multi_texture_format_get_subformats (MetaMultiTextureFormat format,
   for (i = 0; i < multi_format_table[format].n_planes; i++)
     formats_out[i] = multi_format_table[format].subformats[i];
 }
+
+gboolean
+meta_multi_texture_format_needs_shaders (MetaMultiTextureFormat format)
+{
+  g_return_val_if_fail (format < G_N_ELEMENTS (multi_format_table), FALSE);
+
+  return multi_format_table[format].rgb_shaderfunc != NULL;
+}
+
+gboolean
+meta_multi_texture_format_get_snippets (MetaMultiTextureFormat format,
+                                        CoglSnippet          **vertex_snippet,
+                                        CoglSnippet          **fragment_snippet,
+                                        CoglSnippet          **layer_snippet)
+{
+  const char *shader_func;
+  const char *shader_impl;
+  g_autofree char *layer_hook = NULL;
+
+  g_return_val_if_fail (format < G_N_ELEMENTS (multi_format_table), FALSE);
+
+  /* Get the function name; bail out early if we don't need a shader */
+  shader_func = multi_format_table[format].rgb_shaderfunc;
+  if (shader_func == NULL)
+    return FALSE;
+
+  shader_impl = multi_format_table[format].rgb_shader;
+
+  /* Make sure we actually call the function */
+  layer_hook = g_strdup_printf ("cogl_layer = %s(cogl_tex_coord0_in.st);\n",
+                                shader_func);
+
+  if (vertex_snippet)
+    *vertex_snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX_GLOBALS,
+                                        shader_impl,
+                                        NULL);
+
+  if (fragment_snippet)
+    *fragment_snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT_GLOBALS,
+                                          shader_impl,
+                                          NULL);
+
+  if (layer_snippet)
+    *layer_snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_LAYER_FRAGMENT,
+                                       NULL,
+                                       layer_hook);
+
+  return TRUE;
+}
diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c
index 360e913d5b..5654a4a5bb 100644
--- a/src/compositor/meta-shaped-texture.c
+++ b/src/compositor/meta-shaped-texture.c
@@ -272,24 +272,31 @@ static CoglPipeline *
 get_base_pipeline (MetaShapedTexture *stex,
                    CoglContext       *ctx)
 {
+  guint i, n_planes;
+  MetaMultiTextureFormat format;
   CoglPipeline *pipeline;
   graphene_matrix_t matrix;
 
   if (stex->base_pipeline)
     return stex->base_pipeline;
 
+  /* We'll add as many layers as there are planes in the multi texture,
+   * plus an extra one for the mask */
+  n_planes = meta_multi_texture_get_n_planes (stex->texture);
+
   pipeline = cogl_pipeline_new (ctx);
-  cogl_pipeline_set_layer_wrap_mode_s (pipeline, 0,
-                                       COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
-  cogl_pipeline_set_layer_wrap_mode_t (pipeline, 0,
-                                       COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
-  cogl_pipeline_set_layer_wrap_mode_s (pipeline, 1,
-                                       COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
-  cogl_pipeline_set_layer_wrap_mode_t (pipeline, 1,
-                                       COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
+
+  for (i = 0; i < n_planes; i++)
+    {
+      cogl_pipeline_set_layer_wrap_mode_s (pipeline, i,
+                                           COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
+      cogl_pipeline_set_layer_wrap_mode_t (pipeline, i,
+                                           COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
+    }
 
   graphene_matrix_init_identity (&matrix);
 
+  /* Apply transformation if needed */
   if (stex->transform != META_MONITOR_TRANSFORM_NORMAL)
     {
       graphene_euler_t euler;
@@ -334,6 +341,7 @@ get_base_pipeline (MetaShapedTexture *stex,
                                  &GRAPHENE_POINT3D_INIT (0.5, 0.5, 0.0));
     }
 
+  /* Apply viewport scaling if neeed */
   if (stex->has_viewport_src_rect)
     {
       float scaled_tex_width = stex->tex_width / (float) stex->buffer_scale;
@@ -375,9 +383,29 @@ get_base_pipeline (MetaShapedTexture *stex,
       cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix);
     }
 
-  cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix);
-  cogl_pipeline_set_layer_matrix (pipeline, 1, &matrix);
+  for (i = 0; i < n_planes + 1; i++)
+    cogl_pipeline_set_layer_matrix (pipeline, i, &matrix);
+
+  /* Add color conversion shaders if needed */
+  format = meta_multi_texture_get_format (stex->texture);
+  if (meta_multi_texture_format_needs_shaders (format))
+    {
+      CoglSnippet *vertex_snippet;
+      CoglSnippet *fragment_snippet;
+      CoglSnippet *layer_snippet;
 
+      meta_multi_texture_format_get_snippets (format,
+                                              &vertex_snippet,
+                                              &fragment_snippet,
+                                              &layer_snippet);
+      cogl_pipeline_add_snippet (pipeline, vertex_snippet);
+      cogl_pipeline_add_snippet (pipeline, fragment_snippet);
+
+      for (i = 0; i < n_planes; i++)
+        cogl_pipeline_add_layer_snippet (pipeline, i, layer_snippet);
+    }
+
+  /* And custom external shaders (e.g. for EGLStreams) */
   if (stex->snippet)
     cogl_pipeline_add_layer_snippet (pipeline, 0, stex->snippet);
 
@@ -398,12 +426,14 @@ get_masked_pipeline (MetaShapedTexture *stex,
                      CoglContext       *ctx)
 {
   CoglPipeline *pipeline;
+  guint n_planes;
 
   if (stex->masked_pipeline)
     return stex->masked_pipeline;
 
   pipeline = cogl_pipeline_copy (get_base_pipeline (stex, ctx));
-  cogl_pipeline_set_layer_combine (pipeline, 1,
+  n_planes = meta_multi_texture_get_n_planes (stex->texture);
+  cogl_pipeline_set_layer_combine (pipeline, n_planes,
                                    "RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
                                    NULL);
 
diff --git a/src/meta/meta-multi-texture-format.h b/src/meta/meta-multi-texture-format.h
index e5ae4e8493..bb0b5fc176 100644
--- a/src/meta/meta-multi-texture-format.h
+++ b/src/meta/meta-multi-texture-format.h
@@ -124,6 +124,15 @@ META_EXPORT
 void  meta_multi_texture_format_get_subformats          (MetaMultiTextureFormat format,
                                                          CoglPixelFormat       *formats_out);
 
+META_EXPORT
+gboolean meta_multi_texture_format_needs_shaders        (MetaMultiTextureFormat format);
+
+META_EXPORT
+gboolean meta_multi_texture_format_get_snippets         (MetaMultiTextureFormat format,
+                                                        CoglSnippet          **vertex_snippet,
+                                                        CoglSnippet          **fragment_snippet,
+                                                        CoglSnippet          **layer_snippet);
+
 G_END_DECLS
 
 #endif


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]