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)
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)
135EOLIAN static Efl_VG * 135EOLIAN static Efl_VG *
136_efl_canvas_vg_root_node_get(Eo *obj EINA_UNUSED, Efl_Canvas_Vg_Data *pd) 136_efl_canvas_vg_root_node_get(Eo *obj EINA_UNUSED, Efl_Canvas_Vg_Data *pd)
137{ 137{
138 Efl_VG *root = NULL;
139
138 if (pd->vg_entry) 140 if (pd->vg_entry)
139 { 141 root = evas_cache_vg_tree_get(pd->vg_entry);
140 return evas_cache_vg_tree_get(pd->vg_entry); 142 else if (pd->user_entry)
141 } 143 root = pd->user_entry->root;
142 return pd->vg_tree; 144
145 return root;
143} 146}
144 147
145EOLIAN static void 148EOLIAN static void
146_efl_canvas_vg_root_node_set(Eo *obj EINA_UNUSED, Efl_Canvas_Vg_Data *pd, Efl_VG *root_node) 149_efl_canvas_vg_root_node_set(Eo *obj, Efl_Canvas_Vg_Data *pd, Efl_VG *root_node)
147{ 150{
148 // if the same root is already set 151 // if the same root is already set
149 if (pd->vg_tree == root_node) 152 if (pd->user_entry && pd->user_entry->root == root_node)
150 return; 153 return;
151 154
152 // check if a file has been already set 155 // 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
157 } 160 }
158 161
159 // detach/free the old root_node 162 // detach/free the old root_node
160 if (pd->vg_tree) 163 if (pd->user_entry && pd->user_entry->root)
161 efl_parent_set(pd->vg_tree, NULL); 164 efl_parent_set(pd->user_entry->root, NULL);
162 165
163 pd->vg_tree = root_node; 166 if (root_node)
164
165 if (pd->vg_tree)
166 { 167 {
168 pd->user_entry = calloc(1, sizeof(User_Vg_Entry));
169 pd->user_entry->root = root_node;
167 // set the parent so that vg canvas can render it. 170 // set the parent so that vg canvas can render it.
168 efl_parent_set(pd->vg_tree, pd->root); 171 efl_parent_set(pd->user_entry->root, pd->root);
172 }
173 else
174 {
175 if (pd->user_entry)
176 {
177 // drop any surface cache attached to it.
178 Evas_Object_Protected_Data *eobj = efl_data_scope_get(obj, EFL_CANVAS_OBJECT_CLASS);
179 eobj->layer->evas->engine.func->ector_surface_cache_drop(_evas_engine_context(eobj->layer->evas), pd->user_entry);
180 free(pd->user_entry);
181 }
182 pd->user_entry = NULL;
169 } 183 }
170 184
171 // force a redraw 185 // force a redraw
@@ -304,13 +318,8 @@ _cleanup_reference(void *data, const Efl_Event *event EINA_UNUSED)
304EOLIAN static void 318EOLIAN static void
305_efl_canvas_vg_efl_object_destructor(Eo *eo_obj, Efl_Canvas_Vg_Data *pd) 319_efl_canvas_vg_efl_object_destructor(Eo *eo_obj, Efl_Canvas_Vg_Data *pd)
306{ 320{
307 Evas_Object_Protected_Data *obj;
308 Evas *e = evas_object_evas_get(eo_obj); 321 Evas *e = evas_object_evas_get(eo_obj);
309 322
310 obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
311 if (pd->engine_data)
312 obj->layer->evas->engine.func->ector_free(pd->engine_data);
313
314 efl_event_callback_del(e, EFL_CANVAS_EVENT_RENDER_POST, _cleanup_reference, pd); 323 efl_event_callback_del(e, EFL_CANVAS_EVENT_RENDER_POST, _cleanup_reference, pd);
315 324
316 efl_del(pd->root); 325 efl_del(pd->root);
@@ -376,13 +385,193 @@ _evas_vg_render(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Data *vd,
376 385
377 nd = efl_data_scope_get(n, EFL_VG_CLASS); 386 nd = efl_data_scope_get(n, EFL_VG_CLASS);
378 387
379 obj->layer->evas->engine.func->ector_renderer_draw(engine, output, context, surface, vd->engine_data, nd->renderer, clips, do_async); 388 obj->layer->evas->engine.func->ector_renderer_draw(engine, output, context, surface, nd->renderer, clips, do_async);
380 389
381 if (do_async) 390 if (do_async)
382 eina_array_push(&vd->cleanup, efl_ref(nd->renderer)); 391 eina_array_push(&vd->cleanup, efl_ref(nd->renderer));
383 } 392 }
384} 393}
385 394
395// renders a vg_tree to an offscreen buffer
396// and push it to the cache.
397static void *
398_render_to_buffer(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Data *vd,
399 void *engine, void *surface,
400 Efl_VG *root, int w, int h, void *key,
401 void *buffer, Eina_Bool do_async)
402{
403 Ector_Surface *ector;
404 RGBA_Draw_Context *context;
405 int error = 0;
406 Eina_Bool buffer_created = EINA_FALSE;
407
408 ector = evas_ector_get(obj->layer->evas);
409 if (!ector) return NULL;
410
411 if (!buffer)
412 {
413 // 2. create a buffer
414 buffer = obj->layer->evas->engine.func->ector_surface_create(engine,
415 w, h,
416 &error);
417 if (error)
418 return NULL; // surface creation error
419 buffer_created = EINA_TRUE;
420 }
421
422
423 //1. render pre
424 _evas_vg_render_pre(root, ector, NULL);
425
426 //3. draw into the buffer
427 context = evas_common_draw_context_new();
428 evas_common_draw_context_set_render_op(context, _EVAS_RENDER_COPY);
429 evas_common_draw_context_set_color(context, 255, 255, 255, 255);
430 obj->layer->evas->engine.func->ector_begin(engine, buffer,
431 context, surface,
432 ector,
433 0, 0,
434 do_async);
435 _evas_vg_render(obj, vd,
436 engine, buffer,
437 context, surface,
438 root, NULL,
439 do_async);
440 obj->layer->evas->engine.func->image_dirty_region(engine, buffer, 0, 0, 0, 0);
441 obj->layer->evas->engine.func->ector_end(engine, buffer,
442 context, surface,
443 ector,do_async);
444
445 evas_common_draw_context_free(context);
446
447 if (buffer_created)
448 obj->layer->evas->engine.func->ector_surface_cache_set(engine, key, buffer);
449
450 return buffer;
451}
452
453static void
454_render_buffer_to_screen(Evas_Object_Protected_Data *obj,
455 void *engine, void *output, void *context, void *surface,
456 void *buffer,
457 int x, int y, int w, int h,
458 Eina_Bool do_async)
459{
460 Eina_Bool async_unref;
461
462 // draw the buffer as image to canvas
463 async_unref = obj->layer->evas->engine.func->image_draw(engine, output, context, surface,
464 buffer,
465 0, 0, w, h,
466 x, y, w, h,
467 EINA_TRUE, do_async);
468 if (do_async && async_unref)
469 {
470 evas_cache_image_ref((Image_Entry *)buffer);
471 evas_unref_queue_image_put(obj->layer->evas, buffer);
472 }
473}
474
475static void
476_cache_vg_entry_render(Evas_Object_Protected_Data *obj,
477 Efl_Canvas_Vg_Data *vd,
478 void *engine, void *output, void *context, void *surface,
479 int x, int y, int w, int h, Eina_Bool do_async)
480{
481 Evas_Cache_Vg_Entry *vg_entry = vd->vg_entry;
482 Efl_VG *root, *dupe_root;
483 void *buffer;
484
485 // if the size changed in between path set and the draw call;
486 if ((vg_entry->w != w) ||
487 (vg_entry->h != h))
488 {
489 evas_cache_vg_entry_del(vg_entry);
490 vg_entry = evas_cache_vg_entry_find(vg_entry->file, vg_entry->key,
491 w, h);
492 vd->vg_entry = vg_entry;
493 }
494 // if the buffer is not created yet
495 root = evas_cache_vg_tree_get(vg_entry);
496 if (!root) return;
497 buffer = obj->layer->evas->engine.func->ector_surface_cache_get(engine, root);
498 if (!buffer)
499 {
500 dupe_root = evas_vg_node_dup(root);
501 // render to the buffer
502 buffer = _render_to_buffer(obj, vd,
503 engine, surface,
504 dupe_root,
505 w, h,
506 root,
507 buffer,
508 do_async);
509 efl_del(dupe_root);
510 }
511 else
512 {
513 obj->layer->evas->engine.func->ector_surface_cache_drop(engine, root);
514 }
515
516 _render_buffer_to_screen(obj,
517 engine, output, context, surface,
518 buffer,
519 x, y, w, h,
520 do_async);
521}
522
523static void
524_user_vg_entry_render(Evas_Object_Protected_Data *obj,
525 Efl_Canvas_Vg_Data *vd,
526 void *engine, void *output, void *context, void *surface,
527 int x, int y, int w, int h, Eina_Bool do_async)
528{
529 User_Vg_Entry *user_entry = vd->user_entry;
530 void *buffer;
531
532 // if the size dosen't match
533 if ((user_entry->w != w ) ||
534 (user_entry->h != h))
535 {
536 obj->layer->evas->engine.func->ector_surface_cache_drop(engine, user_entry);
537 user_entry->w = w;
538 user_entry->h = h;
539 vd->user_entry = user_entry;
540 }
541 // if the buffer is not created yet
542 buffer = obj->layer->evas->engine.func->ector_surface_cache_get(engine, user_entry);
543 if (!buffer)
544 {
545 // render to the buffer
546 buffer = _render_to_buffer(obj, vd,
547 engine, surface,
548 user_entry->root,
549 w, h,
550 user_entry,
551 buffer,
552 do_async);
553 }
554 else
555 {
556 // render to the buffer
557 if (vd->changed)
558 buffer = _render_to_buffer(obj, vd,
559 engine, surface,
560 user_entry->root,
561 w, h,
562 user_entry,
563 buffer,
564 do_async);
565 obj->layer->evas->engine.func->ector_surface_cache_drop(engine, user_entry);
566 }
567
568 _render_buffer_to_screen(obj,
569 engine, output, context, surface,
570 buffer,
571 x, y, w, h,
572 do_async);
573}
574
386static void 575static void
387_efl_canvas_vg_render(Evas_Object *eo_obj EINA_UNUSED, 576_efl_canvas_vg_render(Evas_Object *eo_obj EINA_UNUSED,
388 Evas_Object_Protected_Data *obj, 577 Evas_Object_Protected_Data *obj,
@@ -391,13 +580,6 @@ _efl_canvas_vg_render(Evas_Object *eo_obj EINA_UNUSED,
391 int x, int y, Eina_Bool do_async) 580 int x, int y, Eina_Bool do_async)
392{ 581{
393 Efl_Canvas_Vg_Data *vd = type_private_data; 582 Efl_Canvas_Vg_Data *vd = type_private_data;
394 Efl_VG *root = NULL;
395 Ector_Surface *ector = evas_ector_get(obj->layer->evas);
396
397 obj->layer->evas->engine.func->ector_output_set(engine, surface, output);
398
399 if (!vd->engine_data)
400 vd->engine_data = obj->layer->evas->engine.func->ector_new(engine, context, ector, surface);
401 583
402 /* render object to surface with context, and offxet by x,y */ 584 /* render object to surface with context, and offxet by x,y */
403 obj->layer->evas->engine.func->context_color_set(engine, 585 obj->layer->evas->engine.func->context_color_set(engine,
@@ -418,25 +600,18 @@ _efl_canvas_vg_render(Evas_Object *eo_obj EINA_UNUSED,
418 obj->cur->render_op); 600 obj->cur->render_op);
419 if (vd->vg_entry) 601 if (vd->vg_entry)
420 { 602 {
421 root = evas_cache_vg_tree_get(vd->vg_entry); 603 _cache_vg_entry_render(obj, vd,
422 if (!root) return; 604 engine, output, context, surface,
423 _evas_vg_render_pre(root, ector, NULL); 605 obj->cur->geometry.x + x, obj->cur->geometry.y + y,
606 obj->cur->geometry.w, obj->cur->geometry.h, do_async);
424 } 607 }
425 else 608 if (vd->user_entry)
426 { 609 {
427 root = vd->root; 610 _user_vg_entry_render(obj, vd,
611 engine, output, context, surface,
612 obj->cur->geometry.x + x, obj->cur->geometry.y + y,
613 obj->cur->geometry.w, obj->cur->geometry.h, do_async);
428 } 614 }
429 obj->layer->evas->engine.func->ector_begin(engine, context,
430 ector, surface,
431 vd->engine_data,
432 obj->cur->geometry.x + x, obj->cur->geometry.y + y,
433 do_async);
434 _evas_vg_render(obj, vd,
435 engine, output, context, surface,
436 root, NULL,
437 do_async);
438 obj->layer->evas->engine.func->ector_end(engine, context, ector, surface, vd->engine_data, do_async);
439
440 vd->changed = EINA_FALSE; 615 vd->changed = EINA_FALSE;
441} 616}
442 617
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
32 int ref; 32 int ref;
33}; 33};
34 34
35typedef struct _User_Vg_Entry
36{
37 int w; // current surface width
38 int h; // current surface height
39 Efl_VG *root;
40}User_Vg_Entry; // holds the vg tree info set by the user
41
35struct _Efl_Canvas_Vg_Data 42struct _Efl_Canvas_Vg_Data
36{ 43{
37 void *engine_data; 44 void *engine_data;
38 Efl_VG *root; 45 Efl_VG *root;
39 Efl_VG *vg_tree;
40 Evas_Cache_Vg_Entry *vg_entry; 46 Evas_Cache_Vg_Entry *vg_entry;
47 User_Vg_Entry *user_entry; // holds the user set vg tree
41 Eina_Rect fill; 48 Eina_Rect fill;
42 Eina_Rect viewbox; 49 Eina_Rect viewbox;
43 unsigned int width, height; 50 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)
341 341
342#define LINK2GENERIC(sym) \ 342#define LINK2GENERIC(sym) \
343 glsym_##sym = dlsym(RTLD_DEFAULT, #sym); 343 glsym_##sym = dlsym(RTLD_DEFAULT, #sym);
344
344 LINK2GENERIC(evas_gl_symbols); 345 LINK2GENERIC(evas_gl_symbols);
345 LINK2GENERIC(evas_gl_common_context_new); 346 LINK2GENERIC(evas_gl_common_context_new);
346 LINK2GENERIC(evas_gl_common_context_free); 347 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,
4462 void *context, void *remove EINA_UNUSED, 4462 void *context, void *remove EINA_UNUSED,
4463 Ector_Renderer *renderer, Eina_Array *clips, Eina_Bool do_async) 4463 Ector_Renderer *renderer, Eina_Array *clips, Eina_Bool do_async)
4464{ 4464{
4465
4466 RGBA_Image *dst = surface; 4465 RGBA_Image *dst = surface;
4467 RGBA_Draw_Context *dc = context; 4466 RGBA_Draw_Context *dc = context;
4468 Evas_Thread_Command_Ector ector; 4467 Evas_Thread_Command_Ector ector;