From 8e54460a48042512d0dde981a0e82323afcf7330 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 2 Sep 2024 23:32:38 +0100 Subject: [PATCH] testsuite: Extract common code from gdk/memorytexture and gsk/scaling Signed-off-by: Simon McVittie --- testsuite/gdk/gdktestutils.c | 670 +++++++++++++++++++++++++++++++++ testsuite/gdk/gdktestutils.h | 49 +++ testsuite/gdk/memorytexture.c | 688 +--------------------------------- testsuite/gdk/meson.build | 2 +- testsuite/gsk/meson.build | 2 +- testsuite/gsk/scaling.c | 629 +------------------------------ 6 files changed, 723 insertions(+), 1317 deletions(-) create mode 100644 testsuite/gdk/gdktestutils.c create mode 100644 testsuite/gdk/gdktestutils.h diff --git a/testsuite/gdk/gdktestutils.c b/testsuite/gdk/gdktestutils.c new file mode 100644 index 0000000000..9e48ac092c --- /dev/null +++ b/testsuite/gdk/gdktestutils.c @@ -0,0 +1,670 @@ +#include "gdktestutils.h" + +#include "gsk/gl/fp16private.h" + +gsize +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: + case GDK_MEMORY_A16_FLOAT: + return 2; + + 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_A8B8G8R8_PREMULTIPLIED: + case GDK_MEMORY_B8G8R8A8: + case GDK_MEMORY_A8R8G8B8: + case GDK_MEMORY_R8G8B8A8: + case GDK_MEMORY_A8B8G8R8: + case GDK_MEMORY_B8G8R8X8: + case GDK_MEMORY_X8R8G8B8: + case GDK_MEMORY_R8G8B8X8: + case GDK_MEMORY_X8B8G8R8: + case GDK_MEMORY_G16A16_PREMULTIPLIED: + case GDK_MEMORY_G16A16: + case GDK_MEMORY_A32_FLOAT: + return 4; + + case GDK_MEMORY_R16G16B16: + case GDK_MEMORY_R16G16B16_FLOAT: + return 6; + + case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED: + case GDK_MEMORY_R16G16B16A16: + case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED: + case GDK_MEMORY_R16G16B16A16_FLOAT: + return 8; + + case GDK_MEMORY_R32G32B32_FLOAT: + return 12; + + case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED: + case GDK_MEMORY_R32G32B32A32_FLOAT: + return 16; + + case GDK_MEMORY_N_FORMATS: + default: + g_assert_not_reached (); + return 4; + } +} + +ChannelType +gdk_memory_format_get_channel_type (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_A8B8G8R8_PREMULTIPLIED: + case GDK_MEMORY_B8G8R8A8: + case GDK_MEMORY_A8R8G8B8: + case GDK_MEMORY_R8G8B8A8: + case GDK_MEMORY_A8B8G8R8: + case GDK_MEMORY_B8G8R8X8: + case GDK_MEMORY_X8R8G8B8: + case GDK_MEMORY_R8G8B8X8: + case GDK_MEMORY_X8B8G8R8: + case GDK_MEMORY_G8: + case GDK_MEMORY_G8A8: + case GDK_MEMORY_G8A8_PREMULTIPLIED: + case GDK_MEMORY_A8: + return CHANNEL_UINT_8; + + case GDK_MEMORY_R16G16B16: + case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED: + case GDK_MEMORY_R16G16B16A16: + case GDK_MEMORY_G16: + case GDK_MEMORY_G16A16: + case GDK_MEMORY_G16A16_PREMULTIPLIED: + case GDK_MEMORY_A16: + return CHANNEL_UINT_16; + + case GDK_MEMORY_R16G16B16_FLOAT: + case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED: + case GDK_MEMORY_R16G16B16A16_FLOAT: + case GDK_MEMORY_A16_FLOAT: + return CHANNEL_FLOAT_16; + + case GDK_MEMORY_R32G32B32_FLOAT: + case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED: + case GDK_MEMORY_R32G32B32A32_FLOAT: + case GDK_MEMORY_A32_FLOAT: + return CHANNEL_FLOAT_32; + + case GDK_MEMORY_N_FORMATS: + default: + g_assert_not_reached (); + return CHANNEL_UINT_8; + } +} + +/* return the number of color channels, ignoring alpha */ +guint +gdk_memory_format_n_colors (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_B8G8R8A8_PREMULTIPLIED: + case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED: + case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED: + case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED: + case GDK_MEMORY_B8G8R8A8: + case GDK_MEMORY_A8R8G8B8: + case GDK_MEMORY_R8G8B8A8: + case GDK_MEMORY_A8B8G8R8: + case GDK_MEMORY_B8G8R8X8: + case GDK_MEMORY_X8R8G8B8: + case GDK_MEMORY_R8G8B8X8: + case GDK_MEMORY_X8B8G8R8: + 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: + return 3; + + case GDK_MEMORY_G8: + case GDK_MEMORY_G16: + case GDK_MEMORY_G8A8_PREMULTIPLIED: + case GDK_MEMORY_G8A8: + case GDK_MEMORY_G16A16_PREMULTIPLIED: + case GDK_MEMORY_G16A16: + return 1; + + case GDK_MEMORY_A8: + case GDK_MEMORY_A16: + case GDK_MEMORY_A16_FLOAT: + case GDK_MEMORY_A32_FLOAT: + return 0; + + case GDK_MEMORY_N_FORMATS: + default: + g_assert_not_reached (); + return TRUE; + } +} + +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: + case GDK_MEMORY_B8G8R8X8: + case GDK_MEMORY_X8R8G8B8: + case GDK_MEMORY_R8G8B8X8: + case GDK_MEMORY_X8B8G8R8: + return FALSE; + + case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED: + case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED: + case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED: + case GDK_MEMORY_A8B8G8R8_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: + case GDK_MEMORY_A16_FLOAT: + case GDK_MEMORY_A32_FLOAT: + return TRUE; + + case GDK_MEMORY_N_FORMATS: + default: + g_assert_not_reached (); + return TRUE; + } +} + +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_A8B8G8R8_PREMULTIPLIED: + case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED: + case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED: + case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED: + case GDK_MEMORY_G8A8_PREMULTIPLIED: + case GDK_MEMORY_G16A16_PREMULTIPLIED: + case GDK_MEMORY_A8: + case GDK_MEMORY_A16: + case GDK_MEMORY_A16_FLOAT: + case GDK_MEMORY_A32_FLOAT: + 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_B8G8R8X8: + case GDK_MEMORY_X8R8G8B8: + case GDK_MEMORY_R8G8B8X8: + case GDK_MEMORY_X8B8G8R8: + case GDK_MEMORY_R16G16B16A16: + case GDK_MEMORY_R16G16B16A16_FLOAT: + case GDK_MEMORY_R32G32B32A32_FLOAT: + case GDK_MEMORY_G8: + case GDK_MEMORY_G8A8: + case GDK_MEMORY_G16: + case GDK_MEMORY_G16A16: + return FALSE; + + case GDK_MEMORY_N_FORMATS: + default: + g_assert_not_reached (); + return FALSE; + } +} + +gboolean +gdk_memory_format_is_deep (GdkMemoryFormat format) +{ + return gdk_memory_format_get_channel_type (format) != CHANNEL_UINT_8; +} + +gboolean +gdk_memory_format_pixel_equal (GdkMemoryFormat format, + gboolean accurate, + const guchar *pixel1, + const guchar *pixel2) +{ + switch (format) + { + case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED: + case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED: + case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED: + case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED: + case GDK_MEMORY_R8G8B8: + case GDK_MEMORY_B8G8R8: + case GDK_MEMORY_B8G8R8A8: + case GDK_MEMORY_A8R8G8B8: + case GDK_MEMORY_R8G8B8A8: + case GDK_MEMORY_A8B8G8R8: + case GDK_MEMORY_A8: + case GDK_MEMORY_G8: + case GDK_MEMORY_G8A8: + case GDK_MEMORY_G8A8_PREMULTIPLIED: + return memcmp (pixel1, pixel2, gdk_memory_format_bytes_per_pixel (format)) == 0; + + case GDK_MEMORY_B8G8R8X8: + case GDK_MEMORY_R8G8B8X8: + return memcmp (pixel1, pixel2, 3) == 0; + + case GDK_MEMORY_X8R8G8B8: + case GDK_MEMORY_X8B8G8R8: + return memcmp (pixel1 + 1, pixel2 + 1, 3) == 0; + + case GDK_MEMORY_R16G16B16: + case GDK_MEMORY_R16G16B16A16: + case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED: + case GDK_MEMORY_G16: + case GDK_MEMORY_G16A16: + case GDK_MEMORY_G16A16_PREMULTIPLIED: + case GDK_MEMORY_A16: + { + const guint16 *u1 = (const guint16 *) pixel1; + const guint16 *u2 = (const guint16 *) pixel2; + guint i; + for (i = 0; i < gdk_memory_format_bytes_per_pixel (format) / sizeof (guint16); i++) + { + if (!G_APPROX_VALUE (u1[i], u2[i], accurate ? 1 : 256)) + return FALSE; + } + } + return TRUE; + + case GDK_MEMORY_R16G16B16_FLOAT: + case GDK_MEMORY_R16G16B16A16_FLOAT: + case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED: + case GDK_MEMORY_A16_FLOAT: + { + guint i; + for (i = 0; i < gdk_memory_format_bytes_per_pixel (format) / sizeof (guint16); i++) + { + float f1 = half_to_float_one (((guint16 *) pixel1)[i]); + float f2 = half_to_float_one (((guint16 *) pixel2)[i]); + if (!G_APPROX_VALUE (f1, f2, accurate ? 1./65535 : 1./255)) + return FALSE; + } + } + return TRUE; + + case GDK_MEMORY_R32G32B32_FLOAT: + case GDK_MEMORY_R32G32B32A32_FLOAT: + case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED: + case GDK_MEMORY_A32_FLOAT: + { + const float *f1 = (const float *) pixel1; + const float *f2 = (const float *) pixel2; + guint i; + for (i = 0; i < gdk_memory_format_bytes_per_pixel (format) / sizeof (float); i++) + { + if (!G_APPROX_VALUE (f1[i], f2[i], accurate ? 1./65535 : 1./255)) + return FALSE; + } + } + return TRUE; + + case GDK_MEMORY_N_FORMATS: + default: + g_assert_not_reached (); + return FALSE; + } +} + +void +texture_builder_init (TextureBuilder *builder, + GdkMemoryFormat format, + int width, + int height) +{ + gsize extra_stride; + + builder->format = format; + builder->width = width; + builder->height = height; + + extra_stride = g_test_rand_bit() ? g_test_rand_int_range (0, 16) : 0; + builder->offset = g_test_rand_bit() ? g_test_rand_int_range (0, 128) : 0; + builder->stride = width * gdk_memory_format_bytes_per_pixel (format) + extra_stride; + builder->pixels = g_malloc0 (builder->offset + builder->stride * height); +} + +GdkTexture * +texture_builder_finish (TextureBuilder *builder) +{ + GBytes *bytes; + GdkTexture *texture; + + bytes = g_bytes_new_with_free_func (builder->pixels + builder->offset, + builder->height * builder->stride, + g_free, + builder->pixels); + texture = gdk_memory_texture_new (builder->width, + builder->height, + builder->format, + bytes, + builder->stride); + g_bytes_unref (bytes); + + return texture; +} + +static inline void +set_pixel_u8 (guchar *data, + int r, + int g, + int b, + int a, + gboolean premultiply, + const GdkRGBA *color) +{ + if (a >= 0) + data[a] = CLAMP (color->alpha * 255.f + 0.5f, 0.f, 255.f); + if (premultiply) + { + data[r] = CLAMP (color->red * color->alpha * 255.f + 0.5f, 0.f, 255.f); + data[g] = CLAMP (color->green * color->alpha * 255.f + 0.5f, 0.f, 255.f); + data[b] = CLAMP (color->blue * color->alpha * 255.f + 0.5f, 0.f, 255.f); + } + else + { + data[r] = CLAMP (color->red * 255.f + 0.5f, 0.f, 255.f); + data[g] = CLAMP (color->green * 255.f + 0.5f, 0.f, 255.f); + data[b] = CLAMP (color->blue * 255.f + 0.5f, 0.f, 255.f); + } +} + +static float +color_gray (const GdkRGBA *color) +{ + return 1/3.f * (color->red + color->green + color->blue); +} + +void +texture_builder_set_pixel (TextureBuilder *builder, + int x, + int y, + const GdkRGBA *color) +{ + guchar *data; + + g_assert_cmpint (x, >=, 0); + g_assert_cmpint (x, <, builder->width); + g_assert_cmpint (y, >=, 0); + g_assert_cmpint (y, <, builder->height); + + data = builder->pixels + + builder->offset + + y * builder->stride + + x * gdk_memory_format_bytes_per_pixel (builder->format); + + switch (builder->format) + { + case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED: + set_pixel_u8 (data, 2, 1, 0, 3, TRUE, color); + break; + case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED: + set_pixel_u8 (data, 1, 2, 3, 0, TRUE, color); + break; + case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED: + set_pixel_u8 (data, 0, 1, 2, 3, TRUE, color); + break; + case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED: + set_pixel_u8 (data, 3, 2, 1, 0, TRUE, color); + break; + case GDK_MEMORY_B8G8R8A8: + set_pixel_u8 (data, 2, 1, 0, 3, FALSE, color); + break; + case GDK_MEMORY_A8R8G8B8: + set_pixel_u8 (data, 1, 2, 3, 0, FALSE, color); + break; + case GDK_MEMORY_R8G8B8A8: + set_pixel_u8 (data, 0, 1, 2, 3, FALSE, color); + break; + case GDK_MEMORY_A8B8G8R8: + set_pixel_u8 (data, 3, 2, 1, 0, FALSE, color); + break; + case GDK_MEMORY_B8G8R8X8: + set_pixel_u8 (data, 2, 1, 0, -1, TRUE, color); + break; + case GDK_MEMORY_X8R8G8B8: + set_pixel_u8 (data, 1, 2, 3, -1, TRUE, color); + break; + case GDK_MEMORY_R8G8B8X8: + set_pixel_u8 (data, 0, 1, 2, -1, TRUE, color); + break; + case GDK_MEMORY_X8B8G8R8: + set_pixel_u8 (data, 3, 2, 1, -1, TRUE, color); + break; + case GDK_MEMORY_R8G8B8: + set_pixel_u8 (data, 0, 1, 2, -1, TRUE, color); + break; + case GDK_MEMORY_B8G8R8: + set_pixel_u8 (data, 2, 1, 0, -1, TRUE, color); + break; + case GDK_MEMORY_R16G16B16: + { + guint16 pixels[3] = { + CLAMP (color->red * color->alpha * 65535.f + 0.5f, 0, 65535.f), + CLAMP (color->green * color->alpha * 65535.f + 0.5f, 0, 65535.f), + CLAMP (color->blue * color->alpha * 65535.f + 0.5f, 0, 65535.f), + }; + memcpy (data, pixels, 3 * sizeof (guint16)); + } + break; + case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED: + { + guint16 pixels[4] = { + CLAMP (color->red * color->alpha * 65535.f + 0.5f, 0, 65535.f), + CLAMP (color->green * color->alpha * 65535.f + 0.5f, 0, 65535.f), + CLAMP (color->blue * color->alpha * 65535.f + 0.5f, 0, 65535.f), + CLAMP (color->alpha * 65535.f + 0.5f, 0, 65535.f), + }; + memcpy (data, pixels, 4 * sizeof (guint16)); + } + break; + case GDK_MEMORY_R16G16B16A16: + { + guint16 pixels[4] = { + CLAMP (color->red * 65535.f + 0.5f, 0, 65535.f), + CLAMP (color->green * 65535.f + 0.5f, 0, 65535.f), + CLAMP (color->blue * 65535.f + 0.5f, 0, 65535.f), + CLAMP (color->alpha * 65535.f + 0.5f, 0, 65535.f), + }; + memcpy (data, pixels, 4 * sizeof (guint16)); + } + break; + case GDK_MEMORY_R16G16B16_FLOAT: + { + guint16 pixels[3] = { + float_to_half_one (color->red * color->alpha), + float_to_half_one (color->green * color->alpha), + float_to_half_one (color->blue * color->alpha) + }; + memcpy (data, pixels, 3 * sizeof (guint16)); + } + break; + case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED: + { + guint16 pixels[4] = { + float_to_half_one (color->red * color->alpha), + float_to_half_one (color->green * color->alpha), + float_to_half_one (color->blue * color->alpha), + float_to_half_one (color->alpha) + }; + memcpy (data, pixels, 4 * sizeof (guint16)); + } + break; + case GDK_MEMORY_R16G16B16A16_FLOAT: + { + guint16 pixels[4] = { + float_to_half_one (color->red), + float_to_half_one (color->green), + float_to_half_one (color->blue), + float_to_half_one (color->alpha) + }; + memcpy (data, pixels, 4 * sizeof (guint16)); + } + break; + case GDK_MEMORY_R32G32B32_FLOAT: + { + float pixels[3] = { + color->red * color->alpha, + color->green * color->alpha, + color->blue * color->alpha + }; + memcpy (data, pixels, 3 * sizeof (float)); + } + break; + case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED: + { + float pixels[4] = { + color->red * color->alpha, + color->green * color->alpha, + color->blue * color->alpha, + color->alpha + }; + memcpy (data, pixels, 4 * sizeof (float)); + } + break; + case GDK_MEMORY_R32G32B32A32_FLOAT: + { + float pixels[4] = { + color->red, + color->green, + color->blue, + color->alpha + }; + memcpy (data, pixels, 4 * sizeof (float)); + } + break; + case GDK_MEMORY_G8A8_PREMULTIPLIED: + { + data[0] = CLAMP (color_gray (color) * color->alpha * 255.f + 0.5f, 0.f, 255.f); + data[1] = CLAMP (color->alpha * 255.f + 0.5f, 0.f, 255.f); + } + break; + case GDK_MEMORY_G8A8: + { + data[0] = CLAMP (color_gray (color) * 255.f + 0.5f, 0.f, 255.f); + data[1] = CLAMP (color->alpha * 255.f + 0.5f, 0.f, 255.f); + } + break; + case GDK_MEMORY_G8: + { + *data = CLAMP (color_gray (color) * color->alpha * 255.f + 0.5f, 0.f, 255.f); + } + break; + case GDK_MEMORY_G16A16_PREMULTIPLIED: + { + guint16 pixels[2] = { + CLAMP (color_gray (color) * color->alpha * 65535.f + 0.5f, 0.f, 65535.f), + CLAMP (color->alpha * 65535.f + 0.5f, 0.f, 65535.f), + }; + memcpy (data, pixels, 2 * sizeof (guint16)); + } + break; + case GDK_MEMORY_G16A16: + { + guint16 pixels[2] = { + CLAMP (color_gray (color) * 65535.f + 0.5f, 0.f, 65535.f), + CLAMP (color->alpha * 65535.f + 0.5f, 0.f, 65535.f), + }; + memcpy (data, pixels, 2 * sizeof (guint16)); + } + break; + case GDK_MEMORY_G16: + { + guint16 pixel = CLAMP (color_gray (color) * color->alpha * 65535.f + 0.5f, 0.f, 65535.f); + memcpy (data, &pixel, sizeof (guint16)); + } + break; + case GDK_MEMORY_A8: + { + *data = CLAMP (color->alpha * 255.f + 0.5f, 0.f, 255.f); + } + break; + case GDK_MEMORY_A16: + { + guint16 pixel = CLAMP (color->alpha * 65535.f, 0.f, 65535.f); + memcpy (data, &pixel, sizeof (guint16)); + } + break; + case GDK_MEMORY_A16_FLOAT: + { + guint16 pixel = float_to_half_one (color->alpha); + memcpy (data, &pixel, sizeof (guint16)); + } + break; + case GDK_MEMORY_A32_FLOAT: + { + memcpy (data, &color->alpha, sizeof (float)); + } + break; + case GDK_MEMORY_N_FORMATS: + default: + g_assert_not_reached (); + break; + } +} + +void +texture_builder_fill (TextureBuilder *builder, + const GdkRGBA *color) +{ + int x, y; + for (y = 0; y < builder->height; y++) + for (x = 0; x < builder->width; x++) + texture_builder_set_pixel (builder, x, y, color); +} diff --git a/testsuite/gdk/gdktestutils.h b/testsuite/gdk/gdktestutils.h new file mode 100644 index 0000000000..b126867a55 --- /dev/null +++ b/testsuite/gdk/gdktestutils.h @@ -0,0 +1,49 @@ +#pragma once + +#include + +/* This shadows a function of the same name in a GDK private header, + * because tests can't use hidden functions from the shared library */ +#define gdk_memory_format_bytes_per_pixel test_memory_format_bytes_per_pixel + +typedef enum { + CHANNEL_UINT_8, + CHANNEL_UINT_16, + CHANNEL_FLOAT_16, + CHANNEL_FLOAT_32, +} ChannelType; + +typedef struct _TextureBuilder TextureBuilder; +struct _TextureBuilder +{ + GdkMemoryFormat format; + int width; + int height; + + guchar *pixels; + gsize stride; + gsize offset; +}; + +gsize gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format); +ChannelType gdk_memory_format_get_channel_type (GdkMemoryFormat format); +guint gdk_memory_format_n_colors (GdkMemoryFormat format); +gboolean gdk_memory_format_has_alpha (GdkMemoryFormat format); +gboolean gdk_memory_format_is_premultiplied (GdkMemoryFormat format); +gboolean gdk_memory_format_is_deep (GdkMemoryFormat format); +gboolean gdk_memory_format_pixel_equal (GdkMemoryFormat format, + gboolean accurate, + const guchar *pixel1, + const guchar *pixel2); + +void texture_builder_init (TextureBuilder *builder, + GdkMemoryFormat format, + int width, + int height); +GdkTexture *texture_builder_finish (TextureBuilder *builder); +void texture_builder_fill (TextureBuilder *builder, + const GdkRGBA *color); +void texture_builder_set_pixel (TextureBuilder *builder, + int x, + int y, + const GdkRGBA *color); diff --git a/testsuite/gdk/memorytexture.c b/testsuite/gdk/memorytexture.c index 2fc0e14a60..389c983f49 100644 --- a/testsuite/gdk/memorytexture.c +++ b/testsuite/gdk/memorytexture.c @@ -3,6 +3,7 @@ #include #include "gsk/gl/fp16private.h" +#include "testsuite/gdk/gdktestutils.h" #define N 10 @@ -11,8 +12,6 @@ static GskRenderer *gl_renderer = NULL; static GskRenderer *ngl_renderer = NULL; static GskRenderer *vulkan_renderer = NULL; -typedef struct _TextureBuilder TextureBuilder; - typedef enum { TEXTURE_METHOD_LOCAL, TEXTURE_METHOD_GL, @@ -28,294 +27,6 @@ typedef enum { N_TEXTURE_METHODS } TextureMethod; -typedef enum { - CHANNEL_UINT_8, - CHANNEL_UINT_16, - CHANNEL_FLOAT_16, - CHANNEL_FLOAT_32, -} ChannelType; - -struct _TextureBuilder -{ - GdkMemoryFormat format; - int width; - int height; - - guchar *pixels; - gsize stride; - gsize offset; -}; - -static gsize -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: - case GDK_MEMORY_A16_FLOAT: - return 2; - - 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_A8B8G8R8_PREMULTIPLIED: - case GDK_MEMORY_B8G8R8A8: - case GDK_MEMORY_A8R8G8B8: - case GDK_MEMORY_R8G8B8A8: - case GDK_MEMORY_A8B8G8R8: - case GDK_MEMORY_B8G8R8X8: - case GDK_MEMORY_X8R8G8B8: - case GDK_MEMORY_R8G8B8X8: - case GDK_MEMORY_X8B8G8R8: - case GDK_MEMORY_G16A16_PREMULTIPLIED: - case GDK_MEMORY_G16A16: - case GDK_MEMORY_A32_FLOAT: - return 4; - - case GDK_MEMORY_R16G16B16: - case GDK_MEMORY_R16G16B16_FLOAT: - return 6; - - case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED: - case GDK_MEMORY_R16G16B16A16: - case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED: - case GDK_MEMORY_R16G16B16A16_FLOAT: - return 8; - - case GDK_MEMORY_R32G32B32_FLOAT: - return 12; - - case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED: - case GDK_MEMORY_R32G32B32A32_FLOAT: - return 16; - - case GDK_MEMORY_N_FORMATS: - default: - g_assert_not_reached (); - return 4; - } -} - -static ChannelType -gdk_memory_format_get_channel_type (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_A8B8G8R8_PREMULTIPLIED: - case GDK_MEMORY_B8G8R8A8: - case GDK_MEMORY_A8R8G8B8: - case GDK_MEMORY_R8G8B8A8: - case GDK_MEMORY_A8B8G8R8: - case GDK_MEMORY_B8G8R8X8: - case GDK_MEMORY_X8R8G8B8: - case GDK_MEMORY_R8G8B8X8: - case GDK_MEMORY_X8B8G8R8: - case GDK_MEMORY_G8: - case GDK_MEMORY_G8A8: - case GDK_MEMORY_G8A8_PREMULTIPLIED: - case GDK_MEMORY_A8: - return CHANNEL_UINT_8; - - case GDK_MEMORY_R16G16B16: - case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED: - case GDK_MEMORY_R16G16B16A16: - case GDK_MEMORY_G16: - case GDK_MEMORY_G16A16: - case GDK_MEMORY_G16A16_PREMULTIPLIED: - case GDK_MEMORY_A16: - return CHANNEL_UINT_16; - - case GDK_MEMORY_R16G16B16_FLOAT: - case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED: - case GDK_MEMORY_R16G16B16A16_FLOAT: - case GDK_MEMORY_A16_FLOAT: - return CHANNEL_FLOAT_16; - - case GDK_MEMORY_R32G32B32_FLOAT: - case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED: - case GDK_MEMORY_R32G32B32A32_FLOAT: - case GDK_MEMORY_A32_FLOAT: - return CHANNEL_FLOAT_32; - - case GDK_MEMORY_N_FORMATS: - default: - g_assert_not_reached (); - return CHANNEL_UINT_8; - } -} - -/* return the number of color channels, ignoring alpha */ -static guint -gdk_memory_format_n_colors (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_B8G8R8A8_PREMULTIPLIED: - case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED: - case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED: - case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED: - case GDK_MEMORY_B8G8R8A8: - case GDK_MEMORY_A8R8G8B8: - case GDK_MEMORY_R8G8B8A8: - case GDK_MEMORY_A8B8G8R8: - case GDK_MEMORY_B8G8R8X8: - case GDK_MEMORY_X8R8G8B8: - case GDK_MEMORY_R8G8B8X8: - case GDK_MEMORY_X8B8G8R8: - 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: - return 3; - - case GDK_MEMORY_G8: - case GDK_MEMORY_G16: - case GDK_MEMORY_G8A8_PREMULTIPLIED: - case GDK_MEMORY_G8A8: - case GDK_MEMORY_G16A16_PREMULTIPLIED: - case GDK_MEMORY_G16A16: - return 1; - - case GDK_MEMORY_A8: - case GDK_MEMORY_A16: - case GDK_MEMORY_A16_FLOAT: - case GDK_MEMORY_A32_FLOAT: - return 0; - - case GDK_MEMORY_N_FORMATS: - default: - g_assert_not_reached (); - return TRUE; - } -} - -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: - case GDK_MEMORY_B8G8R8X8: - case GDK_MEMORY_X8R8G8B8: - case GDK_MEMORY_R8G8B8X8: - case GDK_MEMORY_X8B8G8R8: - return FALSE; - - case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED: - case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED: - case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED: - case GDK_MEMORY_A8B8G8R8_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: - case GDK_MEMORY_A16_FLOAT: - case GDK_MEMORY_A32_FLOAT: - 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_A8B8G8R8_PREMULTIPLIED: - case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED: - case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED: - case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED: - case GDK_MEMORY_G8A8_PREMULTIPLIED: - case GDK_MEMORY_G16A16_PREMULTIPLIED: - case GDK_MEMORY_A8: - case GDK_MEMORY_A16: - case GDK_MEMORY_A16_FLOAT: - case GDK_MEMORY_A32_FLOAT: - 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_B8G8R8X8: - case GDK_MEMORY_X8R8G8B8: - case GDK_MEMORY_R8G8B8X8: - case GDK_MEMORY_X8B8G8R8: - case GDK_MEMORY_R16G16B16A16: - case GDK_MEMORY_R16G16B16A16_FLOAT: - case GDK_MEMORY_R32G32B32A32_FLOAT: - case GDK_MEMORY_G8: - case GDK_MEMORY_G8A8: - case GDK_MEMORY_G16: - case GDK_MEMORY_G16A16: - return FALSE; - - case GDK_MEMORY_N_FORMATS: - default: - g_assert_not_reached (); - return FALSE; - } -} - -static gboolean -gdk_memory_format_is_deep (GdkMemoryFormat format) -{ - return gdk_memory_format_get_channel_type (format) != CHANNEL_UINT_8; -} - static void gdk_memory_format_pixel_print (GdkMemoryFormat format, const guchar *data, @@ -437,96 +148,6 @@ gdk_memory_format_pixel_print (GdkMemoryFormat format, } } -static gboolean -gdk_memory_format_pixel_equal (GdkMemoryFormat format, - gboolean accurate, - const guchar *pixel1, - const guchar *pixel2) -{ - switch (format) - { - case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED: - case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED: - case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED: - case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED: - case GDK_MEMORY_R8G8B8: - case GDK_MEMORY_B8G8R8: - case GDK_MEMORY_B8G8R8A8: - case GDK_MEMORY_A8R8G8B8: - case GDK_MEMORY_R8G8B8A8: - case GDK_MEMORY_A8B8G8R8: - case GDK_MEMORY_A8: - case GDK_MEMORY_G8: - case GDK_MEMORY_G8A8: - case GDK_MEMORY_G8A8_PREMULTIPLIED: - return memcmp (pixel1, pixel2, gdk_memory_format_bytes_per_pixel (format)) == 0; - - case GDK_MEMORY_B8G8R8X8: - case GDK_MEMORY_R8G8B8X8: - return memcmp (pixel1, pixel2, 3) == 0; - - case GDK_MEMORY_X8R8G8B8: - case GDK_MEMORY_X8B8G8R8: - return memcmp (pixel1 + 1, pixel2 + 1, 3) == 0; - - case GDK_MEMORY_R16G16B16: - case GDK_MEMORY_R16G16B16A16: - case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED: - case GDK_MEMORY_G16: - case GDK_MEMORY_G16A16: - case GDK_MEMORY_G16A16_PREMULTIPLIED: - case GDK_MEMORY_A16: - { - const guint16 *u1 = (const guint16 *) pixel1; - const guint16 *u2 = (const guint16 *) pixel2; - guint i; - for (i = 0; i < gdk_memory_format_bytes_per_pixel (format) / sizeof (guint16); i++) - { - if (!G_APPROX_VALUE (u1[i], u2[i], accurate ? 1 : 256)) - return FALSE; - } - } - return TRUE; - - case GDK_MEMORY_R16G16B16_FLOAT: - case GDK_MEMORY_R16G16B16A16_FLOAT: - case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED: - case GDK_MEMORY_A16_FLOAT: - { - guint i; - for (i = 0; i < gdk_memory_format_bytes_per_pixel (format) / sizeof (guint16); i++) - { - float f1 = half_to_float_one (((guint16 *) pixel1)[i]); - float f2 = half_to_float_one (((guint16 *) pixel2)[i]); - if (!G_APPROX_VALUE (f1, f2, accurate ? 1./65535 : 1./255)) - return FALSE; - } - } - return TRUE; - - case GDK_MEMORY_R32G32B32_FLOAT: - case GDK_MEMORY_R32G32B32A32_FLOAT: - case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED: - case GDK_MEMORY_A32_FLOAT: - { - const float *f1 = (const float *) pixel1; - const float *f2 = (const float *) pixel2; - guint i; - for (i = 0; i < gdk_memory_format_bytes_per_pixel (format) / sizeof (float); i++) - { - if (!G_APPROX_VALUE (f1[i], f2[i], accurate ? 1./65535 : 1./255)) - return FALSE; - } - } - return TRUE; - - case GDK_MEMORY_N_FORMATS: - default: - g_assert_not_reached (); - return FALSE; - } -} - static gpointer encode (GdkMemoryFormat format, TextureMethod method) @@ -567,313 +188,6 @@ decode_two_formats (gconstpointer data, *format1 = value; } -static void -texture_builder_init (TextureBuilder *builder, - GdkMemoryFormat format, - int width, - int height) -{ - gsize extra_stride; - - builder->format = format; - builder->width = width; - builder->height = height; - - extra_stride = g_test_rand_bit() ? g_test_rand_int_range (0, 16) : 0; - builder->offset = g_test_rand_bit() ? g_test_rand_int_range (0, 128) : 0; - builder->stride = width * gdk_memory_format_bytes_per_pixel (format) + extra_stride; - builder->pixels = g_malloc0 (builder->offset + builder->stride * height); -} - -static GdkTexture * -texture_builder_finish (TextureBuilder *builder) -{ - GBytes *bytes; - GdkTexture *texture; - - bytes = g_bytes_new_with_free_func (builder->pixels + builder->offset, - builder->height * builder->stride, - g_free, - builder->pixels); - texture = gdk_memory_texture_new (builder->width, - builder->height, - builder->format, - bytes, - builder->stride); - g_bytes_unref (bytes); - - return texture; -} - -static inline void -set_pixel_u8 (guchar *data, - int r, - int g, - int b, - int a, - gboolean premultiply, - const GdkRGBA *color) -{ - if (a >= 0) - data[a] = CLAMP (color->alpha * 255.f + 0.5f, 0.f, 255.f); - if (premultiply) - { - data[r] = CLAMP (color->red * color->alpha * 255.f + 0.5f, 0.f, 255.f); - data[g] = CLAMP (color->green * color->alpha * 255.f + 0.5f, 0.f, 255.f); - data[b] = CLAMP (color->blue * color->alpha * 255.f + 0.5f, 0.f, 255.f); - } - else - { - data[r] = CLAMP (color->red * 255.f + 0.5f, 0.f, 255.f); - data[g] = CLAMP (color->green * 255.f + 0.5f, 0.f, 255.f); - data[b] = CLAMP (color->blue * 255.f + 0.5f, 0.f, 255.f); - } -} - -static float -color_gray (const GdkRGBA *color) -{ - return 1/3.f * (color->red + color->green + color->blue); -} - -static void -texture_builder_set_pixel (TextureBuilder *builder, - int x, - int y, - const GdkRGBA *color) -{ - guchar *data; - - g_assert_cmpint (x, >=, 0); - g_assert_cmpint (x, <, builder->width); - g_assert_cmpint (y, >=, 0); - g_assert_cmpint (y, <, builder->height); - - data = builder->pixels - + builder->offset - + y * builder->stride - + x * gdk_memory_format_bytes_per_pixel (builder->format); - - switch (builder->format) - { - case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED: - set_pixel_u8 (data, 2, 1, 0, 3, TRUE, color); - break; - case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED: - set_pixel_u8 (data, 1, 2, 3, 0, TRUE, color); - break; - case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED: - set_pixel_u8 (data, 0, 1, 2, 3, TRUE, color); - break; - case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED: - set_pixel_u8 (data, 3, 2, 1, 0, TRUE, color); - break; - case GDK_MEMORY_B8G8R8A8: - set_pixel_u8 (data, 2, 1, 0, 3, FALSE, color); - break; - case GDK_MEMORY_A8R8G8B8: - set_pixel_u8 (data, 1, 2, 3, 0, FALSE, color); - break; - case GDK_MEMORY_R8G8B8A8: - set_pixel_u8 (data, 0, 1, 2, 3, FALSE, color); - break; - case GDK_MEMORY_A8B8G8R8: - set_pixel_u8 (data, 3, 2, 1, 0, FALSE, color); - break; - case GDK_MEMORY_B8G8R8X8: - set_pixel_u8 (data, 2, 1, 0, -1, TRUE, color); - break; - case GDK_MEMORY_X8R8G8B8: - set_pixel_u8 (data, 1, 2, 3, -1, TRUE, color); - break; - case GDK_MEMORY_R8G8B8X8: - set_pixel_u8 (data, 0, 1, 2, -1, TRUE, color); - break; - case GDK_MEMORY_X8B8G8R8: - set_pixel_u8 (data, 3, 2, 1, -1, TRUE, color); - break; - case GDK_MEMORY_R8G8B8: - set_pixel_u8 (data, 0, 1, 2, -1, TRUE, color); - break; - case GDK_MEMORY_B8G8R8: - set_pixel_u8 (data, 2, 1, 0, -1, TRUE, color); - break; - case GDK_MEMORY_R16G16B16: - { - guint16 pixels[3] = { - CLAMP (color->red * color->alpha * 65535.f + 0.5f, 0, 65535.f), - CLAMP (color->green * color->alpha * 65535.f + 0.5f, 0, 65535.f), - CLAMP (color->blue * color->alpha * 65535.f + 0.5f, 0, 65535.f), - }; - memcpy (data, pixels, 3 * sizeof (guint16)); - } - break; - case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED: - { - guint16 pixels[4] = { - CLAMP (color->red * color->alpha * 65535.f + 0.5f, 0, 65535.f), - CLAMP (color->green * color->alpha * 65535.f + 0.5f, 0, 65535.f), - CLAMP (color->blue * color->alpha * 65535.f + 0.5f, 0, 65535.f), - CLAMP (color->alpha * 65535.f + 0.5f, 0, 65535.f), - }; - memcpy (data, pixels, 4 * sizeof (guint16)); - } - break; - case GDK_MEMORY_R16G16B16A16: - { - guint16 pixels[4] = { - CLAMP (color->red * 65535.f + 0.5f, 0, 65535.f), - CLAMP (color->green * 65535.f + 0.5f, 0, 65535.f), - CLAMP (color->blue * 65535.f + 0.5f, 0, 65535.f), - CLAMP (color->alpha * 65535.f + 0.5f, 0, 65535.f), - }; - memcpy (data, pixels, 4 * sizeof (guint16)); - } - break; - case GDK_MEMORY_R16G16B16_FLOAT: - { - guint16 pixels[3] = { - float_to_half_one (color->red * color->alpha), - float_to_half_one (color->green * color->alpha), - float_to_half_one (color->blue * color->alpha) - }; - memcpy (data, pixels, 3 * sizeof (guint16)); - } - break; - case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED: - { - guint16 pixels[4] = { - float_to_half_one (color->red * color->alpha), - float_to_half_one (color->green * color->alpha), - float_to_half_one (color->blue * color->alpha), - float_to_half_one (color->alpha) - }; - memcpy (data, pixels, 4 * sizeof (guint16)); - } - break; - case GDK_MEMORY_R16G16B16A16_FLOAT: - { - guint16 pixels[4] = { - float_to_half_one (color->red), - float_to_half_one (color->green), - float_to_half_one (color->blue), - float_to_half_one (color->alpha) - }; - memcpy (data, pixels, 4 * sizeof (guint16)); - } - break; - case GDK_MEMORY_R32G32B32_FLOAT: - { - float pixels[3] = { - color->red * color->alpha, - color->green * color->alpha, - color->blue * color->alpha - }; - memcpy (data, pixels, 3 * sizeof (float)); - } - break; - case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED: - { - float pixels[4] = { - color->red * color->alpha, - color->green * color->alpha, - color->blue * color->alpha, - color->alpha - }; - memcpy (data, pixels, 4 * sizeof (float)); - } - break; - case GDK_MEMORY_R32G32B32A32_FLOAT: - { - float pixels[4] = { - color->red, - color->green, - color->blue, - color->alpha - }; - memcpy (data, pixels, 4 * sizeof (float)); - } - break; - case GDK_MEMORY_G8A8_PREMULTIPLIED: - { - data[0] = CLAMP (color_gray (color) * color->alpha * 255.f + 0.5f, 0.f, 255.f); - data[1] = CLAMP (color->alpha * 255.f + 0.5f, 0.f, 255.f); - } - break; - case GDK_MEMORY_G8A8: - { - data[0] = CLAMP (color_gray (color) * 255.f + 0.5f, 0.f, 255.f); - data[1] = CLAMP (color->alpha * 255.f + 0.5f, 0.f, 255.f); - } - break; - case GDK_MEMORY_G8: - { - *data = CLAMP (color_gray (color) * color->alpha * 255.f + 0.5f, 0.f, 255.f); - } - break; - case GDK_MEMORY_G16A16_PREMULTIPLIED: - { - guint16 pixels[2] = { - CLAMP (color_gray (color) * color->alpha * 65535.f + 0.5f, 0.f, 65535.f), - CLAMP (color->alpha * 65535.f + 0.5f, 0.f, 65535.f), - }; - memcpy (data, pixels, 2 * sizeof (guint16)); - } - break; - case GDK_MEMORY_G16A16: - { - guint16 pixels[2] = { - CLAMP (color_gray (color) * 65535.f + 0.5f, 0.f, 65535.f), - CLAMP (color->alpha * 65535.f + 0.5f, 0.f, 65535.f), - }; - memcpy (data, pixels, 2 * sizeof (guint16)); - } - break; - case GDK_MEMORY_G16: - { - guint16 pixel = CLAMP (color_gray (color) * color->alpha * 65535.f + 0.5f, 0.f, 65535.f); - memcpy (data, &pixel, sizeof (guint16)); - } - break; - case GDK_MEMORY_A8: - { - *data = CLAMP (color->alpha * 255.f + 0.5f, 0.f, 255.f); - } - break; - case GDK_MEMORY_A16: - { - guint16 pixel = CLAMP (color->alpha * 65535.f, 0.f, 65535.f); - memcpy (data, &pixel, sizeof (guint16)); - } - break; - case GDK_MEMORY_A16_FLOAT: - { - guint16 pixel = float_to_half_one (color->alpha); - memcpy (data, &pixel, sizeof (guint16)); - } - break; - case GDK_MEMORY_A32_FLOAT: - { - memcpy (data, &color->alpha, sizeof (float)); - } - break; - case GDK_MEMORY_N_FORMATS: - default: - g_assert_not_reached (); - break; - } -} - -static void -texture_builder_fill (TextureBuilder *builder, - const GdkRGBA *color) -{ - int x, y; - for (y = 0; y < builder->height; y++) - for (x = 0; x < builder->width; x++) - texture_builder_set_pixel (builder, x, y, color); -} - static void compare_textures (GdkTexture *texture1, GdkTexture *texture2, diff --git a/testsuite/gdk/meson.build b/testsuite/gdk/meson.build index 06b65a8e3a..cc7f38d811 100644 --- a/testsuite/gdk/meson.build +++ b/testsuite/gdk/meson.build @@ -17,7 +17,7 @@ tests = [ { 'name': 'displaymanager' }, { 'name': 'glcontext' }, { 'name': 'keysyms' }, - { 'name': 'memorytexture' }, + { 'name': 'memorytexture', 'sources': [ 'gdktestutils.c' ] }, { 'name': 'rectangle' }, { 'name': 'rgba' }, { 'name': 'seat' }, diff --git a/testsuite/gsk/meson.build b/testsuite/gsk/meson.build index 608ffdb6aa..fd55c237d9 100644 --- a/testsuite/gsk/meson.build +++ b/testsuite/gsk/meson.build @@ -542,7 +542,7 @@ tests = [ [ 'opaque' ], [ 'path', [ 'path-utils.c' ], [ 'flaky'] ], [ 'path-special-cases' ], - [ 'scaling' ], + [ 'scaling', [ 'scaling.c', '../gdk/gdktestutils.c' ] ], ] test_cargs = [] diff --git a/testsuite/gsk/scaling.c b/testsuite/gsk/scaling.c index 1f3c5e2b98..09869a4889 100644 --- a/testsuite/gsk/scaling.c +++ b/testsuite/gsk/scaling.c @@ -3,6 +3,7 @@ #define N 10 #include "gsk/gl/fp16private.h" +#include "testsuite/gdk/gdktestutils.h" struct { const char *name; @@ -30,327 +31,6 @@ struct { }, }; -typedef struct _TextureBuilder TextureBuilder; - -typedef enum { - CHANNEL_UINT_8, - CHANNEL_UINT_16, - CHANNEL_FLOAT_16, - CHANNEL_FLOAT_32, -} ChannelType; - -struct _TextureBuilder -{ - GdkMemoryFormat format; - int width; - int height; - - guchar *pixels; - gsize stride; - gsize offset; -}; - -static gsize -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: - case GDK_MEMORY_A16_FLOAT: - return 2; - - 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_A8B8G8R8_PREMULTIPLIED: - case GDK_MEMORY_B8G8R8A8: - case GDK_MEMORY_A8R8G8B8: - case GDK_MEMORY_R8G8B8A8: - case GDK_MEMORY_A8B8G8R8: - case GDK_MEMORY_B8G8R8X8: - case GDK_MEMORY_X8R8G8B8: - case GDK_MEMORY_R8G8B8X8: - case GDK_MEMORY_X8B8G8R8: - case GDK_MEMORY_G16A16_PREMULTIPLIED: - case GDK_MEMORY_G16A16: - case GDK_MEMORY_A32_FLOAT: - return 4; - - case GDK_MEMORY_R16G16B16: - case GDK_MEMORY_R16G16B16_FLOAT: - return 6; - - case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED: - case GDK_MEMORY_R16G16B16A16: - case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED: - case GDK_MEMORY_R16G16B16A16_FLOAT: - return 8; - - case GDK_MEMORY_R32G32B32_FLOAT: - return 12; - - case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED: - case GDK_MEMORY_R32G32B32A32_FLOAT: - return 16; - - case GDK_MEMORY_N_FORMATS: - default: - g_assert_not_reached (); - return 4; - } -} - -/* return the number of color channels, ignoring alpha */ -static guint -gdk_memory_format_n_colors (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_B8G8R8A8_PREMULTIPLIED: - case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED: - case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED: - case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED: - case GDK_MEMORY_B8G8R8A8: - case GDK_MEMORY_A8R8G8B8: - case GDK_MEMORY_R8G8B8A8: - case GDK_MEMORY_A8B8G8R8: - case GDK_MEMORY_B8G8R8X8: - case GDK_MEMORY_X8R8G8B8: - case GDK_MEMORY_R8G8B8X8: - case GDK_MEMORY_X8B8G8R8: - 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: - return 3; - - case GDK_MEMORY_G8: - case GDK_MEMORY_G16: - case GDK_MEMORY_G8A8_PREMULTIPLIED: - case GDK_MEMORY_G8A8: - case GDK_MEMORY_G16A16_PREMULTIPLIED: - case GDK_MEMORY_G16A16: - return 1; - - case GDK_MEMORY_A8: - case GDK_MEMORY_A16: - case GDK_MEMORY_A16_FLOAT: - case GDK_MEMORY_A32_FLOAT: - return 0; - - case GDK_MEMORY_N_FORMATS: - default: - g_assert_not_reached (); - return TRUE; - } -} - -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: - case GDK_MEMORY_B8G8R8X8: - case GDK_MEMORY_X8R8G8B8: - case GDK_MEMORY_R8G8B8X8: - case GDK_MEMORY_X8B8G8R8: - return FALSE; - - case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED: - case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED: - case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED: - case GDK_MEMORY_A8B8G8R8_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: - case GDK_MEMORY_A16_FLOAT: - case GDK_MEMORY_A32_FLOAT: - 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_A8B8G8R8_PREMULTIPLIED: - case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED: - case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED: - case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED: - case GDK_MEMORY_G8A8_PREMULTIPLIED: - case GDK_MEMORY_G16A16_PREMULTIPLIED: - case GDK_MEMORY_A8: - case GDK_MEMORY_A16: - case GDK_MEMORY_A16_FLOAT: - case GDK_MEMORY_A32_FLOAT: - 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_B8G8R8X8: - case GDK_MEMORY_X8R8G8B8: - case GDK_MEMORY_R8G8B8X8: - case GDK_MEMORY_X8B8G8R8: - case GDK_MEMORY_R16G16B16A16: - case GDK_MEMORY_R16G16B16A16_FLOAT: - case GDK_MEMORY_R32G32B32A32_FLOAT: - case GDK_MEMORY_G8: - case GDK_MEMORY_G8A8: - case GDK_MEMORY_G16: - case GDK_MEMORY_G16A16: - 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, - const guchar *pixel1, - const guchar *pixel2) -{ - switch (format) - { - case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED: - case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED: - case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED: - case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED: - case GDK_MEMORY_R8G8B8: - case GDK_MEMORY_B8G8R8: - case GDK_MEMORY_B8G8R8A8: - case GDK_MEMORY_A8R8G8B8: - case GDK_MEMORY_R8G8B8A8: - case GDK_MEMORY_A8B8G8R8: - case GDK_MEMORY_A8: - case GDK_MEMORY_G8: - case GDK_MEMORY_G8A8: - case GDK_MEMORY_G8A8_PREMULTIPLIED: - return memcmp (pixel1, pixel2, gdk_memory_format_bytes_per_pixel (format)) == 0; - - case GDK_MEMORY_B8G8R8X8: - case GDK_MEMORY_R8G8B8X8: - return memcmp (pixel1, pixel2, 3) == 0; - - case GDK_MEMORY_X8R8G8B8: - case GDK_MEMORY_X8B8G8R8: - return memcmp (pixel1 + 1, pixel2 + 1, 3) == 0; - - case GDK_MEMORY_R16G16B16: - case GDK_MEMORY_R16G16B16A16: - case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED: - case GDK_MEMORY_G16: - case GDK_MEMORY_G16A16: - case GDK_MEMORY_G16A16_PREMULTIPLIED: - case GDK_MEMORY_A16: - { - const guint16 *u1 = (const guint16 *) pixel1; - const guint16 *u2 = (const guint16 *) pixel2; - guint i; - for (i = 0; i < gdk_memory_format_bytes_per_pixel (format) / sizeof (guint16); i++) - { - if (!G_APPROX_VALUE (u1[i], u2[i], accurate ? 1 : 256)) - return FALSE; - } - } - return TRUE; - - case GDK_MEMORY_R16G16B16_FLOAT: - case GDK_MEMORY_R16G16B16A16_FLOAT: - case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED: - case GDK_MEMORY_A16_FLOAT: - { - guint i; - for (i = 0; i < gdk_memory_format_bytes_per_pixel (format) / sizeof (guint16); i++) - { - float f1 = half_to_float_one (((guint16 *) pixel1)[i]); - float f2 = half_to_float_one (((guint16 *) pixel2)[i]); - if (!G_APPROX_VALUE (f1, f2, accurate ? 1./65535 : 1./255)) - return FALSE; - } - } - return TRUE; - - case GDK_MEMORY_R32G32B32_FLOAT: - case GDK_MEMORY_R32G32B32A32_FLOAT: - case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED: - case GDK_MEMORY_A32_FLOAT: - { - const float *f1 = (const float *) pixel1; - const float *f2 = (const float *) pixel2; - guint i; - for (i = 0; i < gdk_memory_format_bytes_per_pixel (format) / sizeof (float); i++) - { - if (!G_APPROX_VALUE (f1[i], f2[i], accurate ? 1./65535 : 1./255)) - return FALSE; - } - } - return TRUE; - - case GDK_MEMORY_N_FORMATS: - default: - g_assert_not_reached (); - return FALSE; - } -} - static gpointer encode_renderer_format (guint renderer, GdkMemoryFormat format) @@ -371,313 +51,6 @@ decode_renderer_format (gconstpointer data, *format = value; } -static void -texture_builder_init (TextureBuilder *builder, - GdkMemoryFormat format, - int width, - int height) -{ - gsize extra_stride; - - builder->format = format; - builder->width = width; - builder->height = height; - - extra_stride = g_test_rand_bit() ? g_test_rand_int_range (0, 16) : 0; - builder->offset = g_test_rand_bit() ? g_test_rand_int_range (0, 128) : 0; - builder->stride = width * gdk_memory_format_bytes_per_pixel (format) + extra_stride; - builder->pixels = g_malloc0 (builder->offset + builder->stride * height); -} - -static GdkTexture * -texture_builder_finish (TextureBuilder *builder) -{ - GBytes *bytes; - GdkTexture *texture; - - bytes = g_bytes_new_with_free_func (builder->pixels + builder->offset, - builder->height * builder->stride, - g_free, - builder->pixels); - texture = gdk_memory_texture_new (builder->width, - builder->height, - builder->format, - bytes, - builder->stride); - g_bytes_unref (bytes); - - return texture; -} - -static inline void -set_pixel_u8 (guchar *data, - int r, - int g, - int b, - int a, - gboolean premultiply, - const GdkRGBA *color) -{ - if (a >= 0) - data[a] = CLAMP (color->alpha * 255.f + 0.5f, 0.f, 255.f); - if (premultiply) - { - data[r] = CLAMP (color->red * color->alpha * 255.f + 0.5f, 0.f, 255.f); - data[g] = CLAMP (color->green * color->alpha * 255.f + 0.5f, 0.f, 255.f); - data[b] = CLAMP (color->blue * color->alpha * 255.f + 0.5f, 0.f, 255.f); - } - else - { - data[r] = CLAMP (color->red * 255.f + 0.5f, 0.f, 255.f); - data[g] = CLAMP (color->green * 255.f + 0.5f, 0.f, 255.f); - data[b] = CLAMP (color->blue * 255.f + 0.5f, 0.f, 255.f); - } -} - -static float -color_gray (const GdkRGBA *color) -{ - return 1/3.f * (color->red + color->green + color->blue); -} - -static void -texture_builder_set_pixel (TextureBuilder *builder, - int x, - int y, - const GdkRGBA *color) -{ - guchar *data; - - g_assert_cmpint (x, >=, 0); - g_assert_cmpint (x, <, builder->width); - g_assert_cmpint (y, >=, 0); - g_assert_cmpint (y, <, builder->height); - - data = builder->pixels - + builder->offset - + y * builder->stride - + x * gdk_memory_format_bytes_per_pixel (builder->format); - - switch (builder->format) - { - case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED: - set_pixel_u8 (data, 2, 1, 0, 3, TRUE, color); - break; - case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED: - set_pixel_u8 (data, 1, 2, 3, 0, TRUE, color); - break; - case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED: - set_pixel_u8 (data, 0, 1, 2, 3, TRUE, color); - break; - case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED: - set_pixel_u8 (data, 3, 2, 1, 0, TRUE, color); - break; - case GDK_MEMORY_B8G8R8A8: - set_pixel_u8 (data, 2, 1, 0, 3, FALSE, color); - break; - case GDK_MEMORY_A8R8G8B8: - set_pixel_u8 (data, 1, 2, 3, 0, FALSE, color); - break; - case GDK_MEMORY_R8G8B8A8: - set_pixel_u8 (data, 0, 1, 2, 3, FALSE, color); - break; - case GDK_MEMORY_A8B8G8R8: - set_pixel_u8 (data, 3, 2, 1, 0, FALSE, color); - break; - case GDK_MEMORY_B8G8R8X8: - set_pixel_u8 (data, 2, 1, 0, -1, TRUE, color); - break; - case GDK_MEMORY_X8R8G8B8: - set_pixel_u8 (data, 1, 2, 3, -1, TRUE, color); - break; - case GDK_MEMORY_R8G8B8X8: - set_pixel_u8 (data, 0, 1, 2, -1, TRUE, color); - break; - case GDK_MEMORY_X8B8G8R8: - set_pixel_u8 (data, 3, 2, 1, -1, TRUE, color); - break; - case GDK_MEMORY_R8G8B8: - set_pixel_u8 (data, 0, 1, 2, -1, TRUE, color); - break; - case GDK_MEMORY_B8G8R8: - set_pixel_u8 (data, 2, 1, 0, -1, TRUE, color); - break; - case GDK_MEMORY_R16G16B16: - { - guint16 pixels[3] = { - CLAMP (color->red * color->alpha * 65535.f + 0.5f, 0, 65535.f), - CLAMP (color->green * color->alpha * 65535.f + 0.5f, 0, 65535.f), - CLAMP (color->blue * color->alpha * 65535.f + 0.5f, 0, 65535.f), - }; - memcpy (data, pixels, 3 * sizeof (guint16)); - } - break; - case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED: - { - guint16 pixels[4] = { - CLAMP (color->red * color->alpha * 65535.f + 0.5f, 0, 65535.f), - CLAMP (color->green * color->alpha * 65535.f + 0.5f, 0, 65535.f), - CLAMP (color->blue * color->alpha * 65535.f + 0.5f, 0, 65535.f), - CLAMP (color->alpha * 65535.f + 0.5f, 0, 65535.f), - }; - memcpy (data, pixels, 4 * sizeof (guint16)); - } - break; - case GDK_MEMORY_R16G16B16A16: - { - guint16 pixels[4] = { - CLAMP (color->red * 65535.f + 0.5f, 0, 65535.f), - CLAMP (color->green * 65535.f + 0.5f, 0, 65535.f), - CLAMP (color->blue * 65535.f + 0.5f, 0, 65535.f), - CLAMP (color->alpha * 65535.f + 0.5f, 0, 65535.f), - }; - memcpy (data, pixels, 4 * sizeof (guint16)); - } - break; - case GDK_MEMORY_R16G16B16_FLOAT: - { - guint16 pixels[3] = { - float_to_half_one (color->red * color->alpha), - float_to_half_one (color->green * color->alpha), - float_to_half_one (color->blue * color->alpha) - }; - memcpy (data, pixels, 3 * sizeof (guint16)); - } - break; - case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED: - { - guint16 pixels[4] = { - float_to_half_one (color->red * color->alpha), - float_to_half_one (color->green * color->alpha), - float_to_half_one (color->blue * color->alpha), - float_to_half_one (color->alpha) - }; - memcpy (data, pixels, 4 * sizeof (guint16)); - } - break; - case GDK_MEMORY_R16G16B16A16_FLOAT: - { - guint16 pixels[4] = { - float_to_half_one (color->red), - float_to_half_one (color->green), - float_to_half_one (color->blue), - float_to_half_one (color->alpha) - }; - memcpy (data, pixels, 4 * sizeof (guint16)); - } - break; - case GDK_MEMORY_R32G32B32_FLOAT: - { - float pixels[3] = { - color->red * color->alpha, - color->green * color->alpha, - color->blue * color->alpha - }; - memcpy (data, pixels, 3 * sizeof (float)); - } - break; - case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED: - { - float pixels[4] = { - color->red * color->alpha, - color->green * color->alpha, - color->blue * color->alpha, - color->alpha - }; - memcpy (data, pixels, 4 * sizeof (float)); - } - break; - case GDK_MEMORY_R32G32B32A32_FLOAT: - { - float pixels[4] = { - color->red, - color->green, - color->blue, - color->alpha - }; - memcpy (data, pixels, 4 * sizeof (float)); - } - break; - case GDK_MEMORY_G8A8_PREMULTIPLIED: - { - data[0] = CLAMP (color_gray (color) * color->alpha * 255.f + 0.5f, 0.f, 255.f); - data[1] = CLAMP (color->alpha * 255.f + 0.5f, 0.f, 255.f); - } - break; - case GDK_MEMORY_G8A8: - { - data[0] = CLAMP (color_gray (color) * 255.f + 0.5f, 0.f, 255.f); - data[1] = CLAMP (color->alpha * 255.f + 0.5f, 0.f, 255.f); - } - break; - case GDK_MEMORY_G8: - { - *data = CLAMP (color_gray (color) * color->alpha * 255.f + 0.5f, 0.f, 255.f); - } - break; - case GDK_MEMORY_G16A16_PREMULTIPLIED: - { - guint16 pixels[2] = { - CLAMP (color_gray (color) * color->alpha * 65535.f + 0.5f, 0.f, 65535.f), - CLAMP (color->alpha * 65535.f + 0.5f, 0.f, 65535.f), - }; - memcpy (data, pixels, 2 * sizeof (guint16)); - } - break; - case GDK_MEMORY_G16A16: - { - guint16 pixels[2] = { - CLAMP (color_gray (color) * 65535.f + 0.5f, 0.f, 65535.f), - CLAMP (color->alpha * 65535.f + 0.5f, 0.f, 65535.f), - }; - memcpy (data, pixels, 2 * sizeof (guint16)); - } - break; - case GDK_MEMORY_G16: - { - guint16 pixel = CLAMP (color_gray (color) * color->alpha * 65535.f + 0.5f, 0.f, 65535.f); - memcpy (data, &pixel, sizeof (guint16)); - } - break; - case GDK_MEMORY_A8: - { - *data = CLAMP (color->alpha * 255.f + 0.5f, 0.f, 255.f); - } - break; - case GDK_MEMORY_A16: - { - guint16 pixel = CLAMP (color->alpha * 65535.f, 0.f, 65535.f); - memcpy (data, &pixel, sizeof (guint16)); - } - break; - case GDK_MEMORY_A16_FLOAT: - { - guint16 pixel = float_to_half_one (color->alpha); - memcpy (data, &pixel, sizeof (guint16)); - } - break; - case GDK_MEMORY_A32_FLOAT: - { - memcpy (data, &color->alpha, sizeof (float)); - } - break; - case GDK_MEMORY_N_FORMATS: - default: - g_assert_not_reached (); - break; - } -} - -static void -texture_builder_fill (TextureBuilder *builder, - const GdkRGBA *color) -{ - int x, y; - for (y = 0; y < builder->height; y++) - for (x = 0; x < builder->width; x++) - texture_builder_set_pixel (builder, x, y, color); -} - static void compare_textures (GdkTexture *texture1, GdkTexture *texture2,