[PATCH 3/3] compositor: unify plane and output handling

Jesse Barnes jbarnes at virtuousgeek.org
Wed Jan 25 14:00:34 PST 2012


Plane and output handling are mostly the same; they both create fbs for
display and then assign them to either the primary or one of the overlay
planes.  So unify them using a new drm_buffer_reference object, making
the plane handling code work much better.
---
 src/compositor-drm.c |  411 +++++++++++++++++++++++++++++++++++++-------------
 src/compositor.c     |   62 +++-----
 src/compositor.h     |    6 +-
 3 files changed, 336 insertions(+), 143 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 2cab9d5..e7feee2 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -67,6 +67,16 @@ struct drm_mode {
 	drmModeModeInfo mode_info;
 };
 
+struct drm_buffer_reference {
+	struct drm_compositor *compositor;
+	struct wl_buffer *buffer;
+	struct wl_listener buffer_destroy_listener;
+	struct wl_buffer *pending_buffer;
+	struct wl_listener pending_buffer_destroy_listener;
+	uint32_t fb_id;
+	uint32_t pending_fb_id;
+};
+
 struct drm_output {
 	struct weston_output   base;
 
@@ -77,12 +87,11 @@ struct drm_output {
 	uint32_t fb_id[2];
 	EGLImageKHR image[2];
 	struct gbm_bo *bo[2];
-	uint32_t current;	
+	uint32_t current;
 
 	struct wl_list sprite_list;
 
-	uint32_t fs_surf_fb_id;
-	uint32_t pending_fs_surf_fb_id;
+	struct drm_buffer_reference fb_reference;
 };
 
 /*
@@ -90,12 +99,16 @@ struct drm_output {
  * blending display contents.
  */
 struct drm_sprite {
+	struct drm_buffer_reference ref;
+
+	uint32_t fb_id;
+	uint32_t current;
+
 	struct wl_list link;
 	struct wl_list output_link;
 
 	uint32_t possible_crtcs;
 	uint32_t plane_id;
-	uint32_t fb_id;
 	uint32_t count_formats;
 
 	int32_t src_x, src_y;
@@ -106,45 +119,113 @@ struct drm_sprite {
 	uint32_t formats[];
 };
 
-/**
- * drm_queue_scanout_surface - add a surface to the pending output list
- * @output: output using scanout surface
- * @es: surface to queue
- *
- * When we queue a page flip, we need to make sure the buffer is marked
- * busy until the flip completes.  Call this function to do that for
- * buffers that will be flipped to.
- */
 static int
-drm_queue_scanout_surface(struct weston_output *output,
-			  struct weston_surface *es)
+surface_is_fullscreen(struct weston_output *output,
+		      struct weston_surface *es)
 {
-	/* assert output->pending_scanout_buffer == NULL */
-	output->pending_scanout_buffer = es->buffer;
-	output->pending_scanout_buffer->busy_count++;
+	if (es->x != output->x ||
+	    es->y != output->y ||
+	    es->width != output->current->width ||
+	    es->height != output->current->height)
+		return 0;
 
-	wl_list_insert(output->pending_scanout_buffer->resource.destroy_listener_list.prev,
-		       &output->pending_scanout_buffer_destroy_listener.link);
+	return -1;
+}
+
+static int
+surface_is_primary(struct weston_compositor *ec, struct weston_surface *es)
+{
+	struct weston_surface *primary;
 
+	primary = container_of(ec->surface_list.next, struct weston_surface,
+			       link);
+	if (es == primary)
+		return -1;
 	return 0;
 }
 
+static int
+surface_is_cursor(struct weston_compositor *ec, struct weston_surface *es)
+{
+	if (!es->buffer)
+		return -1;
+	return 0;
+}
+
+static void
+handle_buffer_destroy(struct wl_listener *listener,
+		      struct wl_resource *resource, uint32_t time)
+{
+	struct drm_buffer_reference *reference =
+		container_of(listener, struct drm_buffer_reference,
+			     buffer_destroy_listener);
+
+	reference->buffer = NULL;
+
+	if (!reference->pending_buffer)
+		weston_compositor_schedule_repaint(&reference->compositor->base);
+}
+
 static void
-drm_dequeue_scanout_surface(struct weston_output *output)
+handle_pending_buffer_destroy(struct wl_listener *listener,
+			      struct wl_resource *resource, uint32_t time)
 {
-	if (output->scanout_buffer) {
-		weston_buffer_post_release(output->scanout_buffer);
-		wl_list_remove(&output->scanout_buffer_destroy_listener.link);
-		output->scanout_buffer = NULL;
+	struct drm_buffer_reference *reference =
+		container_of(listener, struct drm_buffer_reference,
+			     pending_buffer_destroy_listener);
+
+	reference->pending_buffer = NULL;
+
+	weston_compositor_schedule_repaint(&reference->compositor->base);
+}
+
+static void
+drm_buffer_reference_queue(struct drm_buffer_reference *reference,
+			   struct wl_buffer *buffer, uint32_t fb_id)
+{
+	reference->pending_buffer = buffer;
+	reference->pending_buffer->busy_count++;
+
+	wl_list_insert(reference->pending_buffer->resource.destroy_listener_list.prev,
+		       &reference->pending_buffer_destroy_listener.link);
+	reference->pending_fb_id = fb_id;
+}
+
+static uint32_t
+drm_buffer_reference_shift(struct drm_buffer_reference *reference)
+{
+	uint32_t old_fb_id = 0;
+
+	if (reference->buffer) {
+		weston_buffer_post_release(reference->buffer);
+		wl_list_remove(&reference->buffer_destroy_listener.link);
+		reference->buffer = NULL;
+		old_fb_id = reference->fb_id;
+		reference->fb_id = 0;
 	}
 
-	if (output->pending_scanout_buffer) {
-		output->scanout_buffer = output->pending_scanout_buffer;
-		wl_list_remove(&output->pending_scanout_buffer_destroy_listener.link);
-		wl_list_insert(output->scanout_buffer->resource.destroy_listener_list.prev,
-			       &output->scanout_buffer_destroy_listener.link);
-		output->pending_scanout_buffer = NULL;
+	if (reference->pending_buffer) {
+		reference->buffer = reference->pending_buffer;
+		wl_list_remove(&reference->pending_buffer_destroy_listener.link);
+		wl_list_insert(reference->buffer->resource.destroy_listener_list.prev,
+			       &reference->buffer_destroy_listener.link);
+		reference->pending_buffer = NULL;
+		reference->fb_id = reference->pending_fb_id;
+		reference->pending_fb_id = 0;
 	}
+
+	return old_fb_id;
+}
+
+static void
+drm_buffer_reference_init(struct drm_buffer_reference *reference,
+			  struct drm_compositor *compositor)
+{
+	reference->compositor = compositor;
+
+	reference->buffer_destroy_listener.func = handle_buffer_destroy;
+	reference->pending_buffer_destroy_listener.func =
+		handle_pending_buffer_destroy;
 }
 
 static int
@@ -169,14 +250,20 @@ drm_output_present(struct weston_output *output_base)
 	struct drm_output *output = (struct drm_output *) output_base;
 	struct drm_compositor *c =
 		(struct drm_compositor *) output->base.compositor;
+	struct drm_sprite *s;
 	uint32_t fb_id = 0;
+	uint32_t flags = 0;
+	int ret, queued_sprite = 0;
 
 	glFlush();
 
+	/*
+	 * First, flip the scanout surface onto the screen.
+	 */
 	output->current ^= 1;
 
-	if (output->pending_fs_surf_fb_id != 0) {
-		fb_id = output->pending_fs_surf_fb_id;
+	if (output->fb_reference.pending_fb_id != 0) {
+		fb_id = output->fb_reference.pending_fb_id;
 	} else {
 		fb_id = output->fb_id[output->current ^ 1];
 	}
@@ -188,36 +275,93 @@ drm_output_present(struct weston_output *output_base)
 		return -1;
 	}
 
+	/*
+	 * Now, update all the sprite surfaces
+	 */
+	wl_list_for_each(s, &output->sprite_list, output_link) {
+		if (s->ref.pending_fb_id)
+			fb_id = s->ref.pending_fb_id;
+		else
+			continue;
+
+		ret = drmModeSetPlane(c->drm.fd, s->plane_id,
+				      output->crtc_id, fb_id, flags,
+				      s->dest_x, s->dest_y,
+				      s->dest_w, s->dest_h,
+				      s->src_x, s->src_y,
+				      s->src_w, s->src_h);
+		if (ret)
+			fprintf(stderr, "setplane failed: %d: %s\n",
+				ret, strerror(errno));
+		queued_sprite = 1;
+		s->fb_id = fb_id;
+	}
+
+	/*
+	 * Request a vblank event for the next seqno so we can free up
+	 * the sprite surfaces.
+	 */
+	if (queued_sprite) {
+		drmVBlank vbl = {
+			.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
+			.request.sequence = 1,
+		};
+
+		vbl.request.signal = (unsigned long)output;
+		ret = drmWaitVBlank(c->drm.fd, &vbl);
+		if (ret) {
+			fprintf(stderr, "vblank event request failed: %d: %s\n",
+				ret, strerror(errno));
+		}
+	}
+
 	return 0;
 }
 
 static void
-page_flip_handler(int fd, unsigned int frame,
-		  unsigned int sec, unsigned int usec, void *data)
+vblank_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec,
+	       void *data)
 {
 	struct drm_output *output = (struct drm_output *) data;
 	struct drm_compositor *c =
 		(struct drm_compositor *) output->base.compositor;
-	uint32_t msecs;
+	struct drm_sprite *s;
+	uint32_t old_fb_id;
 
-	if (output->fs_surf_fb_id) {
-		drmModeRmFB(c->drm.fd, output->fs_surf_fb_id);
-		output->fs_surf_fb_id = 0;
+	/* Free the FBs for the sprites */
+	wl_list_for_each(s, &output->sprite_list, output_link) {
+		old_fb_id = drm_buffer_reference_shift(&s->ref);
+		/*
+		 * Only remove the old fb here, not the current one.  If no
+		 * overlays are in use, the last one will be removed in
+		 * the disable_unused call.
+		 */
+		if (old_fb_id && old_fb_id != s->fb_id)
+			drmModeRmFB(c->drm.fd, old_fb_id);
 	}
+}
 
-	if (output->pending_fs_surf_fb_id) {
-		output->fs_surf_fb_id = output->pending_fs_surf_fb_id;
-		output->pending_fs_surf_fb_id = 0;
-	}
+static void
+page_flip_handler(int fd, unsigned int frame,
+		  unsigned int sec, unsigned int usec, void *data)
+{
+	struct drm_output *output = (struct drm_output *) data;
+	struct drm_compositor *c =
+		(struct drm_compositor *) output->base.compositor;
+	uint32_t msecs, old_fb_id;
+
+	old_fb_id = drm_buffer_reference_shift(&output->fb_reference);
+	if (old_fb_id)
+		drmModeRmFB(c->drm.fd, old_fb_id);
 
-	drm_dequeue_scanout_surface(&output->base);
 	msecs = sec * 1000 + usec / 1000;
 	weston_output_finish_frame(&output->base, msecs);
 }
 
 static int
-drm_output_prepare_scanout_surface(struct weston_output *output_base,
-				   struct weston_surface *es)
+drm_prepare_scanout_surface(struct weston_output *output_base,
+			    struct weston_surface *es,
+			    struct drm_buffer_reference *ref)
 {
 	struct drm_output *output = (struct drm_output *) output_base;
 	struct drm_compositor *c =
@@ -226,13 +370,8 @@ drm_output_prepare_scanout_surface(struct weston_output *output_base,
 	int ret;
 	uint32_t fb_id = 0;
 	struct gbm_bo *bo;
-
-	if (es->x != output->base.x ||
-	    es->y != output->base.y ||
-	    es->width != output->base.current->width ||
-	    es->height != output->base.current->height ||
-	    es->image == EGL_NO_IMAGE_KHR)
-		return -1;
+	uint32_t drm_format = DRM_FORMAT_XRGB8888, flags = 0;
+	uint32_t handles[4], pitches[4], offsets[4];
 
 	bo = gbm_bo_create_from_egl_image(c->gbm,
 					  c->base.display, es->image,
@@ -247,76 +386,127 @@ drm_output_prepare_scanout_surface(struct weston_output *output_base,
 	if (handle == 0)
 		return -1;
 
-	ret = drmModeAddFB(c->drm.fd,
-			   output->base.current->width,
-			   output->base.current->height,
-			   24, 32, stride, handle, &fb_id);
+	handles[0] = handle;
+	pitches[0] = stride;
+	offsets[0] = 0;
 
+	ret = drmModeAddFB2(c->drm.fd, es->width, es->height, drm_format,
+			    handles, pitches, offsets, &fb_id, flags);
 	if (ret)
 		return -1;
 
-	output->pending_fs_surf_fb_id = fb_id;
+	drm_buffer_reference_queue(ref, es->buffer, fb_id);
 
 	return 0;
 }
 
 static int
-drm_assign_overlay_surface(struct weston_output *output_base,
-			   struct weston_surface *es)
+drm_output_prepare_scanout_surface(struct weston_output *output_base,
+				   struct weston_surface *es)
+{
+	struct drm_output *output = (struct drm_output *) output_base;
+
+	if (!surface_is_fullscreen(output_base, es) ||
+	    es->image == EGL_NO_IMAGE_KHR)
+		return -1;
+
+	return drm_prepare_scanout_surface(output_base, es,
+					   &output->fb_reference);
+}
+
+static int
+drm_surface_format_supported(struct weston_surface *es)
+{
+	int ret = 0;
+	enum wl_shm_format format;
+
+	format = wl_shm_buffer_get_format(es->buffer);
+	switch (format) {
+	case WL_SHM_FORMAT_ARGB8888:
+	default:
+#ifdef DEBUG_PLANES
+		/*
+		 * Enable this code to test non-overlapping surfaces even
+		 * if they need alpha blending.
+		 */
+		if (es->overlapped)
+			ret = 0;
+		else
+			ret = 1;
+#endif
+		break;
+	case WL_SHM_FORMAT_XRGB8888:
+		ret = 1;
+		break;
+	}
+
+	return ret;
+}
+
+static void
+drm_disable_unused_sprites(struct weston_output *output_base)
 {
 	struct weston_compositor *ec = output_base->compositor;
 	struct drm_compositor *c =(struct drm_compositor *) ec;
 	struct drm_output *output = (struct drm_output *) output_base;
 	struct drm_sprite *s;
-	int found = 0;
-	EGLint handle, stride;
-	struct gbm_bo *bo;
-	uint32_t fb_id = 0;
-	uint32_t handles[4], pitches[4], offsets[4];
 	int ret;
 
 	wl_list_for_each(s, &output->sprite_list, output_link) {
-		if (!s->fb_id) {
-			found = 1;
+		if (!s->ref.pending_fb_id) {
+			ret = drmModeSetPlane(c->drm.fd, s->plane_id,
+					      output->crtc_id, 0, 0,
+					      0, 0, 0, 0, 0, 0, 0, 0);
+			if (ret)
+				fprintf(stderr,
+					"failed to disable plane: %d: %s\n",
+					ret, strerror(errno));
+			drmModeRmFB(c->drm.fd, s->fb_id);
 			break;
 		}
 	}
+}
 
-	/* No sprites available */
-	if (!found)
+static int
+drm_assign_overlay_surface(struct weston_output *output_base,
+			   struct weston_surface *es)
+{
+	struct drm_output *output = (struct drm_output *) output_base;
+	struct drm_sprite *s;
+	int found = 0;
+	int ret;
+
+	if (es->image == EGL_NO_IMAGE_KHR)
 		return -1;
 
-	bo = gbm_bo_create_from_egl_image(c->gbm, c->base.display, es->image,
-					  es->width, es->height,
-					  GBM_BO_USE_SCANOUT);
-	handle = gbm_bo_get_handle(bo).s32;
-	stride = gbm_bo_get_pitch(bo);
+	if (!drm_surface_format_supported(es))
+		return -1;
 
-	gbm_bo_destroy(bo);
+	wl_list_for_each(s, &output->sprite_list, output_link) {
+		if (!s->ref.pending_fb_id) {
+			found = 1;
+			break;
+		}
+	}
 
-	if (!handle)
+	/* No sprites available */
+	if (!found)
 		return -1;
 
-	handles[0] = handle;
-	pitches[0] = stride;
-	offsets[0] = 0;
-
-	ret = drmModeAddFB2(c->drm.fd, es->width, es->height,
-			    DRM_FORMAT_XRGB8888, handles, pitches, offsets,
-			    &fb_id, 0);
+	ret = drm_prepare_scanout_surface(output_base, es, &s->ref);
 	if (ret) {
 		fprintf(stderr, "addfb2 failed: %d\n", ret);
 		return -1;
 	}
 
-	ret = drmModeSetPlane(c->drm.fd, s->plane_id, output->crtc_id, fb_id, 0,
-			      es->x, es->y, es->width, es->height, 0, 0,
-			      es->width, es->height);
-	if (ret) {
-		fprintf(stderr, "setplane failed %d: %s\n", ret,
-			strerror(errno));
-		return -1;
-	}
+	s->dest_x = es->x;
+	s->dest_y = es->y;
+	s->dest_w = es->width;
+	s->dest_h = es->height;
+	s->src_x = 0;
+	s->src_y = 0;
+	s->src_w = es->width;
+	s->src_h = es->height;
 
 	return 0;
 }
@@ -330,10 +520,8 @@ drm_assign_planes(struct weston_output *output)
 	es = container_of(ec->surface_list.next, struct weston_surface, link);
 
 	if (es->visual == WESTON_RGB_VISUAL) {
-		if (!drm_output_prepare_scanout_surface(output, es)) {
-			drm_queue_scanout_surface(output, es);
+		if (!drm_output_prepare_scanout_surface(output, es))
 			scanout = es;
-		}
 	}
 
 	/*
@@ -349,14 +537,27 @@ drm_assign_planes(struct weston_output *output)
 	 * the client buffer can be used directly for the sprite surface
 	 * as we do for flipping full screen surfaces.
 	 */
-	wl_list_for_each_reverse(es, &ec->surface_list, link) {
-		if (es == scanout)
+	wl_list_for_each(es, &ec->surface_list, link) {
+		if (surface_is_primary(ec, es))
 			continue;
 
+		if (surface_is_cursor(ec, es))
+			continue;
+
+		/* FIXME: if an upper surface is on a hw plane, we don't
+		 * need to track its overlap.
+		 * FIXME: try to assign hw cursors here too, they're just
+		 * special overlays
+		 */
 		if (!drm_assign_overlay_surface(output, es))
 			pixman_region32_init(&es->damage);
+		else
+			pixman_region32_init_rect(&es->damage, es->x, es->y,
+						  es->width, es->height);
 	}
 
+	drm_disable_unused_sprites(output);
+
 	return 0;
 }
 
@@ -483,6 +684,7 @@ on_drm_input(int fd, uint32_t mask, void *data)
 	memset(&evctx, 0, sizeof evctx);
 	evctx.version = DRM_EVENT_CONTEXT_VERSION;
 	evctx.page_flip_handler = page_flip_handler;
+	evctx.vblank_handler = vblank_handler;
 	drmHandleEvent(fd, &evctx);
 
 	return 1;
@@ -635,6 +837,8 @@ create_sprites(struct drm_compositor *ec)
 		drmModeFreePlane(plane);
 
 		ec->sprite_allocator = (1 << sprite->plane_id);
+		drm_buffer_reference_init(&sprite->ref, ec);
+		sprite->fb_id = -1;
 		wl_list_insert(&ec->sprite_list, &sprite->link);
 	}
 
@@ -696,13 +900,14 @@ create_output_for_connector(struct drm_compositor *ec,
 	drmModeFreeEncoder(encoder);
 
 	wl_list_for_each(sprite, &ec->sprite_list, link) {
-		for (i = 0; i < resources->count_crtcs; i++)
-			if (sprite->possible_crtcs & (1 << i)) {
+		for (i = 0; i < resources->count_crtcs; i++) {
+			if (resources->crtcs[i] != output->crtc_id)
+				continue;
+
+			if (sprite->possible_crtcs & (1 << i))
 				wl_list_insert(&output->sprite_list,
 					       &sprite->output_link);
-				fprintf(stderr, "found sprite %d\n",
-					sprite->plane_id);
-			}
+		}
 	}
 
 	for (i = 0; i < connector->count_modes; i++) {
@@ -778,7 +983,7 @@ create_output_for_connector(struct drm_compositor *ec,
 
 	wl_list_insert(ec->base.output_list.prev, &output->base.link);
 
-	output->pending_fs_surf_fb_id = 0;
+	drm_buffer_reference_init(&output->fb_reference, ec);
 	output->base.assign_planes = drm_assign_planes;
 	output->base.prepare_render = drm_output_prepare_render;
 	output->base.present = drm_output_present;
@@ -985,7 +1190,7 @@ drm_compositor_create_cursor_image(struct weston_compositor *ec,
 	bo = gbm_bo_create(c->gbm,
 			   /* width, height, */ 64, 64,
 			   GBM_BO_FORMAT_ARGB8888,
-			   GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_RENDERING);
+			   GBM_BO_USE_CURSOR_64X64);
 
 	image = ec->create_image(c->base.display, NULL,
 				 EGL_NATIVE_PIXMAP_KHR, bo, NULL);
diff --git a/src/compositor.c b/src/compositor.c
index 51038fa..5bc40a7 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -171,36 +171,6 @@ surface_handle_buffer_destroy(struct wl_listener *listener,
 	es->buffer = NULL;
 }
 
-static void
-output_handle_scanout_buffer_destroy(struct wl_listener *listener,
-				     struct wl_resource *resource,
-				     uint32_t time)
-{
-	struct weston_output *output =
-		container_of(listener, struct weston_output,
-			     scanout_buffer_destroy_listener);
-
-	output->scanout_buffer = NULL;
-
-	if (!output->pending_scanout_buffer)
-		weston_compositor_schedule_repaint(output->compositor);
-}
-
-static void
-output_handle_pending_scanout_buffer_destroy(struct wl_listener *listener,
-					     struct wl_resource *resource,
-					     uint32_t time)
-{
-	struct weston_output *output =
-		container_of(listener, struct weston_output,
-			     pending_scanout_buffer_destroy_listener);
-
-	output->pending_scanout_buffer = NULL;
-
-	weston_compositor_schedule_repaint(output->compositor);
-}
-
-
 WL_EXPORT struct weston_surface *
 weston_surface_create(struct weston_compositor *compositor,
 		      int32_t x, int32_t y, int32_t width, int32_t height)
@@ -213,6 +183,7 @@ weston_surface_create(struct weston_compositor *compositor,
 
 	wl_list_init(&surface->link);
 	wl_list_init(&surface->buffer_link);
+	wl_list_init(&surface->output_link);
 
 	glGenTextures(1, &surface->texture);
 	glBindTexture(GL_TEXTURE_2D, surface->texture);
@@ -230,6 +201,7 @@ weston_surface_create(struct weston_compositor *compositor,
 	surface->width = width;
 	surface->height = height;
 	surface->alpha = 255;
+	surface->overlapped = 0;
 
 	surface->fullscreen_output = NULL;
 	surface->buffer = NULL;
@@ -394,6 +366,7 @@ destroy_surface(struct wl_resource *resource)
 	weston_surface_flush_damage(surface);
 
 	wl_list_remove(&surface->link);
+	wl_list_remove(&surface->output_link);
 	weston_compositor_repick(compositor);
 
 	if (surface->saved_texture == 0)
@@ -767,7 +740,8 @@ weston_output_repaint(struct weston_output *output)
 {
 	struct weston_compositor *ec = output->compositor;
 	struct weston_surface *es;
-	pixman_region32_t opaque, new_damage, total_damage, repaint;
+	pixman_region32_t opaque, new_damage, total_damage, repaint, overlap,
+		surf_intersect;
 
 	output->prepare_render(output);
 
@@ -801,12 +775,33 @@ weston_output_repaint(struct weston_output *output)
 
 	es = container_of(ec->surface_list.next, struct weston_surface, link);
 
+	pixman_region32_init(&overlap);
+
 	wl_list_for_each(es, &ec->surface_list, link) {
+		pixman_region32_init(&surf_intersect);
+
+		/* Set 'overlap' flags on each surface */
+		pixman_region32_intersect_rect(&surf_intersect, &overlap,
+					       es->x, es->y,
+					       es->width, es->height);
+		es->overlapped = pixman_region32_not_empty(&surf_intersect);
+
+		/* Sum the regions into the overlap area */
+		pixman_region32_union_rect(&overlap, &overlap, es->x, es->y,
+					   es->width, es->height);
+
+		pixman_region32_fini(&surf_intersect);
+	}
+
+	wl_list_for_each(es, &ec->surface_list, link) {
+		/* Sum the damage for the screen by walking each surf damage */
 		pixman_region32_copy(&es->damage, &total_damage);
 		pixman_region32_subtract(&total_damage, &total_damage,
 					 &es->opaque);
 	}
 
+	pixman_region32_fini(&overlap);
+
 	if (output->assign_planes)
 		/* This will queue flips for the fbs and sprites where
 		 * applicable and clear the damage for those surfaces.
@@ -1795,11 +1790,6 @@ weston_output_init(struct weston_output *output, struct weston_compositor *c,
 	output->flags = flags;
 	weston_output_move(output, x, y);
 
-	output->scanout_buffer_destroy_listener.func =
-		output_handle_scanout_buffer_destroy;
-	output->pending_scanout_buffer_destroy_listener.func =
-		output_handle_pending_scanout_buffer_destroy;
-
 	wl_list_init(&output->frame_callback_list);
 
 	wl_display_add_global(c->wl_display,
diff --git a/src/compositor.h b/src/compositor.h
index 759937b..3f8b783 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -82,10 +82,6 @@ struct weston_output {
 	
 	struct weston_mode *current;
 	struct wl_list mode_list;
-	struct wl_buffer *scanout_buffer;
-	struct wl_listener scanout_buffer_destroy_listener;
-	struct wl_buffer *pending_scanout_buffer;
-	struct wl_listener pending_scanout_buffer_destroy_listener;
 
 	int (*prepare_render)(struct weston_output *output);
 	int (*present)(struct weston_output *output);
@@ -237,9 +233,11 @@ struct weston_surface {
 	int32_t pitch;
 	struct wl_list link;
 	struct wl_list buffer_link;
+	struct wl_list output_link;
 	struct weston_transform *transform;
 	uint32_t alpha;
 	uint32_t visual;
+	int overlapped;
 
 	/*
 	 * Which output to vsync this surface to.
-- 
1.7.4.1



More information about the wayland-devel mailing list