forked from enlightenment/efl
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:
parent
f6caca1d70
commit
408bfb3e35
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue