jpeg pushed a commit to branch master.

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

commit c45ae022c8d23a9e7aa7590d9ac7615a5d61882b
Author: Jean-Philippe Andre <jp.an...@samsung.com>
Date:   Mon Jul 27 14:10:29 2015 +0900

    Evas masking: Fix crash in async rendering
    
    There was a FIXME comment... >_<
    
    Improper management of image resources in async render led to
    a rare crash. This should fix that.
    
    @fix
---
 src/lib/evas/canvas/evas_render.c                   | 21 +++++++++++++--------
 src/lib/evas/filters/evas_filter.c                  |  3 ++-
 src/lib/evas/include/evas_common_private.h          |  2 ++
 src/lib/evas/include/evas_private.h                 |  2 +-
 src/modules/evas/engines/gl_generic/evas_engine.c   |  7 ++++++-
 .../evas/engines/software_generic/evas_engine.c     | 21 ++++++++++++++-------
 6 files changed, 38 insertions(+), 18 deletions(-)

diff --git a/src/lib/evas/canvas/evas_render.c 
b/src/lib/evas/canvas/evas_render.c
index 6af4cd6..80faf6f 100644
--- a/src/lib/evas/canvas/evas_render.c
+++ b/src/lib/evas/canvas/evas_render.c
@@ -1520,7 +1520,8 @@ evas_render_mapped(Evas_Public_Data *e, Evas_Object 
*eo_obj,
                                   (e->engine.data.output, context,
                                    mask->mask->surface,
                                    mask->cur->geometry.x + off_x,
-                                   mask->cur->geometry.y + off_y);
+                                   mask->cur->geometry.y + off_y,
+                                   e, do_async);
                          }
                     }
                }
@@ -1548,7 +1549,7 @@ evas_render_mapped(Evas_Public_Data *e, Evas_Object 
*eo_obj,
              else
                e->engine.func->context_clip_unset(e->engine.data.output, 
context);
              e->engine.func->context_clip_image_set
-               (e->engine.data.output, context, oldm_sfc, oldm_x, oldm_y);
+               (e->engine.data.output, context, oldm_sfc, oldm_x, oldm_y, e, 
do_async);
           }
 
         // FIXME: needs to cache these maps and
@@ -1607,7 +1608,8 @@ evas_render_mapped(Evas_Public_Data *e, Evas_Object 
*eo_obj,
                                   (e->engine.data.output, ctx,
                                    mask->mask->surface,
                                    mask->cur->geometry.x + off_x,
-                                   mask->cur->geometry.y + off_y);
+                                   mask->cur->geometry.y + off_y,
+                                   e, do_async);
                          }
                     }
 
@@ -1666,7 +1668,8 @@ evas_render_mapped(Evas_Public_Data *e, Evas_Object 
*eo_obj,
                                        (e->engine.data.output, ctx,
                                         mask->mask->surface,
                                         mask->cur->geometry.x + off_x,
-                                        mask->cur->geometry.y + off_y);
+                                        mask->cur->geometry.y + off_y,
+                                        e, do_async);
                               }
                          }
                     }
@@ -1681,7 +1684,7 @@ evas_render_mapped(Evas_Public_Data *e, Evas_Object 
*eo_obj,
                   else
                     e->engine.func->context_clip_unset(e->engine.data.output, 
ctx);
                   e->engine.func->context_clip_image_set
-                    (e->engine.data.output, ctx, oldm_sfc, oldm_x, oldm_y);
+                    (e->engine.data.output, ctx, oldm_sfc, oldm_x, oldm_y, e, 
do_async);
                }
              if (!use_mapped_ctx)
                e->engine.func->context_free(e->engine.data.output, ctx);
@@ -1943,7 +1946,8 @@ evas_render_mask_subrender(Evas_Public_Data *evas,
                ENFN->context_clip_image_set(ENDT, ctx,
                                             prev_mask->mask->surface,
                                             prev_mask->cur->geometry.x - x,
-                                            prev_mask->cur->geometry.y - y);
+                                            prev_mask->cur->geometry.y - y,
+                                            evas, EINA_FALSE);
             }
           evas_render_mapped(evas, mask->object, mask, ctx, mdata->surface,
                              -x, -y, 2, 0, 0, evas->output.w, evas->output.h,
@@ -2508,7 +2512,8 @@ evas_render_updates_internal(Evas *eo_e,
                                              e->engine.data.context,
                                              mask->mask->surface,
                                              mask->cur->geometry.x + off_x,
-                                             mask->cur->geometry.y + off_y);
+                                             mask->cur->geometry.y + off_y,
+                                             e, do_async);
                                    }
                               }
 
@@ -2534,7 +2539,7 @@ evas_render_updates_internal(Evas *eo_e,
 
                             if (mask)
                               {
-                                  e->engine.func->context_clip_image_unset
+                                 e->engine.func->context_clip_image_unset
                                     (e->engine.data.output, 
e->engine.data.context);
                               }
                          }
diff --git a/src/lib/evas/filters/evas_filter.c 
b/src/lib/evas/filters/evas_filter.c
index 5d22df2..16efbba 100644
--- a/src/lib/evas/filters/evas_filter.c
+++ b/src/lib/evas/filters/evas_filter.c
@@ -1637,7 +1637,8 @@ _filter_target_render(Evas_Filter_Context *ctx)
 
    if (ctx->target.mask)
      ENFN->context_clip_image_set(ENDT, drawctx,
-                                  ctx->target.mask, ctx->target.mask_x, 
ctx->target.mask_y);
+                                  ctx->target.mask, ctx->target.mask_x, 
ctx->target.mask_y,
+                                  ctx->evas, EINA_FALSE);
    else
      ENFN->context_clip_image_unset(ENDT, drawctx);
 
diff --git a/src/lib/evas/include/evas_common_private.h 
b/src/lib/evas/include/evas_common_private.h
index 934daa8..0f01545 100644
--- a/src/lib/evas/include/evas_common_private.h
+++ b/src/lib/evas/include/evas_common_private.h
@@ -738,9 +738,11 @@ struct _RGBA_Draw_Context
    } col;
    struct RGBA_Draw_Context_clip {
       int    x, y, w, h;
+      Evas_Public_Data *evas; // for async unref
       void  *mask;
       int    mask_x, mask_y;
       Eina_Bool use : 1;
+      Eina_Bool async : 1;
    } clip;
    Cutout_Rects cutout;
    struct {
diff --git a/src/lib/evas/include/evas_private.h 
b/src/lib/evas/include/evas_private.h
index 2e54ab0..01b4340 100644
--- a/src/lib/evas/include/evas_private.h
+++ b/src/lib/evas/include/evas_private.h
@@ -1264,7 +1264,7 @@ struct _Evas_Func
    Eina_Bool (*canvas_alpha_get)           (void *data, void *context);
    void (*context_free)                    (void *data, void *context);
    void (*context_clip_set)                (void *data, void *context, int x, 
int y, int w, int h);
-   void (*context_clip_image_set)          (void *data, void *context, void 
*surface, int x, int y);
+   void (*context_clip_image_set)          (void *data, void *context, void 
*surface, int x, int y, Evas_Public_Data *evas, Eina_Bool do_async);
    void (*context_clip_image_unset)        (void *data, void *context);
    void (*context_clip_image_get)          (void *data, void *context, void 
**surface, int *x, int *y);
    void (*context_clip_clip)               (void *data, void *context, int x, 
int y, int w, int h);
diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c 
b/src/modules/evas/engines/gl_generic/evas_engine.c
index caa2da6..9c9d560 100644
--- a/src/modules/evas/engines/gl_generic/evas_engine.c
+++ b/src/modules/evas/engines/gl_generic/evas_engine.c
@@ -2073,7 +2073,8 @@ eng_context_clip_image_unset(void *data EINA_UNUSED, void 
*context)
 }
 
 static void
-eng_context_clip_image_set(void *data, void *context, void *surface, int x, 
int y)
+eng_context_clip_image_set(void *data, void *context, void *surface, int x, 
int y,
+                           Evas_Public_Data *evas, Eina_Bool do_async)
 {
    RGBA_Draw_Context *ctx = context;
    Evas_GL_Image *im = surface;
@@ -2091,6 +2092,10 @@ eng_context_clip_image_set(void *data, void *context, 
void *surface, int x, int
    ctx->clip.mask_x = x;
    ctx->clip.mask_y = y;
 
+   // useless in gl since the engines are sync only
+   ctx->clip.evas = evas;
+   ctx->clip.async = do_async;
+
    if (im)
      {
         if (!noinc) evas_gl_common_image_ref(im);
diff --git a/src/modules/evas/engines/software_generic/evas_engine.c 
b/src/modules/evas/engines/software_generic/evas_engine.c
index 234be12..3b50c4f 100644
--- a/src/modules/evas/engines/software_generic/evas_engine.c
+++ b/src/modules/evas/engines/software_generic/evas_engine.c
@@ -452,20 +452,25 @@ eng_context_clip_image_unset(void *data EINA_UNUSED, void 
*context)
    if (ctx->clip.mask)
      {
         Image_Entry *ie = ctx->clip.mask;
-#ifdef EVAS_CSERVE2
-        if (evas_cserve2_use_get())
-          evas_cache2_image_close(ie);
+
+        if (ctx->clip.async)
+          evas_unref_queue_image_put(ctx->clip.evas, ie);
         else
+          {
+#ifdef EVAS_CSERVE2
+             if (evas_cserve2_use_get())
+               evas_cache2_image_close(ie);
+             else
 #endif
-          evas_cache_image_drop(ie);
-        // Is the above code safe? Hmmm...
-        //evas_unref_queue_image_put(EVAS???, &ctx->clip.ie->cache_entry);
+               evas_cache_image_drop(ie);
+          }
         ctx->clip.mask = NULL;
      }
 }
 
 static void
-eng_context_clip_image_set(void *data EINA_UNUSED, void *context, void 
*surface, int x, int y)
+eng_context_clip_image_set(void *data EINA_UNUSED, void *context, void 
*surface, int x, int y,
+                           Evas_Public_Data *evas, Eina_Bool do_async)
 {
    RGBA_Draw_Context *ctx = context;
    Eina_Bool noinc = EINA_FALSE;
@@ -481,6 +486,8 @@ eng_context_clip_image_set(void *data EINA_UNUSED, void 
*context, void *surface,
    ctx->clip.mask = surface;
    ctx->clip.mask_x = x;
    ctx->clip.mask_y = y;
+   ctx->clip.evas = evas;
+   ctx->clip.async = do_async;
 
    if (surface)
      {

-- 


Reply via email to