[PATCH 5/9] compositor: Output unplug in clone mode
Pekka Paalanen
ppaalanen at gmail.com
Thu Feb 13 23:56:06 PST 2014
On Fri, 14 Feb 2014 15:17:40 +0800
Xiong Zhang <xiong.y.zhang at intel.com> wrote:
> If unplugged output is a slave output, no need to restore views.
>
> If unplugged output is a master output which doesn't have slave
> output related it, views will be restored the same as extend mode.
>
> If unplugged output is a master output which have slave output
> related it, one slave output will be upgraded to master output,
> moving output following unplugged output isn't necessay,
> views on unplugged output will be marked as dirty.
>
> Signed-off-by: Xiong Zhang <xiong.y.zhang at intel.com>
> ---
> desktop-shell/shell.c | 13 ++++++-
> src/compositor-drm.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++---
> src/compositor.c | 15 ++++++--
> src/compositor.h | 1 +
> 4 files changed, 122 insertions(+), 10 deletions(-)
>
> diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
> index 1e4a255..85987e5 100644
> --- a/desktop-shell/shell.c
> +++ b/desktop-shell/shell.c
> @@ -5600,6 +5600,9 @@ handle_output_destroy(struct wl_listener *listener, void *data)
> wl_list_remove(&output_listener->role_change_listener.link);
> wl_list_remove(&output_listener->link);
> free(output_listener);
> +
> + /* Trigger compositor repaint */
> + weston_compositor_schedule_repaint(output_listener->output->compositor);
> }
>
> static void
> @@ -5676,10 +5679,18 @@ setup_output_destroy_handler(struct weston_compositor *ec,
> struct desktop_shell *shell)
> {
> struct weston_output *output;
> + struct weston_output *clone_output;
>
> wl_list_init(&shell->output_list);
> - wl_list_for_each(output, &ec->output_list, link)
> + wl_list_for_each(output, &ec->output_list, link) {
> create_shell_output(shell, output);
> + if (!output->is_slave) {
> + wl_list_for_each(clone_output,
> + &output->clone_output_list,
> + link)
> + create_shell_output(shell, clone_output);
> + }
> + }
>
> shell->output_create_listener.notify = handle_output_create;
> wl_signal_add(&ec->output_created_signal,
> diff --git a/src/compositor-drm.c b/src/compositor-drm.c
> index 1d8c983..842710f 100644
> --- a/src/compositor-drm.c
> +++ b/src/compositor-drm.c
> @@ -1217,6 +1217,8 @@ drm_assign_planes(struct weston_output *output)
>
> static void
> drm_output_fini_pixman(struct drm_output *output);
> +static void
> +drm_output_destroy_with_slave(struct drm_output *output);
>
> static void
> drm_output_destroy(struct weston_output *output_base)
> @@ -1259,6 +1261,15 @@ drm_output_destroy(struct weston_output *output_base)
> weston_plane_release(&output->fb_plane);
> weston_plane_release(&output->cursor_plane);
>
> + if (!output->base.is_slave &&
> + !wl_list_empty(&output->base.clone_output_list)) {
> + drm_output_destroy_with_slave(output);
> +
> + /* One slave is upgraded to master, Don't move
> + * the following output.*/
> + output_base.dont_move = 1;
> + }
> +
> weston_output_destroy(&output->base);
>
> free(output);
> @@ -2420,6 +2431,73 @@ drm_output_add_slave(struct drm_compositor *ec)
> }
> }
>
> +/* The output with max width will be new_master. */
> +static struct weston_output *
> +find_new_master(struct weston_output *master)
> +{
> + struct weston_output *new_master, *output;
> + int32_t max_width = 0;
> +
> + new_master = NULL;
> + wl_list_for_each(output, &master->clone_output_list,
> + link) {
> + if (output->current_mode->width > max_width) {
> + max_width = output->current_mode->width;
> + new_master = output;
> + }
> + }
> +
> + return new_master;
> +}
> +
> +/* If a master is unplugged, a output will be chosen from
> + * master->clone_output_list to replace the unplugged master.*/
> +static void
> +drm_output_destroy_with_slave(struct drm_output *output)
> +{
> + struct weston_output *new_master, *tmp;
> + struct drm_output *clone_output, *next;
> + int offset, move;
> +
> + new_master = find_new_master(&output->base);
> +
> + /* When old master's width is different from new master's
> + * width, move the output following the old master. */
> + offset = output->base.width - new_master->width;
> + if (offset != 0) {
> + move = 0;
> + wl_list_for_each(tmp, &new_master->compositor->output_list,
> + link) {
> + if (move == 1)
> + weston_output_move(tmp,
> + tmp->x - offset, tmp->y);
> +
> + if (tmp == &output->base)
> + move = 1;
> + }
> + }
> +
> + wl_list_remove(&new_master->link);
> + wl_list_insert(output->base.link.prev,
> + &new_master->link);
> + new_master->is_slave = 0;
> +
> + /* Link the remained clone output to new master */
> + wl_list_for_each_safe(clone_output, next,
> + &output->base.clone_output_list,
> + base.link) {
> + clone_output->base.master_output = new_master;
> + if (clone_output_need_adjust_mode(&clone_output->base))
> + adjust_clone_output_mode(&clone_output->base);
> +
> + wl_list_remove(&clone_output->base.link);
> + wl_list_insert(new_master->clone_output_list.prev,
> + &clone_output->base.link);
> + }
> +
> + wl_signal_emit(&new_master->role_change_signal, new_master);
> +}
> +
> static int
> create_outputs(struct drm_compositor *ec, uint32_t option_connector,
> struct udev_device *drm_device)
> @@ -2489,6 +2567,7 @@ update_outputs(struct drm_compositor *ec, struct udev_device *drm_device)
> struct drm_output *output, *next;
> uint32_t connected = 0, disconnects = 0;
> int i;
> + struct drm_output *clone_output, *found_output;
>
> resources = drmModeGetResources(ec->drm.fd);
> if (!resources) {
> @@ -2525,12 +2604,26 @@ update_outputs(struct drm_compositor *ec, struct udev_device *drm_device)
> if (disconnects) {
> wl_list_for_each_safe(output, next, &ec->base.output_list,
> base.link) {
> - if (disconnects & (1 << output->connector_id)) {
> - disconnects &= ~(1 << output->connector_id);
> - weston_log("connector %d disconnected\n",
> - output->connector_id);
> - drm_output_destroy(&output->base);
> + found_output = NULL;
> + if (disconnects & (1 << output->connector_id))
> + found_output = output;
> + else if (!output->base.is_slave) {
> + wl_list_for_each(clone_output,
> + &output->base.clone_output_list,
> + base.link) {
> + if (disconnects &
> + (1 << clone_output->connector_id))
> + found_output = clone_output;
> + }
> }
> +
> + if (!found_output)
> + continue;
> +
> + disconnects &= ~(1 << found_output->connector_id);
> + weston_log("connector %d disconnected\n",
> + found_output->connector_id);
> + drm_output_destroy(&found_output->base);
> }
> }
>
> diff --git a/src/compositor.c b/src/compositor.c
> index 5c0f67d..5020fcf 100644
> --- a/src/compositor.c
> +++ b/src/compositor.c
> @@ -3056,6 +3056,9 @@ weston_compositor_remove_output(struct weston_compositor *compositor,
> struct weston_output *output;
> int offset = 0;
>
> + if (remove_output->dont_move == 1)
> + return;
> +
> wl_list_for_each(output, &compositor->output_list, link) {
> if (output == remove_output) {
> offset = output->width;
> @@ -3227,8 +3230,8 @@ weston_output_init_geometry(struct weston_output *output, int x, int y)
> WL_EXPORT void
> weston_output_move(struct weston_output *output, int x, int y)
> {
> - pixman_region32_t old_region;
> struct wl_resource *resource;
> + struct weston_output *clone_output;
>
> output->move_x = x - output->x;
> output->move_y = y - output->y;
> @@ -3236,9 +3239,6 @@ weston_output_move(struct weston_output *output, int x, int y)
> if (output->move_x == 0 && output->move_y == 0)
> return;
>
> - pixman_region32_init(&old_region);
> - pixman_region32_copy(&old_region, &output->region);
> -
> weston_output_init_geometry(output, x, y);
>
> output->dirty = 1;
> @@ -3257,6 +3257,13 @@ weston_output_move(struct weston_output *output, int x, int y)
> output->make,
> output->model,
> output->transform);
> +
> + /* Move slave_output associated with it. */
> + if (!output->is_slave) {
> + wl_list_for_each(clone_output, &output->clone_output_list,
> + link)
> + weston_output_move(clone_output, x, y);
> + }
> }
>
> WL_EXPORT void
> diff --git a/src/compositor.h b/src/compositor.h
> index 0938078..6701081 100644
> --- a/src/compositor.h
> +++ b/src/compositor.h
> @@ -217,6 +217,7 @@ struct weston_output {
> struct weston_output *master_output;
> struct wl_list clone_output_list;
> struct wl_signal role_change_signal;
> + uint32_t dont_move;
>
> void (*start_repaint_loop)(struct weston_output *output);
> int (*repaint)(struct weston_output *output,
Hi,
just a general note: it seems the DRM backend code is getting into
pretty deep indentation levels. I would recommend splitting chunks out
into functions where you have a logical does-one-thing block, even
if the function would be only used in one place. It makes the code flow
easier to read, when the blocks have been chosen properly and the
resulting functions have descriptive names. Only if possible, of course.
Thanks,
pq
More information about the wayland-devel
mailing list