Compare commits

...

2 Commits

Author SHA1 Message Date
Matthias Clasen
cc57956008 offload: Fix handling of clips
When we are inside a non-representable clip, we can't offload. The
reason for this is that the renderer will offscreen due to that
clip, and then the hole we need to punch will end up in the offscreen
and not in the main surface where we need it.

Fixes: #6499
2024-03-10 19:58:19 -04:00
Matthias Clasen
1cf79ff52d Cosmetics 2024-03-10 19:58:19 -04:00

View File

@@ -38,7 +38,7 @@ typedef struct
guint is_rectilinear : 1;
guint is_fully_contained : 1;
guint is_empty : 1;
guint is_complex : 1;
guint is_complex : 1; /* Inside a non-representable clip, even if fully contained */
} Clip;
struct _GskOffload
@@ -225,10 +225,13 @@ static void
push_rect_clip (GskOffload *self,
const GskRoundedRect *rect)
{
Clip *current_clip = self->clips->data;
Clip *clip = g_new0 (Clip, 1);
clip->rect = *rect;
clip->is_rectilinear = gsk_rounded_rect_is_rectilinear (rect);
clip->is_empty = (rect->bounds.size.width == 0 || rect->bounds.size.height == 0);
clip->is_complex = current_clip && current_clip->is_complex;
self->clips = g_slist_prepend (self->clips, clip);
self->current_clip = self->clips->data;
@@ -249,6 +252,7 @@ push_contained_clip (GskOffload *self)
clip->rect = current_clip->rect;
clip->is_rectilinear = TRUE;
clip->is_fully_contained = TRUE;
clip->is_complex = current_clip && current_clip->is_complex;
self->clips = g_slist_prepend (self->clips, clip);
self->current_clip = self->clips->data;
@@ -278,6 +282,8 @@ pop_clip (GskOffload *self)
self->clips = self->clips->next;
if (self->clips)
self->current_clip = self->clips->data;
else
self->current_clip = NULL;
g_slist_free_1 (l);
g_free (clip);
@@ -454,7 +460,7 @@ visit_node (GskOffload *self,
case GSK_MASK_NODE:
case GSK_FILL_NODE:
case GSK_STROKE_NODE:
break;
break;
case GSK_CLIP_NODE:
{
@@ -515,21 +521,21 @@ visit_node (GskOffload *self,
push_empty_clip (self);
else if (result == GSK_INTERSECTION_NONEMPTY)
push_rect_clip (self, &intersection);
else if (gsk_rounded_rect_contains_rect (&self->current_clip->rect, &transformed_clip.bounds))
push_rect_clip (self, &transformed_clip);
else
goto complex_clip;
visit_node (self, gsk_rounded_clip_node_get_child (node));
pop_clip (self);
push_complex_clip (self);
}
else
{
complex_clip:
if (gsk_rounded_rect_contains_rect (&self->current_clip->rect, &transformed_clip.bounds))
push_rect_clip (self, &transformed_clip);
else
push_complex_clip (self);
visit_node (self, gsk_rounded_clip_node_get_child (node));
pop_clip (self);
}
visit_node (self, gsk_rounded_clip_node_get_child (node));
pop_clip (self);
}
break;
@@ -566,6 +572,12 @@ complex_clip:
"Can't offload subsurface %p: clipped",
subsurface);
}
else if (self->current_clip->is_complex)
{
GDK_DISPLAY_DEBUG (gdk_surface_get_display (self->surface), OFFLOAD,
"Can't offload subsurface %p: inside non-representable clip",
subsurface);
}
else if (self->transforms &&
gsk_transform_get_category ((GskTransform *)self->transforms->data) < GSK_TRANSFORM_CATEGORY_2D_AFFINE)
{
@@ -594,7 +606,7 @@ complex_clip:
case GSK_NOT_A_RENDER_NODE:
default:
g_assert_not_reached ();
break;
break;
}
if (has_clip)