jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=41062cb15d2fecf57d3e649eabdb373f909ca53c

commit 41062cb15d2fecf57d3e649eabdb373f909ca53c
Author: subhransu mohanty <sub.moha...@samsung.com>
Date:   Thu Nov 9 16:57:00 2017 +0900

    evas/vg: use surface cache for efl vg canvas
---
 src/lib/evas/canvas/efl_canvas_vg.c                | 257 +++++++++++++++++----
 src/lib/evas/canvas/evas_vg_private.h              |   9 +-
 src/modules/evas/engines/gl_sdl/evas_engine.c      |   1 +
 .../evas/engines/software_generic/evas_engine.c    |   1 -
 4 files changed, 225 insertions(+), 43 deletions(-)

diff --git a/src/lib/evas/canvas/efl_canvas_vg.c 
b/src/lib/evas/canvas/efl_canvas_vg.c
index a869308651..4d204edd41 100644
--- a/src/lib/evas/canvas/efl_canvas_vg.c
+++ b/src/lib/evas/canvas/efl_canvas_vg.c
@@ -135,18 +135,21 @@ evas_object_vg_add(Evas *e)
 EOLIAN static Efl_VG *
 _efl_canvas_vg_root_node_get(Eo *obj EINA_UNUSED, Efl_Canvas_Vg_Data *pd)
 {
+   Efl_VG *root = NULL;
+
    if (pd->vg_entry)
-     {
-        return evas_cache_vg_tree_get(pd->vg_entry);
-     }
-   return pd->vg_tree;
+     root = evas_cache_vg_tree_get(pd->vg_entry);
+   else if (pd->user_entry)
+     root = pd->user_entry->root;
+
+   return root;
 }
 
 EOLIAN static void
-_efl_canvas_vg_root_node_set(Eo *obj EINA_UNUSED, Efl_Canvas_Vg_Data *pd, 
Efl_VG *root_node)
+_efl_canvas_vg_root_node_set(Eo *obj, Efl_Canvas_Vg_Data *pd, Efl_VG 
*root_node)
 {
    // if the same root is already set
-   if (pd->vg_tree == root_node)
+   if (pd->user_entry && pd->user_entry->root == root_node)
      return;
 
    // check if a file has been already set
@@ -157,15 +160,26 @@ _efl_canvas_vg_root_node_set(Eo *obj EINA_UNUSED, 
Efl_Canvas_Vg_Data *pd, Efl_VG
      }
 
    // detach/free the old root_node
-   if (pd->vg_tree)
-     efl_parent_set(pd->vg_tree, NULL);
+   if (pd->user_entry && pd->user_entry->root)
+     efl_parent_set(pd->user_entry->root, NULL);
 
-   pd->vg_tree = root_node;
-
-   if (pd->vg_tree)
+   if (root_node)
      {
+        pd->user_entry = calloc(1, sizeof(User_Vg_Entry));
+        pd->user_entry->root = root_node;
         // set the parent so that vg canvas can render it.
-        efl_parent_set(pd->vg_tree, pd->root);
+        efl_parent_set(pd->user_entry->root, pd->root);
+     }
+   else
+     {
+        if (pd->user_entry)
+          {
+             // 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->user_entry);
+             free(pd->user_entry);
+          }
+        pd->user_entry = NULL;
      }
 
    // force a redraw
@@ -304,13 +318,8 @@ _cleanup_reference(void *data, const Efl_Event *event 
EINA_UNUSED)
 EOLIAN static void
 _efl_canvas_vg_efl_object_destructor(Eo *eo_obj, Efl_Canvas_Vg_Data *pd)
 {
-   Evas_Object_Protected_Data *obj;
    Evas *e = evas_object_evas_get(eo_obj);
 
-   obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
-   if (pd->engine_data)
-     obj->layer->evas->engine.func->ector_free(pd->engine_data);
-
    efl_event_callback_del(e, EFL_CANVAS_EVENT_RENDER_POST, _cleanup_reference, 
pd);
 
    efl_del(pd->root);
@@ -376,13 +385,193 @@ _evas_vg_render(Evas_Object_Protected_Data *obj, 
Efl_Canvas_Vg_Data *vd,
 
         nd = efl_data_scope_get(n, EFL_VG_CLASS);
 
-        obj->layer->evas->engine.func->ector_renderer_draw(engine, output, 
context, surface, vd->engine_data, nd->renderer, clips, do_async);
+        obj->layer->evas->engine.func->ector_renderer_draw(engine, output, 
context, surface, nd->renderer, clips, do_async);
 
         if (do_async)
           eina_array_push(&vd->cleanup, efl_ref(nd->renderer));
      }
 }
 
+// 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 *vd,
+                  void *engine, void *surface,
+                  Efl_VG *root, int w, int h, void *key,
+                  void *buffer, Eina_Bool do_async)
+{
+   Ector_Surface *ector;
+   RGBA_Draw_Context *context;
+   int error = 0;
+   Eina_Bool buffer_created = EINA_FALSE;
+
+   ector = evas_ector_get(obj->layer->evas);
+   if (!ector) return NULL;
+
+   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
+        buffer_created = EINA_TRUE;
+     }
+
+
+   //1. render pre
+   _evas_vg_render_pre(root, ector, NULL);
+
+   //3. draw into the 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);
+   obj->layer->evas->engine.func->ector_begin(engine, buffer,
+                                              context, surface,
+                                              ector,
+                                              0, 0,
+                                              do_async);
+   _evas_vg_render(obj, vd,
+                   engine, buffer,
+                   context, surface,
+                   root, NULL,
+                   do_async);
+   obj->layer->evas->engine.func->image_dirty_region(engine, buffer, 0, 0, 0, 
0);
+   obj->layer->evas->engine.func->ector_end(engine, buffer,
+                                            context, surface,
+                                            ector,do_async);
+
+   evas_common_draw_context_free(context);
+
+   if (buffer_created)
+     obj->layer->evas->engine.func->ector_surface_cache_set(engine, key, 
buffer);
+
+   return buffer;
+}
+
+static void
+_render_buffer_to_screen(Evas_Object_Protected_Data *obj,
+                         void *engine, void *output, void *context, void 
*surface,
+                         void *buffer,
+                         int x, int y, int w, int h,
+                         Eina_Bool do_async)
+{
+   Eina_Bool async_unref;
+
+   // draw the buffer as image to canvas
+   async_unref = obj->layer->evas->engine.func->image_draw(engine, output, 
context, surface,
+                                                           buffer,
+                                                           0, 0, w, h,
+                                                           x, y, w, h,
+                                                           EINA_TRUE, 
do_async);
+   if (do_async && async_unref)
+     {
+        evas_cache_image_ref((Image_Entry *)buffer);
+        evas_unref_queue_image_put(obj->layer->evas, buffer);
+     }
+}
+
+static void
+_cache_vg_entry_render(Evas_Object_Protected_Data *obj,
+                       Efl_Canvas_Vg_Data *vd,
+                       void *engine, void *output, void *context, void 
*surface,
+                       int x, int y, int w, int h, Eina_Bool do_async)
+{
+   Evas_Cache_Vg_Entry *vg_entry = vd->vg_entry;
+   Efl_VG *root, *dupe_root;
+   void *buffer;
+
+   // 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_del(vg_entry);
+         vg_entry = evas_cache_vg_entry_find(vg_entry->file, vg_entry->key,
+                                             w, h);
+         vd->vg_entry = vg_entry;
+     }
+   // if the buffer is not created yet
+   root = evas_cache_vg_tree_get(vg_entry);
+   if (!root) return;
+   buffer = obj->layer->evas->engine.func->ector_surface_cache_get(engine, 
root);
+   if (!buffer)
+     {
+        dupe_root = evas_vg_node_dup(root);
+        // render to the buffer
+        buffer = _render_to_buffer(obj, vd,
+                                   engine, surface,
+                                   dupe_root,
+                                   w, h,
+                                   root,
+                                   buffer,
+                                   do_async);
+        efl_del(dupe_root);
+     }
+   else
+     {
+        obj->layer->evas->engine.func->ector_surface_cache_drop(engine, root);
+     }
+
+   _render_buffer_to_screen(obj,
+                            engine, output, context, surface,
+                            buffer,
+                            x, y, w, h,
+                            do_async);
+}
+
+static void
+_user_vg_entry_render(Evas_Object_Protected_Data *obj,
+                      Efl_Canvas_Vg_Data *vd,
+                      void *engine, void *output, void *context, void *surface,
+                      int x, int y, int w, int h, Eina_Bool do_async)
+{
+   User_Vg_Entry *user_entry = vd->user_entry;
+   void *buffer;
+
+   // if the size dosen't match
+   if ((user_entry->w != w ) ||
+       (user_entry->h != h))
+     {
+         obj->layer->evas->engine.func->ector_surface_cache_drop(engine, 
user_entry);
+         user_entry->w = w;
+         user_entry->h = h;
+         vd->user_entry = user_entry;
+     }
+   // if the buffer is not created yet
+   buffer = obj->layer->evas->engine.func->ector_surface_cache_get(engine, 
user_entry);
+   if (!buffer)
+     {
+        // render to the buffer
+        buffer = _render_to_buffer(obj, vd,
+                                   engine, surface,
+                                   user_entry->root,
+                                   w, h,
+                                   user_entry,
+                                   buffer,
+                                   do_async);
+     }
+   else
+     {
+        // render to the buffer
+        if (vd->changed)
+          buffer = _render_to_buffer(obj, vd,
+                                     engine, surface,
+                                     user_entry->root,
+                                     w, h,
+                                     user_entry,
+                                     buffer,
+                                     do_async);
+        obj->layer->evas->engine.func->ector_surface_cache_drop(engine, 
user_entry);
+     }
+
+   _render_buffer_to_screen(obj,
+                            engine, output, context, surface,
+                            buffer,
+                            x, y, w, h,
+                            do_async);
+}
+
 static void
 _efl_canvas_vg_render(Evas_Object *eo_obj EINA_UNUSED,
                       Evas_Object_Protected_Data *obj,
@@ -391,13 +580,6 @@ _efl_canvas_vg_render(Evas_Object *eo_obj EINA_UNUSED,
                       int x, int y, Eina_Bool do_async)
 {
    Efl_Canvas_Vg_Data *vd = type_private_data;
-   Efl_VG *root = NULL;
-   Ector_Surface *ector = evas_ector_get(obj->layer->evas);
-
-   obj->layer->evas->engine.func->ector_output_set(engine, surface, output);
-
-   if (!vd->engine_data)
-     vd->engine_data = obj->layer->evas->engine.func->ector_new(engine, 
context, ector, surface);
 
    /* render object to surface with context, and offxet by x,y */
    obj->layer->evas->engine.func->context_color_set(engine,
@@ -418,25 +600,18 @@ _efl_canvas_vg_render(Evas_Object *eo_obj EINA_UNUSED,
                                                         obj->cur->render_op);
    if (vd->vg_entry)
      {
-        root = evas_cache_vg_tree_get(vd->vg_entry);
-        if (!root) return;
-        _evas_vg_render_pre(root, ector, NULL);
+        _cache_vg_entry_render(obj, vd,
+                               engine, output, context, surface,
+                               obj->cur->geometry.x + x, obj->cur->geometry.y 
+ y,
+                               obj->cur->geometry.w, obj->cur->geometry.h, 
do_async);
      }
-   else
+   if (vd->user_entry)
      {
-        root = vd->root;
+        _user_vg_entry_render(obj, vd,
+                              engine, output, context, surface,
+                              obj->cur->geometry.x + x, obj->cur->geometry.y + 
y,
+                              obj->cur->geometry.w, obj->cur->geometry.h, 
do_async);
      }
-   obj->layer->evas->engine.func->ector_begin(engine, context,
-                                              ector, surface,
-                                              vd->engine_data,
-                                              obj->cur->geometry.x + x, 
obj->cur->geometry.y + y,
-                                              do_async);
-   _evas_vg_render(obj, vd,
-                   engine, output, context, surface,
-                   root, NULL,
-                   do_async);
-   obj->layer->evas->engine.func->ector_end(engine, context, ector, surface, 
vd->engine_data, do_async);
-
    vd->changed = EINA_FALSE;
 }
 
diff --git a/src/lib/evas/canvas/evas_vg_private.h 
b/src/lib/evas/canvas/evas_vg_private.h
index dda171bdad..987991097c 100644
--- a/src/lib/evas/canvas/evas_vg_private.h
+++ b/src/lib/evas/canvas/evas_vg_private.h
@@ -32,12 +32,19 @@ struct _Evas_Cache_Vg_Entry
    int                   ref;
 };
 
+typedef struct _User_Vg_Entry
+{
+   int                   w; // current surface width
+   int                   h; // current surface height
+   Efl_VG               *root;
+}User_Vg_Entry; // holds the vg tree info set by the user
+
 struct _Efl_Canvas_Vg_Data
 {
    void                     *engine_data;
    Efl_VG                   *root;
-   Efl_VG                   *vg_tree;
    Evas_Cache_Vg_Entry      *vg_entry;
+   User_Vg_Entry            *user_entry; // holds the user set vg tree
    Eina_Rect                 fill;
    Eina_Rect                 viewbox;
    unsigned int              width, height;
diff --git a/src/modules/evas/engines/gl_sdl/evas_engine.c 
b/src/modules/evas/engines/gl_sdl/evas_engine.c
index 8a00b1196b..9e650f275e 100644
--- a/src/modules/evas/engines/gl_sdl/evas_engine.c
+++ b/src/modules/evas/engines/gl_sdl/evas_engine.c
@@ -341,6 +341,7 @@ gl_symbols(void)
 
 #define LINK2GENERIC(sym)                       \
    glsym_##sym = dlsym(RTLD_DEFAULT, #sym);
+
    LINK2GENERIC(evas_gl_symbols);
    LINK2GENERIC(evas_gl_common_context_new);
    LINK2GENERIC(evas_gl_common_context_free);
diff --git a/src/modules/evas/engines/software_generic/evas_engine.c 
b/src/modules/evas/engines/software_generic/evas_engine.c
index 69cc07b39b..016179da2f 100644
--- a/src/modules/evas/engines/software_generic/evas_engine.c
+++ b/src/modules/evas/engines/software_generic/evas_engine.c
@@ -4462,7 +4462,6 @@ eng_ector_renderer_draw(void *engine EINA_UNUSED, void 
*surface,
                         void *context, void *remove EINA_UNUSED,
                         Ector_Renderer *renderer, Eina_Array *clips, Eina_Bool 
do_async)
 {
-
    RGBA_Image *dst = surface;
    RGBA_Draw_Context *dc = context;
    Evas_Thread_Command_Ector ector;

-- 


Reply via email to