[PATCH 05/12] compositor: Track damage properly for overlapping outputs

Xiong Zhang xiong.y.zhang at intel.com
Fri Mar 7 00:27:23 PST 2014


From: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira at intel.com>

The assumption that there are no overlapping outputs allows damage to
be kept in a compositor-wide region that is cleared by the backends
after output repaint. When outputs overlap, however, the repaint of
one output clears the damage for the overlapping region before it is
seen during the repaint of another output.

To fix this problem, this patch decouples the primary plane damage from
output damage. During repaint of any output, all primary plane damage is
processed and pushed to an output specific damage region. The backends
clear only the damage of the output being repainted, without affecting
any other overlapping output.

Signed-off-by: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira at intel.com>
---
 src/compositor-drm.c      |  4 ++--
 src/compositor-fbdev.c    |  8 ++++----
 src/compositor-headless.c |  4 ++--
 src/compositor-rdp.c      |  4 ++--
 src/compositor-rpi.c      |  5 ++---
 src/compositor-wayland.c  |  8 ++++----
 src/compositor-x11.c      |  8 ++++----
 src/compositor.c          | 26 +++++++++++++++++++++++---
 src/compositor.h          |  1 +
 9 files changed, 44 insertions(+), 24 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 6109cec..78292a6 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -567,8 +567,8 @@ drm_output_render(struct drm_output *output, pixman_region32_t *damage)
 	else
 		drm_output_render_gl(output, damage);
 
-	pixman_region32_subtract(&c->base.primary_plane.damage,
-				 &c->base.primary_plane.damage, damage);
+	pixman_region32_subtract(&output->base.damage,
+				 &output->base.damage, damage);
 }
 
 static void
diff --git a/src/compositor-fbdev.c b/src/compositor-fbdev.c
index 3eaa57b..0c9625e 100644
--- a/src/compositor-fbdev.c
+++ b/src/compositor-fbdev.c
@@ -182,8 +182,8 @@ fbdev_output_repaint_pixman(struct weston_output *base, pixman_region32_t *damag
 	}
 
 	/* Update the damage region. */
-	pixman_region32_subtract(&ec->primary_plane.damage,
-	                         &ec->primary_plane.damage, damage);
+	pixman_region32_subtract(&output->base.damage,
+				 &output->base.damage, damage);
 
 	/* Schedule the end of the frame. We do not sync this to the frame
 	 * buffer clock because users who want that should be using the DRM
@@ -208,8 +208,8 @@ fbdev_output_repaint(struct weston_output *base, pixman_region32_t *damage)
 	} else {
 		ec->renderer->repaint_output(base, damage);
 		/* Update the damage region. */
-		pixman_region32_subtract(&ec->primary_plane.damage,
-	                         &ec->primary_plane.damage, damage);
+		pixman_region32_subtract(&output->base.damage,
+					 &output->base.damage, damage);
 
 		wl_event_source_timer_update(output->finish_frame_timer,
 	                             1000000 / output->mode.refresh);
diff --git a/src/compositor-headless.c b/src/compositor-headless.c
index a07fd49..52a2aec 100644
--- a/src/compositor-headless.c
+++ b/src/compositor-headless.c
@@ -69,8 +69,8 @@ headless_output_repaint(struct weston_output *output_base,
 
 	ec->renderer->repaint_output(&output->base, damage);
 
-	pixman_region32_subtract(&ec->primary_plane.damage,
-				 &ec->primary_plane.damage, damage);
+	pixman_region32_subtract(&output->base.damage,
+				 &output->base.damage, damage);
 
 	wl_event_source_timer_update(output->finish_frame_timer, 16);
 
diff --git a/src/compositor-rdp.c b/src/compositor-rdp.c
index a6c192b..cc8a839 100644
--- a/src/compositor-rdp.c
+++ b/src/compositor-rdp.c
@@ -328,8 +328,8 @@ rdp_output_repaint(struct weston_output *output_base, pixman_region32_t *damage)
 		}
 	}
 
-	pixman_region32_subtract(&ec->primary_plane.damage,
-				 &ec->primary_plane.damage, damage);
+	pixman_region32_subtract(&output->base.damage,
+				 &output->base.damage, damage);
 
 	wl_event_source_timer_update(output->finish_frame_timer, 16);
 	return 0;
diff --git a/src/compositor-rpi.c b/src/compositor-rpi.c
index 8dc12d1..6b0f062 100644
--- a/src/compositor-rpi.c
+++ b/src/compositor-rpi.c
@@ -230,7 +230,6 @@ rpi_output_repaint(struct weston_output *base, pixman_region32_t *damage)
 {
 	struct rpi_output *output = to_rpi_output(base);
 	struct rpi_compositor *compositor = output->compositor;
-	struct weston_plane *primary_plane = &compositor->base.primary_plane;
 	DISPMANX_UPDATE_HANDLE_T update;
 
 	DBG("frame update start\n");
@@ -243,8 +242,8 @@ rpi_output_repaint(struct weston_output *base, pixman_region32_t *damage)
 	rpi_renderer_set_update_handle(&output->base, update);
 	compositor->base.renderer->repaint_output(&output->base, damage);
 
-	pixman_region32_subtract(&primary_plane->damage,
-				 &primary_plane->damage, damage);
+	pixman_region32_subtract(&output->base.damage,
+				 &output->base.damage, damage);
 
 	/* schedule callback to rpi_output_update_complete() */
 	rpi_dispmanx_update_submit(update, output);
diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c
index a850dab..dc91285 100644
--- a/src/compositor-wayland.c
+++ b/src/compositor-wayland.c
@@ -405,8 +405,8 @@ wayland_output_repaint_gl(struct weston_output *output_base,
 
 	ec->renderer->repaint_output(&output->base, damage);
 
-	pixman_region32_subtract(&ec->primary_plane.damage,
-				 &ec->primary_plane.damage, damage);
+	pixman_region32_subtract(&output->base.damage,
+				 &output->base.damage, damage);
 	return 0;
 }
 
@@ -533,8 +533,8 @@ wayland_output_repaint_pixman(struct weston_output *output_base,
 	pixman_region32_init(&sb->damage);
 	sb->frame_damaged = 0;
 
-	pixman_region32_subtract(&c->base.primary_plane.damage,
-				 &c->base.primary_plane.damage, damage);
+	pixman_region32_subtract(&output->base.damage,
+				 &output->base.damage, damage);
 	return 0;
 }
 
diff --git a/src/compositor-x11.c b/src/compositor-x11.c
index 6c3eb15..099e774 100644
--- a/src/compositor-x11.c
+++ b/src/compositor-x11.c
@@ -355,8 +355,8 @@ x11_output_repaint_gl(struct weston_output *output_base,
 
 	ec->renderer->repaint_output(output_base, damage);
 
-	pixman_region32_subtract(&ec->primary_plane.damage,
-				 &ec->primary_plane.damage, damage);
+	pixman_region32_subtract(&output->base.damage,
+				 &output->base.damage, damage);
 
 	wl_event_source_timer_update(output->finish_frame_timer, 10);
 	return 0;
@@ -427,8 +427,8 @@ x11_output_repaint_shm(struct weston_output *output_base,
 	pixman_renderer_output_set_buffer(output_base, output->hw_surface);
 	ec->renderer->repaint_output(output_base, damage);
 
-	pixman_region32_subtract(&ec->primary_plane.damage,
-				 &ec->primary_plane.damage, damage);
+	pixman_region32_subtract(&output->base.damage,
+				 &output->base.damage, damage);
 	set_clip_for_output(output_base, damage);
 	cookie = xcb_shm_put_image_checked(c->conn, output->window, output->gc,
 					pixman_image_get_width(output->hw_surface),
diff --git a/src/compositor.c b/src/compositor.c
index 524e24a..6aff7ab 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -1544,8 +1544,22 @@ view_accumulate_damage(struct weston_view *view,
 }
 
 static void
+output_update_damage(struct weston_output *output)
+{
+	struct weston_compositor *ec = output->compositor;
+	pixman_region32_t new_damage;
+
+	pixman_region32_init(&new_damage);
+	pixman_region32_intersect(&new_damage,
+				  &ec->primary_plane.damage, &output->region);
+	pixman_region32_union(&output->damage, &output->damage, &new_damage);
+	pixman_region32_fini(&new_damage);
+}
+
+static void
 compositor_accumulate_damage(struct weston_compositor *ec)
 {
+	struct weston_output *output;
 	struct weston_plane *plane;
 	struct weston_view *ev;
 	pixman_region32_t opaque, clip;
@@ -1570,6 +1584,12 @@ compositor_accumulate_damage(struct weston_compositor *ec)
 
 	pixman_region32_fini(&clip);
 
+	wl_list_for_each(output, &ec->output_list, link)
+		output_update_damage(output);
+
+	pixman_region32_fini(&ec->primary_plane.damage);
+	pixman_region32_init(&ec->primary_plane.damage);
+
 	wl_list_for_each(ev, &ec->view_list, link)
 		ev->surface->touched = 0;
 
@@ -1749,10 +1769,8 @@ weston_output_repaint(struct weston_output *output, uint32_t msecs)
 	compositor_accumulate_damage(ec);
 
 	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);
+				 &output->damage, &ec->primary_plane.clip);
 
 	if (output->dirty)
 		weston_output_update_matrix(output);
@@ -3084,6 +3102,7 @@ weston_output_destroy(struct weston_output *output)
 	free(output->name);
 	pixman_region32_fini(&output->region);
 	pixman_region32_fini(&output->previous_damage);
+	pixman_region32_fini(&output->damage);
 	output->compositor->output_id_pool &= ~(1 << output->id);
 
 	wl_global_destroy(output->global);
@@ -3216,6 +3235,7 @@ weston_output_init_geometry(struct weston_output *output, int x, int y)
 	output->x = x;
 	output->y = y;
 
+	pixman_region32_init(&output->damage);
 	pixman_region32_init(&output->previous_damage);
 	pixman_region32_init_rect(&output->region, x, y,
 				  output->width,
diff --git a/src/compositor.h b/src/compositor.h
index e3412a1..6cfd09c 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -187,6 +187,7 @@ struct weston_output {
 	int32_t x, y, width, height;
 	int32_t mm_width, mm_height;
 	pixman_region32_t region;
+	pixman_region32_t damage;
 	pixman_region32_t previous_damage;
 	int repaint_needed;
 	int repaint_scheduled;
-- 
1.8.3.2



More information about the wayland-devel mailing list