testsuite: Add conversion tests

Ensure we can convert from any format to any other format.
This commit is contained in:
Benjamin Otte
2023-05-29 00:37:37 +02:00
parent 788bd575d6
commit 3dc3d03a08

View File

@@ -20,6 +20,13 @@ 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;
@@ -105,6 +112,44 @@ gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
}
}
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_B8G8R8A8:
case GDK_MEMORY_A8R8G8B8:
case GDK_MEMORY_R8G8B8A8:
case GDK_MEMORY_A8B8G8R8:
return CHANNEL_UINT_8;
case GDK_MEMORY_R16G16B16:
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
case GDK_MEMORY_R16G16B16A16:
return CHANNEL_UINT_16;
case GDK_MEMORY_R16G16B16_FLOAT:
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
case GDK_MEMORY_R16G16B16A16_FLOAT:
return CHANNEL_FLOAT_16;
case GDK_MEMORY_R32G32B32_FLOAT:
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
case GDK_MEMORY_R32G32B32A32_FLOAT:
return CHANNEL_FLOAT_32;
case GDK_MEMORY_N_FORMATS:
default:
g_assert_not_reached ();
return CHANNEL_UINT_8;
}
}
static gboolean
gdk_memory_format_has_alpha (GdkMemoryFormat format)
{
@@ -272,6 +317,26 @@ decode (gconstpointer data,
return TRUE;
}
static gpointer
encode_two_formats (GdkMemoryFormat format1,
GdkMemoryFormat format2)
{
return GSIZE_TO_POINTER (format1 * GDK_MEMORY_N_FORMATS + format2);
}
static void
decode_two_formats (gconstpointer data,
GdkMemoryFormat *format1,
GdkMemoryFormat *format2)
{
gsize value = GPOINTER_TO_SIZE (data);
*format2 = value % GDK_MEMORY_N_FORMATS;
value /= GDK_MEMORY_N_FORMATS;
*format1 = value;
}
static void
texture_builder_init (TextureBuilder *builder,
GdkMemoryFormat format,
@@ -719,6 +784,16 @@ ensure_texture_format (GdkTexture *texture,
return result;
}
static void
color_make_opaque (GdkRGBA *result,
const GdkRGBA *color)
{
result->red *= color->alpha;
result->green *= color->alpha;
result->blue *= color->alpha;
result->alpha = 1.0f;
}
static void
create_random_color (GdkRGBA *color)
{
@@ -830,6 +905,70 @@ test_download_192x192 (gconstpointer data)
g_object_unref (test);
}
static void
test_conversion (gconstpointer data,
int size)
{
GdkMemoryFormat format1, format2;
GdkTexture *test1, *test2;
GdkRGBA color1, color2;
gboolean accurate;
gsize i;
decode_two_formats (data, &format1, &format2);
if (gdk_memory_format_get_channel_type (format1) == CHANNEL_FLOAT_16)
accurate = FALSE;
else
accurate = TRUE;
for (i = 0; i < N; i++)
{
/* non-premultiplied can represet GdkRGBA (1, 1, 1, 0)
* but premultiplied cannot.
* Premultiplied will always represent this as (0, 0, 0, 0)
*/
do
{
create_random_color (&color1);
}
while (color1.alpha == 0 &&
gdk_memory_format_is_premultiplied (format1) !=
gdk_memory_format_is_premultiplied (format2));
/* If the source can't handle alpha, make sure
* the target uses with the opaque version of the color.
*/
color2 = color1;
if (!gdk_memory_format_has_alpha (format1) &&
gdk_memory_format_has_alpha (format2))
color_make_opaque (&color2, &color2);
test1 = create_texture (format1, TEXTURE_METHOD_LOCAL, 1, 1, &color1);
test2 = create_texture (format2, TEXTURE_METHOD_LOCAL, 1, 1, &color2);
/* Convert the first one to the format of the 2nd */
test1 = ensure_texture_format (test1, format2);
compare_textures (test1, test2, accurate);
g_object_unref (test2);
g_object_unref (test1);
}
}
static void
test_conversion_1x1 (gconstpointer data)
{
test_conversion (data, 1);
}
static void
test_conversion_4x4 (gconstpointer data)
{
test_conversion (data, 4);
}
static void
add_test (const char *name,
GTestDataFunc func)
@@ -855,6 +994,29 @@ add_test (const char *name,
}
}
static void
add_conversion_test (const char *name,
GTestDataFunc func)
{
GdkMemoryFormat format1, format2;
GEnumClass *enum_class;
enum_class = g_type_class_ref (GDK_TYPE_MEMORY_FORMAT);
for (format1 = 0; format1 < GDK_MEMORY_N_FORMATS; format1++)
{
for (format2 = 0; format2 < GDK_MEMORY_N_FORMATS; format2++)
{
char *test_name = g_strdup_printf ("%s/%s/%s",
name,
g_enum_get_value (enum_class, format1)->value_nick,
g_enum_get_value (enum_class, format2)->value_nick);
g_test_add_data_func_full (test_name, encode_two_formats (format1, format2), func, NULL);
g_free (test_name);
}
}
}
int
main (int argc, char *argv[])
{
@@ -865,6 +1027,8 @@ main (int argc, char *argv[])
add_test ("/memorytexture/download_1x1", test_download_1x1);
add_test ("/memorytexture/download_4x4", test_download_4x4);
add_test ("/memorytexture/download_192x192", test_download_192x192);
add_conversion_test ("/memorytexture/conversion_1x1", test_conversion_1x1);
add_conversion_test ("/memorytexture/conversion_4x4", test_conversion_4x4);
gl_renderer = gsk_gl_renderer_new ();
if (!gsk_renderer_realize (gl_renderer, NULL, NULL))