From b84f268abea65d54088e444419a776fcb7bb5585 Mon Sep 17 00:00:00 2001 From: MinJeong Kim Date: Mon, 20 Mar 2017 16:23:21 +0900 Subject: [PATCH] Video buffers are included into window transition effect Change-Id: I996b5cf329ce871fc3100f6d0b8dcfbd47a69b74 Signed-off-by: MinJeong Kim --- configure.ac | 2 +- data/group/zoom.edc | 60 +++++ packaging/e-mod-tizen-effect.spec | 5 +- src/e_mod_effect.c | 466 ++++++++++++++++++++++++++++++-------- src/e_mod_effect.h | 2 + 5 files changed, 440 insertions(+), 95 deletions(-) diff --git a/configure.ac b/configure.ac index d1e0713..50adf4e 100644 --- a/configure.ac +++ b/configure.ac @@ -60,7 +60,7 @@ PKG_PROG_PKG_CONFIG dnl ======================================================================== # checks for pkg-config dnl ======================================================================== -PKG_CHECK_MODULES(ENLIGHTENMENT, [enlightenment]) +PKG_CHECK_MODULES(ENLIGHTENMENT, [enlightenment, wayland-server, tizen-extension-server, wayland-tbm-server, libtdm]) AC_SUBST(ENLIGHTENMENT_CFLAGS) AC_SUBST(ENLIGHTENMENT_LIBS) diff --git a/data/group/zoom.edc b/data/group/zoom.edc index e82b0a8..c266440 100644 --- a/data/group/zoom.edc +++ b/data/group/zoom.edc @@ -10,30 +10,35 @@ group { name: "e/comp/effects/zoom"; set_state(PART:"clipper", "default", 0.0); set_state(PART:"shower", "default", 0.0); set_state(PART:"e.swallow.content", "default", 0.0); + set_state(PART:"under", "default", 0.0); } else if (st == 1) { set_state(PART:"clipper", "visible", 0.0); set_state(PART:"shower", "visible", 0.0); set_state(PART:"e.swallow.content", "visible", 0.0); + set_state(PART:"under", "visible", 0.0); } else if (st == 2) { set_state(PART:"clipper", "restack_hidden", 0.0); set_state(PART:"shower", "restack_hidden", 0.0); set_state(PART:"e.swallow.content", "restack_hidden", 0.0); + set_state(PART:"under", "restack_hidden", 0.0); } else if (st == 3) { set_state(PART:"clipper", "restack_visible", 0.0); set_state(PART:"shower", "restack_visible", 0.0); set_state(PART:"e.swallow.content", "restack_visible", 0.0); + set_state(PART:"under", "restack_visible", 0.0); } else if (st == 4) { set_state(PART:"clipper", "restack_done", 0.0); set_state(PART:"shower", "restack_done", 0.0); set_state(PART:"e.swallow.content", "restack_done", 0.0); + set_state(PART:"under", "restack_done", 0.0); } } else if ((type == MSG_INT_SET) && (id == 1)) { @@ -137,6 +142,49 @@ group { name: "e/comp/effects/zoom"; inherit: "visible" 0.0; } } + part { name: "under"; + type: SWALLOW; + clip_to: "clipper"; + description { state: "default" 0.0; + rel1.to: "shower"; + rel2.to: "shower"; + map { + on: 1; + smooth: 1; + zoom.x: 0.9; + zoom.y: 0.9; + } + } + description { state: "visible" 0.0; + rel1.to: "shower"; + rel2.to: "shower"; + map { + on: 1; + smooth: 1; + zoom.x: 1; + zoom.y: 1; + } + } + description { state: "visible_default" 0.0; + rel1.to: "shower"; + rel2.to: "shower"; + rel1.relative: 0 0; + rel2.relative: 1 1; + map.on : 0; + } + description { state: "hide" 0.0; + inherit: "default" 0.0; + } + description { state: "restack_visible" 0.0; + inherit: "visible" 0.0; + } + description { state: "restack_hidden" 0.0; + inherit: "default" 0.0; + } + description { state: "restack_done" 0.0; + inherit: "visible" 0.0; + } + } } programs { program { name: "show1"; @@ -148,6 +196,7 @@ group { name: "e/comp/effects/zoom"; target: "shower"; target: "clipper"; target: "e.swallow.content"; + target: "under"; after: "show2"; } program { name: "show2"; @@ -156,10 +205,12 @@ group { name: "e/comp/effects/zoom"; target: "shower"; target: "clipper"; target: "e.swallow.content"; + target: "under"; after: "show3"; } program { name: "show3"; action: STATE_SET "visible_default" 0.0; + target: "under"; target: "e.swallow.content"; after: "done"; } @@ -172,6 +223,7 @@ group { name: "e/comp/effects/zoom"; target: "shower"; target: "clipper"; target: "e.swallow.content"; + target: "under"; after: "hide2"; } program { name: "hide2"; @@ -180,6 +232,7 @@ group { name: "e/comp/effects/zoom"; target: "shower"; target: "clipper"; target: "e.swallow.content"; + target: "under"; after: "hide3"; } program { name: "hide3"; @@ -187,6 +240,7 @@ group { name: "e/comp/effects/zoom"; target: "shower"; target: "clipper"; target: "e.swallow.content"; + target: "under"; after: "done"; } program { name: "restack,show1"; @@ -198,6 +252,7 @@ group { name: "e/comp/effects/zoom"; target: "shower"; target: "clipper"; target: "e.swallow.content"; + target: "under"; after: "restack,show2"; } program { name: "restack,show2"; @@ -206,11 +261,13 @@ group { name: "e/comp/effects/zoom"; target: "shower"; target: "clipper"; target: "e.swallow.content"; + target: "under"; after: "restack,show3"; } program { name: "restack,show3"; action: STATE_SET "visible_default" 0.0; target: "e.swallow.content"; + target: "under"; after: "done"; } program { name: "restack,hide1"; @@ -222,6 +279,7 @@ group { name: "e/comp/effects/zoom"; target: "shower"; target: "clipper"; target: "e.swallow.content"; + target: "under"; after: "restack,hide2"; } program { name: "restack,hide2"; @@ -230,6 +288,7 @@ group { name: "e/comp/effects/zoom"; target: "shower"; target: "clipper"; target: "e.swallow.content"; + target: "under"; after: "done"; } program { name: "restack,finish"; @@ -240,6 +299,7 @@ group { name: "e/comp/effects/zoom"; target: "shower"; target: "clipper"; target: "e.swallow.content"; + target: "under"; after: "done"; } program { name: "done"; diff --git a/packaging/e-mod-tizen-effect.spec b/packaging/e-mod-tizen-effect.spec index b091dde..1b44363 100644 --- a/packaging/e-mod-tizen-effect.spec +++ b/packaging/e-mod-tizen-effect.spec @@ -12,9 +12,10 @@ BuildRequires: pkgconfig(ecore) BuildRequires: pkgconfig(edje) BuildRequires: gettext BuildRequires: edje-tools -BuildRequires: pkgconfig(wayland-server) -BuildRequires: pkgconfig(tizen-extension-server) +BuildRequires: pkgconfig(wayland-server) +BuildRequires: pkgconfig(tizen-extension-server) BuildRequires: pkgconfig(wayland-tbm-server) +BuildRequires: pkgconfig(libtdm) %global TZ_SYS_RO_SHARE %{?TZ_SYS_RO_SHARE:%TZ_SYS_RO_SHARE}%{!?TZ_SYS_RO_SHARE:/usr/share} diff --git a/src/e_mod_effect.c b/src/e_mod_effect.c index d8d4a06..2fb2cc5 100644 --- a/src/e_mod_effect.c +++ b/src/e_mod_effect.c @@ -1,4 +1,5 @@ #include "e_mod_effect.h" +#include static E_Effect *_eff = NULL; @@ -10,8 +11,169 @@ typedef struct _E_Effect_Client E_Comp_Wl_Buffer_Ref buffer_ref; E_Pixmap *ep; E_Client *reverse_ec; + + Evas_Object *under; + unsigned int under_ref; } E_Effect_Client; +typedef struct +{ + tdm_layer *tlayer; + int zpos; +} Under_Layer; + +static int +_eff_object_underlayer_sort(const void *data1, const void *data2) +{ + const Under_Layer *layer1, *layer2; + + layer1 = data1; + layer2 = data2; + + if (layer1->zpos < layer2->zpos) + return -1; + else if (layer1->zpos > layer2->zpos) + return 1; + else + return 0; +} + +static Evas_Object * +_eff_object_underlayer_get(E_Client *ec) +{ + Evas_Object *underlay = NULL; + E_Comp_Screen *e_comp_screen; + Eina_List *l; + tdm_layer *layer; + Under_Layer *ulayer; + + e_comp_screen = e_comp->e_comp_screen; + if (!e_comp_screen) + return NULL; + + if (e_client_video_client_has(ec)) + { + if ((!_eff->under_layers) && (!_eff->under_checked)) + { + int i, count; + int primary_index, primary_zpos; + tdm_layer *primary_layer; + tdm_output *output; + tdm_layer_capability capabilities; + + output = tdm_display_get_output(e_comp_screen->tdisplay, 0, NULL); + if (!output) return NULL; + + tdm_output_get_primary_index(output, &primary_index); + primary_layer = tdm_output_get_layer(output, primary_index, NULL); + if (!primary_layer) return NULL; + + tdm_layer_get_zpos(primary_layer, &primary_zpos); + tdm_output_get_layer_count(output, &count); + + for (i = 0; i < count; i++) + { + int zpos; + + if (i == primary_index) continue; + + layer = tdm_output_get_layer(output, i, NULL); + if (!layer) continue; + + tdm_layer_get_capabilities(layer, &capabilities); + if (!(capabilities & TDM_LAYER_CAPABILITY_GRAPHIC)) continue; + + tdm_layer_get_zpos(layer, &zpos); + if (zpos >= primary_zpos) continue; + + ulayer = E_NEW(Under_Layer, 1); + ulayer->zpos = zpos; + ulayer->tlayer = layer; + + _eff->under_layers = eina_list_append(_eff->under_layers, + ulayer); + } + + _eff->under_checked = EINA_TRUE; + + if (!_eff->under_layers) + return NULL; + + _eff->under_layers = eina_list_sort(_eff->under_layers, + eina_list_count(_eff->under_layers), + _eff_object_underlayer_sort); + } + + if (!_eff->under_layers) return NULL; + + EINA_LIST_FOREACH(_eff->under_layers, l, ulayer) + { + tdm_layer *layer; + Evas_Object *img; + tbm_surface_h buffer; + Evas_Native_Surface ns; + tdm_info_layer info; + + layer = ulayer->tlayer; + + buffer = tdm_layer_get_displaying_buffer(layer, NULL); + if (!buffer) continue; + + img = evas_object_image_filled_add(e_comp->evas); + if (!img) continue; + + tdm_layer_get_info(layer, &info); + + if (info.dst_pos.w <= 0 || info.dst_pos.h <= 0) + + memset(&ns, 0, sizeof(Evas_Native_Surface)); + ns.version = EVAS_NATIVE_SURFACE_VERSION; + ns.type = EVAS_NATIVE_SURFACE_TBM; + ns.data.tbm.buffer = buffer; + + evas_object_image_size_set(img, info.dst_pos.w, info.dst_pos.h); + evas_object_image_native_surface_set(img, &ns); + evas_object_image_pixels_dirty_set(img, EINA_TRUE); + + if (!underlay) + { + Evas_Object *bg; + + underlay = e_layout_add(e_comp->evas); + if (!underlay) + { + evas_object_del(img); + return NULL; + } + + evas_object_name_set(underlay, "effect-under-layout"); + e_layout_virtual_size_set(underlay, ec->zone->w, ec->zone->h); + evas_object_move(underlay, ec->zone->x, ec->zone->y); + + bg = evas_object_rectangle_add(e_comp->evas); + evas_object_color_set(bg, 0, 0, 0, 255); + e_layout_pack(underlay, bg); + e_layout_child_move(bg, 0, 0); + e_layout_child_resize(bg, ec->zone->w, ec->zone->h); + evas_object_show(bg); + } + + e_layout_pack(underlay, img); + e_layout_child_move(img, info.dst_pos.x, info.dst_pos.y); + e_layout_child_resize(img, info.dst_pos.w, info.dst_pos.h); + e_layout_child_raise(img); + evas_object_show(img); + + EFFDBG("Video Object Created img(%p) %d,%d %dx%d underlay(%p)", + ec->pixmap, ec, + img, info.dst_pos.x, info.dst_pos.y, info.dst_pos.w, info.dst_pos.h, + underlay); + } + } + + return underlay; +} + static void _eff_event_send(E_Client *ec, Eina_Bool start, E_Effect_Type type) { @@ -87,6 +249,8 @@ _eff_client_new(E_Client *ec) efc->animating = 0; efc->delay_del_ref = 0; efc->ep = NULL; + efc->under_ref = 0; + efc->under = NULL; return efc; } @@ -147,97 +311,6 @@ _eff_group_angle_get(E_Client *ec, E_Effect_Group group) return ec->e.state.rot.ang.curr; } -static Eina_Bool -_eff_ref(E_Client *ec) -{ - E_Effect_Client *efc; - - if (!_eff) return EINA_FALSE; - - efc = _eff_client_get(ec); - if (!efc) return EINA_FALSE; - - if (e_object_is_del(E_OBJECT(ec))) - { - if (!e_object_delay_del_ref_get(E_OBJECT(ec))) - { - ERR("Client is deleted already! ec(%p)", ec); - eina_hash_del_by_key(_eff->clients, &ec); - return EINA_FALSE; - } - } - - if (!ec->pixmap) return EINA_FALSE; - if ((e_comp_object_content_type_get(ec->frame) == E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE) && - (!e_pixmap_usable_get(ec->pixmap))) - return EINA_FALSE; - - if (e_object_is_del(E_OBJECT(ec))) - { - e_object_delay_del_ref(E_OBJECT(ec)); - efc->delay_del_ref ++; - } - - efc->animating++; - e_object_ref(E_OBJECT(ec)); - efc->ep = e_pixmap_ref(ec->pixmap); - - EFFINF("effect ref efc(%p) animating:%d", - efc->ep, efc->ec, efc, efc->animating); - - return EINA_TRUE; -} - -static E_Client * -_eff_unref(E_Client *ec) -{ - E_Effect_Client *efc; - int do_unref = 1; - - if (!_eff) return NULL; - if (!ec) return NULL; - - efc = _eff_client_get(ec); - if (!efc) return NULL; - - while (efc->delay_del_ref) - { - e_object_delay_del_unref(E_OBJECT(ec)); - efc->delay_del_ref--; - } - - if (e_object_is_del(E_OBJECT(ec))) - do_unref = efc->animating; - - efc->animating -= do_unref; - while (do_unref) - { - e_pixmap_free(efc->ep); - if (!e_object_unref(E_OBJECT(ec))) - { - EFFINF("eff unref ec(%p) ep(%p) efc(%p) Client free'd", - NULL, NULL, ec, efc->ep, efc); - - efc->ec = NULL; - efc = NULL; - eina_hash_del_by_key(_eff->clients, &ec); - return NULL; - } - do_unref --; - } - - EFFINF("eff Unref efc(%p) animating:%d", - ec->pixmap, ec, efc, efc->animating); - - /* The reference count of wl_buffer will get decremented - * immediately after window effect. - */ - if ((efc) && (efc->buffer_ref.buffer)) - e_comp_wl_buffer_reference(&efc->buffer_ref, NULL); - - return ec; -} - static void _eff_object_setup(E_Client *ec, E_Effect_Group group) { @@ -278,6 +351,103 @@ _eff_object_setup(E_Client *ec, E_Effect_Group group) } static void +_eff_object_under_cb_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + E_Effect_Client *efc = (E_Effect_Client *)data; + Eina_List *children; + Evas_Object *child; + + if (efc->under != obj) return; + + children = e_layout_children_get(obj); + EINA_LIST_FREE(children, child) + { + e_layout_unpack(child); + evas_object_del(child); + } + + efc->under = NULL; + efc->under_ref = 0; +} + +static void +_eff_object_under_setup(E_Client *ec) +{ + E_Effect_Client *efc = NULL; + Evas_Object *underlay = NULL; + + efc = _eff_client_get(ec); + if (!efc) return; + + if (efc->under) + { + efc->under_ref ++; + } + else if ((underlay = _eff_object_underlayer_get(ec))) + { + Eina_List *children; + Evas_Object *child; + + if (e_comp_object_effect_object_part_swallow(ec->frame, "under", underlay)) + { + evas_object_event_callback_add(underlay, + EVAS_CALLBACK_DEL, + _eff_object_under_cb_del, + efc); + evas_object_show(underlay); + efc->under = underlay; + efc->under_ref ++; + } + else + { + children = e_layout_children_get(underlay); + EINA_LIST_FREE(children, child) + { + e_layout_unpack(child); + evas_object_del(child); + } + + evas_object_del(underlay); + } + } +} + +static void +_eff_object_under_del(E_Client *ec) +{ + E_Effect_Client *efc = NULL; + Eina_List *children; + Evas_Object *child; + + efc = _eff_client_get(ec); + if (!efc) return; + if (!efc->under) return; + if (efc->under_ref <= 0) + { + efc->under_ref = 0; + return; + } + + efc->under_ref --; + if (efc->under_ref > 0) return; + + evas_object_event_callback_del_full(efc->under, + EVAS_CALLBACK_DEL, + _eff_object_under_cb_del, + efc); + + children = e_layout_children_get(efc->under); + EINA_LIST_FREE(children, child) + { + e_layout_unpack(child); + evas_object_del(child); + } + + evas_object_del(efc->under); + efc->under = NULL; +} + +static void _eff_object_layer_up(E_Client *ec) { int map_ly; @@ -452,6 +622,100 @@ _eff_restack_effect_check(E_Client *ec) return emission; } +static Eina_Bool +_eff_ref(E_Client *ec) +{ + E_Effect_Client *efc; + + if (!_eff) return EINA_FALSE; + + efc = _eff_client_get(ec); + if (!efc) return EINA_FALSE; + + if (e_object_is_del(E_OBJECT(ec))) + { + if (!e_object_delay_del_ref_get(E_OBJECT(ec))) + { + ERR("Client is deleted already! ec(%p)", ec); + eina_hash_del_by_key(_eff->clients, &ec); + return EINA_FALSE; + } + } + + if (!ec->pixmap) return EINA_FALSE; + if ((e_comp_object_content_type_get(ec->frame) == E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE) && + (!e_pixmap_usable_get(ec->pixmap))) + return EINA_FALSE; + + if (e_object_is_del(E_OBJECT(ec))) + { + e_object_delay_del_ref(E_OBJECT(ec)); + efc->delay_del_ref ++; + } + + efc->animating++; + e_object_ref(E_OBJECT(ec)); + efc->ep = e_pixmap_ref(ec->pixmap); + + EFFINF("effect ref efc(%p) animating:%d", + efc->ep, efc->ec, efc, efc->animating); + + return EINA_TRUE; +} + +static E_Client * +_eff_unref(E_Client *ec) +{ + E_Effect_Client *efc; + int do_unref = 1; + + if (!_eff) return NULL; + if (!ec) return NULL; + + efc = _eff_client_get(ec); + if (!efc) return NULL; + + while (efc->delay_del_ref) + { + e_object_delay_del_unref(E_OBJECT(ec)); + efc->delay_del_ref--; + } + + if (e_object_is_del(E_OBJECT(ec))) + do_unref = efc->animating; + + efc->animating -= do_unref; + while (do_unref) + { + e_pixmap_free(efc->ep); + if (efc->under) + _eff_object_under_del(ec); + if (!e_object_unref(E_OBJECT(ec))) + { + EFFINF("eff unref ec(%p) ep(%p) efc(%p) Client free'd", + NULL, NULL, ec, efc->ep, efc); + + efc->ec = NULL; + efc = NULL; + eina_hash_del_by_key(_eff->clients, &ec); + return NULL; + } + do_unref --; + } + + EFFINF("eff Unref efc(%p) animating:%d", + ec->pixmap, ec, efc, efc->animating); + + /* The reference count of wl_buffer will get decremented + * immediately after window effect. + */ + if ((efc) && (efc->buffer_ref.buffer)) + e_comp_wl_buffer_reference(&efc->buffer_ref, NULL); + + return ec; +} + + static void _eff_cb_visible_done(void *data, Evas_Object *obj EINA_UNUSED, const char *sig EINA_UNUSED, const char *src EINA_UNUSED) { @@ -494,6 +758,8 @@ _eff_cb_visible(void *data, Evas_Object *obj, const char *signal) ec->extra_animating = EINA_TRUE; _eff_object_setup(ec, group); + _eff_object_under_setup(ec); + ang = _eff_group_angle_get(ec, group); e_comp_object_effect_params_set(ec->frame, 0, (int[]){0, ang}, 2); if (e_comp->nocomp) @@ -588,6 +854,8 @@ _eff_cb_hidden(void *data, Evas_Object *obj, const char *signal) _eff_object_layer_up(ec); _eff_object_setup(ec, group); + _eff_object_under_setup(ec); + ang = _eff_group_angle_get(ec, group); e_comp_object_effect_params_set(ec->frame, 0, (int[]){1, ang}, 2); @@ -696,6 +964,8 @@ _eff_cb_uniconify(void *data, Evas_Object *obj, const char *signal) e_comp_override_add(); _eff_object_setup(ec, group); + _eff_object_under_setup(ec); + ang = _eff_group_angle_get(ec, group); e_comp_object_effect_params_set(ec->frame, 0, (int[]){0, ang}, 2); @@ -770,6 +1040,8 @@ _eff_cb_iconify(void *data, Evas_Object *obj, const char *signal) e_comp_override_add(); _eff_object_setup(ec, group); + _eff_object_under_setup(ec); + ang = _eff_group_angle_get(ec, group); e_comp_object_effect_params_set(ec->frame, 0, (int[]){1, ang}, 2); @@ -931,6 +1203,8 @@ _eff_cb_restack(void *data, Evas_Object *obj, const char *signal) e_comp_override_add(); _eff_object_setup(ec, group); + _eff_object_under_setup(ec); + ang = _eff_group_angle_get(ec, group); e_comp_object_effect_params_set(ec->frame, 0, (int[]){2, ang}, 2); @@ -981,6 +1255,8 @@ _eff_cb_restack(void *data, Evas_Object *obj, const char *signal) _eff_object_layer_up(ec); _eff_object_setup(ec, group); + _eff_object_under_setup(ec); + ang = _eff_group_angle_get(ec, group); e_comp_object_effect_params_set(ec->frame, 0, (int[]){3, ang}, 2); @@ -1003,6 +1279,8 @@ _eff_cb_restack(void *data, Evas_Object *obj, const char *signal) e_comp_override_add(); _eff_object_setup(ec, group); + _eff_object_under_setup(ec); + ang = _eff_group_angle_get(ec, group); e_comp_object_effect_params_set(ec->frame, 0, (int[]){4, ang}, 2); @@ -1086,7 +1364,10 @@ _eff_cb_hook_client_del(void *d EINA_UNUSED, E_Client *ec) if ((efc = _eff_client_get(ec))) { if (!efc->animating) - eina_hash_del_by_key(_eff->clients, &ec); + { + _eff_object_under_del(ec); + eina_hash_del_by_key(_eff->clients, &ec); + } } } @@ -1311,6 +1592,7 @@ e_mod_effect_shutdown() E_FREE_FUNC(_eff->stack.old, eina_list_free); E_FREE_FUNC(_eff->stack.cur, eina_list_free); + E_FREE_LIST(_eff->under_layers, free); E_FREE_LIST(_eff->providers, e_comp_object_effect_mover_del); E_FREE_LIST(_eff->event_hdlrs, ecore_event_handler_del); E_FREE_LIST(_eff->hooks_ec, e_client_hook_del); diff --git a/src/e_mod_effect.h b/src/e_mod_effect.h index ab319a9..b7074ba 100644 --- a/src/e_mod_effect.h +++ b/src/e_mod_effect.h @@ -74,6 +74,8 @@ struct _E_Effect E_Effect_Type type; } next_done; + Eina_List *under_layers; + Eina_Bool under_checked; }; EAPI Eina_Bool e_mod_effect_init(void); -- 2.7.4