From ed0ac9fec7b0ee178e769e33ac7aa07f9383438d Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Fri, 21 Mar 2014 17:03:33 +0900 Subject: [PATCH] Evas image: Gracefully handle filter failures Add proper callback and mark filter as invalid in case of failure. This might still trigger a redraw. --- src/lib/evas/canvas/evas_object_image.c | 69 ++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 7 deletions(-) diff --git a/src/lib/evas/canvas/evas_object_image.c b/src/lib/evas/canvas/evas_object_image.c index 1d4fe495dd..7a82c1e0f6 100644 --- a/src/lib/evas/canvas/evas_object_image.c +++ b/src/lib/evas/canvas/evas_object_image.c @@ -2980,6 +2980,35 @@ evas_process_dirty_pixels(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, return pixels; } +static void +_filter_cb(Evas_Filter_Context *ctx, void *data, Eina_Bool success) +{ + Eo *eo_obj = data; + + // Destroy context as we won't reuse it. + evas_filter_context_destroy(ctx); + + // Redraw image normally + if (!success) + { + Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJ_CLASS); + Evas_Image_Data *o = (Evas_Image_Data *) obj->private_data; + + ERR("Filter failed at runtime!"); + EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write) + state_write->filter.invalid = EINA_TRUE; + EINA_COW_IMAGE_STATE_WRITE_END(o, state_write) + + // Update object + obj = eo_data_scope_get(eo_obj, EVAS_OBJ_CLASS); + o->changed = EINA_TRUE; + evas_object_change(eo_obj, obj); + evas_object_clip_dirty(eo_obj, obj); + evas_object_coords_recalc(eo_obj, obj); + evas_object_inform_call_resize(eo_obj); + } +} + static void evas_object_image_render(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, void *type_private_data, void *output, void *context, void *surface, int x, int y, Eina_Bool do_async) @@ -3128,6 +3157,7 @@ evas_object_image_render(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, v Eina_Bool clear = EINA_FALSE; int W, H, offx, offy; +start_draw: obj->layer->evas->engine.func->image_scale_hint_set(output, pixels, o->scale_hint); @@ -3167,7 +3197,7 @@ evas_object_image_render(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, v if (!o->cur->filter.invalid && o->cur->filter.code) { Evas_Filter_Program *pgm = o->cur->filter.chain;; - Eina_Bool redraw = o->cur->filter.changed; + Eina_Bool redraw = (o->changed || o->cur->filter.changed); Eina_Bool ok; evas_filter_program_padding_get(pgm, &l, &r, &t, &b); @@ -3269,6 +3299,7 @@ state_write: evas_filter_program_del(pgm); state_write->filter.invalid = EINA_TRUE; state_write->filter.chain = NULL; + l = r = t = b = 0; filter = NULL; } } @@ -3513,6 +3544,8 @@ state_write: /* Evas filters wrap-up */ if (filter) { + Eina_Bool ok; + void *outbuf = evas_filter_buffer_backing_steal(filter, EVAS_FILTER_BUFFER_OUTPUT_ID); if (outbuf != o->cur->filter.output) { @@ -3528,12 +3561,33 @@ state_write: evas_filter_buffer_backing_release(filter, surface); evas_filter_target_set(filter, context_save, surface_save, obj->cur->geometry.x + x, obj->cur->geometry.y + y); - evas_filter_context_autodestroy(filter); - evas_filter_run(filter); + evas_filter_context_post_run_callback_set(filter, _filter_cb, eo_obj); + ok = evas_filter_run(filter); if (!input_stolen) obj->layer->evas->engine.func->image_map_surface_free(output, surface); obj->layer->evas->engine.func->context_free(output, context); + + if (!ok) + { + ERR("Rendering failed"); + EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write) + state_write->filter.invalid = EINA_TRUE; + EINA_COW_IMAGE_STATE_WRITE_END(o, state_write) + l = r = t = b = 0; + context = context_save; + surface = surface_save; + input_stolen = EINA_FALSE; + clear = EINA_FALSE; + filter = NULL; + goto start_draw; + } + else + { + EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write) + state_write->filter.changed = EINA_FALSE; + EINA_COW_IMAGE_STATE_WRITE_END(o, state_write) + } } } } @@ -3694,6 +3748,11 @@ evas_object_image_render_pre(Evas_Object *eo_obj, evas_object_render_pre_prev_cur_add(&e->clip_changes, eo_obj, obj); if (!o->pixels->pixel_updates) goto done; } + if (o->cur->filter.changed) + { + evas_object_render_pre_prev_cur_add(&e->clip_changes, eo_obj, obj); + if (!o->pixels->pixel_updates) goto done; + } if (o->changed) { if ((o->cur->fill.x != o->prev->fill.x) || @@ -4723,11 +4782,7 @@ _evas_image_filter_program_set(Eo *eo_obj, Evas_Image_Data *o, const char *arg) // Update object obj = eo_data_scope_get(eo_obj, EVAS_OBJ_CLASS); o->changed = EINA_TRUE; - o->written = EINA_FALSE; evas_object_change(eo_obj, obj); - evas_object_clip_dirty(eo_obj, obj); - evas_object_coords_recalc(eo_obj, obj); - evas_object_inform_call_resize(eo_obj); } static void