[PATCH weston 3/3] compositor-drm: Fix artifacts when scanning out a client buffer

Ander Conselvan de Oliveira ander.conselvan.de.oliveira at intel.com
Wed Nov 21 05:11:38 PST 2012


Consider the following scenario: a fullscreen surface is composited for
a few frames and suddenly it is moved to a scan out plane. (This could
happen for instance if it used a big cursor and later switched to a
cursor that fits in the hw cursor overlay.) If that surface is resized
during one frame such that it can no longer be scanned out, the
following frames won't be repainted properly.

The reason for this is that the renderer's repaint function is not
called if a client buffer is scanned out. When the surface moves to the
scan out plane, the primary plane is damaged but that damage never hits
the renderer. When we switch back to compositing, the output back
buffers are dirty. One of them is updated because of the damage stored
on the gl renderer per buffer damage for the last composited frame, but
the other buffer is not redraw.

This patch fix this bug by storing all the damage coming from the
compositor when scanning out a client buffer and feeding that back to
the renderer once it switches back to compositing.
---
 src/compositor-drm.c |   22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 142faa5..2be903c 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -142,6 +142,7 @@ struct drm_output {
 	int current_cursor;
 	struct drm_fb *current, *next;
 	struct backlight *backlight;
+	pixman_region32_t pending_damage;
 };
 
 /*
@@ -382,10 +383,21 @@ drm_output_repaint(struct weston_output *output_base,
 	struct drm_mode *mode;
 	int ret = 0;
 
-	if (!output->next)
+	if (output->next) {
+		/* Since the renderer is not going to be called, save this
+		 * damage for later */
+		pixman_region32_union(&output->pending_damage,
+				      &output->pending_damage, damage);
+	} else {
+		pixman_region32_union(damage,
+				      damage, &output->pending_damage);
+		pixman_region32_fini(&output->pending_damage);
+		pixman_region32_init(&output->pending_damage);
+
 		drm_output_render(output, damage);
-	if (!output->next)
-		return;
+		if (!output->next)
+			return;
+	}
 
 	mode = container_of(output->base.current, struct drm_mode, base);
 	if (!output->current) {
@@ -837,6 +849,8 @@ drm_output_destroy(struct weston_output *output_base)
 
 	gbm_surface_destroy(output->surface);
 
+	pixman_region32_fini(&output->pending_damage);
+
 	weston_plane_release(&output->fb_plane);
 	weston_plane_release(&output->cursor_plane);
 
@@ -1404,6 +1418,8 @@ create_output_for_connector(struct drm_compositor *ec,
 	weston_plane_init(&output->cursor_plane, 0, 0);
 	weston_plane_init(&output->fb_plane, 0, 0);
 
+	pixman_region32_init(&output->pending_damage);
+
 	weston_log("Output %s, (connector %d, crtc %d)\n",
 		   output->name, output->connector_id, output->crtc_id);
 	wl_list_for_each(m, &output->base.mode_list, link)
-- 
1.7.10.4



More information about the wayland-devel mailing list