[gtk/gamma-shenanigans: 3/13] Support 16bit textures
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/gamma-shenanigans: 3/13] Support 16bit textures
- Date: Thu, 9 Sep 2021 11:10:55 +0000 (UTC)
commit d1b938b135e4f6a7190791a421d1a5b9287f4cc6
Author: Matthias Clasen <mclasen redhat com>
Date: Wed Sep 8 19:51:25 2021 -0400
Support 16bit textures
Add GDK_MEMORY_R16G16B16A16_PREMULTIPLIED, which
matches the libpng PNG_FORMAT_LINEAR_RGB_ALPHA
format. This format will be used to provide
linear (gamma-corrected) input in future commits.
GL can upload this format directly. This is not only
less work for us, it also avoids losing precision
during upload.
gdk/gdkglcontext.c | 7 +++++++
gdk/gdkmemorytexture.c | 37 ++++++++++++++++++++++++++++++++++++-
gdk/gdkmemorytexture.h | 6 ++++++
testsuite/gdk/memorytexture.c | 15 +++++++++------
4 files changed, 58 insertions(+), 7 deletions(-)
---
diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c
index 522cbcecf6..464612e616 100644
--- a/gdk/gdkglcontext.c
+++ b/gdk/gdkglcontext.c
@@ -278,6 +278,13 @@ gdk_gl_context_upload_texture (GdkGLContext *context,
gl_type = GL_UNSIGNED_BYTE;
bpp = 3;
}
+ else if (data_format == GDK_MEMORY_R16G16B16A16_PREMULTIPLIED)
+ {
+ gl_internalformat = GL_RGBA16;
+ gl_format = GL_RGBA;
+ gl_type = GL_UNSIGNED_SHORT;
+ bpp = 8;
+ }
else /* Fall-back, convert to cairo-surface-format */
{
copy = g_malloc (width * height * 4);
diff --git a/gdk/gdkmemorytexture.c b/gdk/gdkmemorytexture.c
index 06fa3d6619..43179ac45f 100644
--- a/gdk/gdkmemorytexture.c
+++ b/gdk/gdkmemorytexture.c
@@ -62,6 +62,9 @@ gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
case GDK_MEMORY_B8G8R8:
return 3;
+ case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
+ return 8;
+
case GDK_MEMORY_N_FORMATS:
default:
g_assert_not_reached ();
@@ -283,6 +286,37 @@ 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 SWIZZLE_16TO8(A,R,G,B) \
+static void \
+convert_16to8_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++) \
+ { \
+ guint16 *src = (guint16 *)src_data; \
+ for (x = 0; x < width; x++) \
+ { \
+ dest_data[4 * x + A] = (guchar)(src[4 * x + 0] >> 8); \
+ dest_data[4 * x + R] = (guchar)(src[4 * x + 1] >> 8); \
+ dest_data[4 * x + G] = (guchar)(src[4 * x + 2] >> 8); \
+ dest_data[4 * x + B] = (guchar)(src[4 * x + 3] >> 8); \
+ } \
+\
+ dest_data += dest_stride; \
+ src_data += src_stride; \
+ } \
+}
+
+SWIZZLE_16TO8(0,1,2,3)
+SWIZZLE_16TO8(2,1,0,3)
+SWIZZLE_16TO8(1,2,3,0)
+
typedef void (* ConversionFunc) (guchar *dest_data,
gsize dest_stride,
const guchar *src_data,
@@ -300,7 +334,8 @@ static ConversionFunc converters[GDK_MEMORY_N_FORMATS][3] =
{ 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_swizzle_opaque_3012, convert_swizzle_opaque_0321, convert_swizzle_opaque_3210 },
+ { convert_16to8_swizzle_2103, convert_16to8_swizzle_1230, convert_16to8_swizzle_0123 }
};
void
diff --git a/gdk/gdkmemorytexture.h b/gdk/gdkmemorytexture.h
index b9f1f21282..4e463174a6 100644
--- a/gdk/gdkmemorytexture.h
+++ b/gdk/gdkmemorytexture.h
@@ -42,6 +42,9 @@ G_BEGIN_DECLS
* @GDK_MEMORY_A8B8G8R8: 4 bytes; for alpha, blue, green, red.
* @GDK_MEMORY_R8G8B8: 3 bytes; for red, green, blue. The data is opaque.
* @GDK_MEMORY_B8G8R8: 3 bytes; for blue, green, red. The data is opaque.
+ * @GDK_MEMORY_R16G16B16A16_PREMULTIPLIED: 4 guint16 values; for red, green,
+ * blue, alpha. The color values are premultiplied with the alpha value.
+ * Since 4.6
* @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.
*
@@ -53,6 +56,8 @@ G_BEGIN_DECLS
* CAIRO_FORMAT_ARGB32 is represented by different `GdkMemoryFormats`
* on architectures with different endiannesses.
*
+ * Note that color data is assumed to be linear.
+ *
* Its naming is modelled after
* [VkFormat](https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VkFormat)
* for details).
@@ -67,6 +72,7 @@ typedef enum {
GDK_MEMORY_A8B8G8R8,
GDK_MEMORY_R8G8B8,
GDK_MEMORY_B8G8R8,
+ GDK_MEMORY_R16G16B16A16_PREMULTIPLIED,
GDK_MEMORY_N_FORMATS
} GdkMemoryFormat;
diff --git a/testsuite/gdk/memorytexture.c b/testsuite/gdk/memorytexture.c
index ea24c827e3..00bb489b63 100644
--- a/testsuite/gdk/memorytexture.c
+++ b/testsuite/gdk/memorytexture.c
@@ -2,7 +2,7 @@
#include <gdk/gdk.h>
/* maximum bytes per pixel */
-#define MAX_BPP 4
+#define MAX_BPP 8
typedef enum {
BLUE,
@@ -33,6 +33,7 @@ typedef struct _TestData {
} TestData;
#define RGBA(a, b, c, d) { 0x ## a, 0x ## b, 0x ## c, 0x ## d }
+#define RGBA16(a, b, c, d) { 0x ## a, 0x ## a, 0x ## b, 0x ## b, 0x ## c, 0x ## c, 0x ## d, 0x ## d }
static MemoryData tests[GDK_MEMORY_N_FORMATS] = {
{ 4, FALSE, { RGBA(FF,00,00,FF), RGBA(00,FF,00,FF), RGBA(00,00,FF,FF), RGBA(00,00,00,00),
RGBA(66,22,44,AA) } },
@@ -44,12 +45,14 @@ static MemoryData tests[GDK_MEMORY_N_FORMATS] = {
{ 4, FALSE, { RGBA(FF,FF,00,00), RGBA(FF,00,FF,00), RGBA(FF,00,00,FF), RGBA(00,00,00,00),
RGBA(AA,99,33,66) } },
{ 3, TRUE, { RGBA(00,00,FF,00), RGBA(00,FF,00,00), RGBA(FF,00,00,00), RGBA(00,00,00,00),
RGBA(44,22,66,00) } },
{ 3, TRUE, { RGBA(FF,00,00,00), RGBA(00,FF,00,00), RGBA(00,00,FF,00), RGBA(00,00,00,00),
RGBA(66,22,44,00) } },
+ { 8, FALSE, { RGBA16(00,00,FF,FF), RGBA16(00,FF,00,FF), RGBA16(FF,00,00,FF), RGBA16(00,00,00,00),
RGBA16(44,22,66,AA) } },
};
static void
compare_textures (GdkTexture *expected,
GdkTexture *test,
- gboolean ignore_alpha)
+ gboolean ignore_alpha,
+ int bpp)
{
guchar *expected_data, *test_data;
int width, height;
@@ -122,7 +125,7 @@ test_download_1x1 (gconstpointer data)
expected = create_texture (GDK_MEMORY_DEFAULT, test_data->color, 1, 1,
tests[test_data->format].bytes_per_pixel);
test = create_texture (test_data->format, test_data->color, 1, 1,
tests[test_data->format].bytes_per_pixel);
- compare_textures (expected, test, tests[test_data->format].opaque);
+ compare_textures (expected, test, tests[test_data->format].opaque,
tests[test_data->format].bytes_per_pixel);
g_object_unref (expected);
g_object_unref (test);
@@ -137,7 +140,7 @@ test_download_1x1_with_stride (gconstpointer data)
expected = create_texture (GDK_MEMORY_DEFAULT, test_data->color, 1, 1, 4);
test = create_texture (test_data->format, test_data->color, 1, 1, 2 * MAX_BPP);
- compare_textures (expected, test, tests[test_data->format].opaque);
+ compare_textures (expected, test, tests[test_data->format].opaque,
tests[test_data->format].bytes_per_pixel);
g_object_unref (expected);
g_object_unref (test);
@@ -152,7 +155,7 @@ test_download_4x4 (gconstpointer data)
expected = create_texture (GDK_MEMORY_DEFAULT, test_data->color, 4, 4, 16);
test = create_texture (test_data->format, test_data->color, 4, 4, 4 *
tests[test_data->format].bytes_per_pixel);
- compare_textures (expected, test, tests[test_data->format].opaque);
+ compare_textures (expected, test, tests[test_data->format].opaque,
tests[test_data->format].bytes_per_pixel);
g_object_unref (expected);
g_object_unref (test);
@@ -167,7 +170,7 @@ test_download_4x4_with_stride (gconstpointer data)
expected = create_texture (GDK_MEMORY_DEFAULT, test_data->color, 4, 4, 16);
test = create_texture (test_data->format, test_data->color, 4, 4, 4 * MAX_BPP);
- compare_textures (expected, test, tests[test_data->format].opaque);
+ compare_textures (expected, test, tests[test_data->format].opaque,
tests[test_data->format].bytes_per_pixel);
g_object_unref (expected);
g_object_unref (test);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]