gpu: When transforming to simpler transform, we might be all clipped

When transforming back from a complex transform to a simpler transform,
the resulting clip might turn out to clip everything, because clips can
grow while transforming, but the scissor rect won't. So when this
process happens, we can end up with an empty clip by transforming:

1. Set a clip that also sets the scissor
2. transform in a way that grows the clip, say rotate(45)
3. modify the clip to shrink it
4. transform in a way that simplifies the transform, say another
   rotate(45)
5. Figure out that this clip and the scissor rect do no longer overlap

Catch this case and avoid drawing anything.
This commit is contained in:
Benjamin Otte 2024-08-10 02:33:45 +02:00
parent 839d797292
commit 23af1cd8ad
4 changed files with 41 additions and 0 deletions

View File

@ -1431,6 +1431,7 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
{
GskTransform *clip_transform;
float scale_x, scale_y, old_pixels, new_pixels;
graphene_rect_t scissor;
clip_transform = gsk_transform_transform (gsk_transform_translate (NULL, &self->offset), transform);
gsk_gpu_clip_init_copy (&old_clip, &self->clip);
@ -1500,6 +1501,23 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
self->modelview = gsk_transform_scale (self->modelview, 1 / scale_x, 1 / scale_y);
graphene_vec2_init (&self->scale, scale_x, scale_y);
self->offset = *graphene_point_zero ();
if (gsk_gpu_node_processor_rect_device_to_clip (self,
&GSK_RECT_INIT_CAIRO (&self->scissor),
&scissor))
{
GskGpuClip scissored_clip;
if (gsk_gpu_clip_intersect_rect (&scissored_clip, &self->clip, &scissor))
gsk_gpu_clip_init_copy (&self->clip, &scissored_clip);
if (self->clip.type == GSK_GPU_CLIP_ALL_CLIPPED)
{
self->offset = old_offset;
self->scale = old_scale;
gsk_gpu_clip_init_copy (&self->clip, &old_clip);
}
}
}
break;

View File

@ -0,0 +1,22 @@
clip {
clip: 1 -9 26 116;
child: container {
color {
bounds: -10 -10 20 120;
color: rgb(255,255,255);
}
transform {
transform: rotate(45);
child: transform {
transform: rotate(45);
child: shadow {
shadows: rgb(0,0,0) 0 1;
child: color {
bounds: 0 0 100 1;
color: rgb(255,0,0);
}
}
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 B

View File

@ -114,6 +114,7 @@ compare_render_tests = [
'mipmap-with-1x1',
'nested-rounded-clips',
'offscreen-forced-downscale',
'offscreen-forced-downscale-all-clipped',
'offscreen-fractional-translate-nogl',
'offscreen-pixel-alignment-nogl-nocairo',
'offscreen-pixel-alignment2',