summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsubhransu mohanty <sub.mohanty@samsung.com>2017-11-09 16:57:00 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2017-11-10 11:20:38 +0900
commit41062cb15d2fecf57d3e649eabdb373f909ca53c (patch)
tree50aad80dbe1868bffd9a86af6601f19786671151
parentf0b8c37d805fceba15ba317dd96b906d6e12f147 (diff)
downloadefl-devs/subhransu/evas_vg.tar.gz
evas/vg: use surface cache for efl vg canvasdevs/subhransu/evas_vg
-rw-r--r--src/lib/evas/canvas/efl_canvas_vg.c257
-rw-r--r--src/lib/evas/canvas/evas_vg_private.h9
-rw-r--r--src/modules/evas/engines/gl_sdl/evas_engine.c1
-rw-r--r--src/modules/evas/engines/software_generic/evas_engine.c1
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;