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
This commit is contained in:
Jean-Philippe Andre 2015-07-27 14:10:29 +09:00
parent 17823d21ea
commit c45ae022c8
6 changed files with 38 additions and 18 deletions

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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 {

View File

@ -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);

View File

@ -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);

View File

@ -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)
{