jpeg pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=a6951397f619d5f5c2491ec75f26b2facae476ff
commit a6951397f619d5f5c2491ec75f26b2facae476ff Author: Jean-Philippe Andre <jp.an...@samsung.com> Date: Fri Feb 10 16:08:58 2017 +0900 evas: Optimize redraws of snapshot objects If anything in the canvas needs redraw and a snapshot object happens to intersect with the update region then it was redrawn, even if all objects below it hadn't changed. This has an insane performance impact when you apply a blur filter on the snapshot object. Walking the object list will always be cheaper than rendering the snapshot! Note: Added a FIXME comment and forced clean_them to be true because some odd behaviour happens when breaking with GDB and the array snapshot_objects keeps growing at each frame (I guess only if we miss a frame or something like that). --- src/lib/evas/canvas/evas_object_image.c | 11 +++++++--- src/lib/evas/canvas/evas_render.c | 39 +++++++++++++++++++++++++++++---- src/lib/evas/include/evas_private.h | 2 +- 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/src/lib/evas/canvas/evas_object_image.c b/src/lib/evas/canvas/evas_object_image.c index 641e8a4..a3f7e48 100644 --- a/src/lib/evas/canvas/evas_object_image.c +++ b/src/lib/evas/canvas/evas_object_image.c @@ -3567,9 +3567,9 @@ _evas_object_image_video_overlay_do(Evas_Object *eo_obj) } void * -_evas_object_image_surface_get(Evas_Object *eo, Evas_Object_Protected_Data *obj) +_evas_object_image_surface_get(Evas_Object_Protected_Data *obj, Eina_Bool create) { - Evas_Image_Data *pd = efl_data_scope_get(eo, MY_CLASS); + Evas_Image_Data *pd = obj->private_data; if (pd->engine_data && (pd->cur->image.w == obj->cur->geometry.w) && @@ -3577,7 +3577,12 @@ _evas_object_image_surface_get(Evas_Object *eo, Evas_Object_Protected_Data *obj) return pd->engine_data; if (pd->engine_data) - ENFN->image_free(ENDT, pd->engine_data); + { + ENFN->image_free(ENDT, pd->engine_data); + pd->engine_data = NULL; + } + + if (!create) return pd->engine_data; // FIXME: alpha forced to 1 for now, need to figure out Evas alpha here EINA_COW_IMAGE_STATE_WRITE_BEGIN(pd, state_write) diff --git a/src/lib/evas/canvas/evas_render.c b/src/lib/evas/canvas/evas_render.c index 5de9847..a13c693 100644 --- a/src/lib/evas/canvas/evas_render.c +++ b/src/lib/evas/canvas/evas_render.c @@ -2738,6 +2738,31 @@ _is_obj_in_rect(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, #endif static Eina_Bool +_snapshot_needs_redraw(Evas_Public_Data *evas, Evas_Object_Protected_Data *snap) +{ + const int x = snap->cur->geometry.x; + const int y = snap->cur->geometry.y; + const int w = snap->cur->geometry.w; + const int h = snap->cur->geometry.h; + Evas_Object_Protected_Data *obj; + Evas_Active_Entry *ent; + void *surface; + + surface = _evas_object_image_surface_get(snap, EINA_FALSE); + if (!surface) return EINA_TRUE; + + EINA_INARRAY_FOREACH(&evas->active_objects, ent) + { + obj = ent->obj; + if (obj == snap) break; + if (!obj->is_smart && obj->changed && + evas_object_is_in_output_rect(obj->object, obj, x, y, w, h)) + return EINA_TRUE; + } + return EINA_FALSE; +} + +static Eina_Bool evas_render_updates_internal_loop(Evas *eo_e, Evas_Public_Data *evas, void *surface, void *context, Evas_Object_Protected_Data *top, @@ -3089,7 +3114,7 @@ evas_render_updates_internal(Evas *eo_e, { for (i = 0; i < e->snapshot_objects.count; i++) { - obj = (Evas_Object_Protected_Data *)eina_array_data_get(&e->snapshot_objects, i); + obj = eina_array_data_get(&e->snapshot_objects, i); if (evas_object_is_visible(obj->object, obj)) ENFN->output_redraws_rect_add(ENDT, @@ -3173,7 +3198,7 @@ evas_render_updates_internal(Evas *eo_e, { Eina_Rectangle output, cr, ur; - obj = (Evas_Object_Protected_Data *)eina_array_data_get(&e->snapshot_objects, j); + obj = eina_array_data_get(&e->snapshot_objects, j); EINA_RECTANGLE_SET(&output, obj->cur->geometry.x, @@ -3182,7 +3207,8 @@ evas_render_updates_internal(Evas *eo_e, obj->cur->geometry.h); EINA_RECTANGLE_SET(&ur, ux, uy, uw, uh); - if (eina_rectangle_intersection(&ur, &output)) + if (eina_rectangle_intersection(&ur, &output) && + _snapshot_needs_redraw(evas, obj)) { void *pseudo_canvas; unsigned int restore_offset = offset; @@ -3191,7 +3217,7 @@ evas_render_updates_internal(Evas *eo_e, ur.x - output.x, ur.y - output.y, ur.w, ur.h); - pseudo_canvas = _evas_object_image_surface_get(obj->object, obj); + pseudo_canvas = _evas_object_image_surface_get(obj, EINA_TRUE); RD(0, " SNAPSHOT %s [sfc:%p ur:%d,%d %dx%d]\n", RDNAME(obj), pseudo_canvas, ur.x, ur.y, ur.w, ur.h); ctx = ENFN->context_new(ENDT); @@ -3209,6 +3235,11 @@ evas_render_updates_internal(Evas *eo_e, obj->changed = EINA_TRUE; offset = restore_offset; + + // FIXME: For some reason the arrays are not cleaned and + // snapshot objects keep being added to it... only when + // I break in GDB. Normal render flow is fine. Odd. + clean_them = EINA_TRUE; } } eina_evlog("-render_snapshots", eo_e, 0.0, NULL); diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index f3d74d2..02e14f2 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -2033,7 +2033,7 @@ void *efl_input_hold_legacy_info_fill(Efl_Input_Hold *evt, Evas_Event_Flags **pf Eina_Bool evas_vg_loader_svg(Evas_Object *vg, const Eina_File *f, const char *key EINA_UNUSED); -void *_evas_object_image_surface_get(Evas_Object *eo, Evas_Object_Protected_Data *obj); +void *_evas_object_image_surface_get(Evas_Object_Protected_Data *obj, Eina_Bool create); Eina_Bool _evas_image_proxy_source_clip_get(const Eo *eo_obj); void _evas_focus_dispatch_event(Evas_Object_Protected_Data *obj, --