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
This commit is contained in:
Carsten Haitzler 2016-11-27 12:02:12 +09:00
parent e3489d5f89
commit d7c6fca6c0
4 changed files with 158 additions and 147 deletions

View File

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

View File

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

View File

@ -267,148 +267,6 @@ evas_object_coords_recalc(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj)
//// obj->cur->cache.geometry.validity = obj->layer->evas->output_validity;
}
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)
{

View File

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