--- /dev/null
+/*
+ * 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; \
+ dest += 4; \
+ } \
+} \
+\
+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 + 0.5, 0, scale); \
+ dest[G] = CLAMP (src[1] * scale + 0.5, 0, scale); \
+ dest[B] = CLAMP (src[2] * scale + 0.5, 0, scale); \
+ if (A >= 0) dest[A] = CLAMP (src[3] * scale + 0.5, 0, scale); \
+ src += 4; \
+ } \
+}
+
+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)
+ {
+ rgba[0] /= rgba[3];
+ rgba[1] /= rgba[3];
+ rgba[2] /= rgba[3];
+ }
+ rgba += 4;
+ }
+}
+
+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);
+}
#include "config.h"
#include "gdkmemorytextureprivate.h"
+
+#include "gdkmemoryformatprivate.h"
#include "gsk/ngl/fp16private.h"
/**
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)
{
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,
{
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
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();
- }
-}