}
EOLIAN static Efl_VG *
-_efl_canvas_vg_root_node_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Vg_Data *pd)
+_efl_canvas_vg_root_node_get(const Eo *obj, Efl_Canvas_Vg_Data *pd)
{
Efl_VG *root;
- if (pd->vg_entry) root = evas_cache_vg_tree_get(pd->vg_entry, pd->frame_index);
+ if (pd->vg_entry)
+ {
+ Evas_Coord w, h;
+ evas_object_geometry_get(obj, NULL, NULL, &w, &h);
+
+ //Update vg data with current size.
+ if ((pd->vg_entry->w != w) || (pd->vg_entry->h != h))
+ {
+ Vg_Cache_Entry *vg_entry = evas_cache_vg_entry_resize(pd->vg_entry, w, h);
+ evas_cache_vg_entry_del(pd->vg_entry);
+ pd->vg_entry = vg_entry;
+ }
+ root = evas_cache_vg_tree_get(pd->vg_entry, pd->frame_index);
+ }
else if (pd->user_entry) root = pd->user_entry->root;
else root = pd->root;
// drop any surface cache attached to it.
Evas_Object_Protected_Data *eobj = efl_data_scope_get(obj, EFL_CANVAS_OBJECT_CLASS);
eobj->layer->evas->engine.func->ector_surface_cache_drop(_evas_engine_context(eobj->layer->evas),
- pd->cache_key);
+ pd->user_entry->root);
free(pd->user_entry);
pd->user_entry = NULL;
}
// force a redraw
pd->changed = EINA_TRUE;
- pd->cache_key = NULL;
evas_object_change(obj, efl_data_scope_get(obj, EFL_CANVAS_OBJECT_CLASS));
}
else
pd->vg_entry = NULL;
- pd->cache_key = NULL;
evas_object_change(eo_obj, obj);
evas_cache_vg_entry_del(old_entry);
}
}
-// renders a vg_tree to an offscreen buffer
-// and push it to the cache.
+//renders a vg_tree to an offscreen buffer and push it to the cache.
static void *
_render_to_buffer(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Data *pd,
void *engine, void *surface,
ector = evas_ector_get(obj->layer->evas);
if (!ector) return NULL;
+ //create a buffer
if (!buffer)
{
- // 2. create a buffer
buffer = obj->layer->evas->engine.func->ector_surface_create(engine,
w, h,
&error);
- if (error) return NULL; // surface creation error
+ if (error) return NULL;
buffer_created = EINA_TRUE;
}
- //1. render pre
_evas_vg_render_pre(root, ector, NULL);
- //3. draw into the buffer
+ //initialize buffer
context = evas_common_draw_context_new();
evas_common_draw_context_set_render_op(context, _EVAS_RENDER_COPY);
evas_common_draw_context_set_color(context, 255, 255, 255, 255);
ector,
0, 0,
do_async);
+ //draw on buffer
_evas_vg_render(obj, pd,
engine, buffer,
context, surface,
evas_common_draw_context_free(context);
+ //caching buffer only for first and last frames.
if (buffer_created)
{
- pd->cache_key = key;
- obj->layer->evas->engine.func->ector_surface_cache_set(engine, key, buffer);
+ if (pd->frame_index == 0 ||
+ (pd->frame_index == (int) evas_cache_vg_anim_frame_count_get(pd->vg_entry) - 1))
+ obj->layer->evas->engine.func->ector_surface_cache_set(engine, key, buffer);
}
return buffer;
{
Vg_Cache_Entry *vg_entry = pd->vg_entry;
Efl_VG *root;
- void *buffer;
// if the size changed in between path set and the draw call;
+
if ((vg_entry->w != w) ||
(vg_entry->h != h))
{
vg_entry = evas_cache_vg_entry_resize(vg_entry, w, h);
evas_cache_vg_entry_del(pd->vg_entry);
pd->vg_entry = vg_entry;
- pd->cache_key = NULL;
}
root = evas_cache_vg_tree_get(vg_entry, pd->frame_index);
if (!root) return;
- buffer = obj->layer->evas->engine.func->ector_surface_cache_get(engine, pd->cache_key);
- // if the buffer is not created yet
+ void *buffer = obj->layer->evas->engine.func->ector_surface_cache_get(engine, root);
+
if (!buffer)
- {
- // render to the buffer
- buffer = _render_to_buffer(obj, pd,
- engine, surface,
- root,
- w, h,
- root,
- buffer,
- do_async);
- }
+ buffer = _render_to_buffer(obj, pd, engine, surface, root, w, h, root, NULL, do_async);
else
- obj->layer->evas->engine.func->ector_surface_cache_drop(engine, pd->cache_key);
+ //cache reference was increased when we get the cache.
+ obj->layer->evas->engine.func->ector_surface_cache_drop(engine, root);
_render_buffer_to_screen(obj,
engine, output, context, surface,
int x, int y, int w, int h, Eina_Bool do_async)
{
Vg_User_Entry *user_entry = pd->user_entry;
- void *buffer;
- //if the size dosen't match
+ //if the size doesn't match, drop previous cache surface.
if ((user_entry->w != w ) ||
(user_entry->h != h))
{
- obj->layer->evas->engine.func->ector_surface_cache_drop(engine, user_entry);
+ obj->layer->evas->engine.func->ector_surface_cache_drop(engine, user_entry->root);
user_entry->w = w;
user_entry->h = h;
- pd->user_entry = user_entry;
}
//if the buffer is not created yet
- buffer = obj->layer->evas->engine.func->ector_surface_cache_get(engine, pd->cache_key);
+ void *buffer = obj->layer->evas->engine.func->ector_surface_cache_get(engine, user_entry->root);
+
if (!buffer)
{
// render to the buffer
user_entry,
buffer,
do_async);
- obj->layer->evas->engine.func->ector_surface_cache_drop(engine, pd->cache_key);
+ //cache reference was increased when we get the cache.
+ obj->layer->evas->engine.func->ector_surface_cache_drop(engine, user_entry->root);
}
_render_buffer_to_screen(obj,
if (pd->frame_index == frame_index) return EINA_TRUE;
//Image is changed, drop previous cached image.
- pd->cache_key = NULL;
pd->frame_index = frame_index;
pd->changed = EINA_TRUE;
evas_object_change(eo_obj, efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS));
{
Vg_File_Data *vfd = vg_entry->vfd;
- if (vfd->static_viewbox || ((vfd->view_box.w == vg_entry->w) && (vfd->view_box.h == vg_entry->h)))
+ //Case 1: Animatable
+ if (vfd->anim_data)
{
- //Case 1: Animatable
- if (vfd->anim_data)
+ //Start frame
+ if (vg_entry->root[1] && frame_num == 0)
{
- //Start frame
- if (vg_entry->root[1] && frame_num == 0)
- {
- return vg_entry->root[1];
- }
- else if (vg_entry->root[2] && (frame_num == (vfd->anim_data->frame_cnt - 1)))
- {
- return vg_entry->root[2];
- }
+ return vg_entry->root[1];
}
- //Case 2: Static
- else
+ else if (vg_entry->root[2] && (frame_num == (vfd->anim_data->frame_cnt - 1)))
{
- if (vg_entry->root[0])
- return vg_entry->root[0];
+ return vg_entry->root[2];
}
}
+ //Case 2: Static
+ else
+ {
+ if (vg_entry->root[0])
+ return vg_entry->root[0];
+ }
+
return NULL;
}
{
Vg_File_Data *vfd = vg_entry->vfd;
- if (vg_entry->root[0]) efl_unref(vg_entry->root[0]);
- vg_entry->root[0] = efl_ref(vfd->root);
+ /* Optimization: static viewbox may have same root data regardless of size.
+ So we can't use the root data directly, but copy it for each vg_entries.
+ In the meantime, non-static viewbox root data may have difference instance for each
+ size. So it's affordable to share the root data for each vg_entries. */
+ if (vfd->static_viewbox)
+ {
+ /* 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);
+ }
+ else if (vg_entry->root[0] != vfd->root)
+ {
+ if (vg_entry->root[0]) efl_unref(vg_entry->root[0]);
+ vg_entry->root[0] = efl_ref(vfd->root);
+ }
//Animatable?
if (!vfd->anim_data) return;
//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_ref(vfd->root);
+ if (vg_entry->root[1] != vfd->root)
+ {
+ if (vg_entry->root[1]) efl_unref(vg_entry->root[1]);
+ vg_entry->root[1] = efl_ref(vfd->root);
+ }
}
+ //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_ref(vfd->root);
+ if (vg_entry->root[2] != vfd->root)
+ {
+ if (vg_entry->root[2]) efl_unref(vg_entry->root[2]);
+ vg_entry->root[2] = efl_ref(vfd->root);
+ }
}
}
unsigned int
evas_cache_vg_anim_frame_count_get(const Vg_Cache_Entry* vg_entry)
{
+ if (!vg_entry) return 0;
Vg_File_Data *vfd = vg_entry->vfd;
if (!vfd || !vfd->anim_data) return 0;
return vfd->anim_data->frame_cnt;