From d7afa91023f371956b6f483497b07c1c48aecc1c Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 10 Feb 2024 21:23:42 -0500 Subject: [PATCH 1/7] gsk: Add a clip variant to compare tests This creates a random clip rect and applies it as a clip node. Currently, a bunch of the tests fail and need tracking down. --- testsuite/gsk/compare-render.c | 88 ++++++++++++++++++++++++++++++++++ testsuite/gsk/meson.build | 10 ++++ 2 files changed, 98 insertions(+) diff --git a/testsuite/gsk/compare-render.c b/testsuite/gsk/compare-render.c index c6b994fd90..7097063412 100644 --- a/testsuite/gsk/compare-render.c +++ b/testsuite/gsk/compare-render.c @@ -12,6 +12,7 @@ static gboolean rotate = FALSE; static gboolean repeat = FALSE; static gboolean mask = FALSE; static gboolean replay = FALSE; +static gboolean clip = FALSE; extern void replay_node (GskRenderNode *node, GtkSnapshot *snapshot); @@ -166,6 +167,7 @@ static const GOptionEntry options[] = { { "repeat", 0, 0, G_OPTION_ARG_NONE, &repeat, "Do repeated test", NULL }, { "mask", 0, 0, G_OPTION_ARG_NONE, &mask, "Do masked test", NULL }, { "replay", 0, 0, G_OPTION_ARG_NONE, &replay, "Do replay test", NULL }, + { "clip", 0, 0, G_OPTION_ARG_NONE, &clip, "Do clip test", NULL }, { NULL } }; @@ -234,6 +236,38 @@ apply_mask_to_pixbuf (GdkPixbuf *pixbuf) return copy; } +static void +make_random_clip (const graphene_rect_t *bounds, + cairo_rectangle_int_t *int_clip) +{ + int_clip->width = g_test_rand_int_range (1, (int) floor (bounds->size.width)); + int_clip->height = g_test_rand_int_range (1, (int) floor (bounds->size.height)); + + int_clip->x = g_test_rand_int_range ((int) ceil (bounds->origin.x), (int) floor (bounds->origin.x + bounds->size.width - int_clip->width)); + int_clip->y = g_test_rand_int_range ((int) ceil (bounds->origin.y), (int) floor (bounds->origin.y + bounds->size.height - int_clip->height)); +} + +static void +gsk_rect_from_cairo (graphene_rect_t *rect, + const cairo_rectangle_int_t *int_rect) +{ + rect->origin.x = int_rect->x; + rect->origin.y = int_rect->y; + rect->size.width = int_rect->width; + rect->size.height = int_rect->height; +} + +static GdkPixbuf * +apply_clip_to_pixbuf (GdkPixbuf *pixbuf, + const cairo_rectangle_int_t *int_clip) +{ + return gdk_pixbuf_new_subpixbuf (pixbuf, + int_clip->x, + int_clip->y, + int_clip->width, + int_clip->height); +} + /* * Non-option arguments: * 1) .node file to compare @@ -556,6 +590,60 @@ main (int argc, char **argv) gsk_render_node_unref (node2); } + if (clip) + { + GskRenderNode *node2; + GdkPixbuf *pixbuf, *pixbuf2; + graphene_rect_t bounds; + cairo_rectangle_int_t int_clip; + graphene_rect_t clip_rect; + + gsk_render_node_get_bounds (node, &bounds); + + if (bounds.size.width <= 1 || bounds.size.height <= 1) + { + g_test_skip ("Can't make a random clip"); + goto skip_clip; + } + + make_random_clip (&bounds, &int_clip); + gsk_rect_from_cairo (&clip_rect, &int_clip); + g_assert_true (graphene_rect_contains_rect (&bounds, &clip_rect)); + g_assert_true (graphene_rect_get_area (&clip_rect) != 0); + + node2 = gsk_clip_node_new (node, &clip_rect); + save_node (node2, node_file, "-clipped.node"); + + rendered_texture = gsk_renderer_render_texture (renderer, node2, NULL); + save_image (rendered_texture, node_file, "-clipped.out.png"); + + pixbuf = gdk_pixbuf_new_from_file (png_file, &error); + + int_clip.x -= (int) bounds.origin.x; + int_clip.y -= (int) bounds.origin.y; + + pixbuf2 = apply_clip_to_pixbuf (pixbuf, &int_clip); + reference_texture = gdk_texture_new_for_pixbuf (pixbuf2); + g_object_unref (pixbuf2); + g_object_unref (pixbuf); + + save_image (reference_texture, node_file, "-clipped.ref.png"); + + diff_texture = reftest_compare_textures (rendered_texture, reference_texture); + + if (diff_texture) + { + save_image (diff_texture, node_file, "-clipped.diff.png"); + g_object_unref (diff_texture); + success = FALSE; + } + + g_clear_object (&rendered_texture); + g_clear_object (&reference_texture); + gsk_render_node_unref (node2); + } + +skip_clip: gsk_render_node_unref (node); gsk_renderer_unrealize (renderer); diff --git a/testsuite/gsk/meson.build b/testsuite/gsk/meson.build index b2d3dcb5f5..6dd85fc4ff 100644 --- a/testsuite/gsk/meson.build +++ b/testsuite/gsk/meson.build @@ -286,6 +286,16 @@ foreach renderer : renderers env: test_env, suite: suites + [ 'gsk-compare-replayed-' + renderer_name ], ) + test('compare ' + renderer_name + ' ' + testname + ' clipped', compare_render, + args: [ + '--clip', + '--output', join_paths(meson.current_build_dir(), 'compare', renderer_name), + join_paths(meson.current_source_dir(), 'compare', testname + '.node'), + join_paths(meson.current_source_dir(), 'compare', testname + '.png'), + ], + env: test_env, + suite: suites + [ 'gsk-compare-clipped-' + renderer_name ], + ) endif endforeach endforeach From c40f29cb54e4a996c76fa2bc1eb2d93da71d57b1 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 11 Feb 2024 09:18:34 -0500 Subject: [PATCH 2/7] build: Drop an unused array --- testsuite/gsk/meson.build | 7 ------- 1 file changed, 7 deletions(-) diff --git a/testsuite/gsk/meson.build b/testsuite/gsk/meson.build index 6dd85fc4ff..330bd1625e 100644 --- a/testsuite/gsk/meson.build +++ b/testsuite/gsk/meson.build @@ -185,13 +185,6 @@ renderers = [ { 'name': 'vulkan' }, ] -compare_xfails = [ - # Both tests fail because of some font rendering issue - 'empty-linear-gradient', - 'unaligned-offscreen', - 'upside-down-label-nocairo', -] - compare_xfails_small_texture = [ 'big-checkerboard', 'big-checkerboard-scaled-down', From 7e9ce1b266081279f38d1de462cddfa8b502d862 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 11 Feb 2024 09:20:05 -0500 Subject: [PATCH 3/7] compare-render: Add a --plain argument This is entirely ignored, but having an argument to specify for 'run tests as-is' makes the meson code simpler. --- testsuite/gsk/compare-render.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/testsuite/gsk/compare-render.c b/testsuite/gsk/compare-render.c index 7097063412..384faf8645 100644 --- a/testsuite/gsk/compare-render.c +++ b/testsuite/gsk/compare-render.c @@ -7,6 +7,7 @@ static char *arg_output_dir = NULL; +static gboolean plain = FALSE; static gboolean flip = FALSE; static gboolean rotate = FALSE; static gboolean repeat = FALSE; @@ -162,6 +163,7 @@ deserialize_error_func (const GskParseLocation *start, static const GOptionEntry options[] = { { "output", 0, 0, G_OPTION_ARG_FILENAME, &arg_output_dir, "Directory to save image files to", "DIR" }, + { "plain", 0, 0, G_OPTION_ARG_NONE, &plain, "Run test as-is", NULL }, { "flip", 0, 0, G_OPTION_ARG_NONE, &flip, "Do flipped test", NULL }, { "rotate", 0, 0, G_OPTION_ARG_NONE, &rotate, "Do rotated test", NULL }, { "repeat", 0, 0, G_OPTION_ARG_NONE, &repeat, "Do repeated test", NULL }, From f6221835ef286ea76d8e498c8ecd0cd4044aa451 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 11 Feb 2024 09:27:24 -0500 Subject: [PATCH 4/7] build: Compactify compare test setup Make a loop over the variants we have, rather than duplicating so much code. --- testsuite/gsk/meson.build | 98 +++++++++++---------------------------- 1 file changed, 26 insertions(+), 72 deletions(-) diff --git a/testsuite/gsk/meson.build b/testsuite/gsk/meson.build index 330bd1625e..f40bc0541d 100644 --- a/testsuite/gsk/meson.build +++ b/testsuite/gsk/meson.build @@ -192,10 +192,20 @@ compare_xfails_small_texture = [ 'repeat-repeats', # only fails when rotated ] -foreach renderer : renderers - foreach testname : compare_render_tests +variants = { + 'plain': '--plain', + 'flipped': '--flip', + 'rotated': '--rotate', + 'repeated': '--repeat', + 'masked': '--mask', + 'replayed': '--replay', + 'clipped': '--clip', +} - renderer_name = renderer.get('name') +foreach renderer : renderers + renderer_name = renderer.get('name') + + foreach testname : compare_render_tests exclude_term = '-no' + renderer_name suites = [ @@ -220,75 +230,19 @@ foreach renderer : renderers if ((not testname.contains(exclude_term)) and (renderer_name != 'broadway' or broadway_enabled) and (renderer_name != 'vulkan' or have_vulkan)) - test('compare ' + renderer_name + ' ' + testname, compare_render, - args: [ - '--output', join_paths(meson.current_build_dir(), 'compare', renderer_name), - join_paths(meson.current_source_dir(), 'compare', testname + '.node'), - join_paths(meson.current_source_dir(), 'compare', testname + '.png'), - ], - env: test_env, - suite: suites, - ) - test('compare ' + renderer_name + ' ' + testname + ' flipped', compare_render, - args: [ - '--flip', - '--output', join_paths(meson.current_build_dir(), 'compare', renderer_name), - join_paths(meson.current_source_dir(), 'compare', testname + '.node'), - join_paths(meson.current_source_dir(), 'compare', testname + '.png'), - ], - env: test_env, - suite: suites + [ 'gsk-compare-flipped-' + renderer_name ], - ) - test('compare ' + renderer_name + ' ' + testname + ' repeated', compare_render, - args: [ - '--repeat', - '--output', join_paths(meson.current_build_dir(), 'compare', renderer_name), - join_paths(meson.current_source_dir(), 'compare', testname + '.node'), - join_paths(meson.current_source_dir(), 'compare', testname + '.png'), - ], - env: test_env, - suite: suites + [ 'gsk-compare-repeated-' + renderer_name ], - ) - test('compare ' + renderer_name + ' ' + testname + ' rotated', compare_render, - args: [ - '--rotate', - '--output', join_paths(meson.current_build_dir(), 'compare', renderer_name), - join_paths(meson.current_source_dir(), 'compare', testname + '.node'), - join_paths(meson.current_source_dir(), 'compare', testname + '.png'), - ], - env: test_env, - suite: suites + [ 'gsk-compare-rotated-' + renderer_name ], - ) - test('compare ' + renderer_name + ' ' + testname + ' masked', compare_render, - args: [ - '--mask', - '--output', join_paths(meson.current_build_dir(), 'compare', renderer_name), - join_paths(meson.current_source_dir(), 'compare', testname + '.node'), - join_paths(meson.current_source_dir(), 'compare', testname + '.png'), - ], - env: test_env, - suite: suites + [ 'gsk-compare-masked-' + renderer_name ], - ) - test('compare ' + renderer_name + ' ' + testname + ' replayed', compare_render, - args: [ - '--replay', - '--output', join_paths(meson.current_build_dir(), 'compare', renderer_name), - join_paths(meson.current_source_dir(), 'compare', testname + '.node'), - join_paths(meson.current_source_dir(), 'compare', testname + '.png'), - ], - env: test_env, - suite: suites + [ 'gsk-compare-replayed-' + renderer_name ], - ) - test('compare ' + renderer_name + ' ' + testname + ' clipped', compare_render, - args: [ - '--clip', - '--output', join_paths(meson.current_build_dir(), 'compare', renderer_name), - join_paths(meson.current_source_dir(), 'compare', testname + '.node'), - join_paths(meson.current_source_dir(), 'compare', testname + '.png'), - ], - env: test_env, - suite: suites + [ 'gsk-compare-clipped-' + renderer_name ], - ) + + foreach variant : variants.keys() + test('compare ' + renderer_name + ' ' + testname + ' ' + variant, compare_render, + args: [ + variants.get(variant), + '--output', join_paths(meson.current_build_dir(), 'compare', renderer_name), + join_paths(meson.current_source_dir(), 'compare', testname + '.node'), + join_paths(meson.current_source_dir(), 'compare', testname + '.png'), + ], + env: test_env, + suite: suites + [ 'gsk-compare-' + variant + '-' + renderer_name ], + ) + endforeach endif endforeach endforeach From bed3c6f80727d75d7d47b42359fd55c1f8ee78aa Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 11 Feb 2024 09:38:12 -0500 Subject: [PATCH 5/7] ci: Add xfails for some known issues Add xfails for failing compare tests where we have known issues, and annotate them. --- testsuite/gsk/meson.build | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/testsuite/gsk/meson.build b/testsuite/gsk/meson.build index f40bc0541d..25635eeea5 100644 --- a/testsuite/gsk/meson.build +++ b/testsuite/gsk/meson.build @@ -202,10 +202,28 @@ variants = { 'clipped': '--clip', } +compare_xfails = { + 'cairo': { 'subpixel-positioning': ['clipped'], # https://gitlab.freedesktop.org/cairo/cairo/-/issues/821 + 'outset-shadow-scale-offset': ['clipped'], # #6426 + 'glyph-cache-overflow-slices': ['clipped'], # 6427 + 'scaled-texture-scale': ['clipped'], # 6428 + }, + 'ngl': { 'shadow-offset-to-outside-clip': ['clipped'], # 6425 + 'clip-intersection-fail-opacity-nogl': ['clipped'], # 6425 + 'scaled-texture-scale': ['clipped'], # 6428 + }, + 'vulkan': { 'shadow-offset-to-outside-clip': ['clipped'], # 6425 + 'clip-intersection-fail-opacity-nogl': ['clipped'], # 6425 + 'scaled-texture-scale': ['clipped'], # 6428 + }, +} + foreach renderer : renderers renderer_name = renderer.get('name') + renderer_xfails = compare_xfails.get(renderer_name, { }) foreach testname : compare_render_tests + test_xfails = renderer_xfails.get(testname, []) exclude_term = '-no' + renderer_name suites = [ @@ -232,6 +250,10 @@ foreach renderer : renderers (renderer_name != 'vulkan' or have_vulkan)) foreach variant : variants.keys() + extra_suites = [ 'gsk-compare-' + variant + '-' + renderer_name ] + if test_xfails.contains(variant) + extra_suites += ['failing'] + endif test('compare ' + renderer_name + ' ' + testname + ' ' + variant, compare_render, args: [ variants.get(variant), @@ -240,7 +262,7 @@ foreach renderer : renderers join_paths(meson.current_source_dir(), 'compare', testname + '.png'), ], env: test_env, - suite: suites + [ 'gsk-compare-' + variant + '-' + renderer_name ], + suite: suites + extra_suites ) endforeach endif From ed605f01a2374751532778e391dbf3860c78877b Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 11 Feb 2024 11:57:55 -0500 Subject: [PATCH 6/7] testsuite: Give up on cairo for clipping tests Cairo has a number of problems with clipping, such as https://gitlab.freedesktop.org/cairo/cairo/-/issues/821 https://gitlab.gnome.org/GNOME/gtk/-/issues/6426 https://gitlab.gnome.org/GNOME/gtk/-/issues/6427 These require cairo fixes that are hard to come by, given the maintainership situation. And since these the clipping tests are randomized, such failures will pop up randomly, making it very frustrating to deal with ci. So lets focus these tests on the places where it is easier to get fixes, and run the clipping tests only for the other renderers. --- testsuite/gsk/meson.build | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/testsuite/gsk/meson.build b/testsuite/gsk/meson.build index 25635eeea5..616c33e7c1 100644 --- a/testsuite/gsk/meson.build +++ b/testsuite/gsk/meson.build @@ -203,11 +203,6 @@ variants = { } compare_xfails = { - 'cairo': { 'subpixel-positioning': ['clipped'], # https://gitlab.freedesktop.org/cairo/cairo/-/issues/821 - 'outset-shadow-scale-offset': ['clipped'], # #6426 - 'glyph-cache-overflow-slices': ['clipped'], # 6427 - 'scaled-texture-scale': ['clipped'], # 6428 - }, 'ngl': { 'shadow-offset-to-outside-clip': ['clipped'], # 6425 'clip-intersection-fail-opacity-nogl': ['clipped'], # 6425 'scaled-texture-scale': ['clipped'], # 6428 @@ -251,7 +246,7 @@ foreach renderer : renderers foreach variant : variants.keys() extra_suites = [ 'gsk-compare-' + variant + '-' + renderer_name ] - if test_xfails.contains(variant) + if test_xfails.contains(variant) or (renderer_name == 'cairo' and variant == 'clipped') extra_suites += ['failing'] endif test('compare ' + renderer_name + ' ' + testname + ' ' + variant, compare_render, From 0b34af438f60550bd0e72bb22c91d0f3b99d117c Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 11 Feb 2024 20:21:33 -0500 Subject: [PATCH 7/7] ci: Add more xfails These showed up in ci. --- testsuite/gsk/meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/testsuite/gsk/meson.build b/testsuite/gsk/meson.build index 616c33e7c1..0c0a13a025 100644 --- a/testsuite/gsk/meson.build +++ b/testsuite/gsk/meson.build @@ -206,6 +206,7 @@ compare_xfails = { 'ngl': { 'shadow-offset-to-outside-clip': ['clipped'], # 6425 'clip-intersection-fail-opacity-nogl': ['clipped'], # 6425 'scaled-texture-scale': ['clipped'], # 6428 + 'repeat-scaling': ['clipped'], # 6429 }, 'vulkan': { 'shadow-offset-to-outside-clip': ['clipped'], # 6425 'clip-intersection-fail-opacity-nogl': ['clipped'], # 6425