From 50115d70c6caaff0cc7941603d06b8646c88da4e Mon Sep 17 00:00:00 2001 From: Sophie Herold Date: Fri, 26 May 2023 14:38:25 +0200 Subject: [PATCH] gdk: Add grayscale and alpha memory formats --- gdk/gdkenums.h | 24 ++++++ gdk/gdkmemoryformat.c | 156 ++++++++++++++++++++++++++++++---- testsuite/gdk/memorytexture.c | 88 +++++++++++++++++++ 3 files changed, 250 insertions(+), 18 deletions(-) diff --git a/gdk/gdkenums.h b/gdk/gdkenums.h index b0407a2757..f2f7251b66 100644 --- a/gdk/gdkenums.h +++ b/gdk/gdkenums.h @@ -30,6 +30,8 @@ #include +#include + G_BEGIN_DECLS /** @@ -306,6 +308,20 @@ typedef enum * the alpha value. Since: 4.6 * @GDK_MEMORY_R32G32B32A32_FLOAT: 4 float values; for red, green, blue and * alpha. Since: 4.6 + * @GDK_MEMORY_G8A8_PREMULTIPLIED: 2 bytes; for grayscale, alpha. The color + * values are premultiplied with the alpha value. Since: 4.12 + * @GDK_MEMORY_G8A8: 2 bytes; for grayscale, alpha. Since: 4.12 + * @GDK_MEMORY_G8: One byte; for grayscale. The data is opaque. + * Since: 4.12 + * @GDK_MEMORY_G16A16_PREMULTIPLIED: 2 guint16 values; for grayscale, alpha. + * The color values are premultiplied with the alpha value. Since: 4.12 + * @GDK_MEMORY_G16A16: 2 guint16 values; for grayscale, alpha. Since: 4.12 + * @GDK_MEMORY_G16: One guint16 value; for grayscale. The data is opaque. + * Since: 4.12 + * @GDK_MEMORY_A8: One byte; for alpha. + * Since: 4.12 + * @GDK_MEMORY_A16: One guint16 value; for alpha. + * Since: 4.12 * @GDK_MEMORY_N_FORMATS: The number of formats. This value will change as * more formats get added, so do not rely on its concrete integer. * @@ -340,6 +356,14 @@ typedef enum { GDK_MEMORY_R32G32B32_FLOAT, GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED, GDK_MEMORY_R32G32B32A32_FLOAT, + GDK_MEMORY_G8A8_PREMULTIPLIED GDK_AVAILABLE_ENUMERATOR_IN_4_12, + GDK_MEMORY_G8A8 GDK_AVAILABLE_ENUMERATOR_IN_4_12, + GDK_MEMORY_G8 GDK_AVAILABLE_ENUMERATOR_IN_4_12, + GDK_MEMORY_G16A16_PREMULTIPLIED GDK_AVAILABLE_ENUMERATOR_IN_4_12, + GDK_MEMORY_G16A16 GDK_AVAILABLE_ENUMERATOR_IN_4_12, + GDK_MEMORY_G16 GDK_AVAILABLE_ENUMERATOR_IN_4_12, + GDK_MEMORY_A8 GDK_AVAILABLE_ENUMERATOR_IN_4_12, + GDK_MEMORY_A16 GDK_AVAILABLE_ENUMERATOR_IN_4_12, GDK_MEMORY_N_FORMATS } GdkMemoryFormat; diff --git a/gdk/gdkmemoryformat.c b/gdk/gdkmemoryformat.c index 5b7000e229..4e92efe980 100644 --- a/gdk/gdkmemoryformat.c +++ b/gdk/gdkmemoryformat.c @@ -60,6 +60,36 @@ name ## _from_float (guchar *dest_data, \ } \ } +#define TYPED_GRAY_FUNCS(name, T, G, 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); \ + if (G >= 0) dest[0] = (float) src[G] / scale; else dest[0] = 1.0; \ + dest[1] = dest[2] = dest[0]; \ + 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); \ + if (G >= 0) dest[G] = CLAMP ((src[0] + src[1] + src[2]) * scale / 3.f + 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) @@ -72,6 +102,15 @@ 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) +TYPED_GRAY_FUNCS (g8a8_premultiplied, guchar, 0, 1, 2, 255) +TYPED_GRAY_FUNCS (g8a8, guchar, 0, 1, 2, 255) +TYPED_GRAY_FUNCS (g8, guchar, 0, -1, 1, 255) +TYPED_GRAY_FUNCS (a8, guchar, -1, 0, 1, 255) +TYPED_GRAY_FUNCS (g16a16_premultiplied, guint16, 0, 1, 4, 65535) +TYPED_GRAY_FUNCS (g16a16, guint16, 0, 1, 4, 65535) +TYPED_GRAY_FUNCS (g16, guint16, 0, -1, 2, 65535) +TYPED_GRAY_FUNCS (a16, guint16, -1, 0, 2, 65535) + static void r16g16b16_float_to_float (float *dest, const guchar *src_data, @@ -230,6 +269,7 @@ struct _GdkMemoryFormatDescription guint internal_format; guint format; guint type; + GLint swizzle[4]; } gl; /* no premultiplication going on here */ void (* to_float) (float *, const guchar*, gsize); @@ -251,7 +291,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = { G_ALIGNOF (guchar), FALSE, { 0, 0, G_MAXUINT, G_MAXUINT }, - { GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE }, + { GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } }, b8g8r8a8_premultiplied_to_float, b8g8r8a8_premultiplied_from_float, }, @@ -261,7 +301,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = { G_ALIGNOF (guchar), FALSE, { 0, 0, G_MAXUINT, G_MAXUINT }, - { GL_RGBA8, GL_BGRA, GDK_GL_UNSIGNED_BYTE_FLIPPED }, + { GL_RGBA8, GL_BGRA, GDK_GL_UNSIGNED_BYTE_FLIPPED, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } }, a8r8g8b8_premultiplied_to_float, a8r8g8b8_premultiplied_from_float, }, @@ -271,7 +311,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = { G_ALIGNOF (guchar), FALSE, { 0, 0, 0, 0 }, - { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE }, + { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } }, r8g8b8a8_premultiplied_to_float, r8g8b8a8_premultiplied_from_float, }, @@ -281,7 +321,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = { G_ALIGNOF (guchar), FALSE, { 0, 0, G_MAXUINT, G_MAXUINT }, - { GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE }, + { GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } }, b8g8r8a8_to_float, b8g8r8a8_from_float, }, @@ -291,7 +331,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = { G_ALIGNOF (guchar), FALSE, { 0, 0, G_MAXUINT, G_MAXUINT }, - { GL_RGBA8, GL_RGBA, GDK_GL_UNSIGNED_BYTE_FLIPPED }, + { GL_RGBA8, GL_RGBA, GDK_GL_UNSIGNED_BYTE_FLIPPED, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } }, a8r8g8b8_to_float, a8r8g8b8_from_float, }, @@ -301,7 +341,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = { G_ALIGNOF (guchar), FALSE, { 0, 0, 0, 0 }, - { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE }, + { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } }, r8g8b8a8_to_float, r8g8b8a8_from_float, }, @@ -311,7 +351,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = { G_ALIGNOF (guchar), FALSE, { 0, 0, G_MAXUINT, G_MAXUINT }, - { GL_RGBA8, GL_BGRA, GDK_GL_UNSIGNED_BYTE_FLIPPED }, + { GL_RGBA8, GL_BGRA, GDK_GL_UNSIGNED_BYTE_FLIPPED, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } }, a8b8g8r8_to_float, a8b8g8r8_from_float, }, @@ -321,7 +361,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = { G_ALIGNOF (guchar), FALSE, { 0, 0, 0, 0 }, - { GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE }, + { GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } }, r8g8b8_to_float, r8g8b8_from_float, }, @@ -331,7 +371,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = { G_ALIGNOF (guchar), FALSE, { 0, 0, G_MAXUINT, G_MAXUINT }, - { GL_RGB8, GL_BGR, GL_UNSIGNED_BYTE }, + { GL_RGB8, GL_BGR, GL_UNSIGNED_BYTE, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } }, b8g8r8_to_float, b8g8r8_from_float, }, @@ -341,7 +381,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = { G_ALIGNOF (guint16), TRUE, { 0, 0, 3, 0 }, - { GL_RGB16, GL_RGB, GL_UNSIGNED_SHORT }, + { GL_RGB16, GL_RGB, GL_UNSIGNED_SHORT, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } }, r16g16b16_to_float, r16g16b16_from_float, }, @@ -351,7 +391,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = { G_ALIGNOF (guint16), TRUE, { 0, 0, 3, 0 }, - { GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT }, + { GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } }, r16g16b16a16_to_float, r16g16b16a16_from_float, }, @@ -361,7 +401,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = { G_ALIGNOF (guint16), TRUE, { 0, 0, 3, 0 }, - { GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT }, + { GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } }, r16g16b16a16_to_float, r16g16b16a16_from_float, }, @@ -371,7 +411,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = { G_ALIGNOF (guint16), TRUE, { 0, 0, 3, 0 }, - { GL_RGB16F, GL_RGB, GL_HALF_FLOAT }, + { GL_RGB16F, GL_RGB, GL_HALF_FLOAT, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } }, r16g16b16_float_to_float, r16g16b16_float_from_float, }, @@ -381,7 +421,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = { G_ALIGNOF (guint16), TRUE, { 0, 0, 3, 0 }, - { GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT }, + { GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } }, r16g16b16a16_float_to_float, r16g16b16a16_float_from_float, }, @@ -391,7 +431,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = { G_ALIGNOF (guint16), TRUE, { 0, 0, 3, 0 }, - { GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT }, + { GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } }, r16g16b16a16_float_to_float, r16g16b16a16_float_from_float, }, @@ -401,7 +441,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = { G_ALIGNOF (float), TRUE, { 0, 0, 3, 0 }, - { GL_RGB32F, GL_RGB, GL_FLOAT }, + { GL_RGB32F, GL_RGB, GL_FLOAT, { GL_RED, GL_GREEN, GL_BLUE, GL_ONE } }, r32g32b32_float_to_float, r32g32b32_float_from_float, }, @@ -411,7 +451,7 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = { G_ALIGNOF (float), TRUE, { 0, 0, 3, 0 }, - { GL_RGBA32F, GL_RGBA, GL_FLOAT }, + { GL_RGBA32F, GL_RGBA, GL_FLOAT, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } }, r32g32b32a32_float_to_float, r32g32b32a32_float_from_float, }, @@ -421,9 +461,89 @@ static const GdkMemoryFormatDescription memory_formats[GDK_MEMORY_N_FORMATS] = { G_ALIGNOF (float), TRUE, { 0, 0, 3, 0 }, - { GL_RGBA32F, GL_RGBA, GL_FLOAT }, + { GL_RGBA32F, GL_RGBA, GL_FLOAT, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } }, r32g32b32a32_float_to_float, r32g32b32a32_float_from_float, + }, + [GDK_MEMORY_G8A8_PREMULTIPLIED] = { + GDK_MEMORY_ALPHA_PREMULTIPLIED, + 2, + G_ALIGNOF (guchar), + FALSE, + { 0, 0, 3, 0 }, + { GL_RG8, GL_RG, GL_UNSIGNED_BYTE, { GL_RED, GL_RED, GL_RED, GL_GREEN } }, + g8a8_premultiplied_to_float, + g8a8_premultiplied_from_float, + }, + [GDK_MEMORY_G8A8] = { + GDK_MEMORY_ALPHA_STRAIGHT, + 2, + G_ALIGNOF (guchar), + FALSE, + { 0, 0, 3, 0 }, + { GL_RG8, GL_RG, GL_UNSIGNED_BYTE, { GL_RED, GL_RED, GL_RED, GL_GREEN } }, + g8a8_to_float, + g8a8_from_float, + }, + [GDK_MEMORY_G8] = { + GDK_MEMORY_ALPHA_OPAQUE, + 1, + G_ALIGNOF (guchar), + FALSE, + { 0, 0, 3, 0 }, + { GL_R8, GL_RED, GL_UNSIGNED_BYTE, { GL_RED, GL_RED, GL_RED, GL_ONE } }, + g8_to_float, + g8_from_float, + }, + [GDK_MEMORY_G16A16_PREMULTIPLIED] = { + GDK_MEMORY_ALPHA_PREMULTIPLIED, + 4, + G_ALIGNOF (guint16), + TRUE, + { 0, 0, 3, 0 }, + { GL_RG16, GL_RG, GL_UNSIGNED_SHORT, { GL_RED, GL_RED, GL_RED, GL_GREEN } }, + g16a16_premultiplied_to_float, + g16a16_premultiplied_from_float, + }, + [GDK_MEMORY_G16A16] = { + GDK_MEMORY_ALPHA_STRAIGHT, + 4, + G_ALIGNOF (guint16), + TRUE, + { 0, 0, 3, 0 }, + { GL_RG16, GL_RG, GL_UNSIGNED_SHORT, { GL_RED, GL_RED, GL_RED, GL_GREEN } }, + g16a16_to_float, + g16a16_from_float, + }, + [GDK_MEMORY_G16] = { + GDK_MEMORY_ALPHA_OPAQUE, + 2, + G_ALIGNOF (guint16), + TRUE, + { 0, 0, 3, 0 }, + { GL_R16, GL_RED, GL_UNSIGNED_SHORT, { GL_RED, GL_RED, GL_RED, GL_ONE } }, + g16_to_float, + g16_from_float, + }, + [GDK_MEMORY_A8] = { + GDK_MEMORY_ALPHA_STRAIGHT, + 1, + G_ALIGNOF (guchar), + FALSE, + { 0, 0, 3, 0 }, + { GL_R8, GL_RED, GL_UNSIGNED_BYTE, { GL_ONE, GL_ONE, GL_ONE, GL_RED } }, + a8_to_float, + a8_from_float, + }, + [GDK_MEMORY_A16] = { + GDK_MEMORY_ALPHA_STRAIGHT, + 2, + G_ALIGNOF (guint16), + TRUE, + { 0, 0, 3, 0 }, + { GL_R16, GL_RED, GL_UNSIGNED_SHORT, { GL_ONE, GL_ONE, GL_ONE, GL_RED } }, + a16_to_float, + a16_from_float, } }; diff --git a/testsuite/gdk/memorytexture.c b/testsuite/gdk/memorytexture.c index c0b10be67a..a26dcf794b 100644 --- a/testsuite/gdk/memorytexture.c +++ b/testsuite/gdk/memorytexture.c @@ -75,6 +75,16 @@ gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format) { switch (format) { + case GDK_MEMORY_G8: + case GDK_MEMORY_A8: + return 1; + + case GDK_MEMORY_G8A8_PREMULTIPLIED: + case GDK_MEMORY_G8A8: + case GDK_MEMORY_G16: + case GDK_MEMORY_A16: + return 2; + case GDK_MEMORY_R8G8B8: case GDK_MEMORY_B8G8R8: return 3; @@ -86,6 +96,8 @@ gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format) case GDK_MEMORY_A8R8G8B8: case GDK_MEMORY_R8G8B8A8: case GDK_MEMORY_A8B8G8R8: + case GDK_MEMORY_G16A16_PREMULTIPLIED: + case GDK_MEMORY_G16A16: return 4; case GDK_MEMORY_R16G16B16: @@ -218,6 +230,82 @@ gdk_memory_format_is_premultiplied (GdkMemoryFormat format) } } +static gboolean +gdk_memory_format_has_alpha (GdkMemoryFormat format) +{ + switch (format) + { + case GDK_MEMORY_R8G8B8: + case GDK_MEMORY_B8G8R8: + case GDK_MEMORY_R16G16B16: + case GDK_MEMORY_R16G16B16_FLOAT: + case GDK_MEMORY_R32G32B32_FLOAT: + case GDK_MEMORY_G8: + case GDK_MEMORY_G16: + return FALSE; + + 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: + case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED: + case GDK_MEMORY_R16G16B16A16: + case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED: + case GDK_MEMORY_R16G16B16A16_FLOAT: + case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED: + case GDK_MEMORY_R32G32B32A32_FLOAT: + case GDK_MEMORY_G8A8_PREMULTIPLIED: + case GDK_MEMORY_G8A8: + case GDK_MEMORY_G16A16_PREMULTIPLIED: + case GDK_MEMORY_G16A16: + case GDK_MEMORY_A8: + case GDK_MEMORY_A16: + return TRUE; + + case GDK_MEMORY_N_FORMATS: + default: + g_assert_not_reached (); + return TRUE; + } +} + +static gboolean +gdk_memory_format_is_premultiplied (GdkMemoryFormat format) +{ + switch (format) + { + case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED: + case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED: + case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED: + case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED: + case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED: + case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED: + return TRUE; + + case GDK_MEMORY_R8G8B8: + case GDK_MEMORY_B8G8R8: + case GDK_MEMORY_R16G16B16: + case GDK_MEMORY_R16G16B16_FLOAT: + case GDK_MEMORY_R32G32B32_FLOAT: + case GDK_MEMORY_B8G8R8A8: + case GDK_MEMORY_A8R8G8B8: + case GDK_MEMORY_R8G8B8A8: + case GDK_MEMORY_A8B8G8R8: + case GDK_MEMORY_R16G16B16A16: + case GDK_MEMORY_R16G16B16A16_FLOAT: + case GDK_MEMORY_R32G32B32A32_FLOAT: + return FALSE; + + case GDK_MEMORY_N_FORMATS: + default: + g_assert_not_reached (); + return FALSE; + } +} + static gboolean gdk_memory_format_pixel_equal (GdkMemoryFormat format, gboolean accurate, -- 2.30.2