[PATCH 07/12] compositor: Add per connector clone mode support

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


Master output will be in compositor->output_list.
Clone output won't be in compositor->output_list, while it is in
master->clone_output_list.

The group of master output and associated clone outputs will be treated
as one output, client can't get any information about clone output.

Signed-off-by: Xiong Zhang <xiong.y.zhang at intel.com>
---
 src/compositor-drm.c |   9 ++++
 src/compositor.c     | 114 ++++++++++++++++++++++++++++++++++++++++++---------
 src/compositor.h     |   9 ++++
 weston.ini.in        |   2 +
 4 files changed, 115 insertions(+), 19 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index dd1c251..de777b3 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -1951,6 +1951,13 @@ create_output_for_connector(struct drm_compositor *ec,
 	setup_output_seat_constraint(ec, &output->base, s);
 	free(s);
 
+	weston_config_section_get_string(section, "clone", &s, "");
+	if (strcmp(s, "") != 0) {
+		output->base.is_clone = 1;
+		output->base.master_output_name = strdup(s);
+	}
+	free(s);
+
 	output->crtc_id = resources->crtcs[i];
 	output->pipe = i;
 	ec->crtc_allocator |= (1 << output->crtc_id);
@@ -2231,6 +2238,8 @@ create_outputs(struct drm_compositor *ec, uint32_t option_connector,
 		drmModeFreeConnector(connector);
 	}
 
+	weston_compositor_add_clone_outputs(&ec->base);
+
 	if (wl_list_empty(&ec->base.output_list)) {
 		weston_log("No currently active connector found.\n");
 		drmModeFreeResources(resources);
diff --git a/src/compositor.c b/src/compositor.c
index 6aff7ab..402ac75 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -3066,6 +3066,47 @@ bind_output(struct wl_client *client,
 		wl_output_send_done(resource);
 }
 
+static void
+add_clone_output(struct weston_output *clone_output)
+{
+	struct weston_compositor *compositor = clone_output->compositor;
+	struct weston_output *master_output;
+	uint32_t found = 0;
+
+	wl_list_for_each(master_output, &compositor->output_list, link) {
+		if (clone_output->master_output_name == NULL ||
+		    strncmp(clone_output->master_output_name,
+			    master_output->name,
+			    strlen(clone_output->master_output_name) != 0))
+			continue;
+
+		clone_output->master_output = master_output;
+		found = 1;
+	}
+
+	if (found == 0)
+		clone_output->is_clone = 0;
+
+	weston_output_init(clone_output, compositor,
+			   clone_output->mm_width,
+			   clone_output->mm_height,
+			   clone_output->transform,
+			   clone_output->original_scale);
+}
+
+WL_EXPORT void
+weston_compositor_add_clone_outputs(struct weston_compositor *compositor)
+{
+	struct weston_output *clone_output, *next;
+
+	wl_list_for_each_safe(clone_output, next,
+			      &compositor->temp_clone_list, link) {
+		wl_list_remove(&clone_output->link);
+
+		add_clone_output(clone_output);
+	}
+}
+
 /* Move other outputs when one is removed so the space remains contiguos. */
 static void
 weston_compositor_remove_output(struct weston_compositor *compositor,
@@ -3093,19 +3134,27 @@ weston_output_destroy(struct weston_output *output)
 {
 	output->destroying = 1;
 
-	weston_compositor_remove_output(output->compositor, output);
+	if (!output->is_clone)
+		weston_compositor_remove_output(output->compositor, output);
+
 	wl_list_remove(&output->link);
 
-	wl_signal_emit(&output->compositor->output_destroyed_signal, output);
-	wl_signal_emit(&output->destroy_signal, output);
+	if (!output->is_clone) {
+		wl_signal_emit(&output->compositor->output_destroyed_signal,
+			       output);
+		wl_signal_emit(&output->destroy_signal, output);
+	}
 
 	free(output->name);
+	if (output->master_output_name)
+		free(output->master_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);
+	if (!output->is_clone)
+		wl_global_destroy(output->global);
 }
 
 static void
@@ -3284,8 +3333,28 @@ weston_output_init(struct weston_output *output, struct weston_compositor *c,
 {
 	struct weston_output *last;
 
+	output->compositor = c;
+	output->mm_width = mm_width;
+	output->mm_height = mm_height;
+	output->dirty = 1;
+	output->original_scale = scale;
+
+	weston_output_transform_scale_init(output, transform, scale);
+	weston_output_init_zoom(output);
+
+	/* If clone ouptut haven't found master output yet, then put this
+	 * clone output to c->temp_clone_list and delay the init until found
+	 * its master. */
+	if (output->is_clone && output->master_output == NULL) {
+		wl_list_insert(c->temp_clone_list.prev, &output->link);
+		return;
+	}
+
 	/* Find the position for this output */
-	if (!wl_list_empty(&c->output_list)) {
+	if (output->is_clone) {
+		output->x = output->master_output->x;
+		output->y = output->master_output->y;
+	} else if (!wl_list_empty(&c->output_list)) {
 		last = container_of(c->output_list.prev,
 				    struct weston_output, link);
 
@@ -3296,15 +3365,6 @@ weston_output_init(struct weston_output *output, struct weston_compositor *c,
 		output->y = 0;
 	}
 
-	output->compositor = c;
-	output->mm_width = mm_width;
-	output->mm_height = mm_height;
-	output->dirty = 1;
-	output->original_scale = scale;
-
-	weston_output_transform_scale_init(output, transform, scale);
-	weston_output_init_zoom(output);
-
 	weston_output_init_geometry(output, output->x, output->y);
 	weston_output_damage(output);
 
@@ -3316,12 +3376,18 @@ weston_output_init(struct weston_output *output, struct weston_compositor *c,
 	output->id = ffs(~output->compositor->output_id_pool) - 1;
 	output->compositor->output_id_pool |= 1 << output->id;
 
-	wl_list_insert(c->output_list.prev, &output->link);
+	wl_list_init(&output->clone_output_list);
+
+	if (!output->is_clone) {
+		wl_list_insert(c->output_list.prev, &output->link);
 
-	output->global =
-		wl_global_create(c->wl_display, &wl_output_interface, 2,
+		output->global =
+			wl_global_create(c->wl_display, &wl_output_interface, 2,
 				 output, bind_output);
-	wl_signal_emit(&c->output_created_signal, output);
+		wl_signal_emit(&c->output_created_signal, output);
+	} else
+		wl_list_insert(output->master_output->clone_output_list.prev,
+			       &output->link);
 }
 
 WL_EXPORT void
@@ -3604,6 +3670,8 @@ weston_compositor_init(struct weston_compositor *ec,
 	wl_list_init(&ec->axis_binding_list);
 	wl_list_init(&ec->debug_binding_list);
 
+	wl_list_init(&ec->temp_clone_list);
+
 	weston_plane_init(&ec->primary_plane, ec, 0, 0);
 	weston_compositor_stack_plane(ec, &ec->primary_plane, NULL);
 
@@ -3647,14 +3715,22 @@ WL_EXPORT void
 weston_compositor_shutdown(struct weston_compositor *ec)
 {
 	struct weston_output *output, *next;
+	struct weston_output *clone_output, *tmp;
 
 	wl_event_source_remove(ec->idle_source);
 	if (ec->input_loop_source)
 		wl_event_source_remove(ec->input_loop_source);
 
 	/* Destroy all outputs associated with this compositor */
-	wl_list_for_each_safe(output, next, &ec->output_list, link)
+	wl_list_for_each_safe(output, next, &ec->output_list, link) {
+		/* Destroy all clone outputs associated with this output. */
+		wl_list_for_each_safe(clone_output, tmp,
+				      &output->clone_output_list,
+				      link)
+			clone_output->destroy(clone_output);
+
 		output->destroy(output);
+	}
 
 	if (ec->renderer)
 		ec->renderer->destroy(ec);
diff --git a/src/compositor.h b/src/compositor.h
index 6cfd09c..ed7aa45 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -213,6 +213,11 @@ struct weston_output {
 	struct weston_mode *original_mode;
 	struct wl_list mode_list;
 
+	uint32_t is_clone;
+	char *master_output_name;
+	struct weston_output *master_output;
+	struct wl_list clone_output_list;
+
 	void (*start_repaint_loop)(struct weston_output *output);
 	int (*repaint)(struct weston_output *output,
 			pixman_region32_t *damage);
@@ -605,6 +610,8 @@ struct weston_compositor {
 	struct wl_list axis_binding_list;
 	struct wl_list debug_binding_list;
 
+	struct wl_list temp_clone_list;
+
 	uint32_t state;
 	struct wl_event_source *idle_source;
 	uint32_t idle_inhibit;
@@ -1213,6 +1220,8 @@ void
 weston_output_init(struct weston_output *output, struct weston_compositor *c,
 		   int width, int height, uint32_t transform, int32_t scale);
 void
+weston_compositor_add_clone_outputs(struct weston_compositor *compositor);
+void
 weston_output_destroy(struct weston_output *output);
 void
 weston_output_transform_coordinate(struct weston_output *output,
diff --git a/weston.ini.in b/weston.ini.in
index 2c39177..94de52c 100644
--- a/weston.ini.in
+++ b/weston.ini.in
@@ -49,12 +49,14 @@ path=@libexecdir@/weston-keyboard
 #name=LVDS1
 #mode=1680x1050
 #transform=90
+#clone=VGA1
 #icc_profile=/usr/share/color/icc/colord/Bluish.icc
 
 #[output]
 #name=VGA1
 #mode=173.00  1920 2048 2248 2576  1080 1083 1088 1120 -hsync +vsync
 #transform=flipped
+#clone=LVDS1
 
 #[output]
 #name=X1
-- 
1.8.3.2



More information about the wayland-devel mailing list