offload: Find and use source rectangle

Look for nodes like subsurface { clip { texture {} } }, and use
the clip to provide a source rectangle for subsetting the texture.

Update affected tests, and add a new one.
This commit is contained in:
Matthias Clasen 2024-01-30 21:48:26 -05:00
parent 9a30ea1f69
commit 1db696be79
22 changed files with 162 additions and 31 deletions

View File

@ -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;

View File

@ -428,6 +428,8 @@ if os_linux
'move.node',
'start_offloading.node',
'stop_offloading.node',
'source.node',
'nested.node',
]
foreach test : offload_tests

View File

@ -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);

View File

@ -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

View File

View File

@ -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

View File

@ -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

View File

@ -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,<svg width="10" height="21"></svg>');
}
}
}
}
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,<svg width="40" height="40"></svg>');
}
}
}
}
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,<svg width="40" height="40"></svg>');
}
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,<svg width="24" height="24"></svg>');
}
}
}
}

View File

@ -0,0 +1 @@
0: offloaded, raised, above: -, texture: 24x24, source: 2 2 20 20, dest: 4 4 40 40

View File

@ -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,<svg width="16" height="16"></svg>');
bounds: 0 0 16 16;

View File

@ -1,6 +1,12 @@
subsurface {
child: texture {
texture: url('data:image/svg+xml;utf-8,<svg width="16" height="16"></svg>');
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,<svg width="16" height="16"></svg>');
bounds: 0 0 16 16;
}
}
}
}

View File

@ -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

View File

@ -1,2 +1 @@
0 0 16 16
16 16 16 16
15 16 17 17

View File

@ -1,6 +1,12 @@
subsurface {
child: texture {
texture: url('data:image/svg+xml;utf-8,<svg width="16" height="16"></svg>');
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,<svg width="16" height="16"></svg>');
bounds: 0 0 16 16;
}
}
}
}

View File

@ -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,<svg width="16" height="16"></svg>');
bounds: 0 0 16 16;

View File

@ -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

View File

@ -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