diff --git a/gsk/gskoffload.c b/gsk/gskoffload.c index ababf4db92..f4fc9558e7 100644 --- a/gsk/gskoffload.c +++ b/gsk/gskoffload.c @@ -58,8 +58,12 @@ struct _GskOffload static GdkTexture * find_texture_to_attach (GskOffload *self, GdkSubsurface *subsurface, - const GskRenderNode *node) + const GskRenderNode *node, + graphene_rect_t *out_clip) { + gboolean has_clip = FALSE; + graphene_rect_t clip; + for (;;) { switch ((int)GSK_RENDER_NODE_TYPE (node)) @@ -82,6 +86,7 @@ find_texture_to_attach (GskOffload *self, case GSK_TRANSFORM_NODE: { GskTransform *t = gsk_transform_node_get_transform (node); + if (gsk_transform_get_category (t) < GSK_TRANSFORM_CATEGORY_2D_AFFINE) { char *s = gsk_transform_to_string (t); @@ -91,12 +96,69 @@ find_texture_to_attach (GskOffload *self, g_free (s); return NULL; } + + if (has_clip) + { + GskTransform *inv = gsk_transform_invert (gsk_transform_ref (t)); + gsk_transform_transform_bounds (inv, &clip, &clip); + gsk_transform_unref (inv); + } + node = gsk_transform_node_get_child (node); } - break; + break; + + case GSK_CLIP_NODE: + { + const graphene_rect_t *c = gsk_clip_node_get_clip (node); + + if (has_clip) + { + if (!gsk_rect_intersection (c, &clip, &clip)) + { + GDK_DISPLAY_DEBUG (gdk_surface_get_display (self->surface), OFFLOAD, + "Can't offload subsurface %p: empty clip", subsurface); + return NULL; + } + } + else + { + clip = *c; + has_clip = TRUE; + } + + node = gsk_clip_node_get_child (node); + } + break; case GSK_TEXTURE_NODE: - return gsk_texture_node_get_texture (node); + { + GdkTexture *texture = gsk_texture_node_get_texture (node); + + if (has_clip) + { + float dx = node->bounds.origin.x; + float dy = node->bounds.origin.y; + float sx = gdk_texture_get_width (texture) / node->bounds.size.width; + float sy = gdk_texture_get_height (texture) / node->bounds.size.height; + + gsk_rect_intersection (&node->bounds, &clip, &clip); + + out_clip->origin.x = (clip.origin.x - dx) * sx; + out_clip->origin.y = (clip.origin.y - dy) * sy; + out_clip->size.width = clip.size.width * sx; + out_clip->size.height = clip.size.height * sy; + } + else + { + out_clip->origin.x = 0; + out_clip->origin.y = 0; + out_clip->size.width = gdk_texture_get_width (texture); + out_clip->size.height = gdk_texture_get_height (texture); + } + + return texture; + } default: GDK_DISPLAY_DEBUG (gdk_surface_get_display (self->surface), OFFLOAD, @@ -513,15 +575,14 @@ complex_clip: } else { - info->texture = find_texture_to_attach (self, subsurface, gsk_subsurface_node_get_child (node)); + graphene_rect_t clip; + + info->texture = find_texture_to_attach (self, subsurface, gsk_subsurface_node_get_child (node), &clip); if (info->texture) { info->can_offload = TRUE; info->can_raise = TRUE; - graphene_rect_init (&info->source, - 0, 0, - gdk_texture_get_width (info->texture), - gdk_texture_get_height (info->texture)); + info->source = clip; transform_bounds (self, &node->bounds, &info->dest); info->place_above = self->last_info ? self->last_info->subsurface : NULL; self->last_info = info; diff --git a/testsuite/gsk/meson.build b/testsuite/gsk/meson.build index 0c0a13a025..96ea08883f 100644 --- a/testsuite/gsk/meson.build +++ b/testsuite/gsk/meson.build @@ -428,6 +428,8 @@ if os_linux 'move.node', 'start_offloading.node', 'stop_offloading.node', + 'source.node', + 'nested.node', ] foreach test : offload_tests diff --git a/testsuite/gsk/offload.c b/testsuite/gsk/offload.c index f9d4809d8c..3e2b186411 100644 --- a/testsuite/gsk/offload.c +++ b/testsuite/gsk/offload.c @@ -209,6 +209,9 @@ collect_offload_info (GdkSurface *surface, g_string_append_printf (s, "texture: %dx%d, ", gdk_texture_get_width (info->texture), gdk_texture_get_height (info->texture)); + g_string_append_printf (s, "source: %g %g %g %g, ", + info->source.origin.x, info->source.origin.y, + info->source.size.width, info->source.size.height); g_string_append_printf (s, "dest: %g %g %g %g\n", info->dest.origin.x, info->dest.origin.y, info->dest.size.width, info->dest.size.height); diff --git a/testsuite/gsk/offload/deep.offload b/testsuite/gsk/offload/deep.offload index 575a62bcd8..056867698b 100644 --- a/testsuite/gsk/offload/deep.offload +++ b/testsuite/gsk/offload/deep.offload @@ -1,6 +1,6 @@ -0: offloaded, above: -, texture: 10x10, dest: 10 10 250 500 +0: offloaded, above: -, texture: 10x10, source: 0 0 10 10, dest: 10 10 250 500 1: not offloaded 2: not offloaded 3: not offloaded -4: not offloaded +4: offloaded, above: 0, texture: 10x10, source: 0 0 10 10, dest: 0 0 50 50 5: not offloaded diff --git a/testsuite/gsk/offload/deep.offload2 b/testsuite/gsk/offload/deep.offload2 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testsuite/gsk/offload/move.offload b/testsuite/gsk/offload/move.offload index 08f1762fdd..fb192980ae 100644 --- a/testsuite/gsk/offload/move.offload +++ b/testsuite/gsk/offload/move.offload @@ -1 +1 @@ -0: offloaded, raised, above: -, texture: 16x16, dest: 20 20 16 16 +0: offloaded, raised, above: -, texture: 16x16, source: 0 0 16 16, dest: 20 20 16 16 diff --git a/testsuite/gsk/offload/move.offload2 b/testsuite/gsk/offload/move.offload2 index 7079e8d16c..b656abf6a1 100644 --- a/testsuite/gsk/offload/move.offload2 +++ b/testsuite/gsk/offload/move.offload2 @@ -1 +1 @@ -0: offloaded, raised, above: -, texture: 16x16, dest: 40 40 20 20 +0: offloaded, raised, above: -, texture: 16x16, source: 0 0 16 16, dest: 40 40 20 20 diff --git a/testsuite/gsk/offload/nested.node b/testsuite/gsk/offload/nested.node new file mode 100644 index 0000000000..6255a16dd1 --- /dev/null +++ b/testsuite/gsk/offload/nested.node @@ -0,0 +1,38 @@ +subsurface { + child: transform { + transform: translate(0,100); + child: transform { + transform: scale(10, 10); + child: texture { + bounds: 0 0 10 21; + texture: url('data:image/svg+xml;utf-8,'); + } + } + } +} + +subsurface { + child: clip { + clip: 0 0 20 20; + child: clip { + clip: 5 5 200 200; + child: texture { + bounds: 0 0 40 40; + texture: url('data:image/svg+xml;utf-8,'); + } + } + } +} + +subsurface { + child: clip { + clip: 0 0 20 20; + child: transform { + transform: translate(10, 10); + child: texture { + bounds: 0 0 40 40; + texture: url('data:image/svg+xml;utf-8,'); + } + } + } +} diff --git a/testsuite/gsk/offload/nested.offload b/testsuite/gsk/offload/nested.offload new file mode 100644 index 0000000000..e3918dbe25 --- /dev/null +++ b/testsuite/gsk/offload/nested.offload @@ -0,0 +1,3 @@ +0: offloaded, raised, above: -, texture: 10x21, source: 0 0 10 21, dest: 0 100 100 210 +1: offloaded, raised, above: 0, texture: 40x40, source: 5 5 15 15, dest: 5 5 15 15 +2: offloaded, raised, above: 1, texture: 40x40, source: 0 0 10 10, dest: 10 10 10 10 diff --git a/testsuite/gsk/offload/sidebyside.offload b/testsuite/gsk/offload/sidebyside.offload index e1a8803f6f..50ace2635b 100644 --- a/testsuite/gsk/offload/sidebyside.offload +++ b/testsuite/gsk/offload/sidebyside.offload @@ -1,2 +1,2 @@ -0: offloaded, raised, above: -, texture: 10x10, dest: 0 0 10 10 -1: offloaded, raised, above: 0, texture: 20x20, dest: 10 0 20 20 +0: offloaded, raised, above: -, texture: 10x10, source: 0 0 10 10, dest: 0 0 10 10 +1: offloaded, raised, above: 0, texture: 20x20, source: 0 0 20 20, dest: 10 0 20 20 diff --git a/testsuite/gsk/offload/sidebyside.offload2 b/testsuite/gsk/offload/sidebyside.offload2 index d76ee97cdc..8673e2496b 100644 --- a/testsuite/gsk/offload/sidebyside.offload2 +++ b/testsuite/gsk/offload/sidebyside.offload2 @@ -1,2 +1,2 @@ -0: offloaded, above: -, texture: 10x10, dest: 10 10 10 10 -1: offloaded, raised, above: 0, texture: 20x20, dest: 10 0 20 20 +0: offloaded, above: -, texture: 10x10, source: 0 0 10 10, dest: 10 10 10 10 +1: offloaded, raised, above: 0, texture: 20x20, 0 0 20 20, dest: 10 0 20 20 diff --git a/testsuite/gsk/offload/simple.offload b/testsuite/gsk/offload/simple.offload index 5d7a3c73de..aec97cfaab 100644 --- a/testsuite/gsk/offload/simple.offload +++ b/testsuite/gsk/offload/simple.offload @@ -1,3 +1,3 @@ -0: offloaded, above: -, texture: 13x17, dest: 20 20 50 50 -1: offloaded, raised, above: 0, texture: 10x21, dest: 0 100 500 500 +0: offloaded, above: -, texture: 13x17, source: 0 0 13 17, dest: 20 20 50 50 +1: offloaded, raised, above: 0, texture: 10x21, source: 0 0 10 21, dest: 0 100 500 500 2: not offloaded diff --git a/testsuite/gsk/offload/source.node b/testsuite/gsk/offload/source.node new file mode 100644 index 0000000000..5a1f21ba0b --- /dev/null +++ b/testsuite/gsk/offload/source.node @@ -0,0 +1,12 @@ +subsurface { + child: transform { + transform: scale(1); + child: clip { + clip: 4 4 40 40; + child: texture { + bounds: 0 0 48 48; + texture: url('data:image/svg+xml;utf-8,'); + } + } + } +} diff --git a/testsuite/gsk/offload/source.offload b/testsuite/gsk/offload/source.offload new file mode 100644 index 0000000000..c7bed309b3 --- /dev/null +++ b/testsuite/gsk/offload/source.offload @@ -0,0 +1 @@ +0: offloaded, raised, above: -, texture: 24x24, source: 2 2 20 20, dest: 4 4 40 40 diff --git a/testsuite/gsk/offload/start_offloading.node b/testsuite/gsk/offload/start_offloading.node index 85ac549000..f6f97c592e 100644 --- a/testsuite/gsk/offload/start_offloading.node +++ b/testsuite/gsk/offload/start_offloading.node @@ -2,7 +2,7 @@ subsurface { child: clip { clip: 0 0 200 200; child: transform { - transform: translate(16, 16); + transform: rotate(4); child: texture { texture: url('data:image/svg+xml;utf-8,'); bounds: 0 0 16 16; diff --git a/testsuite/gsk/offload/start_offloading.node2 b/testsuite/gsk/offload/start_offloading.node2 index 217c4b6811..85ac549000 100644 --- a/testsuite/gsk/offload/start_offloading.node2 +++ b/testsuite/gsk/offload/start_offloading.node2 @@ -1,6 +1,12 @@ subsurface { - child: texture { - texture: url('data:image/svg+xml;utf-8,'); - bounds: 0 0 16 16; + child: clip { + clip: 0 0 200 200; + child: transform { + transform: translate(16, 16); + child: texture { + texture: url('data:image/svg+xml;utf-8,'); + bounds: 0 0 16 16; + } + } } } diff --git a/testsuite/gsk/offload/start_offloading.offload2 b/testsuite/gsk/offload/start_offloading.offload2 index 5e086eafe4..59247fb74c 100644 --- a/testsuite/gsk/offload/start_offloading.offload2 +++ b/testsuite/gsk/offload/start_offloading.offload2 @@ -1 +1 @@ -0: offloaded, raised, above: -, texture: 16x16, dest: 0 0 16 16 +0: offloaded, raised, above: -, texture: 16x16, source: 0 0 16 16, dest: 16 16 16 16 diff --git a/testsuite/gsk/offload/stop_offloading.diff b/testsuite/gsk/offload/stop_offloading.diff index 039342357c..bdce052ba0 100644 --- a/testsuite/gsk/offload/stop_offloading.diff +++ b/testsuite/gsk/offload/stop_offloading.diff @@ -1,2 +1 @@ -0 0 16 16 -16 16 16 16 +15 16 17 17 diff --git a/testsuite/gsk/offload/stop_offloading.node b/testsuite/gsk/offload/stop_offloading.node index 217c4b6811..85ac549000 100644 --- a/testsuite/gsk/offload/stop_offloading.node +++ b/testsuite/gsk/offload/stop_offloading.node @@ -1,6 +1,12 @@ subsurface { - child: texture { - texture: url('data:image/svg+xml;utf-8,'); - bounds: 0 0 16 16; + child: clip { + clip: 0 0 200 200; + child: transform { + transform: translate(16, 16); + child: texture { + texture: url('data:image/svg+xml;utf-8,'); + bounds: 0 0 16 16; + } + } } } diff --git a/testsuite/gsk/offload/stop_offloading.node2 b/testsuite/gsk/offload/stop_offloading.node2 index 85ac549000..513f36be36 100644 --- a/testsuite/gsk/offload/stop_offloading.node2 +++ b/testsuite/gsk/offload/stop_offloading.node2 @@ -2,7 +2,7 @@ subsurface { child: clip { clip: 0 0 200 200; child: transform { - transform: translate(16, 16); + transform: translate(16, 16) rotate(2); child: texture { texture: url('data:image/svg+xml;utf-8,'); bounds: 0 0 16 16; diff --git a/testsuite/gsk/offload/stop_offloading.offload b/testsuite/gsk/offload/stop_offloading.offload index 5e086eafe4..59247fb74c 100644 --- a/testsuite/gsk/offload/stop_offloading.offload +++ b/testsuite/gsk/offload/stop_offloading.offload @@ -1 +1 @@ -0: offloaded, raised, above: -, texture: 16x16, dest: 0 0 16 16 +0: offloaded, raised, above: -, texture: 16x16, source: 0 0 16 16, dest: 16 16 16 16 diff --git a/testsuite/gsk/offload/transforms.offload b/testsuite/gsk/offload/transforms.offload index d4edcd258a..13de84a579 100644 --- a/testsuite/gsk/offload/transforms.offload +++ b/testsuite/gsk/offload/transforms.offload @@ -1,3 +1,3 @@ 0: not offloaded 1: not offloaded -2: offloaded, raised, above: -, texture: 16x16, dest: 1 2 50 50 +2: offloaded, raised, above: -, texture: 16x16, source: 0 0 16 16, dest: 1 2 50 50