evas: fix ref/unref of ector renderer to always happen in the main loop.
authorCedric BAIL <cedric@osg.samsung.com>
Wed, 19 Aug 2015 14:06:39 +0000 (16:06 +0200)
committerCedric BAIL <cedric@osg.samsung.com>
Wed, 19 Aug 2015 14:06:39 +0000 (16:06 +0200)
src/lib/evas/canvas/evas_object_vg.c
src/modules/evas/engines/software_generic/evas_engine.c

index abf12c3..bdda637 100644 (file)
@@ -22,6 +22,8 @@ struct _Evas_VG_Data
    Eina_Rectangle fill;
 
    unsigned int width, height;
+
+   Eina_Array cleanup;
 };
 
 static void evas_object_vg_render(Evas_Object *eo_obj,
@@ -116,23 +118,25 @@ _evas_vg_eo_base_constructor(Eo *eo_obj, Evas_VG_Data *pd)
    pd->root = eo_add(EFL_VG_ROOT_NODE_CLASS, eo_obj);
    eo_ref(pd->root);
 
+   eina_array_step_set(&pd->cleanup, sizeof(pd->cleanup), 8);
+
    return eo_obj;
 }
 
 static void
-_evas_vg_render(Evas_Object_Protected_Data *obj,
+_evas_vg_render(Evas_Object_Protected_Data *obj, Evas_VG_Data *vd,
                 void *output, void *context, void *surface, Efl_VG *n,
                 Eina_Array *clips, Eina_Bool do_async)
 {
-   Efl_VG_Container_Data *vd = eo_data_scope_get(n, EFL_VG_CONTAINER_CLASS);
+   Efl_VG_Container_Data *vc = eo_data_scope_get(n, EFL_VG_CONTAINER_CLASS);
 
    if (eo_isa(n, EFL_VG_CONTAINER_CLASS))
      {
         Efl_VG *child;
         Eina_List *l;
 
-        EINA_LIST_FOREACH(vd->children, l, child)
-          _evas_vg_render(obj,
+        EINA_LIST_FOREACH(vc->children, l, child)
+          _evas_vg_render(obj, vd,
                           output, context, surface, child,
                           clips, do_async);
      }
@@ -143,6 +147,9 @@ _evas_vg_render(Evas_Object_Protected_Data *obj,
         nd = eo_data_scope_get(n, EFL_VG_BASE_CLASS);
 
         obj->layer->evas->engine.func->ector_renderer_draw(output, context, surface, nd->renderer, clips, do_async);
+
+        if (do_async)
+          eina_array_push(&vd->cleanup, eo_ref(nd->renderer));
      }
 }
 
@@ -182,7 +189,9 @@ evas_object_vg_render(Evas_Object *eo_obj EINA_UNUSED,
    obj->layer->evas->engine.func->ector_begin(output, context, surface,
                                               obj->cur->geometry.x + x, obj->cur->geometry.y + y,
                                               do_async);
-   _evas_vg_render(obj, output, context, surface, vd->root, NULL,
+   _evas_vg_render(obj, vd,
+                   output, context, surface,
+                   vd->root, NULL,
                    do_async);
    obj->layer->evas->engine.func->ector_end(output, context, surface, do_async);
 }
@@ -325,8 +334,13 @@ evas_object_vg_render_pre(Evas_Object *eo_obj,
 static void
 evas_object_vg_render_post(Evas_Object *eo_obj,
                            Evas_Object_Protected_Data *obj EINA_UNUSED,
-                           void *type_private_data EINA_UNUSED)
+                           void *type_private_data)
 {
+   Evas_VG_Data *vd = type_private_data;
+   Eo *renderer;
+   Eina_Array_Iterator iterator;
+   unsigned int i;
+
    /* this moves the current data to the previous state parts of the object */
    /* in whatever way is safest for the object. also if we don't need object */
    /* data anymore we can free it if the object deems this is a good idea */
@@ -334,6 +348,9 @@ evas_object_vg_render_post(Evas_Object *eo_obj,
    evas_object_clip_changes_clean(eo_obj);
    /* move cur to prev safely for object data */
    evas_object_cur_prev(eo_obj);
+   /* unref all renderer and may also destroy them async */
+   EINA_ARRAY_ITER_NEXT((&vd->cleanup), i, renderer, iterator)
+     eo_unref(renderer);
 }
 
 static unsigned int
index 3b50c4f..cdaba07 100644 (file)
@@ -3532,7 +3532,6 @@ _draw_thread_ector_cleanup(Evas_Thread_Command_Ector *ector)
    while ((r = eina_array_pop(ector->clips)))
      eina_rectangle_free(r);
    eina_array_free(ector->clips);
-   eo_unref(ector->r);
 
    if (ector->free_it)
      eina_mempool_free(_mp_command_ector, ector);
@@ -3605,7 +3604,7 @@ eng_ector_renderer_draw(void *data EINA_UNUSED, void *context, void *surface, Ec
    if (eina_array_count(c) == 0)
      eina_array_push(c, eina_rectangle_new(clip.x, clip.y, clip.w, clip.h));
 
-   ector.r = eo_ref(renderer);
+   ector.r = renderer; // This has already been refcounted by Evas_Object_VG
    ector.clips = c;
    ector.render_op = _evas_render_op_to_ector_rop(dc->render_op);
    ector.mul_col = ector_color_multiply(dc->mul.use ? dc->mul.col : 0xffffffff,