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;
|
Vg_Cache_Entry *vg_entry = pd->vg_entry;
|
||||||
Efl_VG *root;
|
Efl_VG *root;
|
||||||
Eina_Position2D offset = {0, 0}; //Offset after keeping aspect ratio.
|
Eina_Position2D offset = {0, 0}; //Offset after keeping aspect ratio.
|
||||||
|
Eina_Bool drop_cache = EINA_FALSE;
|
||||||
void *buffer = NULL;
|
void *buffer = NULL;
|
||||||
|
|
||||||
evas_cache_vg_entry_value_provider_update(pd->vg_entry, efl_key_data_get(obj->object, "_vg_value_providers"));
|
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.
|
//Size is changed, cached data is invalid.
|
||||||
if ((size.w != vg_entry->w) || (size.h != vg_entry->h))
|
if ((size.w != vg_entry->w) || (size.h != vg_entry->h))
|
||||||
{
|
{
|
||||||
//if the size doesn't match, drop previous cache surfaces.
|
drop_cache = EINA_TRUE;
|
||||||
ENFN->ector_surface_cache_drop(engine, (void *) vg_entry->root[1]);
|
|
||||||
ENFN->ector_surface_cache_drop(engine, (void *) vg_entry->root[2]);
|
|
||||||
|
|
||||||
vg_entry = evas_cache_vg_entry_resize(vg_entry, size.w, size.h);
|
vg_entry = evas_cache_vg_entry_resize(vg_entry, size.w, size.h);
|
||||||
evas_cache_vg_entry_del(pd->vg_entry);
|
evas_cache_vg_entry_del(pd->vg_entry);
|
||||||
pd->vg_entry = vg_entry;
|
pd->vg_entry = vg_entry;
|
||||||
|
@ -624,12 +622,17 @@ _cache_vg_entry_render(Evas_Object_Protected_Data *obj,
|
||||||
|
|
||||||
if (cacheable)
|
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!
|
//Cache Hit!
|
||||||
buffer = ENFN->ector_surface_cache_get(engine, (void *) root);
|
else
|
||||||
|
buffer = ENFN->ector_surface_cache_get(engine, (void *) root);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!buffer)
|
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
|
else
|
||||||
//cache reference was increased when we get the cache.
|
//cache reference was increased when we get the cache.
|
||||||
ENFN->ector_surface_cache_drop(engine, (void *) root);
|
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?
|
//Cache surface?
|
||||||
Eina_Bool cacheable = EINA_FALSE;
|
Eina_Bool cacheable = EINA_FALSE;
|
||||||
|
|
||||||
/* Try caching buffer only for first and last frames
|
/* Try caching buffer only for static images. */
|
||||||
because it's an overhead task if it caches all frame images.
|
if (evas_cache_vg_anim_frame_count_get(pd->vg_entry) == 0)
|
||||||
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)))
|
|
||||||
cacheable = EINA_TRUE;
|
cacheable = EINA_TRUE;
|
||||||
|
|
||||||
if (pd->vg_entry)
|
if (pd->vg_entry)
|
||||||
|
|
|
@ -26,7 +26,7 @@ typedef struct _Vg_Cache_Entry
|
||||||
Eina_Stringshare *key;
|
Eina_Stringshare *key;
|
||||||
int w;
|
int w;
|
||||||
int h;
|
int h;
|
||||||
Efl_VG *root[3]; //0: default, 1: start frame, 2: end frame
|
Efl_VG *root;
|
||||||
int ref;
|
int ref;
|
||||||
Vg_File_Data *vfd;
|
Vg_File_Data *vfd;
|
||||||
} Vg_Cache_Entry;
|
} Vg_Cache_Entry;
|
||||||
|
|
|
@ -83,9 +83,7 @@ _vg_load_from_file(const Eina_File *file, const char *key)
|
||||||
if (em)
|
if (em)
|
||||||
{
|
{
|
||||||
loader = em->functions;
|
loader = em->functions;
|
||||||
{
|
vfd = loader->file_open((Eina_File *) file, key, &error);
|
||||||
vfd = loader->file_open((Eina_File *) file, key, &error);
|
|
||||||
}
|
|
||||||
if (vfd)
|
if (vfd)
|
||||||
{
|
{
|
||||||
vfd->loader = loader;
|
vfd->loader = loader;
|
||||||
|
@ -167,9 +165,7 @@ _evas_cache_vg_entry_free_cb(void *data)
|
||||||
|
|
||||||
eina_stringshare_del(vg_entry->key);
|
eina_stringshare_del(vg_entry->key);
|
||||||
free(vg_entry->hash_key);
|
free(vg_entry->hash_key);
|
||||||
efl_unref(vg_entry->root[0]);
|
efl_unref(vg_entry->root);
|
||||||
efl_unref(vg_entry->root[1]);
|
|
||||||
efl_unref(vg_entry->root[2]);
|
|
||||||
free(vg_entry);
|
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;
|
return EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Efl_VG*
|
static void
|
||||||
_cached_root_get(Vg_Cache_Entry *vg_entry, unsigned int frame_num)
|
_root_update(Vg_Cache_Entry *vg_entry)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
Vg_File_Data *vfd = vg_entry->vfd;
|
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
|
/* TODO: Yet trivial but still we may have a better solution to
|
||||||
avoid this unnecessary copy. If the ector surface key is not
|
avoid this unnecessary copy. If the ector surface key is not
|
||||||
to this root pointer. */
|
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]);
|
if (vg_entry->root) efl_unref(vg_entry->root);
|
||||||
vg_entry->root[0] = efl_duplicate(vfd->root);
|
vg_entry->root = efl_ref(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];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return vg_entry->root[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -374,7 +317,6 @@ evas_cache_vg_entry_create(Evas *evas,
|
||||||
if (!vg_cache) return NULL;
|
if (!vg_cache) return NULL;
|
||||||
|
|
||||||
//TODO: zero-sized entry is useless. how to skip it?
|
//TODO: zero-sized entry is useless. how to skip it?
|
||||||
//
|
|
||||||
hash_key = eina_strbuf_new();
|
hash_key = eina_strbuf_new();
|
||||||
eina_strbuf_append_printf(hash_key, "%p/%p/%s/%d/%d/%p", evas, file, key, w, h, vp_list);
|
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));
|
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;
|
Vg_File_Data *vfd = vg_entry->vfd;
|
||||||
if (!vfd) return NULL;
|
if (!vfd) return NULL;
|
||||||
|
|
||||||
Efl_VG *root = _cached_root_get(vg_entry, frame_num);
|
//No need to update.
|
||||||
if (root) return root;
|
if (!vfd->anim_data && vg_entry->root)
|
||||||
|
return vg_entry->root;
|
||||||
|
|
||||||
if (!vfd->static_viewbox)
|
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;
|
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
|
void
|
||||||
|
|
Loading…
Reference in New Issue