hermet pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=408bfb3e355cb101611e314e358183320c56d587
commit 408bfb3e355cb101611e314e358183320c56d587 Author: Hermet Park <[email protected]> Date: Thu Nov 28 13:38:32 2019 +0900 evas vector: make it stable caching logic. We need a more precise caching mechanism to save memory. Current root node(key) is limited for caching buffers, when to share by the multiple animated instances. This patch is a step for further optmization work, at the moment we disable the caching buffers for the animated instances. --- src/lib/evas/canvas/efl_canvas_vg_object.c | 23 ++++---- src/lib/evas/canvas/evas_vg_private.h | 2 +- src/lib/evas/vg/evas_vg_cache.c | 87 ++++++------------------------ 3 files changed, 27 insertions(+), 85 deletions(-) diff --git a/src/lib/evas/canvas/efl_canvas_vg_object.c b/src/lib/evas/canvas/efl_canvas_vg_object.c index 2b66d17109..d0b3a242c1 100644 --- a/src/lib/evas/canvas/efl_canvas_vg_object.c +++ b/src/lib/evas/canvas/efl_canvas_vg_object.c @@ -565,6 +565,7 @@ _cache_vg_entry_render(Evas_Object_Protected_Data *obj, Vg_Cache_Entry *vg_entry = pd->vg_entry; Efl_VG *root; Eina_Position2D offset = {0, 0}; //Offset after keeping aspect ratio. + Eina_Bool drop_cache = EINA_FALSE; void *buffer = NULL; evas_cache_vg_entry_value_provider_update(pd->vg_entry, efl_key_data_get(obj->object, "_vg_value_providers")); @@ -601,10 +602,7 @@ _cache_vg_entry_render(Evas_Object_Protected_Data *obj, //Size is changed, cached data is invalid. if ((size.w != vg_entry->w) || (size.h != vg_entry->h)) { - //if the size doesn't match, drop previous cache surfaces. - ENFN->ector_surface_cache_drop(engine, (void *) vg_entry->root[1]); - ENFN->ector_surface_cache_drop(engine, (void *) vg_entry->root[2]); - + drop_cache = EINA_TRUE; vg_entry = evas_cache_vg_entry_resize(vg_entry, size.w, size.h); evas_cache_vg_entry_del(pd->vg_entry); pd->vg_entry = vg_entry; @@ -624,12 +622,17 @@ _cache_vg_entry_render(Evas_Object_Protected_Data *obj, if (cacheable) { + //if the size doesn't match, drop previous cache surface. + if (drop_cache) + ENFN->ector_surface_cache_drop(engine, (void *) root); //Cache Hit! - buffer = ENFN->ector_surface_cache_get(engine, (void *) root); + else + buffer = ENFN->ector_surface_cache_get(engine, (void *) root); } if (!buffer) - buffer = _render_to_buffer(obj, pd, engine, root, w, h, NULL, do_async, cacheable); + buffer = _render_to_buffer(obj, pd, engine, root, w, h, NULL, + do_async, cacheable); else //cache reference was increased when we get the cache. ENFN->ector_surface_cache_drop(engine, (void *) root); @@ -712,12 +715,8 @@ _efl_canvas_vg_object_render(Evas_Object *eo_obj EINA_UNUSED, //Cache surface? Eina_Bool cacheable = EINA_FALSE; - /* Try caching buffer only for first and last frames - because it's an overhead task if it caches all frame images. - We assume the first and last frame images are the most resusable - in generic scenarios. */ - if (pd->frame_idx == 0 || - (pd->frame_idx == (int) (evas_cache_vg_anim_frame_count_get(pd->vg_entry) - 1))) + /* Try caching buffer only for static images. */ + if (evas_cache_vg_anim_frame_count_get(pd->vg_entry) == 0) cacheable = EINA_TRUE; if (pd->vg_entry) diff --git a/src/lib/evas/canvas/evas_vg_private.h b/src/lib/evas/canvas/evas_vg_private.h index 8a36fd826d..c5ee9c40d2 100644 --- a/src/lib/evas/canvas/evas_vg_private.h +++ b/src/lib/evas/canvas/evas_vg_private.h @@ -26,7 +26,7 @@ typedef struct _Vg_Cache_Entry Eina_Stringshare *key; int w; int h; - Efl_VG *root[3]; //0: default, 1: start frame, 2: end frame + Efl_VG *root; int ref; Vg_File_Data *vfd; } Vg_Cache_Entry; diff --git a/src/lib/evas/vg/evas_vg_cache.c b/src/lib/evas/vg/evas_vg_cache.c index 68d4e7a634..54925bd82d 100644 --- a/src/lib/evas/vg/evas_vg_cache.c +++ b/src/lib/evas/vg/evas_vg_cache.c @@ -83,9 +83,7 @@ _vg_load_from_file(const Eina_File *file, const char *key) if (em) { loader = em->functions; - { - vfd = loader->file_open((Eina_File *) file, key, &error); - } + vfd = loader->file_open((Eina_File *) file, key, &error); if (vfd) { vfd->loader = loader; @@ -167,9 +165,7 @@ _evas_cache_vg_entry_free_cb(void *data) eina_stringshare_del(vg_entry->key); free(vg_entry->hash_key); - efl_unref(vg_entry->root[0]); - efl_unref(vg_entry->root[1]); - efl_unref(vg_entry->root[2]); + efl_unref(vg_entry->root); free(vg_entry); } @@ -198,42 +194,8 @@ _vg_file_save(Vg_File_Data *vfd, const char *file, const char *key, const Efl_Fi return EINA_TRUE; } -static Efl_VG* -_cached_root_get(Vg_Cache_Entry *vg_entry, unsigned int frame_num) -{ - Vg_File_Data *vfd = vg_entry->vfd; - - //Case 1: Animatable - if (vfd->anim_data) - { - //Start frame - if (vg_entry->root[1] && frame_num == 0) - { - return vg_entry->root[1]; - } - //End frame - else if (vg_entry->root[2] && (frame_num == (vfd->anim_data->frame_cnt - 1))) - { - return vg_entry->root[2]; - } - //Current frame - else if (vg_entry->root[0] && (frame_num == (vfd->anim_data->frame_num))) - { - return vg_entry->root[0]; - } - } - //Case 2: Static - else - { - if (vg_entry->root[0]) - return vg_entry->root[0]; - } - - return NULL; -} - -static Efl_VG * -_caching_root_update(Vg_Cache_Entry *vg_entry) +static void +_root_update(Vg_Cache_Entry *vg_entry) { Vg_File_Data *vfd = vg_entry->vfd; @@ -246,33 +208,14 @@ _caching_root_update(Vg_Cache_Entry *vg_entry) /* TODO: Yet trivial but still we may have a better solution to avoid this unnecessary copy. If the ector surface key is not to this root pointer. */ - vg_entry->root[0] = efl_duplicate(vfd->root); + vg_entry->root = efl_duplicate(vfd->root); } - else + //Shareable?? + else if (vg_entry->root != vfd->root) { - if (vg_entry->root[0]) efl_unref(vg_entry->root[0]); - vg_entry->root[0] = efl_duplicate(vfd->root); - - //Animatable? - if (vfd->anim_data) - { - //Start frame - if (vfd->anim_data->frame_num == 0) - { - if (vg_entry->root[1]) efl_unref(vg_entry->root[1]); - vg_entry->root[1] = efl_duplicate(vfd->root); - return vg_entry->root[1]; - } - //End frame - else if (vfd->anim_data->frame_num == (vfd->anim_data->frame_cnt - 1)) - { - if (vg_entry->root[2]) efl_unref(vg_entry->root[2]); - vg_entry->root[2] = efl_duplicate(vfd->root); - return vg_entry->root[2]; - } - } + if (vg_entry->root) efl_unref(vg_entry->root); + vg_entry->root = efl_ref(vfd->root); } - return vg_entry->root[0]; } static void @@ -374,7 +317,6 @@ evas_cache_vg_entry_create(Evas *evas, if (!vg_cache) return NULL; //TODO: zero-sized entry is useless. how to skip it? - // hash_key = eina_strbuf_new(); eina_strbuf_append_printf(hash_key, "%p/%p/%s/%d/%d/%p", evas, file, key, w, h, vp_list); vg_entry = eina_hash_find(vg_cache->vg_entry_hash, eina_strbuf_string_get(hash_key)); @@ -488,8 +430,9 @@ evas_cache_vg_tree_get(Vg_Cache_Entry *vg_entry, unsigned int frame_num) Vg_File_Data *vfd = vg_entry->vfd; if (!vfd) return NULL; - Efl_VG *root = _cached_root_get(vg_entry, frame_num); - if (root) return root; + //No need to update. + if (!vfd->anim_data && vg_entry->root) + return vg_entry->root; if (!vfd->static_viewbox) { @@ -501,11 +444,11 @@ evas_cache_vg_tree_get(Vg_Cache_Entry *vg_entry, unsigned int frame_num) if (!vfd->loader->file_data(vfd)) return NULL; - root = _caching_root_update(vg_entry); + _root_update(vg_entry); - _local_transform(root, vg_entry->w, vg_entry->h, vfd); + _local_transform(vg_entry->root, vg_entry->w, vg_entry->h, vfd); - return root; + return vg_entry->root; } void --
