compositor: Don't rely on surface->clip to cull overlay obscured damage
Before this change, surface->clip would contain the region of this the
surface that is obscured by opaque containing of other surfaces in any
plane. If a surface was obscured only by a surface in another plane and
the renderer was told to draw that region, the rendering would be
clipped because of that.
This patch changes the clip to be plane specific, so that it contains
only the region of the surface obscured by other surfaces in the same
plane. We also calculate a per plane clip, so that we don't tell the
renderer to draw regions of the primary plane that are obscured by
other planes. This damage remains on the primary plane until the its
clip changes so that they are not obscured anymore.
diff --git a/src/compositor.c b/src/compositor.c
index 50d782e..eeb57f9 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -1084,15 +1084,11 @@
surface->geometry.y - surface->plane->y);
}
- pixman_region32_subtract(&surface->damage,
- &surface->damage, &surface->plane->opaque);
+ pixman_region32_subtract(&surface->damage, &surface->damage, opaque);
pixman_region32_union(&surface->plane->damage,
&surface->plane->damage, &surface->damage);
empty_region(&surface->damage);
pixman_region32_copy(&surface->clip, opaque);
- pixman_region32_union(&surface->plane->opaque,
- &surface->plane->opaque,
- &surface->transform.opaque);
pixman_region32_union(opaque, opaque, &surface->transform.opaque);
}
@@ -1101,18 +1097,29 @@
{
struct weston_plane *plane;
struct weston_surface *es;
- pixman_region32_t opaque;
+ pixman_region32_t opaque, clip;
- pixman_region32_init(&opaque);
+ pixman_region32_init(&clip);
wl_list_for_each(plane, &ec->plane_list, link) {
- pixman_region32_fini(&plane->opaque);
- pixman_region32_init(&plane->opaque);
+ pixman_region32_copy(&plane->clip, &clip);
+
+ pixman_region32_init(&opaque);
+
+ wl_list_for_each(es, &ec->surface_list, link) {
+ if (es->plane != plane)
+ continue;
+
+ surface_accumulate_damage(es, &opaque);
+ }
+
+ pixman_region32_union(&clip, &clip, &opaque);
+ pixman_region32_fini(&opaque);
}
- wl_list_for_each(es, &ec->surface_list, link) {
- surface_accumulate_damage(es, &opaque);
+ pixman_region32_fini(&clip);
+ wl_list_for_each(es, &ec->surface_list, link) {
/* Both the renderer and the backend have seen the buffer
* by now. If renderer needs the buffer, it has its own
* reference set. If the backend wants to keep the buffer
@@ -1124,8 +1131,6 @@
if (!es->keep_buffer)
weston_buffer_reference(&es->buffer_ref, NULL);
}
-
- pixman_region32_fini(&opaque);
}
static void
@@ -1167,6 +1172,8 @@
pixman_region32_init(&output_damage);
pixman_region32_intersect(&output_damage,
&ec->primary_plane.damage, &output->region);
+ pixman_region32_subtract(&output_damage,
+ &output_damage, &ec->primary_plane.clip);
if (output->dirty)
weston_output_update_matrix(output);
@@ -1672,7 +1679,7 @@
weston_plane_init(struct weston_plane *plane, int32_t x, int32_t y)
{
pixman_region32_init(&plane->damage);
- pixman_region32_init(&plane->opaque);
+ pixman_region32_init(&plane->clip);
plane->x = x;
plane->y = y;
}
@@ -1681,7 +1688,7 @@
weston_plane_release(struct weston_plane *plane)
{
pixman_region32_fini(&plane->damage);
- pixman_region32_fini(&plane->opaque);
+ pixman_region32_fini(&plane->clip);
}
WL_EXPORT void