[PATCH v2 weston 14/16] compositor-drm: Track primary plane with a drm_plane

Daniel Stone daniels at collabora.com
Mon Jun 22 09:25:19 PDT 2015


Use a real drm_plane to back the primary plane, displacing
output->current and output->next to their plane-tracked equivalents.

v2: Remove extra output->{current,next} members. Add primary plane to
    plane_list so it gets cleaned up.

Signed-off-by: Daniel Stone <daniels at collabora.com>
---
 src/compositor-drm.c | 118 +++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 90 insertions(+), 28 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 689b318..b52de4f 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -265,9 +265,9 @@ struct drm_output {
 	struct drm_fb *cursor_fb[2];
 	struct drm_plane *cursor_plane;
 	struct weston_plane fb_plane;
+	struct drm_plane *primary_plane;
 	struct weston_view *cursor_view;
 	int current_cursor;
-	struct drm_fb *current, *next;
 	struct backlight *backlight;
 
 	struct drm_fb *dumb[2];
@@ -905,13 +905,13 @@ drm_output_prepare_scanout_view(struct drm_output *output,
 		return NULL;
 	}
 
-	output->next = drm_fb_get_from_bo(bo, c, format);
-	if (!output->next) {
+	output->primary_plane->next = drm_fb_get_from_bo(bo, c, format);
+	if (!output->primary_plane->next) {
 		gbm_bo_destroy(bo);
 		return NULL;
 	}
 
-	drm_fb_set_buffer(output->next, buffer);
+	drm_fb_set_buffer(output->primary_plane->next, buffer);
 
 	return &output->fb_plane;
 }
@@ -931,8 +931,8 @@ drm_output_render_gl(struct drm_output *output, pixman_region32_t *damage)
 		return;
 	}
 
-	output->next = drm_fb_get_from_bo(bo, c, output->format);
-	if (!output->next) {
+	output->primary_plane->next = drm_fb_get_from_bo(bo, c, output->format);
+	if (!output->primary_plane->next) {
 		weston_log("failed to get drm_fb for bo\n");
 		gbm_surface_release_buffer(output->surface, bo);
 		return;
@@ -955,7 +955,7 @@ drm_output_render_pixman(struct drm_output *output, pixman_region32_t *damage)
 
 	output->current_image ^= 1;
 
-	output->next = output->dumb[output->current_image];
+	output->primary_plane->next = output->dumb[output->current_image];
 	pixman_renderer_output_set_buffer(&output->base,
 					  output->image[output->current_image]);
 
@@ -1015,16 +1015,17 @@ drm_output_repaint(struct weston_output *output_base,
 	if (output->destroy_pending)
 		return -1;
 
-	if (!output->next)
+	if (!output->primary_plane->next)
 		drm_output_render(output, damage);
-	if (!output->next)
+	if (!output->primary_plane->next)
 		return -1;
 
 	mode = container_of(output->base.current_mode, struct drm_mode, base);
-	if (!output->current ||
-	    output->current->stride != output->next->stride) {
+	if (!output->primary_plane->current ||
+	    output->primary_plane->current->stride !=
+	     output->primary_plane->next->stride) {
 		ret = drmModeSetCrtc(compositor->drm.fd, output->crtc_id,
-				     output->next->fb_id, 0, 0,
+				     output->primary_plane->next->fb_id, 0, 0,
 				     &output->connector_id, 1,
 				     &mode->mode_info);
 		if (ret) {
@@ -1035,7 +1036,7 @@ drm_output_repaint(struct weston_output *output_base,
 	}
 
 	if (drmModePageFlip(compositor->drm.fd, output->crtc_id,
-			    output->next->fb_id,
+			    output->primary_plane->next->fb_id,
 			    DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
 		weston_log("queueing pageflip failed: %m\n");
 		goto err_pageflip;
@@ -1101,9 +1102,9 @@ drm_output_repaint(struct weston_output *output_base,
 
 err_pageflip:
 	output->cursor_view = NULL;
-	if (output->next) {
-		drm_output_release_fb(output, output->next);
-		output->next = NULL;
+	if (output->primary_plane->next) {
+		drm_output_release_fb(output, output->primary_plane->next);
+		output->primary_plane->next = NULL;
 	}
 
 	return -1;
@@ -1121,12 +1122,12 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
 	if (output->destroy_pending)
 		return;
 
-	if (!output->current) {
+	if (!output->primary_plane->current) {
 		/* We can't page flip if there's no mode set */
 		goto finish_frame;
 	}
 
-	fb_id = output->current->fb_id;
+	fb_id = output->primary_plane->current->fb_id;
 
 	if (drmModePageFlip(compositor->drm.fd, output->crtc_id, fb_id,
 			    DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
@@ -1197,9 +1198,9 @@ page_flip_handler(int fd, unsigned int frame,
 	 * we just want to page flip to the current buffer to get an accurate
 	 * timestamp */
 	if (output->page_flip_pending) {
-		drm_output_release_fb(output, output->current);
-		output->current = output->next;
-		output->next = NULL;
+		drm_output_release_fb(output, output->primary_plane->current);
+		output->primary_plane->current = output->primary_plane->next;
+		output->primary_plane->next = NULL;
 	}
 
 	output->page_flip_pending = 0;
@@ -1732,9 +1733,9 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
 		WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
 
 	/* reset rendering stuff. */
-	drm_output_release_fb(output, output->current);
-	drm_output_release_fb(output, output->next);
-	output->current = output->next = NULL;
+	drm_output_release_fb(output, output->primary_plane->current);
+	drm_output_release_fb(output, output->primary_plane->next);
+	output->primary_plane->current = output->primary_plane->next = NULL;
 
 	if (ec->use_pixman) {
 		drm_output_fini_pixman(output);
@@ -2599,6 +2600,60 @@ connector_get_current_mode(drmModeConnector *connector, int drm_fd,
 }
 
 static void
+drm_output_init_primary_plane(struct drm_output *output)
+{
+	struct drm_compositor *ec =
+		(struct drm_compositor *) output->base.compositor;
+	struct drm_plane *plane;
+
+	if (ec->universal_planes) {
+		wl_list_for_each(plane, &ec->plane_list, link) {
+			if (plane->type != WDRM_PLANE_TYPE_PRIMARY)
+				continue;
+			if (plane->output)
+				continue;
+			if (!drm_plane_crtc_supported(output,
+						      plane->possible_crtcs))
+				continue;
+
+			plane->output = output;
+			output->primary_plane = plane;
+			break;
+		}
+	}
+	else {
+		/* XXX: Gross open-coding ... ? */
+		plane = zalloc(sizeof(*plane) + sizeof(uint32_t));
+		if (!plane) {
+			weston_log("%s: out of memory\n", __func__);
+			return;
+		}
+
+		weston_plane_init(&plane->base, &ec->base, 0, 0);
+		wl_list_insert(&ec->plane_list, &plane->link);
+
+		plane->plane_id = 0;
+		plane->possible_crtcs = 0;
+		plane->output = output;
+		plane->current = NULL;
+		plane->next = NULL;
+		plane->compositor = ec;
+		plane->count_formats = 1;
+		plane->formats[0] = output->format;
+		plane->type = WDRM_PLANE_TYPE_PRIMARY;
+
+		output->primary_plane = plane;
+	}
+
+	/* Unlike the cursor plane, we don't stack the primary plane into
+	 * the base list, because it's implicitly placed at the bottom. The
+	 * base compositor's primary_plane covers everything we construct
+	 * with our renderer, with each output taking a chunk of the
+	 * base primary_plane. So here we just internally treat this plane
+	 * as a partial shadow of weston_compositor::primary_plane. */
+}
+
+static void
 drm_output_init_cursor(struct drm_output *output)
 {
 	struct drm_compositor *ec =
@@ -2758,6 +2813,12 @@ create_output_for_connector(struct drm_compositor *ec,
 			   connector->mmWidth, connector->mmHeight,
 			   transform, scale);
 
+	drm_output_init_primary_plane(output);
+	if (!output->primary_plane) {
+		weston_log("Failed to find primary plane for output %s\n",
+			   output->base.name);
+		goto err_output;
+	}
 	drm_output_init_cursor(output);
 
 	if (ec->use_pixman) {
@@ -3172,7 +3233,7 @@ drm_compositor_set_modes(struct drm_compositor *compositor)
 	int ret;
 
 	wl_list_for_each(output, &compositor->base.output_list, base.link) {
-		if (!output->current) {
+		if (!output->primary_plane->current) {
 			/* If something that would cause the output to
 			 * switch mode happened while in another vt, we
 			 * might not have a current drm_fb. In that case,
@@ -3184,7 +3245,7 @@ drm_compositor_set_modes(struct drm_compositor *compositor)
 
 		drm_mode = (struct drm_mode *) output->base.current_mode;
 		ret = drmModeSetCrtc(compositor->drm.fd, output->crtc_id,
-				     output->current->fb_id, 0, 0,
+				     output->primary_plane->current->fb_id, 0, 0,
 				     &output->connector_id, 1,
 				     &drm_mode->mode_info);
 		if (ret < 0) {
@@ -3358,7 +3419,8 @@ recorder_frame_notify(struct wl_listener *listener, void *data)
 	if (!output->recorder)
 		return;
 
-	ret = drmPrimeHandleToFD(c->drm.fd, output->current->handle,
+	ret = drmPrimeHandleToFD(c->drm.fd,
+				 output->primary_plane->current->handle,
 				 DRM_CLOEXEC, &fd);
 	if (ret) {
 		weston_log("[libva recorder] "
@@ -3367,7 +3429,7 @@ recorder_frame_notify(struct wl_listener *listener, void *data)
 	}
 
 	ret = vaapi_recorder_frame(output->recorder, fd,
-				   output->current->stride);
+				   output->primary_plane->current->stride);
 	if (ret < 0) {
 		weston_log("[libva recorder] aborted: %m\n");
 		recorder_destroy(output);
-- 
2.4.3



More information about the wayland-devel mailing list