raster pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=d7c6fca6c00a0bfb05923b4da276ff290ca43f72
commit d7c6fca6c00a0bfb05923b4da276ff290ca43f72 Author: Carsten Haitzler (Rasterman) <[email protected]> Date: Sun Nov 27 12:02:12 2016 +0900 evas render and clip calc - move evas_object_clip_recalc out of inline evas_object_clip_recalc is big. it's fat. it shouldnt be inline. so make it a real function. being inline just hurts performance by making our code bigger, hurting l1 instruction prefetch and cache performance. this function isn't small. it's huge and should not be inline basically because of that reason. also throw in some likely/unlikely hints etc. @optimize --- src/lib/evas/canvas/evas_object_main.c | 145 +++++++++++++++++++++++++++++++++ src/lib/evas/canvas/evas_render.c | 17 ++-- src/lib/evas/include/evas_inline.x | 142 -------------------------------- src/lib/evas/include/evas_private.h | 1 + 4 files changed, 158 insertions(+), 147 deletions(-) diff --git a/src/lib/evas/canvas/evas_object_main.c b/src/lib/evas/canvas/evas_object_main.c index 8466bab..18df96d 100644 --- a/src/lib/evas/canvas/evas_object_main.c +++ b/src/lib/evas/canvas/evas_object_main.c @@ -134,6 +134,151 @@ typedef struct _Map_Same Eina_Bool b1; } Map_Same; +void +evas_object_clip_recalc(Evas_Object_Protected_Data *obj) +{ + Evas_Object_Protected_Data *clipper = NULL; + int cx, cy, cw, ch, cr, cg, cb, ca; + int nx, ny, nw, nh, nr, ng, nb, na; + Eina_Bool cvis, nvis; + Evas_Object *eo_obj; + + EVAS_OBJECT_DATA_ALIVE_CHECK(obj); + + clipper = obj->cur->clipper; + + if (EINA_LIKELY(((!obj->cur->cache.clip.dirty) && + !(!clipper || clipper->cur->cache.clip.dirty)))) return; + + if (EINA_UNLIKELY(obj->layer->evas->is_frozen)) return; + + eo_obj = obj->object; + + evas_object_coords_recalc(eo_obj, obj); + + if (EINA_UNLIKELY((obj->map->cur.map) && (obj->map->cur.usemap))) + { + cx = obj->map->cur.map->normal_geometry.x; + cy = obj->map->cur.map->normal_geometry.y; + cw = obj->map->cur.map->normal_geometry.w; + ch = obj->map->cur.map->normal_geometry.h; + } + else + { + if (obj->is_smart) + { + Evas_Coord_Rectangle bounding_box; + + evas_object_smart_bounding_box_update(eo_obj, obj); + evas_object_smart_bounding_box_get(eo_obj, &bounding_box, NULL); + cx = bounding_box.x; + cy = bounding_box.y; + cw = bounding_box.w; + ch = bounding_box.h; + } + else + { + cx = obj->cur->geometry.x; + cy = obj->cur->geometry.y; + cw = obj->cur->geometry.w; + ch = obj->cur->geometry.h; + } + } + + if (EINA_UNLIKELY((obj->cur->color.a == 0) && + (obj->cur->render_op == EVAS_RENDER_BLEND))) + cvis = EINA_FALSE; + else cvis = obj->cur->visible; + + cr = obj->cur->color.r; cg = obj->cur->color.g; + cb = obj->cur->color.b; ca = obj->cur->color.a; + + if (EVAS_OBJECT_DATA_VALID(clipper)) + { + // this causes problems... hmmm ????? + evas_object_clip_recalc(clipper); + + // I don't know why this test was here in the first place. As I have + // no issue showing up due to this, I keep it and move color out of it. + // breaks cliping of mapped images!!! + if (clipper->map->cur.map_parent == obj->map->cur.map_parent) + { + nx = clipper->cur->cache.clip.x; + ny = clipper->cur->cache.clip.y; + nw = clipper->cur->cache.clip.w; + nh = clipper->cur->cache.clip.h; + RECTS_CLIP_TO_RECT(cx, cy, cw, ch, nx, ny, nw, nh); + } + + obj->clip.prev_mask = NULL; + if (EINA_UNLIKELY(clipper->mask->is_mask)) + { + // Set complex masks the object being clipped (parent) + obj->clip.mask = clipper; + + // Forward any mask from the parents + if (EINA_LIKELY(obj->smart.parent != NULL)) + { + Evas_Object_Protected_Data *parent = + efl_data_scope_get(obj->smart.parent, EFL_CANVAS_OBJECT_CLASS); + if (parent->clip.mask) + { + if (parent->clip.mask != obj->clip.mask) + obj->clip.prev_mask = parent->clip.mask; + } + } + } + else if (EINA_UNLIKELY(clipper->clip.mask != NULL)) + { + // Pass complex masks to children + obj->clip.mask = clipper->clip.mask; + } + else obj->clip.mask = NULL; + + nvis = clipper->cur->cache.clip.visible; + nr = clipper->cur->cache.clip.r; + ng = clipper->cur->cache.clip.g; + nb = clipper->cur->cache.clip.b; + na = clipper->cur->cache.clip.a; + cvis = (cvis & nvis); + cr = (cr * (nr + 1)) >> 8; + cg = (cg * (ng + 1)) >> 8; + cb = (cb * (nb + 1)) >> 8; + ca = (ca * (na + 1)) >> 8; + } + + if (((ca == 0) && (obj->cur->render_op == EVAS_RENDER_BLEND)) || + (cw <= 0) || (ch <= 0)) + cvis = EINA_FALSE; + + if ((obj->cur->cache.clip.dirty == EINA_FALSE) && + (obj->cur->cache.clip.visible == cvis) && + (obj->cur->cache.clip.x == cx) && + (obj->cur->cache.clip.y == cy) && + (obj->cur->cache.clip.w == cw) && + (obj->cur->cache.clip.h == ch) && + (obj->cur->cache.clip.r == cr) && + (obj->cur->cache.clip.g == cg) && + (obj->cur->cache.clip.b == cb) && + (obj->cur->cache.clip.a == ca)) + return; + + EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur) + { + state_write->cache.clip.x = cx; + state_write->cache.clip.y = cy; + state_write->cache.clip.w = cw; + state_write->cache.clip.h = ch; + state_write->cache.clip.visible = cvis; + state_write->cache.clip.r = cr; + state_write->cache.clip.g = cg; + state_write->cache.clip.b = cb; + state_write->cache.clip.a = ca; + state_write->cache.clip.dirty = EINA_FALSE; + } + EINA_COW_STATE_WRITE_END(obj, state_write, cur); +} + static inline Eina_Bool _map_same(const void *map1, const void *map2) { diff --git a/src/lib/evas/canvas/evas_render.c b/src/lib/evas/canvas/evas_render.c index 0b5d10b..c40a864 100644 --- a/src/lib/evas/canvas/evas_render.c +++ b/src/lib/evas/canvas/evas_render.c @@ -401,6 +401,7 @@ _evas_render_phase1_direct(Evas_Public_Data *e, Evas_Active_Entry *ent = eina_inarray_nth(active_objects, i); Evas_Object_Protected_Data *obj = ent->obj; + EINA_PREFETCH(&(obj->cur->clipper)); if (obj->changed) evas_object_clip_recalc(obj); if (obj->proxy->proxies || obj->proxy->proxy_textures) @@ -419,7 +420,7 @@ _evas_render_phase1_direct(Evas_Public_Data *e, for (i = 0; i < render_objects->count; i++) { Evas_Object_Protected_Data *obj = - eina_array_data_get(render_objects, i); + eina_array_data_get(render_objects, i); eo_obj = obj->object; RD(0, " OBJ [%p", obj); @@ -1024,6 +1025,8 @@ _evas_render_phase1_object_process(Phase1_Context *p1ctx, Eina_Bool map, hmap, can_map, map_not_can_map, obj_changed, is_active; Evas_Object *eo_obj = obj->object; + EINA_PREFETCH(&(obj->cur->clipper)); + obj->rect_del = EINA_FALSE; obj->render_pre = EINA_FALSE; @@ -1213,9 +1216,13 @@ _evas_render_check_pending_objects(Eina_Array *pending_objects, Evas *eo_e EINA_ if (!obj->layer) goto clean_stuff; - //If the children are in active objects, They should be cleaned up. - if (obj->changed_map && _evas_render_has_map(obj) && !_evas_render_can_map(obj)) - goto clean_stuff; + EINA_PREFETCH(&(obj->cur->clipper)); + EINA_PREFETCH(&(obj->cur->cache.clip)); + //If the children are in active objects, They should be cleaned up. + if (EINA_UNLIKELY((obj->changed_map) && + (_evas_render_has_map(obj)) && + (!_evas_render_can_map(obj)))) + goto clean_stuff; evas_object_clip_recalc(obj); is_active = evas_object_is_active(eo_obj, obj); @@ -1680,7 +1687,7 @@ evas_render_mapped(Evas_Public_Data *evas, Evas_Object *eo_obj, evas_object_clip_recalc(obj); /* leave early if clipper is not visible */ - if (obj->cur->clipper && !obj->cur->clipper->cur->visible) + if ((obj->cur->clipper) && (!obj->cur->clipper->cur->visible)) return clean_them; eina_evlog("+render_object", eo_obj, 0.0, NULL); diff --git a/src/lib/evas/include/evas_inline.x b/src/lib/evas/include/evas_inline.x index 6939870..d56d365 100644 --- a/src/lib/evas/include/evas_inline.x +++ b/src/lib/evas/include/evas_inline.x @@ -268,148 +268,6 @@ evas_object_coords_recalc(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj) } static inline void -evas_object_clip_recalc(Evas_Object_Protected_Data *obj) -{ - Evas_Object_Protected_Data *clipper = NULL; - int cx, cy, cw, ch, cr, cg, cb, ca; - int nx, ny, nw, nh, nr, ng, nb, na; - Eina_Bool cvis, nvis; - Evas_Object *eo_obj; - - EVAS_OBJECT_DATA_ALIVE_CHECK(obj); - - eo_obj = obj->object; - clipper = obj->cur->clipper; - - if ((!obj->cur->cache.clip.dirty) && - !(!clipper || clipper->cur->cache.clip.dirty)) return; - - if (obj->layer->evas->is_frozen) return; - - evas_object_coords_recalc(eo_obj, obj); - - if ((obj->map->cur.map) && (obj->map->cur.usemap)) - { - cx = obj->map->cur.map->normal_geometry.x; - cy = obj->map->cur.map->normal_geometry.y; - cw = obj->map->cur.map->normal_geometry.w; - ch = obj->map->cur.map->normal_geometry.h; - } - else - { - if (obj->is_smart) - { - Evas_Coord_Rectangle bounding_box = { 0, 0, 0, 0 }; - - evas_object_smart_bounding_box_update(eo_obj, obj); - evas_object_smart_bounding_box_get(eo_obj, &bounding_box, NULL); - cx = bounding_box.x; - cy = bounding_box.y; - cw = bounding_box.w; - ch = bounding_box.h; - } - else - { - cx = obj->cur->geometry.x; - cy = obj->cur->geometry.y; - cw = obj->cur->geometry.w; - ch = obj->cur->geometry.h; - } - } - - if (obj->cur->color.a == 0 && obj->cur->render_op == EVAS_RENDER_BLEND) - cvis = EINA_FALSE; - else cvis = obj->cur->visible; - - cr = obj->cur->color.r; cg = obj->cur->color.g; - cb = obj->cur->color.b; ca = obj->cur->color.a; - - if (EVAS_OBJECT_DATA_VALID(clipper)) - { - // this causes problems... hmmm ????? - evas_object_clip_recalc(clipper); - - // I don't know why this test was here in the first place. As I have - // no issue showing up due to this, I keep it and move color out of it. - // breaks cliping of mapped images!!! - if (clipper->map->cur.map_parent == obj->map->cur.map_parent) - { - nx = clipper->cur->cache.clip.x; - ny = clipper->cur->cache.clip.y; - nw = clipper->cur->cache.clip.w; - nh = clipper->cur->cache.clip.h; - RECTS_CLIP_TO_RECT(cx, cy, cw, ch, nx, ny, nw, nh); - } - - obj->clip.prev_mask = NULL; - if (clipper->mask->is_mask) - { - // Set complex masks the object being clipped (parent) - obj->clip.mask = clipper; - - // Forward any mask from the parents - if (EINA_LIKELY(obj->smart.parent != NULL)) - { - Evas_Object_Protected_Data *parent = - efl_data_scope_get(obj->smart.parent, EFL_CANVAS_OBJECT_CLASS); - if (parent->clip.mask) - { - if (parent->clip.mask != obj->clip.mask) - obj->clip.prev_mask = parent->clip.mask; - } - } - } - else if (clipper->clip.mask) - { - // Pass complex masks to children - obj->clip.mask = clipper->clip.mask; - } - else obj->clip.mask = NULL; - - nvis = clipper->cur->cache.clip.visible; - nr = clipper->cur->cache.clip.r; - ng = clipper->cur->cache.clip.g; - nb = clipper->cur->cache.clip.b; - na = clipper->cur->cache.clip.a; - cvis = (cvis & nvis); - cr = (cr * (nr + 1)) >> 8; - cg = (cg * (ng + 1)) >> 8; - cb = (cb * (nb + 1)) >> 8; - ca = (ca * (na + 1)) >> 8; - } - - if ((ca == 0 && obj->cur->render_op == EVAS_RENDER_BLEND) || - (cw <= 0) || (ch <= 0)) cvis = EINA_FALSE; - - if (obj->cur->cache.clip.x == cx && - obj->cur->cache.clip.y == cy && - obj->cur->cache.clip.w == cw && - obj->cur->cache.clip.h == ch && - obj->cur->cache.clip.visible == cvis && - obj->cur->cache.clip.r == cr && - obj->cur->cache.clip.g == cg && - obj->cur->cache.clip.b == cb && - obj->cur->cache.clip.a == ca && - obj->cur->cache.clip.dirty == EINA_FALSE) - return ; - - EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur) - { - state_write->cache.clip.x = cx; - state_write->cache.clip.y = cy; - state_write->cache.clip.w = cw; - state_write->cache.clip.h = ch; - state_write->cache.clip.visible = cvis; - state_write->cache.clip.r = cr; - state_write->cache.clip.g = cg; - state_write->cache.clip.b = cb; - state_write->cache.clip.a = ca; - state_write->cache.clip.dirty = EINA_FALSE; - } - EINA_COW_STATE_WRITE_END(obj, state_write, cur); -} - -static inline void evas_object_async_block(Evas_Object_Protected_Data *obj) { if (EVAS_OBJECT_DATA_VALID(obj)) diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index 5f355cc..9d5b2e0 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -1562,6 +1562,7 @@ extern "C" { Evas_Object *evas_object_new(Evas *e); void evas_object_change_reset(Evas_Object *obj); +void evas_object_clip_recalc(Evas_Object_Protected_Data *obj); void evas_object_cur_prev(Evas_Object *obj); void evas_object_free(Evas_Object *obj, int clean_layer); void evas_object_update_bounding_box(Evas_Object *obj, Evas_Object_Protected_Data *pd, Evas_Smart_Data *s); --
