From: Hermet Park Date: Fri, 28 Dec 2018 08:46:09 +0000 (+0900) Subject: evas json: optimizing by reusing node-tree. X-Git-Tag: accepted/tizen/unified/20190107.065404~51 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F32%2F196432%2F1;p=platform%2Fupstream%2Fefl.git evas json: optimizing by reusing node-tree. We assume that structure of node tree(scene-graph) is not changable, its tree heirarchy would be same every frame. In this case, we don't need to reconstruct vector nodes, just resuse them of previous frames. Change-Id: I2dc43fac7eb784fd895228ae2b16f25997fccfa9 --- diff --git a/src/lib/evas/canvas/efl_canvas_vg_container.c b/src/lib/evas/canvas/efl_canvas_vg_container.c index b733db5..8277351 100644 --- a/src/lib/evas/canvas/efl_canvas_vg_container.c +++ b/src/lib/evas/canvas/efl_canvas_vg_container.c @@ -64,6 +64,11 @@ _prepare_mask(Evas_Object_Protected_Data *obj, //vector object pd->mask.bound.h = mbound.h; pd->mask.vg_pd = obj; } + else + { + if (pd->mask.pixels) + memset(pd->mask.pixels, 0x0, sizeof(uint32_t) * mbound.w * mbound.h); + } pd->mask.bound.x = mbound.x; pd->mask.bound.y = mbound.y; diff --git a/src/lib/evas/canvas/efl_canvas_vg_object.c b/src/lib/evas/canvas/efl_canvas_vg_object.c index 1d18e66..46df97d 100644 --- a/src/lib/evas/canvas/efl_canvas_vg_object.c +++ b/src/lib/evas/canvas/efl_canvas_vg_object.c @@ -576,7 +576,7 @@ _render_to_buffer(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd //caching buffer only for first and last frames. if (buffer_created && cacheable) - ENFN->ector_surface_cache_set(engine, key, buffer); + ENFN->ector_surface_cache_set(engine, ((void *) key) + pd->frame_index, buffer); return buffer; } @@ -661,15 +661,14 @@ _cache_vg_entry_render(Evas_Object_Protected_Data *obj, } root = evas_cache_vg_tree_get(vg_entry, pd->frame_index); if (!root) return; - - void *buffer = ENFN->ector_surface_cache_get(engine, root); + void *buffer = ENFN->ector_surface_cache_get(engine, ((void *) root) + pd->frame_index); if (!buffer) buffer = _render_to_buffer(obj, pd, engine, root, w, h, root, NULL, do_async, cacheable); else //cache reference was increased when we get the cache. - ENFN->ector_surface_cache_drop(engine, root); + ENFN->ector_surface_cache_drop(engine, ((void *) root) + pd->frame_index); _render_buffer_to_screen(obj, engine, output, context, surface, diff --git a/src/static_libs/vg_common/vg_common_json.c b/src/static_libs/vg_common/vg_common_json.c index c3f6d9e..b41b267 100644 --- a/src/static_libs/vg_common/vg_common_json.c +++ b/src/static_libs/vg_common/vg_common_json.c @@ -6,23 +6,64 @@ #include #ifdef BUILD_VG_LOADER_JSON + +static char* +_get_key_val(void *key) +{ + static char buf[20]; + snprintf(buf, sizeof(buf), "%ld", (size_t) key); + return buf; +} + static void -_construct_drawable_nodes(Efl_VG *root, const LOTLayerNode *layer, int depth EINA_UNUSED) +_construct_drawable_nodes(Efl_Canvas_Vg_Container *parent, const LOTLayerNode *layer, int depth EINA_UNUSED) { - Efl_VG *parent = root; if (!parent) return; +#if TREE_VERIFY + Eina_Bool verified = EINA_TRUE; + Eina_Iterator *itr = efl_canvas_vg_container_children_get(parent); + if (itr) + { + Efl_Canvas_Vg_Shape *child; + int i = 0; + EINA_ITERATOR_FOREACH(itr, child) + { + if (!efl_isa(child, EFL_CANVAS_VG_SHAPE_CLASS)) continue; + + LOTNode *node = layer->mNodeList.ptr[i]; + if (efl_key_data_get(parent, _get_key_val(node)) != child) + { + verified = EINA_FALSE; + } + i++; + efl_gfx_entity_visible_set(child, EINA_FALSE); + } + eina_iterator_free(itr); + } + if (!verified) ERR("Shape: Failed to verify!"); +#endif + for (unsigned int i = 0; i < layer->mNodeList.size; i++) { - const LOTNode *node = layer->mNodeList.ptr[i]; + LOTNode *node = layer->mNodeList.ptr[i]; if (!node) continue; const float *data = node->mPath.ptPtr; if (!data) continue; - Efl_VG* shape = efl_add(EFL_CANVAS_VG_SHAPE_CLASS, parent); - if (!shape) continue; -#if 0 + char *key = _get_key_val(node); + Efl_Canvas_Vg_Shape *shape = efl_key_data_get(parent, key); + if (!shape) + { + shape = efl_add(EFL_CANVAS_VG_SHAPE_CLASS, parent); + efl_key_data_set(parent, key, shape); + } + else + efl_gfx_path_reset(shape); + + efl_gfx_entity_visible_set(shape, EINA_TRUE); +#if DEBUG for (int i = 0; i < depth; i++) printf(" "); printf("%s (%p)\n", efl_class_name_get(efl_class_get(shape)), shape); #endif @@ -118,7 +159,7 @@ _construct_drawable_nodes(Efl_VG *root, const LOTLayerNode *layer, int depth EIN break; case BrushGradient: { - Efl_VG* grad = NULL; + Efl_Canvas_Vg_Gradient* grad = NULL; if (node->mGradient.type == GradientLinear) { @@ -174,10 +215,38 @@ _construct_drawable_nodes(Efl_VG *root, const LOTLayerNode *layer, int depth EIN } static void -_update_vg_tree(Efl_VG *root, const LOTLayerNode *layer, int depth EINA_UNUSED) +_update_vg_tree(Efl_Canvas_Vg_Container *root, const LOTLayerNode *layer, int depth EINA_UNUSED) { - Efl_VG *ptree = NULL; - Efl_VG *ctree = NULL; + if (!layer->mVisible) + { + efl_gfx_entity_visible_set(root, EINA_FALSE); + return; + } + efl_gfx_entity_visible_set(root, EINA_TRUE); + +#if TREE_VERIFY + Eina_Bool verified = EINA_TRUE; + Eina_Iterator *itr = efl_canvas_vg_container_children_get(root); + if (itr) + { + Efl_Canvas_Vg_Node *child; + int i = 0; + EINA_ITERATOR_FOREACH(itr, child) + { + if (!efl_isa(child, EFL_CANVAS_VG_CONTAINER_CLASS)) continue; + LOTLayerNode *clayer = layer->mLayerList.ptr[i]; + if (efl_key_data_get(root, _get_key_val(clayer)) != child) + { + verified = EINA_FALSE; + } + + i++; + } + eina_iterator_free(itr); + } + if (!verified) ERR("Layer: Failed to verify!"); +#endif + Efl_Canvas_Vg_Container *ptree = NULL; //Note: We assume that if matte is valid, next layer must be a matte source. LOTMatteType matte = MatteNone; @@ -186,29 +255,38 @@ _update_vg_tree(Efl_VG *root, const LOTLayerNode *layer, int depth EINA_UNUSED) //Is this layer a container layer? for (unsigned int i = 0; i < layer->mLayerList.size; i++) { - if (!layer->mLayerList.ptr[i]->mVisible || skip) + LOTLayerNode *clayer = layer->mLayerList.ptr[i]; + + //FIXME: we can skip at the top of this function if mVisible is false. + if (skip) { //Next layer must be a dummy. so skip it. - if (layer->mLayerList.ptr[i]->mMatte != MatteNone) + if (clayer->mMatte != MatteNone) skip = EINA_TRUE; else skip = EINA_FALSE; continue; } - ctree = efl_add(EFL_CANVAS_VG_CONTAINER_CLASS, root); -#if 0 + char *key = _get_key_val(clayer); + Efl_Canvas_Vg_Container *ctree = efl_key_data_get(root, key); + if (!ctree) + { + ctree = efl_add(EFL_CANVAS_VG_CONTAINER_CLASS, root); + efl_key_data_set(root, key, ctree); + } +#if DEBUG for (int i = 0; i < depth; i++) printf(" "); printf("%s (%p) matte:%d => %p\n", efl_class_name_get(efl_class_get(ctree)), ctree, matte, ptree); #endif - _update_vg_tree(ctree, layer->mLayerList.ptr[i], depth+1); + _update_vg_tree(ctree, clayer, depth+1); //TODO: Only valid for MatteAlphaInverse? //TODO: Set this blending option to efl_canvas_vg_node... if (matte != MatteNone) efl_canvas_vg_node_mask_set(ptree, ctree, matte); - matte = layer->mLayerList.ptr[i]->mMatte; + matte = clayer->mMatte; ptree = ctree; //Debug Matte Info @@ -242,19 +320,32 @@ vg_common_json_create_vg_node(Vg_File_Data *vfd) Lottie_Animation *lot_anim = (Lottie_Animation *) vfd->loader_data; if (!lot_anim) return EINA_FALSE; - //Root node - if (vfd->root) efl_unref(vfd->root); - - vfd->root = efl_add_ref(EFL_CANVAS_VG_CONTAINER_CLASS, NULL); - Efl_VG *root = vfd->root; - if (!root) return EINA_FALSE; unsigned int frame_num = (vfd->anim_data) ? vfd->anim_data->frame_num : 0; const LOTLayerNode *tree = lottie_animation_render_tree(lot_anim, frame_num, vfd->view_box.w, vfd->view_box.h); -#if 0 +#if DEBUG printf("%s (%p)\n", efl_class_name_get(efl_class_get(vfd->root)), vfd->root); #endif + + //Root node + Efl_Canvas_Vg_Container *root = vfd->root; + if (!root) + { + root = efl_add_ref(EFL_CANVAS_VG_CONTAINER_CLASS, NULL); + if (!root) return EINA_FALSE; + efl_key_data_set(root, _get_key_val((void *) tree), tree); + vfd->root = root; + } + else + { +#if TREE_VERIFY + if (efl_key_data_get(root, _get_key_val((void *) tree)) != tree) + { + ERR("Root: Failed to verify!"); + } +#endif + } _update_vg_tree(root, tree, 1); #else return EINA_FALSE;