[mutter/wip/nielsdg/add-yuv-support] WIP



commit 529b87bc17cf26c701d9cb156977cae4f0e93a06
Author: Niels De Graef <Niels DeGraef barco com>
Date:   Mon Nov 26 15:40:47 2018 +0100

    WIP

 cogl/cogl/Makefile.am                  |   3 +
 cogl/cogl/cogl-colorspace-conversion.c | 163 +++++++++++++++++++++++++++++++++
 cogl/cogl/cogl-colorspace-conversion.h |  92 +++++++++++++++++++
 cogl/cogl/cogl-multi-plane-texture.c   |  72 ---------------
 cogl/cogl/cogl-multi-plane-texture.h   |  26 +++---
 cogl/cogl/cogl-types.h                 |  14 +++
 cogl/cogl/cogl.c                       | 100 ++++++++++++++++++++
 cogl/cogl/cogl.h                       |   1 +
 cogl/cogl/meson.build                  |   6 +-
 src/compositor/meta-shaped-texture.c   |  37 ++++----
 src/wayland/meta-wayland-buffer.c      |  78 +++++++++++-----
 src/wayland/meta-wayland.c             |   7 +-
 12 files changed, 467 insertions(+), 132 deletions(-)
---
diff --git a/cogl/cogl/Makefile.am b/cogl/cogl/Makefile.am
index e86aa2a37..85b85d2e4 100644
--- a/cogl/cogl/Makefile.am
+++ b/cogl/cogl/Makefile.am
@@ -62,6 +62,7 @@ cogl_1_public_h = \
        cogl1-context.h                 \
        cogl-bitmap.h           \
        cogl-color.h                    \
+       cogl-colorspace-conversion.h                    \
        cogl-framebuffer.h              \
        cogl-matrix.h           \
        cogl-offscreen.h                \
@@ -116,6 +117,7 @@ cogl_nonintrospected_h = \
        cogl-error.h                    \
        cogl-bitmap.h                   \
        cogl-color.h                    \
+       cogl-colorspace-conversion.h                    \
        cogl-matrix.h                   \
        cogl-texture.h          \
        cogl-types.h                    \
@@ -238,6 +240,7 @@ cogl_sources_c = \
        cogl-feature-private.c                \
        cogl-color-private.h                    \
        cogl-color.c                            \
+       cogl-colorspace-conversion.c                            \
        cogl-buffer-private.h           \
        cogl-buffer.c                           \
        cogl-pixel-buffer-private.h             \
diff --git a/cogl/cogl/cogl-colorspace-conversion.c b/cogl/cogl/cogl-colorspace-conversion.c
new file mode 100644
index 000000000..35d580bbe
--- /dev/null
+++ b/cogl/cogl/cogl-colorspace-conversion.c
@@ -0,0 +1,163 @@
+/*
+ * Authored By Niels De Graef <niels degraef barco com>
+ *
+ * Copyright (C) 2018 Barco NV
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cogl-config.h"
+
+#include "cogl-object-private.h"
+#include "cogl-gtype-private.h"
+#include "cogl-colorspace-conversion.h"
+#include "cogl-snippet.h"
+#include "cogl-pipeline-layer-state.h"
+#include "cogl-pipeline-state.h"
+
+#define _COGL_YUV_TO_RGBA(res, y, u, v)                     \
+    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"
+
+static const gchar nv12_to_rgba_shader[] =
+    "vec4\n"
+    "cogl_nv12_to_rgba (vec2 UV)\n"
+    "{\n"
+    "  vec4 color;\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"
+       _COGL_YUV_TO_RGBA ("color", "y", "u", "v")
+    "  return color;\n"
+    "}\n";
+
+static const gchar yuv_to_rgba_shader[] =
+    "vec4\n"
+    "cogl_yuv_to_rgba (vec2 UV)\n"
+    "{\n"
+    "  vec4 color;\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"
+       _COGL_YUV_TO_RGBA ("color", "y", "u", "v")
+    "  return color;\n"
+    "}\n";
+
+struct _CoglColorspaceConversion
+{
+  CoglObject _parent;
+
+  CoglSnippet *vertex_declaration_snippet;
+  CoglSnippet *fragment_declaration_snippet;
+
+  CoglSnippet *fragment_execution_snippet;
+};
+
+static void
+_cogl_colorspace_conversion_free (CoglColorspaceConversion *self);
+
+COGL_OBJECT_DEFINE (ColorspaceConversion, colorspace_conversion);
+COGL_GTYPE_DEFINE_CLASS (ColorspaceConversion, colorspace_conversion);
+
+
+void
+cogl_colorspace_conversion_attach_to_pipeline (CoglColorspaceConversion *self,
+                                               CoglPipeline *pipeline,
+                                               gint layer)
+{
+  cogl_pipeline_add_snippet (pipeline, self->fragment_declaration_snippet);
+  cogl_pipeline_add_snippet (pipeline, self->vertex_declaration_snippet);
+
+  cogl_pipeline_add_layer_snippet (pipeline,
+                                   layer,
+                                   self->fragment_execution_snippet);
+}
+
+static gboolean
+get_cogl_snippets (CoglPixelFormat format,
+                   CoglSnippet **vertex_snippet_out,
+                   CoglSnippet **fragment_snippet_out,
+                   CoglSnippet **layer_snippet_out)
+{
+  const gchar *global_hook;
+  const gchar *layer_hook;
+
+  switch (format)
+    {
+    case COGL_PIXEL_FORMAT_YUV444:
+      global_hook = yuv_to_rgba_shader;
+      layer_hook =  "cogl_layer = cogl_yuv_to_rgba(cogl_tex_coord0_in.st);\n";
+      break;
+    case COGL_PIXEL_FORMAT_NV12:
+      /* XXX are we using Y_UV or Y_xUxV? Maybe check for RG support? */
+      global_hook = nv12_to_rgba_shader;
+      layer_hook =  "cogl_layer = cogl_nv12_to_rgba(cogl_tex_coord0_in.st);\n";
+      break;
+    default:
+      *vertex_snippet_out = NULL;
+      *fragment_snippet_out = NULL;
+      *layer_snippet_out = NULL;
+      return FALSE;
+    }
+
+  *vertex_snippet_out = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX_GLOBALS,
+                                          global_hook,
+                                          NULL);
+
+  *fragment_snippet_out = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT_GLOBALS,
+                                            global_hook,
+                                            NULL);
+
+  *layer_snippet_out = cogl_snippet_new (COGL_SNIPPET_HOOK_LAYER_FRAGMENT,
+                                         NULL,
+                                         layer_hook);
+
+  return TRUE;
+}
+
+static void
+_cogl_colorspace_conversion_free (CoglColorspaceConversion *self)
+{
+  cogl_clear_object (&self->vertex_declaration_snippet);
+  cogl_clear_object (&self->fragment_declaration_snippet);
+  cogl_clear_object (&self->fragment_execution_snippet);
+}
+
+CoglColorspaceConversion *
+cogl_colorspace_conversion_new (CoglPixelFormat format)
+{
+  CoglColorspaceConversion *self;
+  CoglSnippet *vertex_declaration_snippet;
+  CoglSnippet *fragment_declaration_snippet;
+  CoglSnippet *fragment_execution_snippet;
+
+  if (!get_cogl_snippets (format,
+                          &vertex_declaration_snippet,
+                          &fragment_declaration_snippet,
+                          &fragment_execution_snippet))
+    return NULL;
+
+  self = g_slice_new0 (CoglColorspaceConversion);
+  _cogl_colorspace_conversion_object_new (self);
+
+  self->vertex_declaration_snippet = vertex_declaration_snippet;
+  self->fragment_declaration_snippet = fragment_declaration_snippet;
+  self->fragment_execution_snippet = fragment_execution_snippet;
+
+  return self;
+}
diff --git a/cogl/cogl/cogl-colorspace-conversion.h b/cogl/cogl/cogl-colorspace-conversion.h
new file mode 100644
index 000000000..9c421054d
--- /dev/null
+++ b/cogl/cogl/cogl-colorspace-conversion.h
@@ -0,0 +1,92 @@
+/*
+ * Authored By Niels De Graef <niels degraef barco com>
+ *
+ * Copyright (C) 2018 Barco NV
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __COGL_COLORSPACE_CONVERSION_H__
+#define __COGL_COLORSPACE_CONVERSION_H__
+
+#include "cogl/cogl-types.h"
+#include "cogl/cogl-pipeline.h"
+
+G_BEGIN_DECLS
+
+/**
+ * SECTION:cogl-color-space-conversion
+ * @title: CoglColorspaceConversion
+ * @short_description: A collection of snippets to handle colorspace conversion
+ *
+ * In some use cases, one might generate non-RGBA textures (e.g. YUV), which is
+ * problematic if you then have to composite them in to an RGBA framebuffer. In
+ * comes #CoglColorspaceConversion, which you can attach to a #CoglPipeline to
+ * do this all for you. Internally, it consists of nothing more than a
+ * collection of #CoglSnippets which do the right thing for you.
+ */
+
+typedef struct _CoglColorspaceConversion CoglColorspaceConversion;
+#define COGL_COLORSPACE_CONVERSION(ptr) ((CoglColorspaceConversion *) ptr)
+
+
+/**
+ * cogl_multiplane_texture_get_gtype:
+ *
+ * Returns: a #GType that can be used with the GLib type system.
+ */
+GType cogl_colorspace_conversion_get_gtype (void);
+
+/*
+ * cogl_is_colorspace_conversion:
+ * @object: A #CoglObject pointer
+ *
+ * Gets whether the given @object references an existing
+ * CoglColorspaceConversion.
+ *
+ * Return value: %TRUE if the @object references a #CoglColorspaceConversion,
+ *   %FALSE otherwise
+ */
+gboolean
+cogl_is_colorspace_conversion (void *object);
+
+/**
+ * cogl_colorspace_conversion_new:
+ * @format: The input format
+ *
+ * Creates a #CoglColorspaceConversion to convert the given @formatro RGBA. If
+ * no such conversion is needed, it will return %NULL.
+ *
+ * Returns: (transfer full) (nullable): A new #CoglColorspaceConversion, or
+ * %NULL if none is needed.
+ */
+CoglColorspaceConversion * cogl_colorspace_conversion_new  (CoglPixelFormat format);
+
+/**
+ * cogl_colorspace_conversion_attach_to_pipeline:
+ * @self: The #CoglColorspaceConversion you want to add
+ * @pipeline: The #CoglPipeline which needs the color conversion
+ * @layer: The layer you want to perform the color space conversion at
+ *
+ * Adds color conversion to the given @pipeline at the given @layer.
+ */
+void cogl_colorspace_conversion_attach_to_pipeline (CoglColorspaceConversion *self,
+                                                    CoglPipeline *pipeline,
+                                                    gint layer);
+
+G_END_DECLS
+
+#endif
diff --git a/cogl/cogl/cogl-multi-plane-texture.c b/cogl/cogl/cogl-multi-plane-texture.c
index f02d1b983..8d297258d 100644
--- a/cogl/cogl/cogl-multi-plane-texture.c
+++ b/cogl/cogl/cogl-multi-plane-texture.c
@@ -23,38 +23,6 @@
 #include "cogl-multi-plane-texture.h"
 #include "cogl-gtype-private.h"
 
-#define _COGL_YUV_TO_RGBA(res, y, u, v)                     \
-    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"
-
-static const gchar nv12_to_rgba_shader[] =
-    "vec4\n"
-    "cogl_nv12_to_rgba (vec2 UV)\n"
-    "{\n"
-    "  vec4 color;\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"
-       _COGL_YUV_TO_RGBA ("color", "y", "u", "v")
-    "  return color;\n"
-    "}\n";
-
-static const gchar yuv_to_rgba_shader[] =
-    "vec4\n"
-    "cogl_yuv_to_rgba (vec2 UV)\n"
-    "{\n"
-    "  vec4 color;\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"
-       _COGL_YUV_TO_RGBA ("color", "y", "u", "v")
-    "  return color;\n"
-    "}\n";
-
 struct _CoglMultiPlaneTexture
 {
   CoglObject _parent;
@@ -115,46 +83,6 @@ cogl_multi_plane_texture_get_height (CoglMultiPlaneTexture *self)
   return cogl_texture_get_height (self->planes[0]);
 }
 
-void
-cogl_multi_plane_texture_create_color_conversion_snippets (CoglMultiPlaneTexture *self,
-                                                           CoglSnippet **vertex_snippet_out,
-                                                           CoglSnippet **fragment_snippet_out,
-                                                           CoglSnippet **layer_snippet_out)
-{
-  const gchar *global_hook;
-  const gchar *layer_hook;
-
-  switch (self->format)
-    {
-    case COGL_PIXEL_FORMAT_YUV444:
-      global_hook = yuv_to_rgba_shader;
-      layer_hook =  "cogl_layer = cogl_yuv_to_rgba(cogl_tex_coord0_in.st);\n";
-      break;
-    case COGL_PIXEL_FORMAT_NV12:
-      /* XXX are we using Y_UV or Y_xUxV? Maybe check for RG support? */
-      global_hook = nv12_to_rgba_shader;
-      layer_hook =  "cogl_layer = cogl_nv12_to_rgba(cogl_tex_coord0_in.st);\n";
-      break;
-    default:
-      *vertex_snippet_out = NULL;
-      *fragment_snippet_out = NULL;
-      *layer_snippet_out = NULL;
-      return;
-    }
-
-    *vertex_snippet_out = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX_GLOBALS,
-                                            global_hook,
-                                            NULL);
-
-    *fragment_snippet_out = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT_GLOBALS,
-                                              global_hook,
-                                              NULL);
-
-    *layer_snippet_out = cogl_snippet_new (COGL_SNIPPET_HOOK_LAYER_FRAGMENT,
-                                           NULL,
-                                           layer_hook);
-}
-
 static void
 _cogl_multi_plane_texture_free (CoglMultiPlaneTexture *self)
 {
diff --git a/cogl/cogl/cogl-multi-plane-texture.h b/cogl/cogl/cogl-multi-plane-texture.h
index aa5fc6d77..c4b3aed31 100644
--- a/cogl/cogl/cogl-multi-plane-texture.h
+++ b/cogl/cogl/cogl-multi-plane-texture.h
@@ -52,12 +52,24 @@ typedef struct _CoglMultiPlaneTexture CoglMultiPlaneTexture;
 
 
 /**
- * cogl_multiplane_texture_get_gtype:
+ * cogl_multi_plane_texture_get_gtype:
  *
  * Returns: a #GType that can be used with the GLib type system.
  */
 GType cogl_multi_plane_texture_get_gtype (void);
 
+/**
+ * cogl_is_multi_plane_texture:
+ * @object: A #CoglObject pointer
+ *
+ * Gets whether the given @object references an existing CoglMultiPlaneTexture.
+ *
+ * Return value: %TRUE if the @object references a #CoglMultiPlaneTexture,
+ *   %FALSE otherwise
+ */
+gboolean
+cogl_is_multi_plane_texture (void *object);
+
 /**
  * cogl_multi_plane_texture_new:
  * @format: The format of the #CoglMultiPlaneTexture
@@ -159,18 +171,6 @@ guint           cogl_multi_plane_texture_get_width    (CoglMultiPlaneTexture *se
  */
 guint           cogl_multi_plane_texture_get_height   (CoglMultiPlaneTexture *self);
 
-/**
- * cogl_multi_plane_texture_create_color_conversion_snippets:
- *
- * Creates a trio of #CoglSnippets that allow you to use this texture inside
- * your pipeline. If no such shader is needed (e.g. because you already have
- * a single-plane RGBA texture), then they will be set to %NULL.
- */
-void cogl_multi_plane_texture_create_color_conversion_snippets (CoglMultiPlaneTexture *self,
-                                                                CoglSnippet **vertex_snippet_out,
-                                                                CoglSnippet **fragment_snippet_out,
-                                                                CoglSnippet **layer_snippet_out);
-
 G_END_DECLS
 
 #endif
diff --git a/cogl/cogl/cogl-types.h b/cogl/cogl/cogl-types.h
index 7e3c2a971..195a5cd3b 100644
--- a/cogl/cogl/cogl-types.h
+++ b/cogl/cogl/cogl-types.h
@@ -408,6 +408,7 @@ typedef enum { /*< prefix=COGL_PIXEL_FORMAT >*/
 
 /**
  * cogl_pixel_format_get_n_planes:
+ * @format: The format for which to get the number of planes
  *
  * Returns the number of planes the given CoglPixelFormat specifies.
  */
@@ -416,6 +417,7 @@ cogl_pixel_format_get_n_planes (CoglPixelFormat format);
 
 /**
  * cogl_pixel_format_get_subsampling_factors:
+ * @format: The format to get the subsampling factors from.
  *
  * Returns the subsampling in both the horizontal as the vertical direction.
  */
@@ -424,6 +426,18 @@ cogl_pixel_format_get_subsampling_factors (CoglPixelFormat format,
                                            guint *horizontal_factors,
                                            guint *vertical_factors);
 
+void
+cogl_pixel_format_get_bits_per_pixel (CoglPixelFormat format, guint *bpp_out);
+
+/**
+ * cogl_pixel_format_get_components:
+ *
+ * XXX make some comments here about (consistently) uploading multiple textures
+ */
+/* void */
+/* cogl_pixel_format_get_texture_components (CoglPixelFormat format, */
+/*                                           CoglTextureComponents *components_out); */
+
 /**
  * CoglFeatureFlags:
  * @COGL_FEATURE_TEXTURE_RECTANGLE: ARB_texture_rectangle support
diff --git a/cogl/cogl/cogl.c b/cogl/cogl/cogl.c
index 964026180..01ca70769 100644
--- a/cogl/cogl/cogl.c
+++ b/cogl/cogl/cogl.c
@@ -796,6 +796,43 @@ _cogl_pixel_format_get_bytes_per_pixel (CoglPixelFormat format)
   return bpp_lut [format & 0xf];
 }
 
+/*
+ * XXX document.
+ *
+ * XXX lol, this is even per macropixel, not per pixel :D
+ */
+void
+cogl_pixel_format_get_bits_per_pixel (CoglPixelFormat format, guint *bpp_out)
+{
+  /* "old" formats */
+  if (format & (0xff << 24))
+    {
+      switch (format)
+        {
+        case COGL_PIXEL_FORMAT_NV12:
+        case COGL_PIXEL_FORMAT_NV21:
+          bpp_out[0] = 8;
+          bpp_out[1] = 4;
+          break;
+        case COGL_PIXEL_FORMAT_YUV420:
+        case COGL_PIXEL_FORMAT_YVU420:
+          bpp_out[0] = 8;
+          bpp_out[1] = 2;
+          bpp_out[2] = 2;
+          break;
+        }
+    }
+  else
+    {
+      int bpp_lut[] = { 0, 1, 3, 4,
+                        2, 2, 2, 0,
+                        1, 2, 0, 0,
+                        3, 4, 0, 0 };
+
+      bpp_out[0] =  8 * bpp_lut [format & 0xf];
+    }
+}
+
 /* Note: this also refers to the mapping defined above for
  * _cogl_pixel_format_get_bytes_per_pixel() */
 CoglBool
@@ -939,3 +976,66 @@ cogl_pixel_format_get_subsampling_factors (CoglPixelFormat format,
       break;
     }
 }
+
+/* void */
+/* cogl_pixel_format_get_texture_components (CoglPixelFormat format, */
+/*                                           CoglTextureComponents *components_out) */
+/* { */
+/*   /1* Check for Pre-YUV formats *1/ */
+/*   if (format & 0xf000) */
+/*     { */
+/*       switch (format) */
+/*         { */
+/*         /1* 2 planes *1/ */
+/*         case COGL_PIXEL_FORMAT_NV12: */
+/*         case COGL_PIXEL_FORMAT_NV21: */
+/*           components_out[0] = COGL_TEXTURE_COMPONENTS_R; */
+/*           components_out[1] = COGL_TEXTURE_COMPONENTS_RG; */
+/*           break; */
+
+/*           /1* XXX TODO *1/ */
+/*         /1* case COGL_PIXEL_FORMAT_XRGB88888_A8: *1/ */
+/*         /1* case COGL_PIXEL_FORMAT_XBGR88888_A8: *1/ */
+/*         /1* case COGL_PIXEL_FORMAT_RGBX88888_A8: *1/ */
+/*         /1* case COGL_PIXEL_FORMAT_BGRX88888_A8: *1/ */
+/*         /1* case COGL_PIXEL_FORMAT_RGB888_A8: *1/ */
+/*         /1* case COGL_PIXEL_FORMAT_BGR888_A8: *1/ */
+/*         /1* case COGL_PIXEL_FORMAT_RGB565_A8: *1/ */
+/*         /1* case COGL_PIXEL_FORMAT_BGR565_A8: *1/ */
+
+/*         /1* /2* 3 planes *2/ *1/ */
+/*         /1* case COGL_PIXEL_FORMAT_YUV410: *1/ */
+/*         /1* case COGL_PIXEL_FORMAT_YVU410: *1/ */
+/*         /1* case COGL_PIXEL_FORMAT_YUV411: *1/ */
+/*         /1* case COGL_PIXEL_FORMAT_YVU411: *1/ */
+/*         /1* case COGL_PIXEL_FORMAT_YUV420: *1/ */
+/*         /1* case COGL_PIXEL_FORMAT_YVU420: *1/ */
+/*         /1* case COGL_PIXEL_FORMAT_YUV422: *1/ */
+/*         /1* case COGL_PIXEL_FORMAT_YVU422: *1/ */
+/*         /1* case COGL_PIXEL_FORMAT_YUV444: *1/ */
+/*         /1* case COGL_PIXEL_FORMAT_YVU444: *1/ */
+
+/*         default: */
+/*           /1* XXX At this point, we might crash 'n burn *1/ */
+/*           g_assert_not_reached (); */
+/*           components_out[0] = COGL_TEXTURE_COMPONENTS_RGB; */
+/*           break; */
+/*         } */
+/*     } */
+/*   else */
+/*     { */
+/*       if (format == COGL_PIXEL_FORMAT_ANY) */
+/*         format = COGL_PIXEL_FORMAT_RGBA_8888_PRE; */
+
+/*       if (format == COGL_PIXEL_FORMAT_A_8) */
+/*         components_out[0] = COGL_TEXTURE_COMPONENTS_A; */
+/*       else if (format == COGL_PIXEL_FORMAT_RG_88) */
+/*         components_out[0] = COGL_TEXTURE_COMPONENTS_RG; */
+/*       else if (format & COGL_DEPTH_BIT) */
+/*         components_out[0] = COGL_TEXTURE_COMPONENTS_DEPTH; */
+/*       else if (format & COGL_A_BIT) */
+/*         components_out[0] = COGL_TEXTURE_COMPONENTS_RGBA; */
+/*       else */
+/*         components_out[0] = COGL_TEXTURE_COMPONENTS_RGB; */
+/*     } */
+/* } */
diff --git a/cogl/cogl/cogl.h b/cogl/cogl/cogl.h
index 84595b595..41c785627 100644
--- a/cogl/cogl/cogl.h
+++ b/cogl/cogl/cogl.h
@@ -61,6 +61,7 @@
 #include <cogl/cogl1-context.h>
 #include <cogl/cogl-bitmap.h>
 #include <cogl/cogl-color.h>
+#include <cogl/cogl-colorspace-conversion.h>
 #include <cogl/cogl-matrix.h>
 #include <cogl/cogl-matrix-stack.h>
 #include <cogl/cogl-offscreen.h>
diff --git a/cogl/cogl/meson.build b/cogl/cogl/meson.build
index 76a42442b..664ee9908 100644
--- a/cogl/cogl/meson.build
+++ b/cogl/cogl/meson.build
@@ -79,6 +79,7 @@ cogl_headers = [
   'cogl1-context.h',
   'cogl-bitmap.h',
   'cogl-color.h',
+  'cogl-colorspace-conversion.h',
   'cogl-framebuffer.h',
   'cogl-matrix.h',
   'cogl-object.h',
@@ -250,10 +251,11 @@ cogl_sources = [
   'cogl-bitmap-pixbuf.c',
   'cogl-clip-stack.h',
   'cogl-clip-stack.c',
-  'cogl-feature-private.h',
-  'cogl-feature-private.c',
   'cogl-color-private.h',
   'cogl-color.c',
+  'cogl-colorspace-conversion.c',
+  'cogl-feature-private.c',
+  'cogl-feature-private.h',
   'cogl-buffer-private.h',
   'cogl-buffer.c',
   'cogl-pixel-buffer-private.h',
diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c
index 546c58461..939e2e455 100644
--- a/src/compositor/meta-shaped-texture.c
+++ b/src/compositor/meta-shaped-texture.c
@@ -94,6 +94,8 @@ struct _MetaShapedTexturePrivate
   CoglPipeline *masked_pipeline;
   CoglPipeline *unblended_pipeline;
 
+  CoglColorspaceConversion *colorspace_conversion;
+
   gboolean is_y_inverted;
 
   /* The region containing only fully opaque pixels */
@@ -220,7 +222,8 @@ meta_shaped_texture_dispose (GObject *object)
     meta_texture_tower_free (priv->paint_tower);
   priv->paint_tower = NULL;
 
-  g_clear_object (&priv->texture);
+  cogl_clear_object (&priv->colorspace_conversion);
+  cogl_clear_object (&priv->texture);
   g_clear_pointer (&priv->opaque_region, cairo_region_destroy);
 
   meta_shaped_texture_set_mask_texture (self, NULL);
@@ -361,32 +364,26 @@ static void
 check_texture_color_format (MetaShapedTexture *self,
                             CoglMultiPlaneTexture *texture)
 {
+  MetaShapedTexturePrivate *priv = self->priv;
   CoglPixelFormat format = cogl_multi_plane_texture_get_format (texture);
-  static CoglSnippet *func1 = NULL, *func2 = NULL, *snippet3 = NULL;
-  guint n_layers = 0;
+  guint n_layers = cogl_pipeline_get_n_layers (priv->base_pipeline);
 
-    n_layers = cogl_pipeline_get_n_layers (self->priv->base_pipeline);
-
-    if (func1 != NULL)
+  if (priv->colorspace_conversion != NULL)
       return;
 
-    cogl_multi_plane_texture_create_color_conversion_snippets (texture,
-                                                               &func1,
-                                                               &func2,
-                                                               &snippet3);
+  cogl_clear_object (&priv->colorspace_conversion);
+  priv->colorspace_conversion = cogl_colorspace_conversion_new (format);
 
-    /* Check if a snippet is actually necessary */
-    if (func1 != NULL)
-      {
-        cogl_pipeline_add_snippet (self->priv->base_pipeline, func1);
-        cogl_pipeline_add_snippet (self->priv->base_pipeline, func2);
-        meta_shaped_texture_set_create_mipmaps (self, FALSE);
+  /* Check if a snippet is actually necessary */
+  if (priv->colorspace_conversion == NULL)
+    return;
 
-        cogl_pipeline_add_layer_snippet (self->priv->base_pipeline,
-                                         n_layers - 1,
-                                         snippet3);
-      }
+  /* XXX disable for now, our changes are still incompatible with texturetower*/
+  meta_shaped_texture_set_create_mipmaps (self, FALSE);
 
+  cogl_colorspace_conversion_attach_to_pipeline (priv->colorspace_conversion,
+                                                 priv->base_pipeline,
+                                                 n_layers - 1);
 }
 
 static void
diff --git a/src/wayland/meta-wayland-buffer.c b/src/wayland/meta-wayland-buffer.c
index 263826151..3e247dacf 100644
--- a/src/wayland/meta-wayland-buffer.c
+++ b/src/wayland/meta-wayland-buffer.c
@@ -163,7 +163,6 @@ shm_buffer_get_cogl_pixel_format (struct wl_shm_buffer  *shm_buffer,
                                   CoglTextureComponents *components_out)
 {
   CoglPixelFormat format;
-  CoglTextureComponents components = COGL_TEXTURE_COMPONENTS_RGBA;
 
   g_warning ("SHM BUFFER_FORMAT: %d", wl_shm_buffer_get_format (shm_buffer));
   switch (wl_shm_buffer_get_format (shm_buffer))
@@ -171,10 +170,11 @@ shm_buffer_get_cogl_pixel_format (struct wl_shm_buffer  *shm_buffer,
 #if G_BYTE_ORDER == G_BIG_ENDIAN
     case WL_SHM_FORMAT_ARGB8888:
       format = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
+      components_out[0] = COGL_TEXTURE_COMPONENTS_RGBA;
       break;
     case WL_SHM_FORMAT_XRGB8888:
       format = COGL_PIXEL_FORMAT_ARGB_8888;
-      components = COGL_TEXTURE_COMPONENTS_RGB;
+      components_out[0] = COGL_TEXTURE_COMPONENTS_RGB;
       break;
 #elif G_BYTE_ORDER == G_LITTLE_ENDIAN
     case WL_SHM_FORMAT_ARGB8888:
@@ -182,38 +182,52 @@ shm_buffer_get_cogl_pixel_format (struct wl_shm_buffer  *shm_buffer,
       break;
     case WL_SHM_FORMAT_XRGB8888:
       format = COGL_PIXEL_FORMAT_BGRA_8888;
-      components = COGL_TEXTURE_COMPONENTS_RGB;
+      components_out[0] = COGL_TEXTURE_COMPONENTS_RGB;
       break;
 #endif
     case WL_SHM_FORMAT_NV12:
       format = COGL_PIXEL_FORMAT_NV12;
-      g_warning ("FORMAT IS NV12");
+      components_out[0] = COGL_TEXTURE_COMPONENTS_A;
+      components_out[1] = COGL_TEXTURE_COMPONENTS_RG;
       break;
     case WL_SHM_FORMAT_NV21:
-      g_warning ("FORMAT IS NV21");
+      format = COGL_PIXEL_FORMAT_NV21;
+      components_out[0] = COGL_TEXTURE_COMPONENTS_A;
+      components_out[1] = COGL_TEXTURE_COMPONENTS_RG;
       break;
     case WL_SHM_FORMAT_YUV422:
-      g_warning ("FORMAT IS YUV422");
+      format = COGL_PIXEL_FORMAT_YUV422;
+      components_out[0] = COGL_TEXTURE_COMPONENTS_A;
+      components_out[1] = COGL_TEXTURE_COMPONENTS_A;
+      components_out[2] = COGL_TEXTURE_COMPONENTS_A;
       break;
     case WL_SHM_FORMAT_YVU422:
-      g_warning ("FORMAT IS YVU422");
+      format = COGL_PIXEL_FORMAT_YVU422;
+      components_out[0] = COGL_TEXTURE_COMPONENTS_A;
+      components_out[1] = COGL_TEXTURE_COMPONENTS_A;
+      components_out[2] = COGL_TEXTURE_COMPONENTS_A;
       break;
     case WL_SHM_FORMAT_YUV444:
-      g_warning ("FORMAT IS YUV444");
+      format = COGL_PIXEL_FORMAT_YUV444;
+      components_out[0] = COGL_TEXTURE_COMPONENTS_A;
+      components_out[1] = COGL_TEXTURE_COMPONENTS_A;
+      components_out[2] = COGL_TEXTURE_COMPONENTS_A;
       break;
     case WL_SHM_FORMAT_YVU444:
-      g_warning ("FORMAT IS YVU444");
+      format = COGL_PIXEL_FORMAT_YVU444;
+      components_out[0] = COGL_TEXTURE_COMPONENTS_A;
+      components_out[1] = COGL_TEXTURE_COMPONENTS_A;
+      components_out[2] = COGL_TEXTURE_COMPONENTS_A;
       break;
 
     default:
       g_warn_if_reached ();
       format = COGL_PIXEL_FORMAT_ARGB_8888;
+      components_out[0] = COGL_TEXTURE_COMPONENTS_RGBA;
     }
 
   if (format_out)
     *format_out = format;
-  if (components_out)
-    *components_out = components;
 }
 
 static gboolean
@@ -226,7 +240,7 @@ shm_buffer_attach (MetaWaylandBuffer *buffer,
   struct wl_shm_buffer *shm_buffer;
   int stride, width, height;
   CoglPixelFormat format;
-  CoglTextureComponents components;
+  CoglTextureComponents components[3];
   guint i, n_planes;
   guint h_factors[3], v_factors[3];
   gsize offset = 0;
@@ -243,7 +257,7 @@ shm_buffer_attach (MetaWaylandBuffer *buffer,
   width = wl_shm_buffer_get_width (shm_buffer);
   height = wl_shm_buffer_get_height (shm_buffer);
 
-  shm_buffer_get_cogl_pixel_format (shm_buffer, &format, &components);
+  shm_buffer_get_cogl_pixel_format (shm_buffer, &format, components);
   n_planes = cogl_pixel_format_get_n_planes (format);
   cogl_pixel_format_get_subsampling_factors (format, h_factors,  v_factors);
 
@@ -252,6 +266,7 @@ shm_buffer_attach (MetaWaylandBuffer *buffer,
   data = wl_shm_buffer_get_data (shm_buffer);
 
   planes = g_ptr_array_new_full (n_planes, cogl_object_unref);
+      g_warning ("Attaching SHM buffer");
   for (i = 0; i < n_planes; i++)
     {
       CoglBitmap *bitmap;
@@ -265,16 +280,19 @@ shm_buffer_attach (MetaWaylandBuffer *buffer,
       else
         offset += (stride / h_factors[i-1]) * (height / v_factors[i-1]);
 
+      g_warning ("Creating plane %d, h_factor = %d, v_factor = %d, offset = %d", i, h_factors[i], 
v_factors[i], offset);
+
       bitmap = cogl_bitmap_new_for_data (cogl_context,
                                          width / h_factors[i],
                                          height / v_factors[i],
+                                         /* COGL_PIXEL_FORMAT_ARGB_8888, */
                                          format,
                                          stride, /* XXX Do we need to change this too?*/
                                          data + offset);
       g_assert (bitmap);
 
       plane = COGL_TEXTURE (cogl_texture_2d_new_from_bitmap (bitmap));
-      cogl_texture_set_components (COGL_TEXTURE (plane), components);
+      cogl_texture_set_components (COGL_TEXTURE (plane), components[i]);
 
       cogl_object_unref (bitmap);
 
@@ -507,35 +525,47 @@ process_shm_buffer_damage (MetaWaylandBuffer *buffer,
   struct wl_shm_buffer *shm_buffer;
   int i, n_rectangles;
   gboolean set_texture_failed = FALSE;
+  CoglPixelFormat format;
+  CoglTextureComponents components[3];
+  guint bpp[3];
+  guint h_factors[3], v_factors[3];
+  guint n_planes = cogl_multi_plane_texture_get_n_planes (buffer->texture);
 
   n_rectangles = cairo_region_num_rectangles (region);
 
   shm_buffer = wl_shm_buffer_get (buffer->resource);
   wl_shm_buffer_begin_access (shm_buffer);
 
+  shm_buffer_get_cogl_pixel_format (shm_buffer, &format, components);
+  /* XXX */
+  cogl_pixel_format_get_bits_per_pixel (format, bpp);
+  cogl_pixel_format_get_subsampling_factors (format, h_factors, v_factors);
+  /* XXX manually overwriting format */
+  /* format = COGL_PIXEL_FORMAT_ARGB_8888; */
+
   for (i = 0; i < n_rectangles; i++)
     {
       const uint8_t *data = wl_shm_buffer_get_data (shm_buffer);
       int32_t stride = wl_shm_buffer_get_stride (shm_buffer);
-      CoglPixelFormat format;
-      guint n_planes;
-      int bpp;
       cairo_rectangle_int_t rect;
 
-      shm_buffer_get_cogl_pixel_format (shm_buffer, &format, NULL);
-      /* XXX */
-      bpp = _cogl_pixel_format_get_bytes_per_pixel (format);
       cairo_region_get_rectangle (region, i, &rect);
 
-      for (i = 0; i < cogl_multi_plane_texture_get_n_planes (buffer->texture); i++)
+      for (i = 0; i < n_planes; i++)
         {
-          CoglTexture *plane = cogl_multi_plane_texture_get_plane (buffer->texture, i);
+          CoglTexture *plane;
+          guint offset = ((guint) (rect.x * bpp[i] / 8.0)) + rect.y * stride;
+
+          plane = cogl_multi_plane_texture_get_plane (buffer->texture, i);
+
+      g_warning ("Creating plane %d, h_factor = %d, v_factor = %d, offset = %d, bpp = %d", i, h_factors[i], 
v_factors[i], offset, bpp[i]);
 
           if (!_cogl_texture_set_region (plane,
-                                         rect.width, rect.height,
+                                         rect.width / h_factors[i],
+                                         rect.height / v_factors[i],
                                          format,
                                          stride,
-                                         data + rect.x * bpp + rect.y * stride,
+                                         data + offset,
                                          rect.x, rect.y,
                                          0,
                                          error))
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index d2436d6b6..8c5c60d5c 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -319,7 +319,12 @@ add_supported_shm_formats (struct wl_display *display)
   /* Note that a Wayland compositor should support WL_SHM_FORMAT_ARGB8888 and
    * WL_SHM_FORMAT_XRGB8888 by default, so no need to add it here. */
   static const guint32 SUPPORTED_FORMATS[] = {
-    WL_SHM_FORMAT_NV12
+    WL_SHM_FORMAT_NV12,
+    WL_SHM_FORMAT_NV21,
+    WL_SHM_FORMAT_YUV422,
+    WL_SHM_FORMAT_YVU422,
+    WL_SHM_FORMAT_YUV444,
+    WL_SHM_FORMAT_YVU444
   };
 
   for (i = 0; i < G_N_ELEMENTS (SUPPORTED_FORMATS); i++)


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