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.
This commit is contained in:
Hermet Park 2019-11-28 13:38:32 +09:00
parent f6caca1d70
commit 408bfb3e35
3 changed files with 27 additions and 85 deletions

View File

@ -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)

View File

@ -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;

View File

@ -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