[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