[mutter/wip/nielsdg/add-yuv-support: 47/48] WIP: add YUV support



commit 3988e2681c6766a9cba81b922e7afb6fd0e7bbe3
Author: Niels De Graef <Niels DeGraef barco com>
Date:   Wed Nov 14 12:22:02 2018 +0100

    WIP: add YUV support

 cogl/cogl/cogl-bitmap-conversion.c              |   1 +
 cogl/cogl/cogl-types.h                          |   4 +-
 cogl/cogl/driver/gl/cogl-texture-2d-gl.c        |   4 +
 cogl/cogl/driver/gl/gl/cogl-driver-gl.c         |   3 +
 cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c |   6 +
 cogl/cogl/driver/gl/gles/cogl-driver-gles.c     |   3 +
 src/Makefile.am                                 |   1 +
 src/compositor/meta-planar-texture.c            | 149 +++++++++++++++
 src/compositor/meta-planar-texture.h            |  66 +++++++
 src/compositor/meta-shaped-texture-private.h    |   3 +-
 src/compositor/meta-shaped-texture.c            | 229 +++++++++++++++++++-----
 src/meson.build                                 |   1 +
 src/wayland/meta-wayland-buffer.c               |  91 +++++++---
 src/wayland/meta-wayland-buffer.h               |   5 +-
 src/wayland/meta-wayland-shell-surface.c        |   6 +-
 src/wayland/meta-wayland-surface.c              |  10 +-
 16 files changed, 499 insertions(+), 83 deletions(-)
---
diff --git a/cogl/cogl/cogl-bitmap-conversion.c b/cogl/cogl/cogl-bitmap-conversion.c
index 9d20a47df..fcd6a38f2 100644
--- a/cogl/cogl/cogl-bitmap-conversion.c
+++ b/cogl/cogl/cogl-bitmap-conversion.c
@@ -321,6 +321,7 @@ _cogl_bitmap_needs_short_temp_buffer (CoglPixelFormat format)
     case COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8:
     case COGL_PIXEL_FORMAT_ANY:
     case COGL_PIXEL_FORMAT_YUV:
+    case COGL_PIXEL_FORMAT_Y_UV:
       g_assert_not_reached ();
 
     case COGL_PIXEL_FORMAT_A_8:
diff --git a/cogl/cogl/cogl-types.h b/cogl/cogl/cogl-types.h
index b351cfd2d..81643bd88 100644
--- a/cogl/cogl/cogl-types.h
+++ b/cogl/cogl/cogl-types.h
@@ -353,7 +353,9 @@ typedef enum { /*< prefix=COGL_PIXEL_FORMAT >*/
   COGL_PIXEL_FORMAT_DEPTH_16  = (9 | COGL_DEPTH_BIT),
   COGL_PIXEL_FORMAT_DEPTH_32  = (3 | COGL_DEPTH_BIT),
 
-  COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8 = (3 | COGL_DEPTH_BIT | COGL_STENCIL_BIT)
+  COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8 = (3 | COGL_DEPTH_BIT | COGL_STENCIL_BIT),
+
+  COGL_PIXEL_FORMAT_Y_UV = 14        /* NV12 */
 } CoglPixelFormat;
 
 /**
diff --git a/cogl/cogl/driver/gl/cogl-texture-2d-gl.c b/cogl/cogl/driver/gl/cogl-texture-2d-gl.c
index ba90998ba..957e20761 100644
--- a/cogl/cogl/driver/gl/cogl-texture-2d-gl.c
+++ b/cogl/cogl/driver/gl/cogl-texture-2d-gl.c
@@ -209,6 +209,8 @@ allocate_from_bitmap (CoglTexture2D *tex_2d,
   GLenum gl_format;
   GLenum gl_type;
 
+  g_warning ("allocate_from_bitmap()");
+
   internal_format =
     _cogl_texture_determine_internal_format (tex, cogl_bitmap_get_format (bmp));
 
@@ -349,6 +351,8 @@ allocate_from_gl_foreign (CoglTexture2D *tex_2d,
   GLint gl_compressed = GL_FALSE;
   GLenum gl_int_format = 0;
 
+  g_warning ("allocate_from_egl_image_foreign()");
+
   if (!ctx->texture_driver->allows_foreign_gl_target (ctx, GL_TEXTURE_2D))
     {
       _cogl_set_error (error,
diff --git a/cogl/cogl/driver/gl/gl/cogl-driver-gl.c b/cogl/cogl/driver/gl/gl/cogl-driver-gl.c
index f7454aa07..d627dddf7 100644
--- a/cogl/cogl/driver/gl/gl/cogl-driver-gl.c
+++ b/cogl/cogl/driver/gl/gl/cogl-driver-gl.c
@@ -108,6 +108,9 @@ _cogl_driver_pixel_format_to_gl_with_target (CoglContext *context,
 
   required_format = format;
 
+  if (format == COGL_PIXEL_FORMAT_Y_UV)
+      g_warning ("cogl-driver-gl: GOT NV12!!");
+
   /* Find GL equivalents */
   switch (format)
     {
diff --git a/cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c b/cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c
index dc3c98ba2..e053f5e0e 100644
--- a/cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c
+++ b/cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c
@@ -99,6 +99,8 @@ _cogl_texture_driver_gen (CoglContext *ctx,
       g_assert_not_reached();
     }
 
+  g_warning ("_cogl_texture_driver_gen %d", internal_format);
+
   /* If the driver doesn't support alpha textures directly then we'll
    * fake them by setting the swizzle parameters */
   if (internal_format == COGL_PIXEL_FORMAT_A_8 &&
@@ -222,6 +224,8 @@ _cogl_texture_driver_upload_subregion_to_gl (CoglContext *ctx,
   int level_width;
   int level_height;
 
+  g_warning ("uploading subregion to gl");
+
   cogl_texture_get_gl_texture (texture, &gl_handle, &gl_target);
 
   data = _cogl_bitmap_gl_bind (source_bmp, COGL_BUFFER_ACCESS_READ, 0, &internal_error);
@@ -326,6 +330,8 @@ _cogl_texture_driver_upload_to_gl (CoglContext *ctx,
   CoglBool status = TRUE;
   CoglError *internal_error = NULL;
 
+  g_warning ("uploading to gl");
+
   data = _cogl_bitmap_gl_bind (source_bmp,
                                COGL_BUFFER_ACCESS_READ,
                                0, /* hints */
diff --git a/cogl/cogl/driver/gl/gles/cogl-driver-gles.c b/cogl/cogl/driver/gl/gles/cogl-driver-gles.c
index cc20a0bd6..fa2e43f82 100644
--- a/cogl/cogl/driver/gl/gles/cogl-driver-gles.c
+++ b/cogl/cogl/driver/gl/gles/cogl-driver-gles.c
@@ -79,6 +79,9 @@ _cogl_driver_pixel_format_to_gl_with_target (CoglContext *context,
 
   required_format = format;
 
+  if (format == COGL_PIXEL_FORMAT_Y_UV)
+      g_warning ("cogl-driver-gles: GOT NV12!!");
+
   /* Find GL equivalents */
   switch (format)
     {
diff --git a/src/Makefile.am b/src/Makefile.am
index b4f22de0d..12d565740 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -243,6 +243,7 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES =      \
        compositor/meta-feedback-actor-private.h        \
        compositor/meta-module.c                \
        compositor/meta-module.h                \
+       compositor/meta-planar-texture.c        \
        compositor/meta-plugin.c                \
        compositor/meta-plugin-manager.c        \
        compositor/meta-plugin-manager.h        \
diff --git a/src/compositor/meta-planar-texture.c b/src/compositor/meta-planar-texture.c
new file mode 100644
index 000000000..36f0214cc
--- /dev/null
+++ b/src/compositor/meta-planar-texture.c
@@ -0,0 +1,149 @@
+/*
+ * 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/>.
+ */
+
+/**
+ * SECTION:meta-planar-texture
+ * @title: MetaPlanarTexture
+ * @short_description: A texture that can have multiple planes (e.g. Y, U, V).
+ */
+
+#include "config.h"
+#include "meta-planar-texture.h"
+
+struct _MetaPlanarTexture
+{
+  GObject parent;
+
+  CoglPixelFormat format;
+
+  guint n_planes;
+  CoglTexture **planes;
+};
+
+G_DEFINE_TYPE (MetaPlanarTexture, meta_planar_texture, G_TYPE_OBJECT);
+
+
+CoglPixelFormat
+meta_planar_texture_get_format (MetaPlanarTexture *self)
+{
+  return self->format;
+}
+
+guint
+meta_planar_texture_get_n_planes (MetaPlanarTexture *self)
+{
+  return self->n_planes;
+}
+
+CoglTexture *
+meta_planar_texture_get_plane (MetaPlanarTexture *self, guint index)
+{
+  g_return_val_if_fail (self->n_planes > 0, NULL);
+  g_return_val_if_fail (index < self->n_planes, NULL);
+
+  return self->planes[index];
+}
+
+CoglTexture **
+meta_planar_texture_get_planes (MetaPlanarTexture *self)
+{
+  return self->planes;
+}
+
+guint
+meta_planar_texture_get_width (MetaPlanarTexture *self)
+{
+  g_return_val_if_fail (self->n_planes > 0, 0);
+
+  return cogl_texture_get_width (self->planes[0]);
+}
+
+guint
+meta_planar_texture_get_height (MetaPlanarTexture *self)
+{
+  g_return_val_if_fail (self->n_planes > 0, 0);
+
+  return cogl_texture_get_height (self->planes[0]);
+}
+
+static void
+meta_planar_texture_finalize (GObject *object)
+{
+  MetaPlanarTexture *self = META_PLANAR_TEXTURE (object);
+
+  g_free (self->planes);
+  /* XXX do we need to unref the CoglTextures as well here? */
+}
+
+static void
+meta_planar_texture_class_init (MetaPlanarTextureClass *klass)
+{
+  GObjectClass *gobj_class = G_OBJECT_CLASS (klass);
+
+  gobj_class->finalize = meta_planar_texture_finalize;
+}
+
+static void
+meta_planar_texture_init (MetaPlanarTexture *self)
+{
+  self->format = COGL_PIXEL_FORMAT_ANY;
+  self->n_planes = 0;
+  self->planes = NULL;
+}
+
+/**
+ * meta_planar_texture_new:
+ * @format: The format of the #MetaPlanarTexture
+ * @planes: (transfer full): The actual planes of the texture
+ * @n_planes: The number of planes
+ *
+ * Creates a #MetaPlanarTexture with the given @format. Each of the
+ * #CoglTexture<!-- -->s represents a plane.
+ */
+MetaPlanarTexture *
+meta_planar_texture_new (CoglPixelFormat format,
+                         CoglTexture **planes, guint n_planes)
+{
+  MetaPlanarTexture *self = g_object_new (META_TYPE_PLANAR_TEXTURE, NULL);
+
+  self->format = format;
+  self->n_planes = n_planes;
+  self->planes = planes;
+
+  return self;
+}
+
+/**
+ * _cogl_pixel_format_get_n_planes:
+ *
+ * Returns the number of planes the given CoglPixelFormat specifies.
+ */
+guint
+_cogl_pixel_format_get_n_planes (CoglPixelFormat format)
+{
+  switch (format)
+    {
+    case COGL_PIXEL_FORMAT_Y_UV:
+      return 2;
+    default:
+      return 1;
+    }
+
+  g_assert_not_reached ();
+}
diff --git a/src/compositor/meta-planar-texture.h b/src/compositor/meta-planar-texture.h
new file mode 100644
index 000000000..616be2781
--- /dev/null
+++ b/src/compositor/meta-planar-texture.h
@@ -0,0 +1,66 @@
+/*
+ * 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 __META_PLANAR_TEXTURE_H__
+#define __META_PLANAR_TEXTURE_H__
+
+#include "cogl/cogl.h"
+
+G_BEGIN_DECLS
+
+#define META_TYPE_PLANAR_TEXTURE (meta_planar_texture_get_type())
+G_DECLARE_FINAL_TYPE (MetaPlanarTexture,
+                      meta_planar_texture,
+                      META, PLANAR_TEXTURE,
+                      GObject)
+
+
+MetaPlanarTexture * meta_planar_texture_new   (CoglPixelFormat format,
+                                               CoglTexture **planes,
+                                               guint n_planes);
+
+
+CoglPixelFormat meta_planar_texture_get_format   (MetaPlanarTexture *self);
+
+guint           meta_planar_texture_get_n_planes (MetaPlanarTexture *self);
+
+CoglTexture *   meta_planar_texture_get_plane    (MetaPlanarTexture *self,
+                                                  guint index);
+
+CoglTexture **  meta_planar_texture_get_planes   (MetaPlanarTexture *self);
+
+guint           meta_planar_texture_get_width    (MetaPlanarTexture *self);
+
+guint           meta_planar_texture_get_height   (MetaPlanarTexture *self);
+
+/**
+ * _cogl_pixel_format_get_n_planes:
+ * @format: a #CoglPixelFormat
+ *
+ * Returns the number of planes the given CoglPixelFormat specifies.
+ */
+guint
+_cogl_pixel_format_get_n_planes (CoglPixelFormat format);
+
+
+G_END_DECLS
+
+#endif
diff --git a/src/compositor/meta-shaped-texture-private.h b/src/compositor/meta-shaped-texture-private.h
index 284f43e36..4ee61c6bb 100644
--- a/src/compositor/meta-shaped-texture-private.h
+++ b/src/compositor/meta-shaped-texture-private.h
@@ -28,10 +28,11 @@
 #define __META_SHAPED_TEXTURE_PRIVATE_H__
 
 #include "meta/meta-shaped-texture.h"
+#include "compositor/meta-planar-texture.h"
 
 ClutterActor *meta_shaped_texture_new (void);
 void meta_shaped_texture_set_texture (MetaShapedTexture *stex,
-                                      CoglTexture       *texture);
+                                      MetaPlanarTexture *texture);
 void meta_shaped_texture_set_is_y_inverted (MetaShapedTexture *stex,
                                             gboolean           is_y_inverted);
 void meta_shaped_texture_set_snippet (MetaShapedTexture *stex,
diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c
index 919e7a9b5..fb1b7a4af 100644
--- a/src/compositor/meta-shaped-texture.c
+++ b/src/compositor/meta-shaped-texture.c
@@ -86,7 +86,7 @@ struct _MetaShapedTexturePrivate
 {
   MetaTextureTower *paint_tower;
 
-  CoglTexture *texture;
+  MetaPlanarTexture *texture;
   CoglTexture *mask_texture;
   CoglSnippet *snippet;
 
@@ -239,19 +239,20 @@ get_base_pipeline (MetaShapedTexture *stex,
 {
   MetaShapedTexturePrivate *priv = stex->priv;
   CoglPipeline *pipeline;
+  guint i = 0;
 
   if (priv->base_pipeline)
     return priv->base_pipeline;
 
   pipeline = cogl_pipeline_new (ctx);
-  cogl_pipeline_set_layer_wrap_mode_s (pipeline, 0,
+  for (i = 0; i < meta_planar_texture_get_n_planes (priv->texture); 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, 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_set_layer_wrap_mode_t (pipeline, i,
                                        COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
+  }
+  g_warning ("is_y_inverted = %d", priv->is_y_inverted);
   if (!priv->is_y_inverted)
     {
       CoglMatrix matrix;
@@ -262,8 +263,8 @@ get_base_pipeline (MetaShapedTexture *stex,
       cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix);
     }
 
-  if (priv->snippet)
-    cogl_pipeline_add_layer_snippet (pipeline, 0, priv->snippet);
+  /* if (priv->snippet) */
+  /*   cogl_pipeline_add_layer_snippet (pipeline, 0, priv->snippet); */
 
   priv->base_pipeline = pipeline;
 
@@ -283,14 +284,20 @@ get_masked_pipeline (MetaShapedTexture *stex,
 {
   MetaShapedTexturePrivate *priv = stex->priv;
   CoglPipeline *pipeline;
+  gint i, n_layers = 0;
 
   if (priv->masked_pipeline)
     return priv->masked_pipeline;
 
   pipeline = cogl_pipeline_copy (get_base_pipeline (stex, ctx));
-  cogl_pipeline_set_layer_combine (pipeline, 1,
-                                   "RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
-                                   NULL);
+  n_layers = meta_planar_texture_get_n_planes (pipeline);
+  /* for (i = 0; i < n_layers; i++) */
+  /*   { */
+  /*     cogl_pipeline_set_layer_combine (pipeline, i, */
+  /*                                      "RGBA = MODULATE (PREVIOUS, TEXTURE[A])", */
+  /*                                      /1* "RGBA = REPLACE (PREVIOUS)", *1/ */
+  /*                                      NULL); */
+  /*   } */
 
   priv->masked_pipeline = pipeline;
 
@@ -350,8 +357,85 @@ paint_clipped_rectangle (CoglFramebuffer       *fb,
 }
 
 static void
-set_cogl_texture (MetaShapedTexture *stex,
-                  CoglTexture       *cogl_tex)
+check_texture_color_format (MetaShapedTexture *self,
+                            MetaPlanarTexture *texture)
+{
+  CoglPixelFormat format = meta_planar_texture_get_format (texture);
+  /* CoglSnippet *snippet1, *snippet2, *snippet3 = NULL; */
+  static CoglSnippet *func_snippet = NULL;
+  static CoglSnippet *snippet3 = NULL;
+  /* static gboolean snippet_set = FALSE; */
+  /* gint i = 0; */
+  gint n_layers = 0;
+
+    n_layers = cogl_pipeline_get_n_layers (self->priv->base_pipeline);
+
+    if (func_snippet == NULL)
+      {
+        /* CoglGstVideoSink version */
+          /* XXX are we using Y_UV or Y_xUxV? Maybe check for RG support? */
+        const gchar *func_snippet_str =
+             "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"
+
+             "  color.r = y + 1.59765625 * v;\n"
+             /* "  color.r = 0.0;\n" */
+             "  color.g = y - 0.390625 * u - 0.8125 * v;\n"
+             /* "  color.g = 0.0;\n" */
+             "  color.b = y + 2.015625 * u;\n"
+             /* "  color.b = 0.0;\n" */
+             "  color.a = 1.0;\n"
+             /* "  color = vec4 (y, u, u, 1.0);\n" */
+
+             "  return color;\n"
+             "}\n";
+
+        func_snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX_GLOBALS,
+                                         func_snippet_str,
+                                         NULL);
+        cogl_pipeline_add_snippet (self->priv->base_pipeline, func_snippet);
+
+        func_snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT_GLOBALS,
+                                         func_snippet_str,
+                                         NULL);
+        cogl_pipeline_add_snippet (self->priv->base_pipeline, func_snippet);
+      }
+
+  if (snippet3 == NULL)
+    {
+      snippet3 = cogl_snippet_new (COGL_SNIPPET_HOOK_LAYER_FRAGMENT,
+         NULL,
+         "cogl_layer = cogl_nv12_to_rgba(cogl_tex_coord0_in.st);\n");
+    }
+
+  switch (format)
+    {
+    case COGL_PIXEL_FORMAT_Y_UV:
+      g_warning ("got a MetaShapedTexture with pixel format NV12!");
+      meta_shaped_texture_set_create_mipmaps (self, FALSE);
+
+      cogl_pipeline_add_layer_snippet (self->priv->base_pipeline, 0, snippet3);
+      cogl_pipeline_add_layer_snippet (self->priv->base_pipeline, 1, snippet3);
+
+      break;
+    default:
+      g_info ("normal pixel format");
+      /* do nothing */
+      break;
+    }
+}
+
+static void
+set_planar_texture (MetaShapedTexture *stex,
+                    MetaPlanarTexture *planar_tex)
 {
   MetaShapedTexturePrivate *priv;
   int width, height;
@@ -360,16 +444,14 @@ set_cogl_texture (MetaShapedTexture *stex,
 
   priv = stex->priv;
 
-  if (priv->texture)
-    cogl_object_unref (priv->texture);
-
-  priv->texture = cogl_tex;
+  g_clear_object (&priv->texture);
+  priv->texture = planar_tex;
 
-  if (cogl_tex != NULL)
+  if (planar_tex != NULL)
     {
-      cogl_object_ref (cogl_tex);
-      width = cogl_texture_get_width (COGL_TEXTURE (cogl_tex));
-      height = cogl_texture_get_height (COGL_TEXTURE (cogl_tex));
+      g_object_ref (planar_tex);
+      width = meta_planar_texture_get_width (planar_tex);
+      height = meta_planar_texture_get_height (planar_tex);
     }
   else
     {
@@ -377,6 +459,7 @@ set_cogl_texture (MetaShapedTexture *stex,
       height = 0;
     }
 
+  /* Do we have a different size? */
   if (priv->tex_width != width ||
       priv->tex_height != height)
     {
@@ -387,13 +470,24 @@ set_cogl_texture (MetaShapedTexture *stex,
       g_signal_emit (stex, signals[SIZE_CHANGED], 0);
     }
 
+  /* Check if we need to do color conversion to RGBA */
+  if (planar_tex != NULL && priv->base_pipeline != NULL)
+    {
+      check_texture_color_format (stex, planar_tex);
+    }
+
   /* NB: We don't queue a redraw of the actor here because we don't
    * know how much of the buffer has changed with respect to the
    * previous buffer. We only queue a redraw in response to surface
    * damage. */
 
-  if (priv->create_mipmaps)
-    meta_texture_tower_set_base_texture (priv->paint_tower, cogl_tex);
+  if (FALSE)
+  /* if (priv->create_mipmaps) */
+    {
+      /* XXX */
+      CoglTexture *cogl_tex = meta_planar_texture_get_plane (planar_tex, 0);
+      meta_texture_tower_set_base_texture (priv->paint_tower, cogl_tex);
+    }
 }
 
 static gboolean
@@ -426,13 +520,14 @@ meta_shaped_texture_paint (ClutterActor *actor)
   cairo_region_t *blended_tex_region;
   CoglContext *ctx;
   CoglFramebuffer *fb;
-  CoglTexture *paint_tex = NULL;
+  MetaPlanarTexture *paint_tex = NULL;
+  guint n_planes;
   ClutterActorBox alloc;
   CoglPipelineFilter filter;
   gint64 now = g_get_monotonic_time ();
 
-  if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
-    return;
+  /* if (priv->clip_region && cairo_region_is_empty (priv->clip_region)) */
+  /*   return; */
 
   if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex)))
     clutter_actor_realize (CLUTTER_ACTOR (stex));
@@ -452,7 +547,8 @@ meta_shaped_texture_paint (ClutterActor *actor)
    * Setting the texture quality to high without SGIS_generate_mipmap
    * support for TFP textures will result in fallbacks to XGetImage.
    */
-  if (priv->create_mipmaps && priv->last_invalidation)
+  if (FALSE)
+  /* if (priv->create_mipmaps && priv->last_invalidation) */
     {
       gint64 age = now - priv->last_invalidation;
 
@@ -463,12 +559,13 @@ meta_shaped_texture_paint (ClutterActor *actor)
 
   if (paint_tex == NULL)
     {
-      paint_tex = COGL_TEXTURE (priv->texture);
+      paint_tex = priv->texture;
 
       if (paint_tex == NULL)
         return;
 
-      if (priv->create_mipmaps)
+      if (FALSE)
+      /* if (priv->create_mipmaps) */
         {
           /* Minus 1000 to ensure we don't fail the age test in timeout */
           priv->earliest_remipmap = now + MIN_MIPMAP_AGE_USEC - 1000;
@@ -481,6 +578,8 @@ meta_shaped_texture_paint (ClutterActor *actor)
         }
     }
 
+  n_planes = meta_planar_texture_get_n_planes (paint_tex);
+
   clutter_actor_get_scale (actor, &tex_scale, NULL);
   tex_width = priv->tex_width;
   tex_height = priv->tex_height;
@@ -585,8 +684,21 @@ meta_shaped_texture_paint (ClutterActor *actor)
       if (!cairo_region_is_empty (region))
         {
           opaque_pipeline = get_unblended_pipeline (stex, ctx);
-          cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex);
-          cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter);
+              g_warning ("Unblended pipeline: adding %d layers", n_planes);
+          for (i = 0; i < n_planes; i++)
+            {
+              CoglTexture *plane = meta_planar_texture_get_plane (paint_tex, i);
+
+
+              cogl_pipeline_set_layer_texture (opaque_pipeline, i, plane);
+              /* cogl_pipeline_set_layer_filters (opaque_pipeline, i, filter, filter); */
+            }
+      cogl_pipeline_set_layer_combine (opaque_pipeline, n_planes,
+                                       /* "RGB=MODULATE(PREVIOUS, TEXTURE_0[A])\n" */
+                                       /*  "A=REPLACE(PREVIOUS[A])", */
+                                       /* "RGBA = MODULATE (PREVIOUS, TEXTURE[A])", */
+                                       "RGBA = REPLACE (PREVIOUS)",
+                                       NULL);
 
           n_rects = cairo_region_num_rectangles (region);
           for (i = 0; i < n_rects; i++)
@@ -613,20 +725,35 @@ meta_shaped_texture_paint (ClutterActor *actor)
   if (!blended_tex_region || !cairo_region_is_empty (blended_tex_region))
     {
       CoglPipeline *blended_pipeline;
+      guint i;
 
       if (priv->mask_texture == NULL)
         {
           blended_pipeline = get_unmasked_pipeline (stex, ctx);
+          g_warning ("blended_pipeline = get_unmasked_pipeline (stex, ctx);");
         }
       else
         {
+          g_warning ("blended_pipeline = get_masked_pipeline (stex, ctx);");
           blended_pipeline = get_masked_pipeline (stex, ctx);
-          cogl_pipeline_set_layer_texture (blended_pipeline, 1, priv->mask_texture);
-          cogl_pipeline_set_layer_filters (blended_pipeline, 1, filter, filter);
+          cogl_pipeline_set_layer_texture (blended_pipeline, n_planes, priv->mask_texture);
+          /* cogl_pipeline_set_layer_filters (blended_pipeline, n_planes, filter, filter); */
         }
 
-      cogl_pipeline_set_layer_texture (blended_pipeline, 0, paint_tex);
-      cogl_pipeline_set_layer_filters (blended_pipeline, 0, filter, filter);
+      for (i = 0; i < n_planes; i++)
+        {
+          CoglTexture *plane = meta_planar_texture_get_plane (paint_tex, i);
+          g_warning ("Blended pipeline: adding layer %d, %p", i, plane);
+
+          cogl_pipeline_set_layer_texture (blended_pipeline, i, plane);
+          /* cogl_pipeline_set_layer_filters (blended_pipeline, i, filter, filter); */
+      cogl_pipeline_set_layer_combine (blended_pipeline, n_planes,
+                                       /* "RGB=MODULATE(PREVIOUS, TEXTURE_0[A])\n" */
+                                       /*  "A=REPLACE(PREVIOUS[A])", */
+                                       "RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
+                                       /* "RGBA = REPLACE (PREVIOUS)", */
+                                       NULL);
+        }
 
       CoglColor color;
       cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity);
@@ -861,15 +988,15 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
 /**
  * meta_shaped_texture_set_texture:
  * @stex: The #MetaShapedTexture
- * @pixmap: The #CoglTexture to display
+ * @pixmap: The #MetaPlanarTexture to display
  */
 void
 meta_shaped_texture_set_texture (MetaShapedTexture *stex,
-                                 CoglTexture       *texture)
+                                 MetaPlanarTexture *texture)
 {
   g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
 
-  set_cogl_texture (stex, texture);
+  set_planar_texture (stex, texture);
 }
 
 /**
@@ -918,7 +1045,8 @@ CoglTexture *
 meta_shaped_texture_get_texture (MetaShapedTexture *stex)
 {
   g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), NULL);
-  return COGL_TEXTURE (stex->priv->texture);
+
+  return meta_planar_texture_get_plane (stex->priv->texture, 0);
 }
 
 /**
@@ -976,19 +1104,19 @@ cairo_surface_t *
 meta_shaped_texture_get_image (MetaShapedTexture     *stex,
                                cairo_rectangle_int_t *clip)
 {
-  CoglTexture *texture, *mask_texture;
+  MetaPlanarTexture *texture, *mask_texture;
   cairo_rectangle_int_t texture_rect = { 0, 0, 0, 0 };
   cairo_surface_t *surface;
 
   g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), NULL);
 
-  texture = COGL_TEXTURE (stex->priv->texture);
+  texture = stex->priv->texture;
 
   if (texture == NULL)
     return NULL;
 
-  texture_rect.width = cogl_texture_get_width (texture);
-  texture_rect.height = cogl_texture_get_height (texture);
+  texture_rect.width = meta_planar_texture_get_width (texture);
+  texture_rect.height = meta_planar_texture_get_height (texture);
 
   if (clip != NULL)
     {
@@ -998,6 +1126,7 @@ meta_shaped_texture_get_image (MetaShapedTexture     *stex,
         return NULL;
     }
 
+  /* XXX */
   if (clip != NULL)
     texture = cogl_texture_new_from_sub_texture (texture,
                                                  clip->x,
@@ -1006,9 +1135,10 @@ meta_shaped_texture_get_image (MetaShapedTexture     *stex,
                                                  clip->height);
 
   surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
-                                        cogl_texture_get_width (texture),
-                                        cogl_texture_get_height (texture));
+                                        meta_planar_texture_get_width (texture),
+                                        meta_planar_texture_get_height (texture));
 
+  /* XXX */
   cogl_texture_get_data (texture, CLUTTER_CAIRO_FORMAT_ARGB32,
                          cairo_image_surface_get_stride (surface),
                          cairo_image_surface_get_data (surface));
@@ -1016,7 +1146,7 @@ meta_shaped_texture_get_image (MetaShapedTexture     *stex,
   cairo_surface_mark_dirty (surface);
 
   if (clip != NULL)
-    cogl_object_unref (texture);
+    g_object_unref (texture);
 
   mask_texture = stex->priv->mask_texture;
   if (mask_texture != NULL)
@@ -1032,8 +1162,8 @@ meta_shaped_texture_get_image (MetaShapedTexture     *stex,
                                                           clip->height);
 
       mask_surface = cairo_image_surface_create (CAIRO_FORMAT_A8,
-                                                 cogl_texture_get_width (mask_texture),
-                                                 cogl_texture_get_height (mask_texture));
+                                                 meta_planar_texture_get_width (mask_texture),
+                                                 meta_planar_texture_get_height (mask_texture));
 
       cogl_texture_get_data (mask_texture, COGL_PIXEL_FORMAT_A_8,
                              cairo_image_surface_get_stride (mask_surface),
@@ -1107,5 +1237,6 @@ cullable_iface_init (MetaCullableInterface *iface)
 ClutterActor *
 meta_shaped_texture_new (void)
 {
+    g_warning ("New MetaShapedTexture!");
   return g_object_new (META_TYPE_SHAPED_TEXTURE, NULL);
 }
diff --git a/src/meson.build b/src/meson.build
index 4ea30b06d..47b32297d 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -271,6 +271,7 @@ mutter_sources = [
   'compositor/meta-feedback-actor-private.h',
   'compositor/meta-module.c',
   'compositor/meta-module.h',
+  'compositor/meta-planar-texture.c',
   'compositor/meta-plugin.c',
   'compositor/meta-plugin-manager.c',
   'compositor/meta-plugin-manager.h',
diff --git a/src/wayland/meta-wayland-buffer.c b/src/wayland/meta-wayland-buffer.c
index 9fee02d52..d3f08125c 100644
--- a/src/wayland/meta-wayland-buffer.c
+++ b/src/wayland/meta-wayland-buffer.c
@@ -184,6 +184,19 @@ shm_buffer_get_cogl_pixel_format (struct wl_shm_buffer  *shm_buffer,
       components = COGL_TEXTURE_COMPONENTS_RGB;
       break;
 #endif
+    case WL_SHM_FORMAT_NV12:
+      g_warning ("FORMAT IS NV12");
+    case WL_SHM_FORMAT_NV21:
+      g_warning ("FORMAT IS NV21");
+    case WL_SHM_FORMAT_YUV422:
+      g_warning ("FORMAT IS YUV422");
+    case WL_SHM_FORMAT_YVU422:
+      g_warning ("FORMAT IS YVU422");
+    case WL_SHM_FORMAT_YUV444:
+      g_warning ("FORMAT IS YUV444");
+    case WL_SHM_FORMAT_YVU444:
+      g_warning ("FORMAT IS YVU444");
+
     default:
       g_warn_if_reached ();
       format = COGL_PIXEL_FORMAT_ARGB_8888;
@@ -257,12 +270,15 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
   EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
   int format, width, height, y_inverted;
   CoglPixelFormat cogl_format;
-  EGLImageKHR egl_image;
-  CoglTexture2D *texture;
+  guint i, n_planes;
+  GPtrArray *textures;
+  gboolean ret = FALSE;
+  EGLint attrib_list[3] = { EGL_NONE, EGL_NONE, EGL_NONE };
 
   if (buffer->texture)
     return TRUE;
 
+  /* Query the necessary properties */
   if (!meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource,
                                       EGL_TEXTURE_FORMAT, &format,
                                       error))
@@ -283,6 +299,7 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
                                       NULL))
     y_inverted = EGL_TRUE;
 
+  /* Map the EGL texture format to CoglPixelFormat, if possible */
   switch (format)
     {
     case EGL_TEXTURE_RGB:
@@ -291,6 +308,10 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
     case EGL_TEXTURE_RGBA:
       cogl_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
       break;
+    case EGL_TEXTURE_Y_UV_WL:
+      g_warning ("Got a NV12 color format texture!!");
+      cogl_format = COGL_PIXEL_FORMAT_Y_UV;
+      break;
     default:
       g_set_error (error, G_IO_ERROR,
                    G_IO_ERROR_FAILED,
@@ -298,30 +319,56 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
       return FALSE;
     }
 
-  /* The WL_bind_wayland_display spec states that EGL_NO_CONTEXT is to be used
-   * in conjunction with the EGL_WAYLAND_BUFFER_WL target. */
-  egl_image = meta_egl_create_image (egl, egl_display, EGL_NO_CONTEXT,
-                                     EGL_WAYLAND_BUFFER_WL, buffer->resource,
-                                     NULL,
-                                     error);
-  if (egl_image == EGL_NO_IMAGE_KHR)
-    return FALSE;
+  n_planes = _cogl_pixel_format_get_n_planes (cogl_format);
+  textures = g_ptr_array_new_full (n_planes, cogl_object_unref);
 
-  texture = cogl_egl_texture_2d_new_from_image (cogl_context,
-                                                width, height,
-                                                cogl_format,
-                                                egl_image,
-                                                error);
+  /* Each EGLImage is a plane in the final texture */
+  for (i = 0; i < n_planes; i++)
+    {
+      EGLImageKHR egl_img;
+      CoglTexture2D *texture;
 
-  meta_egl_destroy_image (egl, egl_display, egl_image, NULL);
+      /* Specify that we want the i'th plane */
+      attrib_list[0] = EGL_WAYLAND_PLANE_WL;
+      attrib_list[1] = i;
 
-  if (!texture)
-    return FALSE;
+      /* The WL_bind_wayland_display spec states that EGL_NO_CONTEXT is to be
+       * used in conjunction with the EGL_WAYLAND_BUFFER_WL target. */
+      egl_img = meta_egl_create_image (egl, egl_display, EGL_NO_CONTEXT,
+                                       EGL_WAYLAND_BUFFER_WL, buffer->resource,
+                                       attrib_list,
+                                       error);
+
+      if (egl_img == EGL_NO_IMAGE_KHR)
+        goto out;
+
+      texture = cogl_egl_texture_2d_new_from_image (cogl_context,
+                                                    width, height,
+                                                    cogl_format,
+                                                    egl_img,
+                                                    error);
+
+      meta_egl_destroy_image (egl, egl_display, egl_img, NULL);
 
-  buffer->texture = COGL_TEXTURE (texture);
+      if (!texture)
+        goto out;
+
+      g_ptr_array_add (textures, texture);
+    }
+
+
+  buffer->texture = meta_planar_texture_new (cogl_format,
+                                             g_ptr_array_free (textures, FALSE),
+                                             n_planes);
   buffer->is_y_inverted = !!y_inverted;
 
-  return TRUE;
+  ret = TRUE;
+
+out:
+  if (!ret)
+    g_ptr_array_free (textures, TRUE);
+
+  return ret;
 }
 
 #ifdef HAVE_WAYLAND_EGLSTREAM
@@ -375,7 +422,7 @@ meta_wayland_buffer_attach (MetaWaylandBuffer *buffer,
   g_assert_not_reached ();
 }
 
-CoglTexture *
+MetaPlanarTexture *
 meta_wayland_buffer_get_texture (MetaWaylandBuffer *buffer)
 {
   return buffer->texture;
@@ -486,7 +533,7 @@ meta_wayland_buffer_finalize (GObject *object)
 {
   MetaWaylandBuffer *buffer = META_WAYLAND_BUFFER (object);
 
-  g_clear_pointer (&buffer->texture, cogl_object_unref);
+  g_clear_object (&buffer->texture);
 #ifdef HAVE_WAYLAND_EGLSTREAM
   g_clear_object (&buffer->egl_stream.stream);
 #endif
diff --git a/src/wayland/meta-wayland-buffer.h b/src/wayland/meta-wayland-buffer.h
index 3709c85ff..42fda4886 100644
--- a/src/wayland/meta-wayland-buffer.h
+++ b/src/wayland/meta-wayland-buffer.h
@@ -29,6 +29,7 @@
 #include <wayland-server.h>
 
 #include "cogl/cogl.h"
+#include "compositor/meta-planar-texture.h"
 #include "wayland/meta-wayland-types.h"
 #include "wayland/meta-wayland-egl-stream.h"
 #include "wayland/meta-wayland-dma-buf.h"
@@ -51,7 +52,7 @@ struct _MetaWaylandBuffer
   struct wl_resource *resource;
   struct wl_listener destroy_listener;
 
-  CoglTexture *texture;
+  MetaPlanarTexture *texture;
   gboolean is_y_inverted;
 
   MetaWaylandBufferType type;
@@ -77,7 +78,7 @@ gboolean                meta_wayland_buffer_is_realized         (MetaWaylandBuff
 gboolean                meta_wayland_buffer_realize             (MetaWaylandBuffer     *buffer);
 gboolean                meta_wayland_buffer_attach              (MetaWaylandBuffer     *buffer,
                                                                  GError               **error);
-CoglTexture *           meta_wayland_buffer_get_texture         (MetaWaylandBuffer     *buffer);
+MetaPlanarTexture *     meta_wayland_buffer_get_texture         (MetaWaylandBuffer     *buffer);
 CoglSnippet *           meta_wayland_buffer_create_snippet      (MetaWaylandBuffer     *buffer);
 gboolean                meta_wayland_buffer_is_y_inverted       (MetaWaylandBuffer     *buffer);
 void                    meta_wayland_buffer_process_damage      (MetaWaylandBuffer     *buffer,
diff --git a/src/wayland/meta-wayland-shell-surface.c b/src/wayland/meta-wayland-shell-surface.c
index 50dbb9bcd..6f4115dd1 100644
--- a/src/wayland/meta-wayland-shell-surface.c
+++ b/src/wayland/meta-wayland-shell-surface.c
@@ -153,7 +153,7 @@ meta_wayland_shell_surface_surface_commit (MetaWaylandSurfaceRole  *surface_role
   MetaWaylandSurfaceRoleClass *surface_role_class;
   MetaWindow *window;
   MetaWaylandBuffer *buffer;
-  CoglTexture *texture;
+  MetaPlanarTexture *texture;
   double scale;
 
   surface_role_class =
@@ -171,8 +171,8 @@ meta_wayland_shell_surface_surface_commit (MetaWaylandSurfaceRole  *surface_role
   scale = meta_wayland_actor_surface_calculate_scale (actor_surface);
   texture = meta_wayland_buffer_get_texture (buffer);
 
-  window->buffer_rect.width = cogl_texture_get_width (texture) * scale;
-  window->buffer_rect.height = cogl_texture_get_height (texture) * scale;
+  window->buffer_rect.width = meta_planar_texture_get_width (texture) * scale;
+  window->buffer_rect.height = meta_planar_texture_get_height (texture) * scale;
 }
 
 static void
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index b918e296e..3202ab98f 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -648,7 +648,7 @@ meta_wayland_surface_apply_pending_state (MetaWaylandSurface      *surface,
           if (switched_buffer && meta_wayland_surface_get_actor (surface))
             {
               MetaShapedTexture *stex;
-              CoglTexture *texture;
+              MetaPlanarTexture *texture;
               CoglSnippet *snippet;
               gboolean is_y_inverted;
 
@@ -1749,8 +1749,8 @@ meta_wayland_surface_get_width (MetaWaylandSurface *surface)
   buffer = surface->buffer_ref.buffer;
   if (buffer)
     {
-      CoglTexture *texture = meta_wayland_buffer_get_texture (buffer);
-      return cogl_texture_get_width (texture) / surface->scale;
+      MetaPlanarTexture *texture = meta_wayland_buffer_get_texture (buffer);
+      return meta_planar_texture_get_width (texture) / surface->scale;
     }
   else
     {
@@ -1766,8 +1766,8 @@ meta_wayland_surface_get_height (MetaWaylandSurface *surface)
   buffer = surface->buffer_ref.buffer;
   if (buffer)
     {
-      CoglTexture *texture = meta_wayland_buffer_get_texture (buffer);
-      return cogl_texture_get_height (texture) / surface->scale;
+      MetaPlanarTexture *texture = meta_wayland_buffer_get_texture (buffer);
+      return meta_planar_texture_get_height (texture) / surface->scale;
     }
   else
     {



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