[PATCH 3/4] compositor: unify sprite and primary handling a bit

Jesse Barnes jbarnes at virtuousgeek.org
Mon Jan 16 14:40:48 PST 2012


In assign_planes, we try to assign the primary buffer to the primary
plane, then look for additional surfaces to match to display planes.  At
present time, we'll then flip all those buffers onto the screen in a
synchronized way, then clean up and release the buffers when the
corresponding page flip or vblank event arrives.
---
 src/compositor-drm.c |  102 ++++++++++++++++++++++++++++++++++++++++++-------
 src/compositor.c     |    2 +
 src/compositor.h     |    1 +
 3 files changed, 90 insertions(+), 15 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 4b42394..9e25ffd 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -81,6 +81,8 @@ struct drm_output {
 
 	struct wl_list sprite_list;
 
+	struct wl_list sprite_surfaces;
+
 	uint32_t fs_surf_fb_id;
 	uint32_t pending_fs_surf_fb_id;
 };
@@ -169,10 +171,16 @@ 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) {
@@ -185,10 +193,73 @@ drm_output_present(struct weston_output *output_base)
 			fb_id,
 			DRM_MODE_PAGE_FLIP_EVENT, output);
 
+	/*
+	 * Now, update all the sprite surfaces
+	 */
+	wl_list_for_each(s, &output->sprite_list, output_link) {
+		if (s->fb_id != 0) {
+			ret = drmModeSetPlane(c->drm.fd, s->plane_id,
+					      output->crtc_id, s->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;
+		}
+	}
+
+	/*
+	 * 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
+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;
+	struct weston_surface *surf, *next;
+	struct drm_sprite *s;
+
+	/* Free the FBs for the sprites */
+	wl_list_for_each(s, &output->sprite_list, output_link) {
+		if (s->fb_id) {
+			drmModeRmFB(c->drm.fd, s->fb_id);
+			s->fb_id = 0;
+		}
+	}
+
+	/* Then send out buffer release messages */
+	wl_list_for_each_safe(surf, next, &output->sprite_surfaces,
+			      output_link) {
+		weston_buffer_post_release(surf->buffer);
+		wl_list_remove(&surf->output_link);
+		wl_list_init(&surf->output_link);
+	}
+}
+
+static void
 page_flip_handler(int fd, unsigned int frame,
 		  unsigned int sec, unsigned int usec, void *data)
 {
@@ -306,20 +377,17 @@ drm_assign_overlay_surface(struct weston_output *output_base,
 		return -1;
 	}
 
-	fprintf(stderr, "displaying surface on sprite %d\n", s->plane_id);
+	s->fb_id = fb_id;
+	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;
 
-	fprintf(stderr, "%d, %d, %d, %d, (%d,%d), %dx%d\n", c->drm.fd,
-		s->plane_id, output->crtc_id, fb_id, es->x, es->y, es->width,
-		es->height);
-
-	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;
-	}
+	wl_list_insert(&output->sprite_surfaces, &es->output_link);
 
 	return 0;
 }
@@ -328,13 +396,15 @@ static int
 drm_assign_planes(struct weston_output *output)
 {
 	struct weston_compositor *ec = output->compositor;
-	struct weston_surface *es;
+	struct weston_surface *es, *scanout = NULL;
 
 	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))
+		if (!drm_output_prepare_scanout_surface(output, es)) {
 			drm_queue_scanout_surface(output, es);
+			scanout = es;
+		}
 	}
 
 	/*
@@ -482,6 +552,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;
@@ -687,6 +758,7 @@ create_output_for_connector(struct drm_compositor *ec,
 	output->base.model = "unknown";
 	wl_list_init(&output->base.mode_list);
 	wl_list_init(&output->sprite_list);
+	wl_list_init(&output->sprite_surfaces);
 
 	output->crtc_id = resources->crtcs[i];
 	ec->crtc_allocator |= (1 << output->crtc_id);
diff --git a/src/compositor.c b/src/compositor.c
index 348b4e7..cd3ad1a 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -213,6 +213,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);
@@ -378,6 +379,7 @@ destroy_surface(struct wl_resource *resource)
 	weston_surface_damage_below(surface);
 
 	wl_list_remove(&surface->link);
+	wl_list_remove(&surface->output_link);
 	weston_compositor_repick(compositor);
 
 	if (surface->saved_texture == 0)
diff --git a/src/compositor.h b/src/compositor.h
index e5e18a3..6716781 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -238,6 +238,7 @@ 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;
-- 
1.7.4.1



More information about the wayland-devel mailing list