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 <[email protected]>
---
 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

_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to