Merge branch 'subsurface-aboveness' into 'main'

offload: Keep was-raised for each subsurface

Closes #6214

See merge request GNOME/gtk!6580
This commit is contained in:
Matthias Clasen
2023-11-18 13:42:27 +00:00
10 changed files with 130 additions and 77 deletions

View File

@@ -53,7 +53,6 @@ struct _GskOffload
Clip *current_clip;
GskOffloadInfo *last_info;
gboolean can_raise;
};
static GdkTexture *
@@ -347,26 +346,31 @@ visit_node (GskOffload *self,
{
gboolean has_clip;
if (self->last_info && self->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->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;
}
}
}
}
@@ -541,10 +545,10 @@ 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;
self->last_info = info;
self->can_raise = TRUE;
}
}
}
@@ -583,6 +587,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);
}
@@ -620,12 +625,13 @@ gsk_offload_new (GdkSurface *surface,
gdk_subsurface_detach (info->subsurface);
}
}
}
if (self->can_raise && self->last_info)
{
GDK_DISPLAY_DEBUG (display, OFFLOAD, "Raising subsurface %p", self->last_info->subsurface);
gdk_subsurface_place_above (self->last_info->subsurface, NULL);
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;
@@ -644,27 +650,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;
}

View File

@@ -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,
@@ -43,10 +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);

View File

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

View File

@@ -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), "-");
@@ -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);
}
}

View File

@@ -0,0 +1,2 @@
0 0 30 10
10 10 20 10

View File

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

View File

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

View File

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

View File

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

View File

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