[gtk/wip/otte/color-profiles: 60/60] memorytexture: Split out GdkMemoryFormat handling




commit 8bdda88f03ece93356f96c5bcc3b569a64266662
Author: Benjamin Otte <otte redhat com>
Date:   Wed Sep 22 02:01:41 2021 +0200

    memorytexture: Split out GdkMemoryFormat handling
    
    Also, now make gdk_memory_convert() the only conversion functions
    and allow conversions between any 2 formats by going via a float[4].
    
    This could be optimized via fast-paths, but so far it isn't.

 gdk/gdkglcontext.c            |   3 +-
 gdk/gdkgltexture.c            |   1 +
 gdk/gdkmemoryformat.c         | 362 +++++++++++++++++++++++++++++
 gdk/gdkmemoryformatprivate.h  |  42 ++++
 gdk/gdkmemorytexture.c        | 518 +-----------------------------------------
 gdk/gdkmemorytextureprivate.h |  35 ---
 gdk/loaders/gdkpng.c          |   1 +
 gdk/loaders/gdktiff.c         |   1 +
 gdk/meson.build               |   1 +
 gsk/ngl/gsknglcommandqueue.c  |   1 +
 gsk/ngl/gsknglglyphlibrary.c  |   4 +-
 gsk/ngl/gskngliconlibrary.c   |   4 +-
 12 files changed, 426 insertions(+), 547 deletions(-)
---
diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c
index 76be3c7ef9..925ae640e6 100644
--- a/gdk/gdkglcontext.c
+++ b/gdk/gdkglcontext.c
@@ -76,6 +76,7 @@
 
 #include "gdkglcontextprivate.h"
 #include "gdkdisplayprivate.h"
+#include "gdkmemoryformatprivate.h"
 #include "gdkmemorytextureprivate.h"
 #include "gdkinternals.h"
 
@@ -294,7 +295,7 @@ gdk_gl_context_upload_texture (GdkGLContext    *context,
     {
       copy = g_malloc (width * height * 4);
       gdk_memory_convert (copy, width * 4,
-                          GDK_MEMORY_CONVERT_GLES_RGBA,
+                          GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
                           data, stride, data_format,
                           width, height);
       data_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
diff --git a/gdk/gdkgltexture.c b/gdk/gdkgltexture.c
index e2e292964d..1a321fa879 100644
--- a/gdk/gdkgltexture.c
+++ b/gdk/gdkgltexture.c
@@ -21,6 +21,7 @@
 #include "gdkgltextureprivate.h"
 
 #include "gdkdisplayprivate.h"
+#include "gdkmemoryformatprivate.h"
 #include "gdkmemorytextureprivate.h"
 #include "gdktextureprivate.h"
 
diff --git a/gdk/gdkmemoryformat.c b/gdk/gdkmemoryformat.c
new file mode 100644
index 0000000000..7db5d3f56a
--- /dev/null
+++ b/gdk/gdkmemoryformat.c
@@ -0,0 +1,362 @@
+/*
+ * Copyright © 2021 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte gnome org>
+ */
+
+#include "config.h"
+
+#include "gdkmemoryformatprivate.h"
+
+#include "gsk/ngl/fp16private.h"
+
+typedef struct _GdkMemoryFormatDescription GdkMemoryFormatDescription;
+
+typedef enum {
+  GDK_MEMORY_ALPHA_PREMULTIPLIED,
+  GDK_MEMORY_ALPHA_STRAIGHT,
+  GDK_MEMORY_ALPHA_OPAQUE
+} GdkMemoryAlpha;
+
+#define TYPED_FUNCS(name, T, R, G, B, A, bpp, scale) \
+static void \
+name ## _to_float (float        *dest, \
+                   const guchar *src_data, \
+                   gsize         n) \
+{ \
+  for (gsize i = 0; i < n; i++) \
+    { \
+      T *src = (T *) (src_data + i * bpp); \
+      dest[0] = (float) src[R] / scale; \
+      dest[1] = (float) src[G] / scale; \
+      dest[2] = (float) src[B] / scale; \
+      if (A >= 0) dest[3] = (float) src[A] / scale; else dest[3] = 1.0; \
+    } \
+} \
+\
+static void \
+name ## _from_float (guchar      *dest_data, \
+                     const float *src, \
+                     gsize        n) \
+{ \
+  for (gsize i = 0; i < n; i++) \
+    { \
+      T *dest = (T *) (dest_data + i * bpp); \
+      dest[R] = CLAMP (src[0] * (scale + 1), 0, scale); \
+      dest[G] = CLAMP (src[1] * (scale + 1), 0, scale); \
+      dest[B] = CLAMP (src[2] * (scale + 1), 0, scale); \
+      if (A >= 0) dest[A] = CLAMP (src[3] * (scale + 1), 0, scale); \
+    } \
+}
+
+TYPED_FUNCS (b8g8r8a8_premultiplied, guchar, 2, 1, 0, 3, 4, 255)
+TYPED_FUNCS (a8r8g8b8_premultiplied, guchar, 1, 2, 3, 0, 4, 255)
+TYPED_FUNCS (r8g8b8a8_premultiplied, guchar, 0, 1, 2, 3, 4, 255)
+TYPED_FUNCS (b8g8r8a8, guchar, 2, 1, 0, 3, 4, 255)
+TYPED_FUNCS (a8r8g8b8, guchar, 1, 2, 3, 0, 4, 255)
+TYPED_FUNCS (r8g8b8a8, guchar, 0, 1, 2, 3, 4, 255)
+TYPED_FUNCS (a8b8g8r8, guchar, 3, 2, 1, 0, 4, 255)
+TYPED_FUNCS (r8g8b8, guchar, 0, 1, 2, -1, 3, 255)
+TYPED_FUNCS (b8g8r8, guchar, 2, 1, 0, -1, 3, 255)
+TYPED_FUNCS (r16g16b16, guint16, 0, 1, 2, -1, 6, 65535)
+TYPED_FUNCS (r16g16b16a16, guint16, 0, 1, 2, 3, 8, 65535)
+
+static void
+r16g16b16_float_to_float (float        *dest,
+                          const guchar *src_data,
+                          gsize         n)
+{
+  guint16 *src = (guint16 *) src_data;
+  for (gsize i = 0; i < n; i++)
+    {
+      half_to_float (src, dest, 3);
+      dest[3] = 1.0;
+      dest += 4;
+      src += 3;
+    }
+}
+
+static void
+r16g16b16_float_from_float (guchar      *dest_data,
+                            const float *src,
+                            gsize        n)
+{
+  guint16 *dest = (guint16 *) dest_data;
+  for (gsize i = 0; i < n; i++)
+    {
+      float_to_half (src, dest, 3);
+      dest += 3;
+      src += 4;
+    }
+}
+
+static void
+r16g16b16a16_float_to_float (float        *dest,
+                             const guchar *src,
+                             gsize         n)
+{
+  half_to_float ((const guint16 *) src, dest, 4 * n);
+}
+
+static void
+r16g16b16a16_float_from_float (guchar      *dest,
+                               const float *src,
+                               gsize        n)
+{
+  float_to_half (src, (guint16 *) dest, 4 * n);
+}
+
+static void
+r32g32b32_float_to_float (float        *dest,
+                          const guchar *src_data,
+                          gsize         n)
+{
+  float *src = (float *) src_data;
+  for (gsize i = 0; i < n; i++)
+    {
+      dest[0] = src[0];
+      dest[1] = src[1];
+      dest[2] = src[2];
+      dest[3] = 1.0;
+      dest += 4;
+      src += 3;
+    }
+}
+
+static void
+r32g32b32_float_from_float (guchar      *dest_data,
+                            const float *src,
+                            gsize        n)
+{
+  float *dest = (float *) dest_data;
+  for (gsize i = 0; i < n; i++)
+    {
+      dest[0] = src[0];
+      dest[1] = src[1];
+      dest[2] = src[2];
+      dest += 3;
+      src += 4;
+    }
+}
+
+static void
+r32g32b32a32_float_to_float (float        *dest,
+                             const guchar *src,
+                             gsize         n)
+{
+  memcpy (dest, src, sizeof (float) * n * 4);
+}
+
+static void
+r32g32b32a32_float_from_float (guchar      *dest,
+                               const float *src,
+                               gsize        n)
+{
+  memcpy (dest, src, sizeof (float) * n * 4);
+}
+
+struct _GdkMemoryFormatDescription
+{
+  GdkMemoryAlpha alpha;
+  gsize bytes_per_pixel;
+  gsize alignment;
+
+  /* no premultiplication going on here */
+  void (* to_float) (float *, const guchar*, gsize);
+  void (* from_float) (guchar *, const float *, gsize);
+};
+
+static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = {
+  [GDK_MEMORY_B8G8R8A8_PREMULTIPLIED] = {
+    GDK_MEMORY_ALPHA_PREMULTIPLIED,
+    4,
+    G_ALIGNOF (guchar),
+    b8g8r8a8_premultiplied_to_float,
+    b8g8r8a8_premultiplied_from_float,
+  },
+  [GDK_MEMORY_A8R8G8B8_PREMULTIPLIED] = {
+    GDK_MEMORY_ALPHA_PREMULTIPLIED,
+    4,
+    G_ALIGNOF (guchar),
+    a8r8g8b8_premultiplied_to_float,
+    a8r8g8b8_premultiplied_from_float,
+  },
+  [GDK_MEMORY_R8G8B8A8_PREMULTIPLIED] = {
+    GDK_MEMORY_ALPHA_PREMULTIPLIED,
+    4,
+    G_ALIGNOF (guchar),
+    r8g8b8a8_premultiplied_to_float,
+    r8g8b8a8_premultiplied_from_float,
+  },
+  [GDK_MEMORY_B8G8R8A8] = {
+    GDK_MEMORY_ALPHA_STRAIGHT,
+    4,
+    G_ALIGNOF (guchar),
+    b8g8r8a8_to_float,
+    b8g8r8a8_from_float,
+  },
+  [GDK_MEMORY_A8R8G8B8] = {
+    GDK_MEMORY_ALPHA_STRAIGHT,
+    4,
+    G_ALIGNOF (guchar),
+    a8r8g8b8_to_float,
+    a8r8g8b8_from_float,
+  },
+  [GDK_MEMORY_R8G8B8A8] = {
+    GDK_MEMORY_ALPHA_STRAIGHT,
+    4,
+    G_ALIGNOF (guchar),
+    r8g8b8a8_to_float,
+    r8g8b8a8_from_float,
+  },
+  [GDK_MEMORY_A8B8G8R8] = {
+    GDK_MEMORY_ALPHA_STRAIGHT,
+    4,
+    G_ALIGNOF (guchar),
+    a8b8g8r8_to_float,
+    a8b8g8r8_from_float,
+  },
+  [GDK_MEMORY_R8G8B8] = {
+    GDK_MEMORY_ALPHA_OPAQUE,
+    3,
+    G_ALIGNOF (guchar),
+    r8g8b8_to_float,
+    r8g8b8_from_float,
+  },
+  [GDK_MEMORY_B8G8R8] = {
+    GDK_MEMORY_ALPHA_OPAQUE,
+    3,
+    G_ALIGNOF (guchar),
+    b8g8r8_to_float,
+    b8g8r8_from_float,
+  },
+  [GDK_MEMORY_R16G16B16] = {
+    GDK_MEMORY_ALPHA_OPAQUE,
+    6,
+    G_ALIGNOF (guint16),
+    r16g16b16_to_float,
+    r16g16b16_from_float,
+  },
+  [GDK_MEMORY_R16G16B16A16_PREMULTIPLIED] = {
+    GDK_MEMORY_ALPHA_PREMULTIPLIED,
+    8,
+    G_ALIGNOF (guint16),
+    r16g16b16a16_to_float,
+    r16g16b16a16_from_float,
+  },
+  [GDK_MEMORY_R16G16B16_FLOAT] = {
+    GDK_MEMORY_ALPHA_OPAQUE,
+    6,
+    G_ALIGNOF (guint16),
+    r16g16b16_float_to_float,
+    r16g16b16_float_from_float,
+  },
+  [GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED] = {
+    GDK_MEMORY_ALPHA_PREMULTIPLIED,
+    8,
+    G_ALIGNOF (guint16),
+    r16g16b16a16_float_to_float,
+    r16g16b16a16_float_from_float,
+  },
+  [GDK_MEMORY_R32G32B32_FLOAT] = {
+    GDK_MEMORY_ALPHA_OPAQUE,
+    12,
+    G_ALIGNOF (float),
+    r32g32b32_float_to_float,
+    r32g32b32_float_from_float,
+  },
+  [GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED] = {
+    GDK_MEMORY_ALPHA_PREMULTIPLIED,
+    16,
+    G_ALIGNOF (float),
+    r32g32b32a32_float_to_float,
+    r32g32b32a32_float_from_float,
+  }
+};
+
+gsize
+gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
+{
+  return memory_formats[format].bytes_per_pixel;
+}
+
+gsize
+gdk_memory_format_alignment (GdkMemoryFormat format)
+{
+  return memory_formats[format].alignment;
+}
+
+static void
+premultiply (float *rgba,
+             gsize  n)
+{
+  for (gsize i = 0; i < n; i++)
+    {
+      rgba[0] *= rgba[3];
+      rgba[1] *= rgba[3];
+      rgba[2] *= rgba[3];
+      rgba += 4;
+    }
+}
+
+static void
+unpremultiply (float *rgba,
+               gsize  n)
+{
+  for (gsize i = 0; i < n; i++)
+    {
+      if (rgba[3] <= 1/255.0)
+        continue;
+      rgba[0] /= rgba[3];
+      rgba[1] /= rgba[3];
+      rgba[2] /= rgba[3];
+    }
+}
+
+void
+gdk_memory_convert (guchar              *dest_data,
+                    gsize                dest_stride,
+                    GdkMemoryFormat      dest_format,
+                    const guchar        *src_data,
+                    gsize                src_stride,
+                    GdkMemoryFormat      src_format,
+                    gsize                width,
+                    gsize                height)
+{
+  const GdkMemoryFormatDescription *dest_desc = &memory_formats[dest_format];
+  const GdkMemoryFormatDescription *src_desc = &memory_formats[src_format];
+  float *tmp;
+  gsize y;
+
+  g_assert (dest_format < GDK_MEMORY_N_FORMATS);
+  g_assert (src_format < GDK_MEMORY_N_FORMATS);
+
+  tmp = g_new (float, width * 4);
+
+  for (y = 0; y < height; y++)
+    {
+      src_desc->to_float (tmp, src_data, width);
+      if (src_desc->alpha == GDK_MEMORY_ALPHA_PREMULTIPLIED && dest_desc->alpha == GDK_MEMORY_ALPHA_STRAIGHT)
+        unpremultiply (tmp, width);
+      else if (src_desc->alpha == GDK_MEMORY_ALPHA_STRAIGHT && dest_desc->alpha != GDK_MEMORY_ALPHA_STRAIGHT)
+        premultiply (tmp, width);
+      dest_desc->from_float (dest_data, tmp, width);
+      src_data += src_stride;
+      dest_data += dest_stride;
+    }
+
+  g_free (tmp);
+}
diff --git a/gdk/gdkmemoryformatprivate.h b/gdk/gdkmemoryformatprivate.h
new file mode 100644
index 0000000000..0de89f0756
--- /dev/null
+++ b/gdk/gdkmemoryformatprivate.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2021 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte gnome org>
+ */
+
+#ifndef __GDK_MEMORY_CONVERT_PRIVATE_H__
+#define __GDK_MEMORY_CONVERT_PRIVATE_H__
+
+#include "gdkmemorytexture.h"
+
+G_BEGIN_DECLS
+
+gsize                   gdk_memory_format_alignment         (GdkMemoryFormat             format) 
G_GNUC_CONST;
+gsize                   gdk_memory_format_bytes_per_pixel   (GdkMemoryFormat             format) 
G_GNUC_CONST;
+
+void                    gdk_memory_convert                  (guchar                     *dest_data,
+                                                             gsize                       dest_stride,
+                                                             GdkMemoryFormat             dest_format,
+                                                             const guchar               *src_data,
+                                                             gsize                       src_stride,
+                                                             GdkMemoryFormat             src_format,
+                                                             gsize                       width,
+                                                             gsize                       height);
+
+
+G_END_DECLS
+
+#endif /* __GDK_MEMORY_CONVERT_PRIVATE_H__ */
diff --git a/gdk/gdkmemorytexture.c b/gdk/gdkmemorytexture.c
index 6c08ef531b..33ba90fe5c 100644
--- a/gdk/gdkmemorytexture.c
+++ b/gdk/gdkmemorytexture.c
@@ -20,6 +20,8 @@
 #include "config.h"
 
 #include "gdkmemorytextureprivate.h"
+
+#include "gdkmemoryformatprivate.h"
 #include "gsk/ngl/fp16private.h"
 
 /**
@@ -45,80 +47,6 @@ struct _GdkMemoryTextureClass
 
 G_DEFINE_TYPE (GdkMemoryTexture, gdk_memory_texture, GDK_TYPE_TEXTURE)
 
-gsize
-gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
-{
-  switch (format)
-    {
-    case GDK_MEMORY_R8G8B8:
-    case GDK_MEMORY_B8G8R8:
-      return 3;
-
-    case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
-    case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
-    case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
-    case GDK_MEMORY_B8G8R8A8:
-    case GDK_MEMORY_A8R8G8B8:
-    case GDK_MEMORY_R8G8B8A8:
-    case GDK_MEMORY_A8B8G8R8:
-      return 4;
-
-    case GDK_MEMORY_R16G16B16:
-    case GDK_MEMORY_R16G16B16_FLOAT:
-      return 6;
-
-    case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
-    case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
-      return 8;
-
-    case GDK_MEMORY_R32G32B32_FLOAT:
-      return 12;
-
-    case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
-      return 16;
-
-    case GDK_MEMORY_N_FORMATS:
-    default:
-      g_assert_not_reached ();
-      return 4;
-    }
-}
-
-static gsize
-gdk_memory_format_alignment (GdkMemoryFormat format)
-{
-  switch (format)
-    {
-    case GDK_MEMORY_R8G8B8:
-    case GDK_MEMORY_B8G8R8:
-    case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
-    case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
-    case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
-    case GDK_MEMORY_B8G8R8A8:
-    case GDK_MEMORY_A8R8G8B8:
-    case GDK_MEMORY_R8G8B8A8:
-    case GDK_MEMORY_A8B8G8R8:
-      return G_ALIGNOF (guchar);
-
-    case GDK_MEMORY_R16G16B16:
-    case GDK_MEMORY_R16G16B16_FLOAT:
-      return G_ALIGNOF (guint16);
-
-    case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
-    case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
-      return G_ALIGNOF (guint16);
-
-    case GDK_MEMORY_R32G32B32_FLOAT:
-    case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
-      return G_ALIGNOF (float);
-
-    case GDK_MEMORY_N_FORMATS:
-    default:
-      g_assert_not_reached ();
-      return G_ALIGNOF (double);
-    }
-}
-
 static void
 gdk_memory_texture_dispose (GObject *object)
 {
@@ -143,7 +71,7 @@ gdk_memory_texture_download (GdkTexture *texture,
   GdkMemoryTexture *self = GDK_MEMORY_TEXTURE (texture);
 
   gdk_memory_convert (data, stride,
-                      GDK_MEMORY_CONVERT_DOWNLOAD,
+                      GDK_MEMORY_DEFAULT,
                       (guchar *) g_bytes_get_data (self->bytes, NULL),
                       self->stride,
                       self->format,
@@ -158,12 +86,14 @@ gdk_memory_texture_download_float (GdkTexture *texture,
 {
   GdkMemoryTexture *self = GDK_MEMORY_TEXTURE (texture);
 
-  gdk_memory_convert_to_float (data, stride,
-                               (guchar *) g_bytes_get_data (self->bytes, NULL),
-                               self->stride,
-                               self->format,
-                               gdk_texture_get_width (texture),
-                               gdk_texture_get_height (texture));
+  gdk_memory_convert ((guchar *) data,
+                      stride * sizeof (float),
+                      GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED,
+                      (guchar *) g_bytes_get_data (self->bytes, NULL),
+                      self->stride,
+                      self->format,
+                      gdk_texture_get_width (texture),
+                      gdk_texture_get_height (texture));
 }
 
 static void
@@ -279,429 +209,3 @@ gdk_memory_texture_get_stride (GdkMemoryTexture *self)
   return self->stride;
 }
 
-static void
-convert_memcpy (guchar       *dest_data,
-                gsize         dest_stride,
-                const guchar *src_data,
-                gsize         src_stride,
-                gsize         width,
-                gsize         height)
-{
-  gsize y;
-
-  for (y = 0; y < height; y++)
-    memcpy (dest_data + y * dest_stride, src_data + y * src_stride, 4 * width);
-}
-
-#define SWIZZLE(A,R,G,B) \
-static void \
-convert_swizzle ## A ## R ## G ## B (guchar       *dest_data, \
-                                     gsize         dest_stride, \
-                                     const guchar *src_data, \
-                                     gsize         src_stride, \
-                                     gsize         width, \
-                                     gsize         height) \
-{ \
-  gsize x, y; \
-\
-  for (y = 0; y < height; y++) \
-    { \
-      for (x = 0; x < width; x++) \
-        { \
-          dest_data[4 * x + A] = src_data[4 * x + 0]; \
-          dest_data[4 * x + R] = src_data[4 * x + 1]; \
-          dest_data[4 * x + G] = src_data[4 * x + 2]; \
-          dest_data[4 * x + B] = src_data[4 * x + 3]; \
-        } \
-\
-      dest_data += dest_stride; \
-      src_data += src_stride; \
-    } \
-}
-
-SWIZZLE(3,2,1,0)
-SWIZZLE(2,1,0,3)
-SWIZZLE(3,0,1,2)
-SWIZZLE(1,2,3,0)
-
-#define SWIZZLE_OPAQUE(A,R,G,B) \
-static void \
-convert_swizzle_opaque_## A ## R ## G ## B (guchar       *dest_data, \
-                                            gsize         dest_stride, \
-                                            const guchar *src_data, \
-                                            gsize         src_stride, \
-                                            gsize         width, \
-                                            gsize         height) \
-{ \
-  gsize x, y; \
-\
-  for (y = 0; y < height; y++) \
-    { \
-      for (x = 0; x < width; x++) \
-        { \
-          dest_data[4 * x + A] = 0xFF; \
-          dest_data[4 * x + R] = src_data[3 * x + 0]; \
-          dest_data[4 * x + G] = src_data[3 * x + 1]; \
-          dest_data[4 * x + B] = src_data[3 * x + 2]; \
-        } \
-\
-      dest_data += dest_stride; \
-      src_data += src_stride; \
-    } \
-}
-
-SWIZZLE_OPAQUE(3,2,1,0)
-SWIZZLE_OPAQUE(3,0,1,2)
-SWIZZLE_OPAQUE(0,1,2,3)
-SWIZZLE_OPAQUE(0,3,2,1)
-
-#define PREMULTIPLY(d,c,a) G_STMT_START { guint t = c * a + 0x80; d = ((t >> 8) + t) >> 8; } G_STMT_END
-#define SWIZZLE_PREMULTIPLY(A,R,G,B, A2,R2,G2,B2) \
-static void \
-convert_swizzle_premultiply_ ## A ## R ## G ## B ## _ ## A2 ## R2 ## G2 ## B2 \
-                                    (guchar       *dest_data, \
-                                     gsize         dest_stride, \
-                                     const guchar *src_data, \
-                                     gsize         src_stride, \
-                                     gsize         width, \
-                                     gsize         height) \
-{ \
-  gsize x, y; \
-\
-  for (y = 0; y < height; y++) \
-    { \
-      for (x = 0; x < width; x++) \
-        { \
-          dest_data[4 * x + A] = src_data[4 * x + A2]; \
-          PREMULTIPLY(dest_data[4 * x + R], src_data[4 * x + R2], src_data[4 * x + A2]); \
-          PREMULTIPLY(dest_data[4 * x + G], src_data[4 * x + G2], src_data[4 * x + A2]); \
-          PREMULTIPLY(dest_data[4 * x + B], src_data[4 * x + B2], src_data[4 * x + A2]); \
-        } \
-\
-      dest_data += dest_stride; \
-      src_data += src_stride; \
-    } \
-}
-
-SWIZZLE_PREMULTIPLY (3,2,1,0, 3,2,1,0)
-SWIZZLE_PREMULTIPLY (0,1,2,3, 3,2,1,0)
-SWIZZLE_PREMULTIPLY (3,2,1,0, 0,1,2,3)
-SWIZZLE_PREMULTIPLY (0,1,2,3, 0,1,2,3)
-SWIZZLE_PREMULTIPLY (3,2,1,0, 3,0,1,2)
-SWIZZLE_PREMULTIPLY (0,1,2,3, 3,0,1,2)
-SWIZZLE_PREMULTIPLY (3,2,1,0, 0,3,2,1)
-SWIZZLE_PREMULTIPLY (0,1,2,3, 0,3,2,1)
-SWIZZLE_PREMULTIPLY (3,0,1,2, 3,2,1,0)
-SWIZZLE_PREMULTIPLY (3,0,1,2, 0,1,2,3)
-SWIZZLE_PREMULTIPLY (3,0,1,2, 3,0,1,2)
-SWIZZLE_PREMULTIPLY (3,0,1,2, 0,3,2,1)
-
-#define CONVERT_FUNC(name,suffix,R,G,B,A,step) \
-static void \
-convert_ ## name ## _to_ ## suffix (guchar       *dest_data, \
-                                    gsize         dest_stride, \
-                                    const guchar *src_data, \
-                                    gsize         src_stride, \
-                                    gsize         width, \
-                                    gsize         height) \
-{ \
-  gsize x, y; \
-\
-  for (y = 0; y < height; y++) \
-    { \
-      for (x = 0; x < width; x++) \
-        { \
-          guchar conv[4]; \
-          convert_pixel_ ## name (conv, src_data + step * x); \
-          dest_data[4 * x + R] = conv[0]; \
-          dest_data[4 * x + G] = conv[1]; \
-          dest_data[4 * x + B] = conv[2]; \
-          dest_data[4 * x + A] = conv[3]; \
-        } \
-\
-      dest_data += dest_stride; \
-      src_data += src_stride; \
-    } \
-}
-
-#define CONVERT_FUNCS(name,step) \
-CONVERT_FUNC(name, download_le, 2, 1, 0, 3, step) \
-CONVERT_FUNC(name, download_be, 1, 2, 3, 0, step) \
-CONVERT_FUNC(name, gles_rgba, 0, 1, 2, 3, step) \
-
-static inline void
-convert_pixel_rgb16 (guchar *dest_data, const guchar *src_data)
-{
-  const guint16 *src = (const guint16 *) src_data;
-  dest_data[0] = (guchar)(src[0] >> 8);
-  dest_data[1] = (guchar)(src[1] >> 8);
-  dest_data[2] = (guchar)(src[2] >> 8);
-  dest_data[3] = 0xFF;
-}
-CONVERT_FUNCS(rgb16, 3 * sizeof (guint16))
-
-static inline void
-convert_pixel_rgba16 (guchar *dest_data, const guchar *src_data)
-{
-  const guint16 *src = (const guint16 *) src_data;
-  dest_data[0] = (guchar)(src[0] >> 8);
-  dest_data[1] = (guchar)(src[1] >> 8);
-  dest_data[2] = (guchar)(src[2] >> 8);
-  dest_data[3] = (guchar)(src[3] >> 8);
-}
-CONVERT_FUNCS(rgba16, 4 * sizeof (guint16))
-
-static inline void
-convert_pixel_rgb16f (guchar *dest_data, const guchar *src_data)
-{
-  float src[4];
-  guint16 tmp[4];
-  memcpy(tmp, src_data, sizeof(guint16) * 3);
-  half_to_float4(tmp, src);
-  dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f);
-  dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f);
-  dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f);
-  dest_data[3] = 0xFF;
-}
-CONVERT_FUNCS(rgb16f, 3 * sizeof (guint16))
-
-static inline void
-convert_pixel_rgba16f (guchar *dest_data, const guchar *src_data)
-{
-  float src[4];
-  half_to_float4((const guint16 *) src_data, src);
-  dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f);
-  dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f);
-  dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f);
-  dest_data[3] = CLAMP (src[3] * 256.f, 0.f, 255.f);
-}
-CONVERT_FUNCS(rgba16f, 4 * sizeof (guint16))
-
-static inline void
-convert_pixel_rgb32f (guchar *dest_data, const guchar *src_data)
-{
-  float *src = (float *) src_data;
-  dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f);
-  dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f);
-  dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f);
-  dest_data[3] = 0xFF;
-}
-CONVERT_FUNCS(rgb32f, 3 * sizeof (float))
-
-static inline void
-convert_pixel_rgba32f (guchar *dest_data, const guchar *src_data)
-{
-  float *src = (float *) src_data;
-  dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f);
-  dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f);
-  dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f);
-  dest_data[3] = CLAMP (src[3] * 256.f, 0.f, 255.f);
-}
-CONVERT_FUNCS(rgba32f, 4 * sizeof (float))
-
-typedef void (* ConversionFunc) (guchar       *dest_data,
-                                 gsize         dest_stride,
-                                 const guchar *src_data,
-                                 gsize         src_stride,
-                                 gsize         width,
-                                 gsize         height);
-
-static ConversionFunc converters[GDK_MEMORY_N_FORMATS][GDK_MEMORY_N_CONVERSIONS] =
-{
-  { convert_memcpy, convert_swizzle3210, convert_swizzle2103 },
-  { convert_swizzle3210, convert_memcpy, convert_swizzle3012 },
-  { convert_swizzle2103, convert_swizzle1230, convert_memcpy },
-  { convert_swizzle_premultiply_3210_3210, convert_swizzle_premultiply_0123_3210, 
convert_swizzle_premultiply_3012_3210,  },
-  { convert_swizzle_premultiply_3210_0123, convert_swizzle_premultiply_0123_0123, 
convert_swizzle_premultiply_3012_0123 },
-  { convert_swizzle_premultiply_3210_3012, convert_swizzle_premultiply_0123_3012, 
convert_swizzle_premultiply_3012_3012 },
-  { convert_swizzle_premultiply_3210_0321, convert_swizzle_premultiply_0123_0321, 
convert_swizzle_premultiply_3012_0321 },
-  { convert_swizzle_opaque_3210, convert_swizzle_opaque_0123, convert_swizzle_opaque_3012 },
-  { convert_swizzle_opaque_3012, convert_swizzle_opaque_0321, convert_swizzle_opaque_3210 },
-  { convert_rgb16_to_download_le, convert_rgb16_to_download_be, convert_rgb16_to_gles_rgba },
-  { convert_rgba16_to_download_le, convert_rgba16_to_download_be, convert_rgba16_to_gles_rgba },
-  { convert_rgb16f_to_download_le, convert_rgb16f_to_download_be, convert_rgb16f_to_gles_rgba },
-  { convert_rgba16f_to_download_le, convert_rgba16f_to_download_be, convert_rgba16f_to_gles_rgba },
-  { convert_rgb32f_to_download_le, convert_rgb32f_to_download_be, convert_rgb32f_to_gles_rgba },
-  { convert_rgba32f_to_download_le, convert_rgba32f_to_download_be, convert_rgba32f_to_gles_rgba }
-};
-
-void
-gdk_memory_convert (guchar              *dest_data,
-                    gsize                dest_stride,
-                    GdkMemoryConversion  dest_format,
-                    const guchar        *src_data,
-                    gsize                src_stride,
-                    GdkMemoryFormat      src_format,
-                    gsize                width,
-                    gsize                height)
-{
-  g_assert (dest_format < 3);
-  g_assert (src_format < GDK_MEMORY_N_FORMATS);
-
-  converters[src_format][dest_format] (dest_data, dest_stride, src_data, src_stride, width, height);
-}
-
-#define CONVERT_FLOAT(R,G,B,A,premultiply) G_STMT_START {\
-  for (y = 0; y < height; y++) \
-    { \
-      for (x = 0; x < width; x++) \
-        { \
-          if (A >= 0) \
-            { \
-              dest_data[4 * x + 0] = src_data[4 * x + R] / 255.0f; \
-              dest_data[4 * x + 1] = src_data[4 * x + G] / 255.0f; \
-              dest_data[4 * x + 2] = src_data[4 * x + B] / 255.0f; \
-              dest_data[4 * x + 3] = src_data[4 * x + A] / 255.0f; \
-              if (premultiply) \
-                { \
-                  dest_data[4 * x + 0] *= dest_data[4 * x + 3]; \
-                  dest_data[4 * x + 1] *= dest_data[4 * x + 3]; \
-                  dest_data[4 * x + 2] *= dest_data[4 * x + 3]; \
-                } \
-            } \
-          else \
-            { \
-              dest_data[4 * x + 0] = src_data[3 * x + R] / 255.0f; \
-              dest_data[4 * x + 1] = src_data[3 * x + G] / 255.0f; \
-              dest_data[4 * x + 2] = src_data[3 * x + B] / 255.0f; \
-              dest_data[4 * x + 3] = 1.0; \
-            } \
-        } \
-\
-      dest_data += dest_stride; \
-      src_data += src_stride; \
-    } \
-}G_STMT_END
-
-#define CONVERT_FLOAT_PIXEL(func,step) G_STMT_START{\
-  for (y = 0; y < height; y++) \
-    { \
-      for (x = 0; x < width; x++) \
-        { \
-          func (dest_data + 4 * x, src_data + step * x); \
-        } \
-\
-      dest_data += dest_stride; \
-      src_data += src_stride; \
-    } \
-}G_STMT_END
-
-static inline void
-convert_rgb16_to_float (float *dest, const guchar *src_data)
-{
-  const guint16 *src = (const guint16 *) src_data;
-  dest[0] = src[0] / 65535.f;
-  dest[1] = src[1] / 65535.f;
-  dest[2] = src[2] / 65535.f;
-  dest[3] = 1.0;
-}
-
-static inline void
-convert_rgba16_to_float (float *dest, const guchar *src_data)
-{
-  const guint16 *src = (const guint16 *) src_data;
-  dest[0] = src[0] / 65535.f;
-  dest[1] = src[1] / 65535.f;
-  dest[2] = src[2] / 65535.f;
-  dest[3] = src[3] / 65535.f;
-}
-
-static inline void
-convert_rgb16f_to_float (float *dest, const guchar *src_data)
-{
-  guint16 tmp[4];
-  memcpy(tmp, src_data, sizeof(guint16) * 3);
-  tmp[3] = FP16_ONE;
-  half_to_float4 (tmp, dest);
-}
-
-static inline void
-convert_rgba16f_to_float (float *dest, const guchar *src_data)
-{
-  half_to_float4 ((const guint16 *) src_data, dest);
-}
-
-static inline void
-convert_rgb32f_to_float (float *dest, const guchar *src_data)
-{
-  const float *src = (const float *) src_data;
-  dest[0] = src[0];
-  dest[1] = src[1];
-  dest[2] = src[2];
-  dest[3] = 1.0;
-}
-
-static inline void
-convert_rgba32f_to_float (float *dest, const guchar *src_data)
-{
-  const float *src = (const float *) src_data;
-  dest[0] = src[0];
-  dest[1] = src[1];
-  dest[2] = src[2];
-  dest[3] = src[3];
-}
-
-void
-gdk_memory_convert_to_float (float           *dest_data,
-                             gsize            dest_stride,
-                             const guchar    *src_data,
-                             gsize            src_stride,
-                             GdkMemoryFormat  src_format,
-                             gsize            width,
-                             gsize            height)
-{
-  gsize x, y;
-
-  switch (src_format)
-  {
-    case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
-      CONVERT_FLOAT (2, 1, 0, 3, FALSE);
-      break;
-    case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
-      CONVERT_FLOAT (1, 2, 3, 0, FALSE);
-      break;
-    case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
-      CONVERT_FLOAT (0, 1, 2, 3, FALSE);
-      break;
-    case GDK_MEMORY_B8G8R8A8:
-      CONVERT_FLOAT (2, 1, 0, 3, TRUE);
-      break;
-    case GDK_MEMORY_A8R8G8B8:
-      CONVERT_FLOAT (1, 2, 3, 0, TRUE);
-      break;
-    case GDK_MEMORY_R8G8B8A8:
-      CONVERT_FLOAT (0, 1, 2, 3, TRUE);
-      break;
-    case GDK_MEMORY_A8B8G8R8:
-      CONVERT_FLOAT (3, 2, 1, 0, TRUE);
-      break;
-    case GDK_MEMORY_R8G8B8:
-      CONVERT_FLOAT (0, 1, 2, -1, FALSE);
-      break;
-    case GDK_MEMORY_B8G8R8:
-      CONVERT_FLOAT (2, 1, 0, -1, FALSE);
-      break;
-    case GDK_MEMORY_R16G16B16:
-      CONVERT_FLOAT_PIXEL (convert_rgb16_to_float, 3 * sizeof (guint16));
-      break;
-    case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
-      CONVERT_FLOAT_PIXEL (convert_rgba16_to_float, 4 * sizeof (guint16));
-      break;
-    case GDK_MEMORY_R16G16B16_FLOAT:
-      CONVERT_FLOAT_PIXEL (convert_rgb16f_to_float, 3 * sizeof (guint16));
-      break;
-    case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
-      CONVERT_FLOAT_PIXEL (convert_rgba16f_to_float, 4 * sizeof (guint16));
-      break;
-    case GDK_MEMORY_R32G32B32_FLOAT:
-      CONVERT_FLOAT_PIXEL (convert_rgb32f_to_float, 3 * sizeof (float));
-      break;
-    case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
-      CONVERT_FLOAT_PIXEL (convert_rgba32f_to_float, 4 * sizeof (float));
-      break;
-
-    case GDK_MEMORY_N_FORMATS:
-    default:
-      g_assert_not_reached();
-  }
-}
diff --git a/gdk/gdkmemorytextureprivate.h b/gdk/gdkmemorytextureprivate.h
index ddd9fd1c37..f61cccb9ef 100644
--- a/gdk/gdkmemorytextureprivate.h
+++ b/gdk/gdkmemorytextureprivate.h
@@ -29,45 +29,10 @@ G_BEGIN_DECLS
 #define GDK_MEMORY_GDK_PIXBUF_OPAQUE GDK_MEMORY_R8G8B8
 #define GDK_MEMORY_GDK_PIXBUF_ALPHA GDK_MEMORY_R8G8B8A8
 
-typedef enum {
-  GDK_MEMORY_CONVERT_DOWNLOAD_LITTLE_ENDIAN,
-  GDK_MEMORY_CONVERT_DOWNLOAD_BIT_ENDIAN,
-  GDK_MEMORY_CONVERT_GLES_RGBA,
-
-  GDK_MEMORY_N_CONVERSIONS
-} GdkMemoryConversion;
-
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
-#define GDK_MEMORY_CONVERT_DOWNLOAD GDK_MEMORY_CONVERT_DOWNLOAD_LITTLE_ENDIAN
-#elif G_BYTE_ORDER == G_BIG_ENDIAN
-#define GDK_MEMORY_CONVERT_DOWNLOAD GDK_MEMORY_CONVERT_DOWNLOAD_BIG_ENDIAN
-#else
-#error "Unknown byte order for GDK_MEMORY_CONVERT_DOWNLOAD"
-#endif
-
-gsize                   gdk_memory_format_bytes_per_pixel   (GdkMemoryFormat    format);
-
 GdkMemoryFormat         gdk_memory_texture_get_format       (GdkMemoryTexture  *self);
 const guchar *          gdk_memory_texture_get_data         (GdkMemoryTexture  *self);
 gsize                   gdk_memory_texture_get_stride       (GdkMemoryTexture  *self);
 
-void                    gdk_memory_convert                  (guchar                     *dest_data,
-                                                             gsize                       dest_stride,
-                                                             GdkMemoryConversion         dest_format,
-                                                             const guchar               *src_data,
-                                                             gsize                       src_stride,
-                                                             GdkMemoryFormat             src_format,
-                                                             gsize                       width,
-                                                             gsize                       height);
-
-void                    gdk_memory_convert_to_float         (float                      *dest_data,
-                                                             gsize                       dest_stride,
-                                                             const guchar               *src_data,
-                                                             gsize                       src_stride,
-                                                             GdkMemoryFormat             src_format,
-                                                             gsize                       width,
-                                                             gsize                       height);
-
 
 G_END_DECLS
 
diff --git a/gdk/loaders/gdkpng.c b/gdk/loaders/gdkpng.c
index 4c32533e36..5dd2184ff4 100644
--- a/gdk/loaders/gdkpng.c
+++ b/gdk/loaders/gdkpng.c
@@ -20,6 +20,7 @@
 #include "gdkpngprivate.h"
 
 #include "gdkintl.h"
+#include "gdkmemoryformatprivate.h"
 #include "gdkmemorytextureprivate.h"
 #include "gdkprofilerprivate.h"
 #include "gdktexture.h"
diff --git a/gdk/loaders/gdktiff.c b/gdk/loaders/gdktiff.c
index d7416391ee..ed1b0e566b 100644
--- a/gdk/loaders/gdktiff.c
+++ b/gdk/loaders/gdktiff.c
@@ -20,6 +20,7 @@
 #include "gdktiffprivate.h"
 
 #include "gdkintl.h"
+#include "gdkmemoryformatprivate.h"
 #include "gdkmemorytextureprivate.h"
 #include "gdkprofilerprivate.h"
 #include "gdktexture.h"
diff --git a/gdk/meson.build b/gdk/meson.build
index 31713fe1a8..ba059f2cb8 100644
--- a/gdk/meson.build
+++ b/gdk/meson.build
@@ -31,6 +31,7 @@ gdk_public_sources = files([
   'gdkhsla.c',
   'gdkkeys.c',
   'gdkkeyuni.c',
+  'gdkmemoryformat.c',
   'gdkmemorytexture.c',
   'gdkmonitor.c',
   'gdkpaintable.c',
diff --git a/gsk/ngl/gsknglcommandqueue.c b/gsk/ngl/gsknglcommandqueue.c
index a5fbf0dc8d..b2a474cf59 100644
--- a/gsk/ngl/gsknglcommandqueue.c
+++ b/gsk/ngl/gsknglcommandqueue.c
@@ -26,6 +26,7 @@
 #include <string.h>
 
 #include <gdk/gdkglcontextprivate.h>
+#include <gdk/gdkmemoryformatprivate.h>
 #include <gdk/gdkmemorytextureprivate.h>
 #include <gdk/gdkprofilerprivate.h>
 #include <gsk/gskdebugprivate.h>
diff --git a/gsk/ngl/gsknglglyphlibrary.c b/gsk/ngl/gsknglglyphlibrary.c
index 33c86cc967..ede4f19105 100644
--- a/gsk/ngl/gsknglglyphlibrary.c
+++ b/gsk/ngl/gsknglglyphlibrary.c
@@ -21,7 +21,7 @@
 #include "config.h"
 
 #include <gdk/gdkglcontextprivate.h>
-#include <gdk/gdkmemorytextureprivate.h>
+#include <gdk/gdkmemoryformatprivate.h>
 #include <gdk/gdkprofilerprivate.h>
 
 #include "gsknglcommandqueueprivate.h"
@@ -237,7 +237,7 @@ gsk_ngl_glyph_library_upload_glyph (GskNglGlyphLibrary     *self,
       pixel_data = free_data = g_malloc (width * height * 4);
       gdk_memory_convert (pixel_data,
                           width * 4,
-                          GDK_MEMORY_CONVERT_GLES_RGBA,
+                          GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
                           cairo_image_surface_get_data (surface),
                           width * 4,
                           GDK_MEMORY_DEFAULT,
diff --git a/gsk/ngl/gskngliconlibrary.c b/gsk/ngl/gskngliconlibrary.c
index ab4d1b4d6f..cfc662a9e6 100644
--- a/gsk/ngl/gskngliconlibrary.c
+++ b/gsk/ngl/gskngliconlibrary.c
@@ -21,7 +21,7 @@
 #include "config.h"
 
 #include <gdk/gdkglcontextprivate.h>
-#include <gdk/gdkmemorytextureprivate.h>
+#include <gdk/gdkmemoryformatprivate.h>
 #include <gdk/gdkprofilerprivate.h>
 #include <gdk/gdktextureprivate.h>
 
@@ -115,7 +115,7 @@ gsk_ngl_icon_library_add (GskNglIconLibrary     *self,
     {
       pixel_data = free_data = g_malloc (width * height * 4);
       gdk_memory_convert (pixel_data, width * 4,
-                          GDK_MEMORY_CONVERT_GLES_RGBA,
+                          GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
                           surface_data, cairo_image_surface_get_stride (surface),
                           GDK_MEMORY_DEFAULT, width, height);
       gl_format = GL_RGBA;


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