[mutter/wip/nielsdg/add-yuv-support: 2/3] cogl: Add CoglMultiPlaneTexture for complex formats



commit 510e10679fbeb3535e806f9e686d7c6b9c56caff
Author: Niels De Graef <niels degraef barco com>
Date:   Wed Nov 14 12:22:02 2018 +0100

    cogl: Add CoglMultiPlaneTexture for complex formats
    
    Mutter always assumed that any texture it got was
    representable by a `CoglTexture`, which does not have this kind of
    concept. This also has the useful feature that each `CoglTexture`
    corresponds to a single layer in a `CoglPipeline`.
    
    To deal with this, we introduce a new object: a `CoglMultiPlaneTexture`
    consists of multiple `CoglTexture`s, each representing a plane in the
    texture we got. It also provides knows when to use a
    CoglPixelFormatConversion.

 cogl/cogl/cogl-multi-plane-texture.c   | 157 +++++++++++++++++++++++++++
 cogl/cogl/cogl-multi-plane-texture.h   | 187 +++++++++++++++++++++++++++++++++
 cogl/cogl/cogl-texture-2d.c            |   4 +
 cogl/cogl/cogl-texture-2d.h            |   1 +
 cogl/cogl/cogl.h                       |   2 +
 cogl/cogl/meson.build                  |   2 +
 cogl/cogl/winsys/cogl-winsys-egl-x11.c |   1 +
 7 files changed, 354 insertions(+)
---
diff --git a/cogl/cogl/cogl-multi-plane-texture.c b/cogl/cogl/cogl-multi-plane-texture.c
new file mode 100644
index 000000000..db12e3471
--- /dev/null
+++ b/cogl/cogl/cogl-multi-plane-texture.c
@@ -0,0 +1,157 @@
+/*
+ * 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-multi-plane-texture.h"
+#include "cogl-gtype-private.h"
+#include "cogl-texture-private.h"
+#include "cogl-texture-2d-sliced.h"
+
+struct _CoglMultiPlaneTexture
+{
+  CoglObject _parent;
+
+  CoglPixelFormat format;
+
+  uint8_t n_planes;
+  CoglTexture **planes;
+};
+
+static void
+_cogl_multi_plane_texture_free (CoglMultiPlaneTexture *self);
+
+COGL_OBJECT_DEFINE (MultiPlaneTexture, multi_plane_texture);
+COGL_GTYPE_DEFINE_CLASS (MultiPlaneTexture, multi_plane_texture);
+
+
+CoglPixelFormat
+cogl_multi_plane_texture_get_format (CoglMultiPlaneTexture *self)
+{
+  return self->format;
+}
+
+uint8_t
+cogl_multi_plane_texture_get_n_planes (CoglMultiPlaneTexture *self)
+{
+  return self->n_planes;
+}
+
+CoglTexture *
+cogl_multi_plane_texture_get_plane (CoglMultiPlaneTexture *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 **
+cogl_multi_plane_texture_get_planes (CoglMultiPlaneTexture *self)
+{
+  return self->planes;
+}
+
+guint
+cogl_multi_plane_texture_get_width (CoglMultiPlaneTexture *self)
+{
+  g_return_val_if_fail (self->n_planes > 0, 0);
+
+  return cogl_texture_get_width (self->planes[0]);
+}
+
+guint
+cogl_multi_plane_texture_get_height (CoglMultiPlaneTexture *self)
+{
+  g_return_val_if_fail (self->n_planes > 0, 0);
+
+  return cogl_texture_get_height (self->planes[0]);
+}
+
+static void
+_cogl_multi_plane_texture_free (CoglMultiPlaneTexture *self)
+{
+  uint8_t i = 0;
+
+  for (i = 0; i < self->n_planes; i++)
+    cogl_object_unref (self->planes[i]);
+
+  g_free (self->planes);
+}
+
+CoglMultiPlaneTexture *
+cogl_multi_plane_texture_new (CoglPixelFormat format,
+                              CoglTexture **planes, uint8_t n_planes)
+{
+  CoglMultiPlaneTexture *self = g_slice_new0 (CoglMultiPlaneTexture);
+
+  _cogl_multi_plane_texture_object_new (self);
+
+  self->format = format;
+  self->n_planes = n_planes;
+  self->planes = planes;
+
+  return self;
+}
+
+CoglMultiPlaneTexture *
+cogl_multi_plane_texture_new_single_plane (CoglPixelFormat format,
+                                           CoglTexture *plane)
+{
+  CoglMultiPlaneTexture *self = g_slice_new0 (CoglMultiPlaneTexture);
+
+  _cogl_multi_plane_texture_object_new (self);
+
+  self->format = format;
+  self->n_planes = 1;
+  self->planes = g_malloc (sizeof (CoglTexture *));
+  self->planes[0] = plane;
+
+  return self;
+}
+
+char *
+cogl_multi_plane_texture_to_string (CoglMultiPlaneTexture *self)
+{
+    g_autoptr(GString) str = NULL;
+    g_autofree char *ret = NULL;
+    uint8_t i;
+
+    str = g_string_new ("");
+    g_string_append_printf (str, "CoglMultiPlaneTexture (%p) {\n", self);
+    g_string_append_printf (str, "  .format   =  %s;\n", cogl_pixel_format_to_string (self->format));
+    g_string_append_printf (str, "  .n_planes =  %u;\n", self->n_planes);
+    g_string_append (str, "  .planes   =  {\n");
+
+    for (i = 0; i < self->n_planes; i++)
+      {
+        CoglTexture *plane = self->planes[i];
+
+        g_string_append_printf (str, "    (%p) { .format = %s },\n",
+                                plane,
+                                cogl_pixel_format_to_string (_cogl_texture_get_format (plane)));
+      }
+
+    g_string_append (str, "  }\n");
+    g_string_append (str, "}");
+
+    ret = g_string_free (g_steal_pointer (&str), FALSE);
+    return g_steal_pointer (&ret);
+}
diff --git a/cogl/cogl/cogl-multi-plane-texture.h b/cogl/cogl/cogl-multi-plane-texture.h
new file mode 100644
index 000000000..f69ff23bd
--- /dev/null
+++ b/cogl/cogl/cogl-multi-plane-texture.h
@@ -0,0 +1,187 @@
+/*
+ * 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_MULTI_PLANE_TEXTURE_H__
+#define __COGL_MULTI_PLANE_TEXTURE_H__
+
+#include "cogl/cogl-texture.h"
+
+G_BEGIN_DECLS
+
+/**
+ * SECTION:cogl-multi-plane-texture
+ * @title: CoglMultiPlaneTexture
+ * @short_description: A non-primitive texture that can have multiple planes.
+ *
+ * #CoglMultiPlaneTexture allows one to deal with non-trivial formats that
+ * have multiple planes, requires subsampling and/or aren't in RGB. A common
+ * example of this are decoded video frames, which often use something in the
+ * YUV colorspace, combined with subsampling.
+ *
+ * The basic idea of a #CoglMultiPlaneTexture is the following:
+ * - Each plane is represented by a separate #CoglTexture. That means that you
+ *   should add each of these planes as a layer to your CoglPipeline.
+ * - When dealing with a color space that is not RGB, you can ask the
+ *   #CoglMultiPlaneTexture to create a shader for you that does the conversion
+ *   in the GPU.
+ * - In case you need to deal with memory access in a format with subsampling,
+ *   you can use cogl_multi_plane_texture_get_width() and its analogous version
+ *   for the height to get the correct size of the texture.
+ */
+
+typedef struct _CoglMultiPlaneTexture CoglMultiPlaneTexture;
+#define COGL_MULTI_PLANE_TEXTURE(tex) ((CoglMultiPlaneTexture *) tex)
+
+
+/**
+ * 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
+ * @planes: (transfer full): The actual planes of the texture
+ * @n_planes: The number of planes
+ *
+ * Creates a #CoglMultiPlaneTexture with the given @format. Each of the
+ * #CoglTexture<!-- -->s represents a plane.
+ *
+ * Returns: (transfer full): A new #CoglMultiPlaneTexture. Use
+ * cogl_object_unref() when you're done with it.
+ */
+CoglMultiPlaneTexture * cogl_multi_plane_texture_new  (CoglPixelFormat format,
+                                                       CoglTexture **planes,
+                                                       uint8_t n_planes);
+
+/**
+ * cogl_multi_plane_texture_new_single_plane:
+ * @format: The format of the #CoglMultiPlaneTexture
+ * @plane: (transfer full): The actual planes of the texture
+ *
+ * Creates a #CoglMultiPlaneTexture for a "simple" texture, i.e. with only one
+ * plane.
+ *
+ * Returns: (transfer full): A new #CoglMultiPlaneTexture. Use
+ * cogl_object_unref() when you're done with it.
+ */
+CoglMultiPlaneTexture * cogl_multi_plane_texture_new_single_plane (CoglPixelFormat format,
+                                                                   CoglTexture *plane);
+
+/**
+ * cogl_multi_plane_texture_get_format:
+ * @self: a #CoglMultiPlaneTexture
+ *
+ * Returns the pixel format that is used by this texture.
+ *
+ * Returns: The pixel format that is used by this #CoglMultiPlaneTexture.
+ */
+CoglPixelFormat cogl_multi_plane_texture_get_format   (CoglMultiPlaneTexture *self);
+
+/**
+ * cogl_multi_plane_texture_get_n_planes:
+ * @self: a #CoglMultiPlaneTexture
+ *
+ * Returns the number of planes for this texture. Note that this is entirely
+ * dependent on the #CoglPixelFormat that is used. For example, simple RGB
+ * textures will have a single plane, while some more convoluted formats like
+ * NV12 and YUV 4:4:4 can have 2 and 3 planes respectively.
+ *
+ * Returns: The number of planes in this #CoglMultiPlaneTexture.
+ */
+uint8_t         cogl_multi_plane_texture_get_n_planes (CoglMultiPlaneTexture *self);
+
+/**
+ * cogl_multi_plane_texture_get_plane:
+ * @self: a #CoglMultiPlaneTexture
+ * @index: the index of the plane
+ *
+ * Returns the n'th plane of the #CoglMultiPlaneTexture. Note that it is a
+ * programming error to use with an index larger than
+ * cogl_multi_plane_texture_get_n_planes().
+ *
+ * Returns: (transfer none): The plane at the given @index.
+ */
+CoglTexture *   cogl_multi_plane_texture_get_plane    (CoglMultiPlaneTexture *self,
+                                                       guint index);
+
+/**
+ * cogl_multi_plane_texture_get_planes:
+ * @self: a #CoglMultiPlaneTexture
+ *
+ * Returns all planes of the #CoglMultiPlaneTexture.
+ *
+ * Returns: (transfer none): The planes of this texture.
+ */
+CoglTexture **  cogl_multi_plane_texture_get_planes   (CoglMultiPlaneTexture *self);
+
+/**
+ * cogl_multi_plane_texture_get_width:
+ * @self: a #CoglMultiPlaneTexture
+ *
+ * Returns the width of the #CoglMultiPlaneTexture. Prefer this over calling
+ * cogl_texture_get_width() on one of the textures, as that might give a
+ * different size when dealing with subsampling.
+ *
+ * Returns: The width of the texture.
+ */
+guint           cogl_multi_plane_texture_get_width    (CoglMultiPlaneTexture *self);
+
+/**
+ * cogl_multi_plane_texture_get_height:
+ * @self: a #CoglMultiPlaneTexture
+ *
+ * Returns the height of the #CoglMultiPlaneTexture. Prefer this over calling
+ * cogl_texture_get_height() on one of the textures, as that might give a
+ * different size when dealing with subsampling.
+ *
+ * Returns: The height of the texture.
+ */
+guint           cogl_multi_plane_texture_get_height   (CoglMultiPlaneTexture *self);
+
+/**
+ * cogl_multi_plane_texture_to_string:
+ * @self: a #CoglMultiPlaneTexture
+ *
+ * Returns a string representation of @self, useful for debugging purposes.
+ *
+ * Returns: (transfer full): A string representation of @self. Use g_free() when
+ * done with it.
+ */
+char *          cogl_multi_plane_texture_to_string    (CoglMultiPlaneTexture *self);
+
+G_END_DECLS
+
+#endif
diff --git a/cogl/cogl/cogl-texture-2d.c b/cogl/cogl/cogl-texture-2d.c
index 73bf7a91f..299592ddc 100644
--- a/cogl/cogl/cogl-texture-2d.c
+++ b/cogl/cogl/cogl-texture-2d.c
@@ -240,6 +240,7 @@ cogl_egl_texture_2d_new_from_image (CoglContext *ctx,
                                     int width,
                                     int height,
                                     CoglPixelFormat format,
+                                    CoglTextureComponents components,
                                     EGLImageKHR image,
                                     CoglError **error)
 {
@@ -264,6 +265,9 @@ cogl_egl_texture_2d_new_from_image (CoglContext *ctx,
 
   tex = _cogl_texture_2d_create_base (ctx, width, height, format, loader);
 
+  /* Make sure we've set the right components before allocating */
+  cogl_texture_set_components (COGL_TEXTURE (tex), components);
+
   if (!cogl_texture_allocate (COGL_TEXTURE (tex), error))
     {
       cogl_object_unref (tex);
diff --git a/cogl/cogl/cogl-texture-2d.h b/cogl/cogl/cogl-texture-2d.h
index e649f24f7..f96e715b1 100644
--- a/cogl/cogl/cogl-texture-2d.h
+++ b/cogl/cogl/cogl-texture-2d.h
@@ -218,6 +218,7 @@ cogl_egl_texture_2d_new_from_image (CoglContext *ctx,
                                     int width,
                                     int height,
                                     CoglPixelFormat format,
+                                    CoglTextureComponents components,
                                     EGLImageKHR image,
                                     CoglError **error);
 
diff --git a/cogl/cogl/cogl.h b/cogl/cogl/cogl.h
index 14ccf5748..9b36d7593 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-pixel-format-conversion.h>
 #include <cogl/cogl-matrix.h>
 #include <cogl/cogl-matrix-stack.h>
 #include <cogl/cogl-offscreen.h>
@@ -110,6 +111,7 @@
 #include <cogl/cogl-sub-texture.h>
 #include <cogl/cogl-atlas-texture.h>
 #include <cogl/cogl-meta-texture.h>
+#include <cogl/cogl-multi-plane-texture.h>
 #include <cogl/cogl-primitive-texture.h>
 #include <cogl/cogl-index-buffer.h>
 #include <cogl/cogl-attribute-buffer.h>
diff --git a/cogl/cogl/meson.build b/cogl/cogl/meson.build
index 8171c9acd..9d5a05706 100644
--- a/cogl/cogl/meson.build
+++ b/cogl/cogl/meson.build
@@ -82,6 +82,7 @@ cogl_headers = [
   'cogl-color.h',
   'cogl-framebuffer.h',
   'cogl-matrix.h',
+  'cogl-multi-plane-texture.h',
   'cogl-object.h',
   'cogl-offscreen.h',
   'cogl-onscreen.h',
@@ -323,6 +324,7 @@ cogl_sources = [
   'cogl-atlas-texture-private.h',
   'cogl-atlas-texture.c',
   'cogl-meta-texture.c',
+  'cogl-multi-plane-texture.c',
   'cogl-primitive-texture.c',
   'cogl-blit.h',
   'cogl-blit.c',
diff --git a/cogl/cogl/winsys/cogl-winsys-egl-x11.c b/cogl/cogl/winsys/cogl-winsys-egl-x11.c
index 4f0a12543..ed07c7091 100644
--- a/cogl/cogl/winsys/cogl-winsys-egl-x11.c
+++ b/cogl/cogl/winsys/cogl-winsys-egl-x11.c
@@ -801,6 +801,7 @@ _cogl_winsys_texture_pixmap_x11_create (CoglTexturePixmapX11 *tex_pixmap)
                                         tex->width,
                                         tex->height,
                                         texture_format,
+                                        COGL_TEXTURE_COMPONENTS_RGBA,
                                         egl_tex_pixmap->image,
                                         NULL));
 


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