From e1fd1c9fc08b9e1b8a2f2d958ce591bb8d256b84 Mon Sep 17 00:00:00 2001 From: Veeresh Kadasani Date: Mon, 16 Dec 2019 19:24:15 +0900 Subject: [PATCH 1/1] ivi-shell: Fix crash due no transmitter screen Registered the events for the output_created, destroyed, resized events.So that the ivi_scrn can be destroyed, created dynamically during destroyed and created events. And the view properties are dynamically changed during resized/moved events. Signed-off-by: Veeresh Kadasani --- ivi-shell/ivi-layout-private.h | 5 ++ ivi-shell/ivi-layout.c | 154 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 140 insertions(+), 19 deletions(-) diff --git a/ivi-shell/ivi-layout-private.h b/ivi-shell/ivi-layout-private.h index c054130..8997edd 100644 --- a/ivi-shell/ivi-layout-private.h +++ b/ivi-shell/ivi-layout-private.h @@ -113,6 +113,11 @@ struct ivi_layout { struct ivi_layout_transition_set *transitions; struct wl_list pending_transition_list; /* transition_node::link */ + + struct wl_listener output_created; + struct wl_listener output_destroyed; + struct wl_listener output_resized; + struct wl_listener output_moved; }; struct ivi_layout *get_instance(void); diff --git a/ivi-shell/ivi-layout.c b/ivi-shell/ivi-layout.c index 2c450f3..1fbfeeb 100644 --- a/ivi-shell/ivi-layout.c +++ b/ivi-shell/ivi-layout.c @@ -67,7 +67,7 @@ #include "ivi-layout-export.h" #include "ivi-layout-private.h" #include "ivi-layout-shell.h" - +#include #include "shared/helpers.h" #include "shared/os-compatibility.h" @@ -259,6 +259,87 @@ ivi_layout_surface_destroy(struct ivi_layout_surface *ivisurf) free(ivisurf); } + +static void +destroy_screen(struct ivi_layout_screen *iviscrn) +{ + struct ivi_layout_layer *ivilayer; + struct ivi_layout_layer *next; + + /*we need to remove the layers from pending and order lists + *otherwise the memory will be corrupted during the + *wl_list_remove of pending.link or order.link from + *ivi_layout_screen_add_layer() or commit_screen_list() + *and on_screen has to be set as NULL otherwise the commit_changes() + *API will try to refer the freed iviscrn*/ + wl_list_for_each_safe(ivilayer, next, &iviscrn->pending.layer_list, pending.link) { + wl_list_remove(&ivilayer->pending.link); + wl_list_init(&ivilayer->pending.link); + ivilayer->on_screen = NULL; + } + + wl_list_for_each_safe(ivilayer, next, &iviscrn->order.layer_list, order.link) { + wl_list_remove(&ivilayer->order.link); + wl_list_init(&ivilayer->order.link); + ivilayer->on_screen = NULL; + } + + wl_list_init(&iviscrn->pending.layer_list); + wl_list_init(&iviscrn->order.layer_list); + + wl_list_remove(&iviscrn->link); + free(iviscrn); +} + +static void +output_destroyed_event(struct wl_listener *listener, void *data) +{ + struct ivi_layout *layout = + wl_container_of(listener, layout, output_destroyed); + struct ivi_layout_screen *iviscrn = NULL; + struct ivi_layout_screen *next = NULL; + struct weston_output *destroyed_output = (struct weston_output*)data; + + wl_list_for_each_safe(iviscrn, next, &layout->screen_list, link) { + if (iviscrn->output == destroyed_output) { + destroy_screen(iviscrn); + } + } + ivi_layout_commit_changes(); +} + +static void +add_screen(struct weston_output *output) +{ + struct ivi_layout *layout = get_instance(); + struct ivi_layout_screen *iviscrn = NULL; + + if(!output) + return; + + iviscrn = calloc(1, sizeof *iviscrn); + if (iviscrn == NULL) { + weston_log("fails to allocate memory\n"); + return; + } + + iviscrn->layout = layout; + iviscrn->output = output; + + wl_list_init(&iviscrn->pending.layer_list); + wl_list_init(&iviscrn->order.layer_list); + wl_list_insert(&layout->screen_list, &iviscrn->link); +} + +static void +output_created_event(struct wl_listener *listener, void *data) +{ + struct weston_output *created_output = (struct weston_output*)data; + + add_screen(created_output); + ivi_layout_commit_changes(); +} + /** * Internal API to initialize ivi_screens found from output_list of weston_compositor. * Called by ivi_layout_init_with_compositor. @@ -266,27 +347,14 @@ ivi_layout_surface_destroy(struct ivi_layout_surface *ivisurf) static void create_screen(struct weston_compositor *ec) { + struct ivi_layout *layout = get_instance(); struct ivi_layout_screen *iviscrn = NULL; - struct weston_output *output = NULL; - - wl_list_for_each(output, &ec->output_list, link) { - iviscrn = calloc(1, sizeof *iviscrn); - if (iviscrn == NULL) { - weston_log("fails to allocate memory\n"); - continue; - } - iviscrn->layout = layout; - - iviscrn->output = output; - - wl_list_init(&iviscrn->pending.layer_list); - - wl_list_init(&iviscrn->order.layer_list); + struct weston_output *output = NULL; - wl_list_insert(&layout->screen_list, &iviscrn->link); - } + wl_list_for_each(output, &ec->output_list, link) + add_screen(output); } /** @@ -822,7 +890,18 @@ build_view_list(struct ivi_layout *layout) if (!ivi_view_is_mapped(ivi_view)) weston_view_unmap(ivi_view->view); } + struct weston_view *view = NULL; + struct weston_view *view_next = NULL; + /* Earlier only the head node was reset, but the remaining links + * won't be changed. Due to this, faced crash issue (or sometimes + * list was looping) in weston_view_destroy API. So clearing the + * entire list*/ + wl_list_for_each_safe(view, view_next, + &layout->layout_layer.view_list.link, layer_link.link) { + wl_list_remove(&view->layer_link.link); + wl_list_init(&view->layer_link.link); + } /* Clear view list of layout ivi_layer */ wl_list_init(&layout->layout_layer.view_list.link); @@ -1791,7 +1870,22 @@ ivi_layout_commit_changes(void) return IVI_SUCCEEDED; } +static void +output_resized_moved_events(struct wl_listener *listener, void *data) +{ + struct ivi_layout_screen *iviscrn = NULL; + struct ivi_layout_layer *ivilayer; + struct ivi_layout_view *ivi_view; + struct weston_output *output = (struct weston_output*)data; + iviscrn = get_screen_from_output(output); + + wl_list_for_each(ivilayer, &iviscrn->order.layer_list, order.link) { + wl_list_for_each(ivi_view, &ivilayer->order.view_list, + order_link) + update_prop(ivi_view); + } +} static int32_t ivi_layout_layer_set_transition(struct ivi_layout_layer *ivilayer, enum ivi_layout_transition_type type, @@ -1931,6 +2025,14 @@ surface_create(struct weston_surface *wl_surface, uint32_t id_surface) return NULL; } + ivisurf = get_surface(&layout->surface_list, id_surface); + if (ivisurf != NULL) { + if (ivisurf->surface != NULL) { + weston_log("id_surface(%d) is already created\n", id_surface); + return NULL; + } + } + ivisurf = calloc(1, sizeof *ivisurf); if (ivisurf == NULL) { weston_log("fails to allocate memory\n"); @@ -1954,6 +2056,8 @@ surface_create(struct weston_surface *wl_surface, uint32_t id_surface) wl_list_insert(&layout->surface_list, &ivisurf->link); + wl_signal_emit(&layout->surface_notification.created, ivisurf); + return ivisurf; } @@ -2006,8 +2110,8 @@ ivi_layout_surface_create(struct weston_surface *wl_surface, return ivisurf; } -static struct ivi_layout_interface ivi_layout_interface; +static struct ivi_layout_interface ivi_layout_interface; void ivi_layout_init_with_compositor(struct weston_compositor *ec) { @@ -2035,6 +2139,18 @@ ivi_layout_init_with_compositor(struct weston_compositor *ec) create_screen(ec); + layout->output_created.notify = output_created_event; + wl_signal_add(&ec->output_created_signal, &layout->output_created); + + layout->output_destroyed.notify = output_destroyed_event; + wl_signal_add(&ec->output_destroyed_signal, &layout->output_destroyed); + + layout->output_resized.notify = output_resized_moved_events; + wl_signal_add(&ec->output_resized_signal, &layout->output_resized); + + layout->output_moved.notify = output_resized_moved_events; + wl_signal_add(&ec->output_moved_signal, &layout->output_moved); + layout->transitions = ivi_layout_transition_set_create(ec); wl_list_init(&layout->pending_transition_list); -- 2.7.4