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