From c45ae022c8d23a9e7aa7590d9ac7615a5d61882b Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Mon, 27 Jul 2015 14:10:29 +0900 Subject: [PATCH] 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 +- .../evas/engines/gl_generic/evas_engine.c | 7 ++++++- .../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 6af4cd6492..80faf6f3c5 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 5d22df2efd..16efbbafde 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 934daa8f57..0f01545317 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 2e54ab046d..01b43401a5 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 caa2da6d7b..9c9d560004 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 234be121fd..3b50c4f1be 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) {