From 392977d670fd55e921f02a981174511aa6b32848 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 18 Nov 2023 08:18:29 -0500 Subject: [PATCH 1/7] offload tests: fix output --- testsuite/gsk/offload.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/gsk/offload.c b/testsuite/gsk/offload.c index b93fc1583b..ffb5d86417 100644 --- a/testsuite/gsk/offload.c +++ b/testsuite/gsk/offload.c @@ -192,7 +192,7 @@ collect_offload_info (GdkSurface *surface, if (info->place_above) g_snprintf (above, sizeof (above), "%d", - GPOINTER_TO_INT (g_object_get_data (G_OBJECT (subsurface), "pos"))); + GPOINTER_TO_INT (g_object_get_data (G_OBJECT (info->place_above), "pos"))); else g_snprintf (above, sizeof (above), "-"); From b4ae2377b35f4bce0491289d4bacdf0d0f8533a6 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 18 Nov 2023 08:13:36 -0500 Subject: [PATCH 2/7] offload tests: Make --verbose work When passing a directory via G_TEST_SRCDIR, still pay attention to --verbose, and print out each file thats tests. This lets us quickly pin down which test fails. --- testsuite/gsk/offload.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/testsuite/gsk/offload.c b/testsuite/gsk/offload.c index ffb5d86417..415f67ac3c 100644 --- a/testsuite/gsk/offload.c +++ b/testsuite/gsk/offload.c @@ -488,6 +488,9 @@ parse_node_file (GFile *file, const char *generate) static gboolean test_file (GFile *file) { + if (g_test_verbose ()) + g_test_message ("%s", g_file_peek_path (file)); + return parse_node_file (file, FALSE); } @@ -599,13 +602,27 @@ main (int argc, char **argv) success = TRUE; - for (i = 1; i < argc; i++) + if (argc > 1) { - GFile *file = g_file_new_for_commandline_arg (argv[i]); + for (i = 1; i < argc; i++) + { + GFile *file = g_file_new_for_commandline_arg (argv[i]); - success &= test_file (file); + success &= test_file (file); - g_object_unref (file); + g_object_unref (file); + } + } + else + { + const char *basedir; + GFile *dir; + + basedir = g_test_get_dir (G_TEST_DIST); + dir = g_file_new_for_path (basedir); + success = test_files_in_directory (dir); + + g_object_unref (dir); } } From 00a63a9fcfce9cb38d817a70bc1a5c544af06e0c Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 18 Nov 2023 08:14:49 -0500 Subject: [PATCH 3/7] offload tests: Fix the simple test This was expecting the wrong 'above'. Oops. --- testsuite/gsk/offload/simple.offload | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/gsk/offload/simple.offload b/testsuite/gsk/offload/simple.offload index 4ace2b1ab6..a0ddad115e 100644 --- a/testsuite/gsk/offload/simple.offload +++ b/testsuite/gsk/offload/simple.offload @@ -1,3 +1,3 @@ 0: offloaded, above: -, texture: 13x17, rect: 20 20 50 50 -1: offloaded, raised, above: 1, texture: 10x21, rect: 0 100 500 500 +1: offloaded, raised, above: 0, texture: 10x21, rect: 0 100 500 500 2: not offloaded From f9fd78b67ef267acd6d55dddcb5b28666ad362ca Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 18 Nov 2023 01:44:58 -0500 Subject: [PATCH 4/7] offload: Keep was-raised for each subsurface We need this information for proper diffing. --- gsk/gskoffload.c | 19 +++++++++++++------ gsk/gskoffloadprivate.h | 6 +++++- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/gsk/gskoffload.c b/gsk/gskoffload.c index 8b659d051f..897078bd86 100644 --- a/gsk/gskoffload.c +++ b/gsk/gskoffload.c @@ -53,7 +53,6 @@ struct _GskOffload Clip *current_clip; GskOffloadInfo *last_info; - gboolean can_raise; }; static GdkTexture * @@ -347,7 +346,7 @@ visit_node (GskOffload *self, { gboolean has_clip; - if (self->last_info && self->can_raise) + if (self->last_info && self->last_info->can_raise) { graphene_rect_t transformed_bounds; @@ -366,7 +365,7 @@ visit_node (GskOffload *self, "Can't raise subsurface %p because a %s overlaps", self->last_info->subsurface, g_type_name_from_instance ((GTypeInstance *) node)); - self->can_raise = FALSE; + self->last_info->can_raise = FALSE; } } } @@ -541,10 +540,16 @@ complex_clip: if (info->texture) { info->can_offload = TRUE; + info->can_raise = TRUE; transform_bounds (self, &node->bounds, &info->rect); - info->place_above = self->last_info ? self->last_info->subsurface : NULL; + if (self->last_info) + { + self->last_info->can_raise = !gsk_rect_intersects (&self->last_info->rect, &info->rect); + info->place_above = self->last_info->subsurface; + } + else + info->place_above = NULL; self->last_info = info; - self->can_raise = TRUE; } } } @@ -583,6 +588,7 @@ gsk_offload_new (GdkSurface *surface, GskOffloadInfo *info = &self->subsurfaces[i]; info->subsurface = gdk_surface_get_subsurface (self->surface, i); info->was_offloaded = gdk_subsurface_get_texture (info->subsurface) != NULL; + info->was_above = gdk_subsurface_is_above_parent (info->subsurface); /* Stack them all below, initially */ gdk_subsurface_place_below (info->subsurface, NULL); } @@ -622,10 +628,11 @@ gsk_offload_new (GdkSurface *surface, } } - if (self->can_raise && self->last_info) + if (self->last_info && self->last_info->can_raise) { GDK_DISPLAY_DEBUG (display, OFFLOAD, "Raising subsurface %p", self->last_info->subsurface); gdk_subsurface_place_above (self->last_info->subsurface, NULL); + self->last_info->is_above = TRUE; } return self; diff --git a/gsk/gskoffloadprivate.h b/gsk/gskoffloadprivate.h index 495c965bc5..36da81974d 100644 --- a/gsk/gskoffloadprivate.h +++ b/gsk/gskoffloadprivate.h @@ -32,9 +32,14 @@ typedef struct GdkTexture *texture; GdkSubsurface *place_above; graphene_rect_t rect; + guint was_offloaded : 1; guint can_offload : 1; guint is_offloaded : 1; + + guint was_above : 1; + guint can_raise : 1; + guint is_above : 1; } GskOffloadInfo; GskOffload * gsk_offload_new (GdkSurface *surface, @@ -49,4 +54,3 @@ gboolean gsk_offload_subsurface_was_offloaded (GskOffload *self, gboolean gsk_offload_subsurface_is_offloaded (GskOffload *self, GdkSubsurface *subsurface); - From c57245b73c40f8095cb66e1e1d1773c05b3e2bde Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 18 Nov 2023 02:16:36 -0500 Subject: [PATCH 5/7] diff: Take above-ness into account We need to include the full area if a subsurface above-ness changes, since we only punch holes if it is above. Fixes: #6214 --- gsk/gskrendernodeimpl.c | 46 +++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c index acc4b03875..9a0d765216 100644 --- a/gsk/gskrendernodeimpl.c +++ b/gsk/gskrendernodeimpl.c @@ -6717,27 +6717,37 @@ gsk_subsurface_node_diff (GskRenderNode *node1, { GskSubsurfaceNode *self1 = (GskSubsurfaceNode *) node1; GskSubsurfaceNode *self2 = (GskSubsurfaceNode *) node2; + GskOffloadInfo *info1, *info2; - if (data->offload) + if (!data->offload) { - /* Include the full area if the offload status changed. */ - if (gsk_offload_subsurface_was_offloaded (data->offload, self1->subsurface) != - gsk_offload_subsurface_is_offloaded (data->offload, self1->subsurface)) - { - gsk_render_node_diff_impossible (node1, node2, data); - } - else if (gsk_offload_subsurface_is_offloaded (data->offload, self1->subsurface)) - { - if (!gsk_rect_equal (&node1->bounds, &node2->bounds)) - gsk_render_node_diff_impossible (node1, node2, data); - } - else - { - gsk_render_node_data_diff (self1->child, self2->child, data); - } + gsk_render_node_data_diff (self1->child, self2->child, data); + return; + } + + info1 = gsk_offload_get_subsurface_info (data->offload, self1->subsurface); + info2 = gsk_offload_get_subsurface_info (data->offload, self2->subsurface); + + if (!info1 || !info2) + { + gsk_render_node_data_diff (self1->child, self2->child, data); + return; + } + + if (info1->is_offloaded != info2->is_offloaded || + info1->is_above != info2->is_above) + { + gsk_render_node_diff_impossible (node1, node2, data); + } + else if (info1->is_offloaded && !info1->is_above && + !gsk_rect_equal (&info1->rect, &info2->rect)) + { + gsk_render_node_diff_impossible (node1, node2, data); + } + else if (!info1->is_offloaded) + { + gsk_render_node_data_diff (self1->child, self2->child, data); } - else - gsk_render_node_data_diff (self1->child, self2->child, data); } static void From ef6ed3185316ce6375743f7a6fea7a9750e48acf Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 18 Nov 2023 02:03:34 -0500 Subject: [PATCH 6/7] offload: Drop unused api --- gsk/gskoffload.c | 24 ------------------------ gsk/gskoffloadprivate.h | 6 ------ 2 files changed, 30 deletions(-) diff --git a/gsk/gskoffload.c b/gsk/gskoffload.c index 897078bd86..da4a4dac78 100644 --- a/gsk/gskoffload.c +++ b/gsk/gskoffload.c @@ -651,27 +651,3 @@ gsk_offload_get_subsurface_info (GskOffload *self, { return find_subsurface_info (self, subsurface); } - -gboolean -gsk_offload_subsurface_was_offloaded (GskOffload *self, - GdkSubsurface *subsurface) -{ - GskOffloadInfo *info = find_subsurface_info (self, subsurface); - - if (!info) - return FALSE; - - return info->was_offloaded; -} - -gboolean -gsk_offload_subsurface_is_offloaded (GskOffload *self, - GdkSubsurface *subsurface) -{ - GskOffloadInfo *info = find_subsurface_info (self, subsurface); - - if (!info) - return FALSE; - - return info->is_offloaded; -} diff --git a/gsk/gskoffloadprivate.h b/gsk/gskoffloadprivate.h index 36da81974d..c1fb8d97f6 100644 --- a/gsk/gskoffloadprivate.h +++ b/gsk/gskoffloadprivate.h @@ -48,9 +48,3 @@ void gsk_offload_free (GskOffload *self); GskOffloadInfo * gsk_offload_get_subsurface_info (GskOffload *self, GdkSubsurface *subsurface); - -gboolean gsk_offload_subsurface_was_offloaded (GskOffload *self, - GdkSubsurface *subsurface); - -gboolean gsk_offload_subsurface_is_offloaded (GskOffload *self, - GdkSubsurface *subsurface); From fb969f543199bdd48ad5849faaea23b1d3f61013 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 18 Nov 2023 02:36:50 -0500 Subject: [PATCH 7/7] offload: Raise all subsurfaces that can be If two subsurfaces don't overlap and aren't otherwise obstructed, we can just raise them both. Tests included. --- gsk/gskoffload.c | 55 +++++++++++------------ testsuite/gsk/offload/sidebyside.diff | 2 + testsuite/gsk/offload/sidebyside.node | 20 +++++++++ testsuite/gsk/offload/sidebyside.node2 | 20 +++++++++ testsuite/gsk/offload/sidebyside.offload | 2 + testsuite/gsk/offload/sidebyside.offload2 | 2 + 6 files changed, 73 insertions(+), 28 deletions(-) create mode 100644 testsuite/gsk/offload/sidebyside.diff create mode 100644 testsuite/gsk/offload/sidebyside.node create mode 100644 testsuite/gsk/offload/sidebyside.node2 create mode 100644 testsuite/gsk/offload/sidebyside.offload create mode 100644 testsuite/gsk/offload/sidebyside.offload2 diff --git a/gsk/gskoffload.c b/gsk/gskoffload.c index da4a4dac78..101027b83a 100644 --- a/gsk/gskoffload.c +++ b/gsk/gskoffload.c @@ -346,26 +346,31 @@ visit_node (GskOffload *self, { gboolean has_clip; - if (self->last_info && self->last_info->can_raise) + for (gsize i = 0; i < self->n_subsurfaces; i++) { - graphene_rect_t transformed_bounds; + GskOffloadInfo *info = &self->subsurfaces[i]; - transform_bounds (self, &node->bounds, &transformed_bounds); - if (gsk_rect_intersects (&transformed_bounds, &self->last_info->rect)) + if (info->can_raise) { - GskRenderNodeType type = GSK_RENDER_NODE_TYPE (node); + graphene_rect_t transformed_bounds; - if (type != GSK_CONTAINER_NODE && - type != GSK_TRANSFORM_NODE && - type != GSK_CLIP_NODE && - type != GSK_ROUNDED_CLIP_NODE && - type != GSK_DEBUG_NODE) + transform_bounds (self, &node->bounds, &transformed_bounds); + if (gsk_rect_intersects (&transformed_bounds, &info->rect)) { - GDK_DISPLAY_DEBUG (gdk_surface_get_display (self->surface), OFFLOAD, - "Can't raise subsurface %p because a %s overlaps", - self->last_info->subsurface, - g_type_name_from_instance ((GTypeInstance *) node)); - self->last_info->can_raise = FALSE; + GskRenderNodeType type = GSK_RENDER_NODE_TYPE (node); + + if (type != GSK_CONTAINER_NODE && + type != GSK_TRANSFORM_NODE && + type != GSK_CLIP_NODE && + type != GSK_ROUNDED_CLIP_NODE && + type != GSK_DEBUG_NODE) + { + GDK_DISPLAY_DEBUG (gdk_surface_get_display (self->surface), OFFLOAD, + "Can't raise subsurface %p because a %s overlaps", + info->subsurface, + g_type_name_from_instance ((GTypeInstance *) node)); + info->can_raise = FALSE; + } } } } @@ -542,13 +547,7 @@ complex_clip: info->can_offload = TRUE; info->can_raise = TRUE; transform_bounds (self, &node->bounds, &info->rect); - if (self->last_info) - { - self->last_info->can_raise = !gsk_rect_intersects (&self->last_info->rect, &info->rect); - info->place_above = self->last_info->subsurface; - } - else - info->place_above = NULL; + info->place_above = self->last_info ? self->last_info->subsurface : NULL; self->last_info = info; } } @@ -626,13 +625,13 @@ gsk_offload_new (GdkSurface *surface, gdk_subsurface_detach (info->subsurface); } } - } - if (self->last_info && self->last_info->can_raise) - { - GDK_DISPLAY_DEBUG (display, OFFLOAD, "Raising subsurface %p", self->last_info->subsurface); - gdk_subsurface_place_above (self->last_info->subsurface, NULL); - self->last_info->is_above = TRUE; + if (info->can_raise) + { + GDK_DISPLAY_DEBUG (display, OFFLOAD, "Raising subsurface %p", info->subsurface); + gdk_subsurface_place_above (info->subsurface, NULL); + info->is_above = TRUE; + } } return self; diff --git a/testsuite/gsk/offload/sidebyside.diff b/testsuite/gsk/offload/sidebyside.diff new file mode 100644 index 0000000000..6705fbdfd7 --- /dev/null +++ b/testsuite/gsk/offload/sidebyside.diff @@ -0,0 +1,2 @@ +0 0 30 10 +10 10 20 10 diff --git a/testsuite/gsk/offload/sidebyside.node b/testsuite/gsk/offload/sidebyside.node new file mode 100644 index 0000000000..78916cdf88 --- /dev/null +++ b/testsuite/gsk/offload/sidebyside.node @@ -0,0 +1,20 @@ + + transform { + transform: translate(0,0); + child: subsurface { + child: texture { + bounds: 0 0 10 10; + texture: url('data:image/svg+xml;utf-8,'); + } + } + } + + transform { + transform: translate(10,0); + child: subsurface { + child: texture { + bounds: 0 0 20 20; + texture: url('data:image/svg+xml;utf-8,'); + } + } + } diff --git a/testsuite/gsk/offload/sidebyside.node2 b/testsuite/gsk/offload/sidebyside.node2 new file mode 100644 index 0000000000..7f61778590 --- /dev/null +++ b/testsuite/gsk/offload/sidebyside.node2 @@ -0,0 +1,20 @@ + + transform { + transform: translate(10, 10); + child: subsurface { + child: texture { + bounds: 0 0 10 10; + texture: url('data:image/svg+xml;utf-8,'); + } + } + } + + transform { + transform: translate(10,0); + child: subsurface { + child: texture { + bounds: 0 0 20 20; + texture: url('data:image/svg+xml;utf-8,'); + } + } + } diff --git a/testsuite/gsk/offload/sidebyside.offload b/testsuite/gsk/offload/sidebyside.offload new file mode 100644 index 0000000000..6a37a24bc9 --- /dev/null +++ b/testsuite/gsk/offload/sidebyside.offload @@ -0,0 +1,2 @@ +0: offloaded, raised, above: -, texture: 10x10, rect: 0 0 10 10 +1: offloaded, raised, above: 0, texture: 20x20, rect: 10 0 20 20 diff --git a/testsuite/gsk/offload/sidebyside.offload2 b/testsuite/gsk/offload/sidebyside.offload2 new file mode 100644 index 0000000000..3b9a8b1ec6 --- /dev/null +++ b/testsuite/gsk/offload/sidebyside.offload2 @@ -0,0 +1,2 @@ +0: offloaded, above: -, texture: 10x10, rect: 10 10 10 10 +1: offloaded, raised, above: 0, texture: 20x20, rect: 10 0 20 20