If adding output is a clone output, first system will find its master,
then system will put this output into master->clone_output_list

If adding output is a master output, system will loop the output_list
to find its clone output. If this master has clone output, the clone
output will downgrade from master to clone.

Signed-off-by: Xiong Zhang <[email protected]>
---
 src/compositor-drm.c |  9 +++++++-
 src/compositor.c     | 61 ++++++++++++++++++++++++++++++++++++++++++++++------
 src/compositor.h     |  2 ++
 3 files changed, 64 insertions(+), 8 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 58a0efa..a30f88d 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -2258,7 +2258,7 @@ update_outputs(struct drm_compositor *ec, struct 
udev_device *drm_device)
        drmModeRes *resources;
        struct drm_output *output, *next;
        uint32_t connected = 0, disconnects = 0;
-       int i;
+       int i, add_output = 0;
 
        resources = drmModeGetResources(ec->drm.fd);
        if (!resources) {
@@ -2287,11 +2287,18 @@ update_outputs(struct drm_compositor *ec, struct 
udev_device *drm_device)
                                                    drm_device);
                        weston_log("connector %d connected\n", connector_id);
 
+                       add_output = 1;
+
                }
                drmModeFreeConnector(connector);
        }
        drmModeFreeResources(resources);
 
+       if (add_output) {
+               weston_compositor_add_clone_outputs(&ec->base);
+               weston_compositor_add_master_outputs(&ec->base);
+       }
+
        disconnects = ec->connector_allocator & ~connected;
        if (disconnects) {
                wl_list_for_each_safe(output, next, &ec->base.output_list,
diff --git a/src/compositor.c b/src/compositor.c
index 72d29a0..39081bb 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -3139,11 +3139,9 @@ weston_compositor_remove_output(struct weston_compositor 
*compositor,
        }
 }
 
-WL_EXPORT void
-weston_output_destroy(struct weston_output *output)
+static void
+delete_output_from_list(struct weston_output *output)
 {
-       output->destroying = 1;
-
        if (!output->is_clone)
                weston_compositor_remove_output(output->compositor, output);
 
@@ -3155,12 +3153,10 @@ weston_output_destroy(struct weston_output *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);
 
        if (!output->is_clone)
@@ -3168,6 +3164,57 @@ weston_output_destroy(struct weston_output *output)
 }
 
 static void
+migrate_clone_output(struct weston_output *clone, struct weston_output *master)
+{
+       delete_output_from_list(clone);
+
+       clone->master_output = master;
+       clone->is_clone = 1;
+
+       weston_output_init(clone, clone->compositor, clone->mm_width,
+                          clone->mm_height,  clone->transform,
+                          clone->original_scale);
+}
+
+WL_EXPORT void
+weston_output_destroy(struct weston_output *output)
+{
+       output->destroying = 1;
+
+       delete_output_from_list(output);
+
+       free(output->name);
+       if (output->master_output_name)
+               free(output->master_output_name);
+}
+
+/* At first a clone output is discoveryed but associated master isn't found
+ * this clone output will be upgraded to master output;
+ * Then the master output is hot plugged, the original clone output
+ * should be downgraded to clone. */
+WL_EXPORT void
+weston_compositor_add_master_outputs(struct weston_compositor *compositor)
+{
+       struct weston_output *output, *master, *clone, *next1, *next2;
+
+       master = container_of(compositor->output_list.prev,
+                       struct weston_output, link);
+
+       wl_list_for_each_safe(output, next1, &compositor->output_list, link) {
+               if (output->master_output_name == NULL ||
+                   strncmp(output->master_output_name, master->name,
+                           strlen(output->master_output_name)) != 0)
+                       continue;
+
+               wl_list_for_each_safe(clone, next2, &output->clone_output_list,
+                                     link)
+                       migrate_clone_output(clone, master);
+
+               migrate_clone_output(output, master);
+       }
+}
+
+static void
 weston_output_compute_transform(struct weston_output *output)
 {
        struct weston_matrix transform;
diff --git a/src/compositor.h b/src/compositor.h
index ed7aa45..da63666 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -1222,6 +1222,8 @@ weston_output_init(struct weston_output *output, struct 
weston_compositor *c,
 void
 weston_compositor_add_clone_outputs(struct weston_compositor *compositor);
 void
+weston_compositor_add_master_outputs(struct weston_compositor *compositor);
+void
 weston_output_destroy(struct weston_output *output);
 void
 weston_output_transform_coordinate(struct weston_output *output,
-- 
1.8.3.2

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

Reply via email to