evas vg: revise buffer caching mechanism from ector version. 00/260000/9
authorHermet Park <chuneon.park@samsung.com>
Thu, 17 Jun 2021 09:44:04 +0000 (18:44 +0900)
committerHermet Park <chuneon.park@samsung.com>
Thu, 24 Jun 2021 01:19:51 +0000 (10:19 +0900)
This helps to save memory when process uses the same resource
among the objects.

In case of ui, many ui instances uses the same visual resources,
So this mechanism is very effective.

Additionally, this keeps the designated buffer for animation frames.

Previously, we didn't reuse the buffer so every frame buffer is
generated and destroyed, it's an inefficient task...

Change-Id: Ida6c59d972ccc130cb0fa990fce475ce5a2dca64

src/lib/evas/canvas/efl_canvas_vg_object.c
src/lib/evas/canvas/evas_vg_private.h
src/lib/evas/common/evas_common_generic_cache.c
src/lib/evas/include/evas_private.h
src/modules/evas/engines/gl_generic/evas_engine.c
src/modules/evas/engines/software_generic/evas_engine.c

index abb3971..cc9bb06 100644 (file)
@@ -52,6 +52,26 @@ static const Evas_Object_Func object_func =
 };
 
 static void
+_drop_vg_image(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd)
+{
+   if (!pd->image) return;
+   ENFN->image_free(ENC, pd->image);
+   pd->image = NULL;
+}
+
+static void
+_drop_vg_caches(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd)
+{
+   if (!pd->vg_entry) return;
+   if (pd->ckeys[0]) ENFN->tvg_image_cache_drop(ENC, pd->ckeys[0]);
+   if (pd->ckeys[1]) ENFN->tvg_image_cache_drop(ENC, pd->ckeys[1]);
+   pd->ckeys[0] = NULL;
+   pd->ckeys[1] = NULL;
+
+   _drop_vg_image(obj, pd);
+}
+
+static void
 _update_vgtree_viewport(Eo *obj, Efl_Canvas_Vg_Object_Data *pd)
 {
    double vb_w, vb_h, vp_w, vp_h, scale_w, scale_h, scale;
@@ -100,19 +120,21 @@ _evas_vg_resize(void *data, const Efl_Event *ev)
 }
 
 EOLIAN static Efl_VG *
-_efl_canvas_vg_object_root_node_get(const Eo *obj, Efl_Canvas_Vg_Object_Data *pd)
+_efl_canvas_vg_object_root_node_get(const Eo *eo_obj, Efl_Canvas_Vg_Object_Data *pd)
 {
    Efl_VG *root;
 
    if (pd->vg_entry)
      {
         Evas_Coord w, h;
-        evas_object_geometry_get(obj, NULL, NULL, &w, &h);
+        evas_object_geometry_get(eo_obj, NULL, NULL, &w, &h);
 
         //Update vg data with current size.
         if ((pd->vg_entry->w != w) || (pd->vg_entry->h != h))
           {
+             Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
              Vg_Cache_Entry *vg_entry = evas_cache_vg_entry_resize(pd->vg_entry, w, h);
+             _drop_vg_caches(obj, pd);
              evas_cache_vg_entry_del(pd->vg_entry);
              pd->vg_entry = vg_entry;
           }
@@ -136,6 +158,7 @@ _efl_canvas_vg_object_root_node_set(Eo *eo_obj, Efl_Canvas_Vg_Object_Data *pd, E
    // check if a file has been already set
    if (pd->vg_entry)
      {
+        _drop_vg_caches(obj, pd);
         evas_cache_vg_entry_del(pd->vg_entry);
         pd->vg_entry = NULL;
      }
@@ -143,6 +166,7 @@ _efl_canvas_vg_object_root_node_set(Eo *eo_obj, Efl_Canvas_Vg_Object_Data *pd, E
    // detach/free the old root_node
    if (pd->user_entry && pd->user_entry->root)
      {
+        ENFN->tvg_image_cache_drop(ENC, pd->user_entry->root);
         efl_canvas_vg_node_vg_obj_set(pd->user_entry->root, NULL, NULL);
         efl_replace(&pd->user_entry->root, NULL);
      }
@@ -240,7 +264,7 @@ _efl_canvas_vg_object_viewbox_align_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Vg
 }
 
 EOLIAN static Eina_Error
-_efl_canvas_vg_object_efl_file_file_set(Eo *eo_obj, Efl_Canvas_Vg_Object_Data *pd EINA_UNUSED, const char *file)
+_efl_canvas_vg_object_efl_file_file_set(Eo *eo_obj, Efl_Canvas_Vg_Object_Data *pd, const char *file)
 {
    /* Careful: delete previous vg entry.
       When a new efl file is set, ex-file will be invalid.
@@ -254,16 +278,11 @@ _efl_canvas_vg_object_efl_file_file_set(Eo *eo_obj, Efl_Canvas_Vg_Object_Data *p
 
         if ((pl != cl) || (pname && file && strcmp(pname, file)))
           {
-             Evas_Object_Protected_Data *obj;
-             obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
+             Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
+             _drop_vg_caches(obj, pd);
              evas_cache_vg_entry_del(pd->vg_entry);
              evas_object_change(eo_obj, obj);
              pd->vg_entry = NULL;
-             if (pd->image)
-               {
-                  ENFN->image_free(ENC, pd->image);
-                  pd->image = NULL;
-               }
              evas_object_change(eo_obj, obj);
              pd->changed = EINA_TRUE;
           }
@@ -312,16 +331,11 @@ _efl_canvas_vg_object_efl_file_unload(Eo *eo_obj, Efl_Canvas_Vg_Object_Data *pd)
 {
    if (!efl_file_loaded_get(eo_obj)) return;
 
-   Evas_Object_Protected_Data *obj;
-   obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
+   Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
+   _drop_vg_caches(obj, pd);
    evas_cache_vg_entry_del(pd->vg_entry);
    evas_object_change(eo_obj, obj);
    pd->vg_entry = NULL;
-   if (pd->image)
-     {
-        ENFN->image_free(ENC, pd->image);
-        pd->image = NULL;
-     }
 }
 
 EOLIAN static Eina_Bool
@@ -343,12 +357,7 @@ _efl_canvas_vg_object_efl_gfx_entity_visible_set(Eo *eo_obj, Efl_Canvas_Vg_Objec
    efl_gfx_entity_visible_set(efl_super(eo_obj, MY_CLASS), vis);
 
    Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
-
-   if (!vis && pd->image)
-     {
-        ENFN->image_free(ENC, pd->image);
-        pd->image = NULL;
-     }
+   _drop_vg_caches(obj, pd);
 }
 
 EOLIAN static void
@@ -361,11 +370,13 @@ _efl_canvas_vg_object_efl_object_invalidate(Eo *eo_obj, Efl_Canvas_Vg_Object_Dat
 
    if (pd->user_entry)
      {
+        ENFN->tvg_image_cache_drop(ENC, pd->user_entry->root);
         if (pd->user_entry->root) efl_unref(pd->user_entry->root);
         free(pd->user_entry);
      }
    pd->user_entry = NULL;
 
+   _drop_vg_caches(obj, pd);
    evas_cache_vg_entry_del(pd->vg_entry);
 
    if (pd->tvg_canvas)
@@ -374,12 +385,6 @@ _efl_canvas_vg_object_efl_object_invalidate(Eo *eo_obj, Efl_Canvas_Vg_Object_Dat
         tvg_canvas_destroy(pd->tvg_canvas);
      }
 
-   if (pd->image)
-     {
-        ENFN->image_free(ENC, pd->image);
-        pd->image = NULL;
-     }
-
    efl_invalidate(efl_super(eo_obj, MY_CLASS));
 }
 
@@ -400,9 +405,6 @@ _efl_canvas_vg_object_efl_object_constructor(Eo *eo_obj, Efl_Canvas_Vg_Object_Da
    pd->obj = obj;
    pd->root = efl_add_ref(EFL_CANVAS_VG_CONTAINER_CLASS, NULL);
    pd->tvg_canvas = tvg_swcanvas_create();
-   pd->size.w = 0;
-   pd->size.h = 0;
-
 
    return eo_obj;
 }
@@ -420,175 +422,249 @@ _efl_canvas_vg_object_efl_object_finalize(Eo *obj, Efl_Canvas_Vg_Object_Data *pd
 }
 
 static void
-_update_scene(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd, Efl_VG *root)
+_render_image_to_screen(Evas_Object_Protected_Data *obj,
+                        void *engine, void *output, void *context, void *surface, void *image,
+                        int x, int y, int w, int h, Eina_Bool async)
 {
+   ENFN->image_dirty_region(engine, image, 0, 0, w, h);
+
+   Eina_Bool async_unref = ENFN->image_draw(engine, output, context, surface, image,
+                                            0, 0, w, h, x, y, w, h,
+                                            EINA_TRUE, async);
+   if (async && async_unref)
+     {
+        evas_cache_image_ref(image);
+        evas_unref_queue_image_put(obj->layer->evas, image);
+     }
+}
+
+static void*
+_render_tvg_to_image(Evas_Object_Protected_Data* obj, Efl_Canvas_Vg_Object_Data *pd, void *engine, void *image, Efl_VG* root, int w, int h, void *ckey)
+{
+   Eina_Bool new_image = EINA_FALSE;
+
+   //create a image
+   if (!image)
+     {
+        image = ENFN->tvg_image_new(engine, w, h);
+        if (!image) return NULL;
+        new_image = EINA_TRUE;
+     }
+
+   //prepare for redering
+   int stride = 0;
+   DATA32* pixels = ENFN->tvg_image_acquire(engine, image, &stride);
+   tvg_swcanvas_set_target(pd->tvg_canvas, (uint32_t*) pixels, stride, w, h, TVG_COLORSPACE_ARGB8888);
+
+   //update scene
    if (!efl_isa(root, EFL_CANVAS_VG_GRADIENT_CLASS))
      {
         Efl_Canvas_Vg_Node_Data *nd = efl_data_scope_get(root, EFL_CANVAS_VG_NODE_CLASS);
         if (nd) nd->render_pre(obj, root, nd, NULL, pd->tvg_canvas, NULL);
      }
-}
 
-static void
-_render_image_to_screen(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd,
-                        void *engine, void *output, void *context, void *surface,
-                        int x, int y, Eina_Bool async)
-{
-   if (!pd || !pd->image) return;
+   //raterize
+   if (tvg_canvas_draw(pd->tvg_canvas) == TVG_RESULT_SUCCESS)
+     tvg_canvas_sync(pd->tvg_canvas);
 
-   ENFN->image_dirty_region(engine, pd->image, 0, 0, pd->size.w, pd->size.h);
+   ENFN->tvg_image_release(engine, image, pixels);
 
-   Eina_Bool async_unref = ENFN->image_draw(engine, output, context, surface, pd->image, 0, 0,
-                                            pd->size.w, pd->size.h, x, y, pd->size.w, pd->size.h,
-                                            EINA_TRUE, async);
-   if (async && async_unref)
+   tvg_canvas_clear(pd->tvg_canvas, EINA_FALSE);
+
+   //caching
+   if (new_image && ckey)
      {
-        evas_cache_image_ref(pd->image);
-        evas_unref_queue_image_put(obj->layer->evas, pd->image);
+        //Drop ex invalid cache images.
+        if (pd->frame_idx == 0 && ckey != pd->ckeys[0])
+          {
+             if (pd->ckeys[0]) ENFN->tvg_image_cache_drop(engine, pd->ckeys[0]);
+             pd->ckeys[0] = ckey;
+          }
+        else if (pd->frame_idx == (int) (evas_cache_vg_anim_frame_count_get(pd->vg_entry) - 1)
+                 && ckey != pd->ckeys[1])
+          {
+             if (pd->ckeys[1]) ENFN->tvg_image_cache_drop(engine, pd->ckeys[1]);
+             pd->ckeys[1] = ckey;
+          }
+        ENFN->tvg_image_cache_set(engine, ckey, image);
      }
+
+   return image;
 }
 
 static void
-_prepare_render_image(Evas_Object_Protected_Data* obj, Efl_Canvas_Vg_Object_Data *pd, void *engine)
+_user_vg_entry_render(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd,
+                       void *engine, void *output, void *context, void *surface,
+                       int x, int y, int w, int h, Eina_Bool do_async)
 {
-   if (pd->image) ENFN->image_free(engine, pd->image);
+   Vg_User_Entry *user_entry = pd->user_entry;
 
-   pd->image = ENFN->tvg_image_new(engine, pd->size.w, pd->size.h);
-   if (!pd->image) return;
+   //if the size doesn't match, drop previous cache surface.
+   if ((user_entry->w != w) || (user_entry->h != h))
+     {
+        ENFN->tvg_image_cache_drop(engine, user_entry->root);
+        user_entry->w = w;
+        user_entry->h = h;
+     }
 
-   int stride = 0;
-   DATA32* pixels = ENFN->tvg_image_acquire(engine, pd->image, &stride);
+   void *image = ENFN->tvg_image_cache_get(engine, user_entry->root);
 
-   tvg_swcanvas_set_target(pd->tvg_canvas, (uint32_t*) pixels, stride, pd->size.w, pd->size.h, TVG_COLORSPACE_ARGB8888);
+   if (!image)
+     {
+        image = _render_tvg_to_image(obj, pd, engine, NULL, user_entry->root, w, h, user_entry->root);
+     }
+   else
+     {
+        if (pd->changed)
+          {
+             image = _render_tvg_to_image(obj, pd, engine, image, user_entry->root, w, h, NULL);
+          }
+        //cache reference was increased when we get the cache.
+        ENFN->tvg_image_cache_drop(engine, user_entry->root);
+     }
 
-   ENFN->tvg_image_release(engine, pd->image, pixels);
+   _render_image_to_screen(obj, engine, output, context, surface, image, x, y, w, h, do_async);
 }
 
+
 static void
-_efl_canvas_vg_object_render(Evas_Object *eo_obj EINA_UNUSED,
-                             Evas_Object_Protected_Data *obj,
-                             void *type_private_data,
-                             void *engine, void *output EINA_UNUSED, void *context, void *surface EINA_UNUSED,
-                             int x, int y, Eina_Bool do_async)
+_cache_vg_entry_render(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd,
+                       void *engine, void *output, void *context, void *surface,
+                       int x, int y, int w, int h, Eina_Bool cacheable, Eina_Bool do_async)
 {
-   Efl_Canvas_Vg_Object_Data *pd = type_private_data;
-   Eina_Position2D offset = {0, 0};  //Offset after keeping aspect ratio.
-   ENFN->context_color_set(engine, context, 255, 255, 255, 255);
-   ENFN->context_multiplier_set(engine, context,
-                                obj->cur->cache.clip.r,
-                                obj->cur->cache.clip.g,
-                                obj->cur->cache.clip.b,
-                                obj->cur->cache.clip.a);
-   ENFN->context_anti_alias_set(engine, context, obj->cur->anti_alias);
-   ENFN->context_render_op_set(engine, context, obj->cur->render_op);
-
-   int w = obj->cur->geometry.w;
-   int h = obj->cur->geometry.h;
-
    Vg_Cache_Entry *vg_entry = pd->vg_entry;
+   Eina_Position2D offset = {0, 0};  //Offset after keeping aspect ratio.
 
    //Update the size only when user entry is not valid.
-   if (!pd->user_entry && vg_entry)
+   evas_cache_vg_entry_value_provider_update(vg_entry, efl_key_data_get(obj->object, "_vg_value_providers"));
+
+   // if the size changed in between path set and the draw call;
+   if ((vg_entry->w != w) || (vg_entry->h != h))
      {
-        evas_cache_vg_entry_value_provider_update(vg_entry, efl_key_data_get(obj->object, "_vg_value_providers"));
+        Eina_Size2D size = evas_cache_vg_entry_default_size_get(vg_entry);
 
-        // if the size changed in between path set and the draw call;
-        if ((vg_entry->w != w) || (vg_entry->h != h))
+        //adjust size for aspect ratio.
+        if (size.w > 0 && size.h > 0)
           {
-             Eina_Size2D size = evas_cache_vg_entry_default_size_get(vg_entry);
+             float rw = (float) w / (float) size.w;
+             float rh = (float) h / (float) size.h;
 
-             //adjust size for aspect ratio.
-             if (size.w > 0 && size.h > 0)
+             if (rw < rh)
                {
-                  float rw = (float) w / (float) size.w;
-                  float rh = (float) h / (float) size.h;
-
-                  if (rw < rh)
-                    {
-                       size.w = w;
-                       size.h = (int) ((float) size.h * rw);
-                    }
-                  else
-                    {
-                       size.w = (int) ((float) size.w * rh);
-                       size.h = h;
-                    }
+                  size.w = w;
+                  size.h = (int) ((float) size.h * rw);
                }
              else
                {
-                  size.w = w;
+                  size.w = (int) ((float) size.w * rh);
                   size.h = h;
                }
+          }
+        else
+          {
+             size.w = w;
+             size.h = h;
+          }
 
-             //Size is changed, cached data is invalid.
-             if ((size.w != vg_entry->w) || (size.h != vg_entry->h))
-               {
-                  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;
-               }
-
-             //update for adjusted pos and size.
-             offset.x = w - size.w;
-             if (offset.x > 0) offset.x /= 2;
-             offset.y = h - size.h;
-             if (offset.y > 0) offset.y /= 2;
-             w = size.w;
-             h = size.h;
+        //Size is changed, cached data is invalid.
+        if ((size.w != vg_entry->w) || (size.h != vg_entry->h))
+          {
+             vg_entry = evas_cache_vg_entry_resize(vg_entry, size.w, size.h);
+             _drop_vg_caches(obj, pd);
+             evas_cache_vg_entry_del(pd->vg_entry);
+             pd->vg_entry = vg_entry;
           }
+
+        //update for adjusted pos and size.
+        offset.x = w - size.w;
+        if (offset.x > 0) offset.x /= 2;
+        offset.y = h - size.h;
+        if (offset.y > 0) offset.y /= 2;
+        w = size.w;
+        h = size.h;
      }
 
-   Eina_Bool resized = EINA_FALSE;
-   Eina_Bool prepared = EINA_FALSE;
+   Efl_VG *root = evas_cache_vg_tree_get(pd->vg_entry, pd->frame_idx);
+   if (!root) return;
 
-   //Reset canvas size
-   if (pd->size.w != w || pd->size.h != h)
-     {
-        pd->size.w = w;
-        pd->size.h = h;
-        resized = EINA_TRUE;
-     }
+   void *key = NULL;
+   void *image = NULL;
 
-   if (pd->vg_entry && (resized || pd->changed))
+   if (cacheable)
      {
-        Efl_VG *root = evas_cache_vg_tree_get(pd->vg_entry, pd->frame_idx);
-        if (root)
+        key = evas_cache_vg_surface_key_get(root, w, h, pd->frame_idx);
+        if (key) image = ENFN->tvg_image_cache_get(engine, key);
+
+        if (!image)
           {
-             if (resized && !prepared)
-               {
-                  _prepare_render_image(obj, pd, engine);
-                  prepared = EINA_TRUE;
-               }
-             _update_scene(obj, pd, root);
+             image = _render_tvg_to_image(obj, pd, engine, NULL, root, w, h, key);
           }
-     }
-
-   if (pd->user_entry && (resized || pd->changed))
-     {
-        if (resized && !prepared)
+        else
           {
-             _prepare_render_image(obj, pd, engine);
-             prepared = EINA_TRUE;
+             //cache reference was increased when we get the cache.
+             if (key) ENFN->tvg_image_cache_drop(engine, key);
           }
-        _update_scene(obj, pd, pd->user_entry->root);
      }
-
-   //Render the vector canvas
-   if ((resized || pd->changed) && pd->image)
+   //Non-cacheable... such as intermediate animation frames.
+   else
      {
-        DATA32 *pixels = ENFN->tvg_image_acquire(engine, pd->image, NULL);
+        if (w != pd->size.w || h != pd->size.h) _drop_vg_image(obj, pd);
+        image = _render_tvg_to_image(obj, pd, engine, pd->image, root, w, h, NULL);
+        pd->image = image;
+        pd->size.w = w;
+        pd->size.h = h;
+     }
 
-        if (tvg_canvas_draw(pd->tvg_canvas) == TVG_RESULT_SUCCESS)
-          tvg_canvas_sync(pd->tvg_canvas);
+   _render_image_to_screen(obj, engine, output, context, surface, image,
+                           x + offset.x, y + offset.y, w, h, do_async);
+}
 
-        ENFN->tvg_image_release(engine, pd->image, pixels);
+static void
+_efl_canvas_vg_object_render(Evas_Object *eo_obj EINA_UNUSED,
+                             Evas_Object_Protected_Data *obj,
+                             void *type_private_data,
+                             void *engine, void *output EINA_UNUSED, void *context, void *surface EINA_UNUSED,
+                             int x, int y, Eina_Bool do_async)
+{
+   Efl_Canvas_Vg_Object_Data *pd = type_private_data;
 
-        tvg_canvas_clear(pd->tvg_canvas, EINA_FALSE);
+   ENFN->context_color_set(engine, context, 255, 255, 255, 255);
+   ENFN->context_multiplier_set(engine, context,
+                                obj->cur->cache.clip.r,
+                                obj->cur->cache.clip.g,
+                                obj->cur->cache.clip.b,
+                                obj->cur->cache.clip.a);
+   ENFN->context_anti_alias_set(engine, context, obj->cur->anti_alias);
+   ENFN->context_render_op_set(engine, context, obj->cur->render_op);
+
+   //Cache tvg image?
+   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)))
+     {
+        cacheable = EINA_TRUE;
+        //Drop owned image since we gonna use cached image.
+        _drop_vg_image(obj, pd);
+     }
+
+   if (pd->vg_entry)
+     {
+        _cache_vg_entry_render(obj, pd, engine, output, context, surface,
+                               obj->cur->geometry.x + x, obj->cur->geometry.y + y,
+                               obj->cur->geometry.w, obj->cur->geometry.h, cacheable, do_async);
      }
 
-   _render_image_to_screen(obj, pd, engine, output, context, surface,
-                           obj->cur->geometry.x + x + offset.x,
-                           obj->cur->geometry.y + y + offset.y, do_async);
+   if (pd->user_entry)
+     {
+        _user_vg_entry_render(obj, pd, engine, output, context, surface,
+                              obj->cur->geometry.x + x, obj->cur->geometry.y + y,
+                              obj->cur->geometry.w, obj->cur->geometry.h, do_async);
+     }
 
    pd->changed = EINA_FALSE;
 }
index 4e71a95..a341b57 100644 (file)
@@ -58,8 +58,8 @@ struct _Efl_Canvas_Vg_Object_Data
    int                        frame_idx;
    void                      *ckeys[2];  //cache keys for first, last frames if animation
    Tvg_Canvas *tvg_canvas;
-   void* image;                          //engine image that holds the canvas buffer
-   Eina_Size2D size;
+   void                      *image;
+   Eina_Size2D                size;
 
    Eina_Bool                  changed : 1;
 };
index cb9a070..c1367b8 100644 (file)
@@ -1,6 +1,6 @@
 #include "evas_common_private.h"
 
-#define LRU_CACHE_LIMIT 50
+#define LRU_CACHE_LIMIT 25
 
 EAPI Generic_Cache*
 generic_cache_new(void *user_data, Generic_Cache_Free func)
index 1d7f794..a824517 100755 (executable)
@@ -1100,6 +1100,9 @@ struct _Evas_Func
    void *(*tvg_image_new)                (void *engine, int widht, int height);
    void *(*tvg_image_acquire)            (void *engine, void *surface, int *stride);
    void (*tvg_image_release)             (void *engine, void *surface, DATA32 *pixels);
+   void (*tvg_image_cache_set)           (void *engine, void *key, void *image);
+   void *(*tvg_image_cache_get)          (void *engine, void *key);
+   void (*tvg_image_cache_drop)          (void *engine, void *key);
 
    Evas_Filter_Support (*gfx_filter_supports) (void *engine, Evas_Filter_Command *cmd);
    Eina_Bool (*gfx_filter_process)       (void *engine, Evas_Filter_Command *cmd);
index b988dd4..ec720f3 100755 (executable)
@@ -2780,6 +2780,27 @@ eng_tvg_image_release(void *engine, void *surface, DATA32 *pixels)
    eng_image_data_put(engine, surface, pixels);
 }
 
+static void
+eng_tvg_image_cache_set(void *engine, void *key , void *image)
+{
+   Render_Engine_GL_Generic *e = engine;
+   generic_cache_data_set(e->software.surface_cache, key, image);
+}
+
+static void *
+eng_tvg_image_cache_get(void *engine, void *key)
+{
+   Render_Engine_GL_Generic *e = engine;
+   return generic_cache_data_get(e->software.surface_cache, key);
+}
+
+static void
+eng_tvg_image_cache_drop(void *engine, void *key)
+{
+   Render_Engine_GL_Generic *e = engine;
+   generic_cache_data_drop(e->software.surface_cache, key);
+}
+
 static Ector_Buffer *
 eng_ector_buffer_new(void *engine, Evas *evas, int w, int h,
                      Efl_Gfx_Colorspace cspace, Ector_Buffer_Flag flags)
@@ -3413,6 +3434,9 @@ module_open(Evas_Module *em)
    ORD(tvg_image_new);
    ORD(tvg_image_acquire);
    ORD(tvg_image_release);
+   ORD(tvg_image_cache_set);
+   ORD(tvg_image_cache_get);
+   ORD(tvg_image_cache_drop);
    ORD(gfx_filter_supports);
    ORD(gfx_filter_process);
    ORD(font_glyphs_gc_collect);
index fe5fdd6..2e453d9 100755 (executable)
@@ -4377,6 +4377,26 @@ eng_tvg_image_release(void *engine EINA_UNUSED, void *surface EINA_UNUSED, DATA3
 {
 }
 
+static void
+eng_tvg_image_cache_set(void *engine, void *key , void *image)
+{
+   Render_Engine_Software_Generic *e = engine;
+   generic_cache_data_set(e->surface_cache, key, image);
+}
+
+static void *
+eng_tvg_image_cache_get(void *engine, void *key)
+{
+   Render_Engine_Software_Generic *e = engine;
+   return generic_cache_data_get(e->surface_cache, key);
+}
+
+static void
+eng_tvg_image_cache_drop(void *engine, void *key)
+{
+   Render_Engine_Software_Generic *e = engine;
+   generic_cache_data_drop(e->surface_cache, key);
+}
 
 // Ector functions
 
@@ -4668,6 +4688,9 @@ static Evas_Func func =
      eng_tvg_image_new,
      eng_tvg_image_acquire,
      eng_tvg_image_release,
+     eng_tvg_image_cache_set,
+     eng_tvg_image_cache_get,
+     eng_tvg_image_cache_drop,
      eng_gfx_filter_supports,
      eng_gfx_filter_process,
    /* FUTURE software generic calls go here */