efl_ui/table: optimize position_set operations with tables

if a table is moved and no other changes are made to the table or its children,
e.g., if the table is scrolled, then there is no need to loop over the table's
items repeatedly in order to accurately calculate all the item geometries
and positions.

instead, simply apply an offset from the last table calc position to each child
item and handle the position changes more transparently

this yields roughly a 12% perf improvement to the 'efl.ui.scroller simple2' test
and brings rendering up to nearly 60fps

Reviewed-by: Cedric BAIL <cedric.bail@free.fr>
Differential Revision: https://phab.enlightenment.org/D9346
This commit is contained in:
Mike Blumenkrantz 2019-07-17 13:12:23 -04:00 committed by Cedric BAIL
parent 1dd5feb22f
commit 3ba31a1f5c
3 changed files with 34 additions and 4 deletions

View File

@ -174,7 +174,7 @@ EOLIAN static void
_efl_ui_table_efl_gfx_entity_size_set(Eo *obj, Efl_Ui_Table_Data *_pd EINA_UNUSED, Eina_Size2D sz)
{
efl_gfx_entity_size_set(efl_super(obj, MY_CLASS), sz);
efl_canvas_group_change(obj);
efl_pack_layout_request(obj);
}
EOLIAN static void
@ -508,8 +508,9 @@ _efl_ui_table_efl_pack_unpack_all(Eo *obj, Efl_Ui_Table_Data *pd)
}
EOLIAN static void
_efl_ui_table_efl_pack_layout_layout_request(Eo *obj, Efl_Ui_Table_Data *pd EINA_UNUSED)
_efl_ui_table_efl_pack_layout_layout_request(Eo *obj, Efl_Ui_Table_Data *pd)
{
pd->full_recalc = EINA_TRUE;
efl_canvas_group_need_recalculate_set(obj, EINA_TRUE);
}

View File

@ -218,6 +218,27 @@ _efl_ui_table_regular_item_size_get(Table_Calc *table_calc, Item_Calc *item, Ein
- item->hints[axis].margin[0] - item->hints[axis].margin[1];
}
/* this function performs a simplified layout when the table has changed position
* but no other changes have occurred, e.g., when a table is being scrolled
*/
static void
_efl_ui_table_layout_simple(Efl_Ui_Table *ui_table, Efl_Ui_Table_Data *pd)
{
Table_Item *ti;
Eina_Position2D pos = efl_gfx_entity_position_get(ui_table);
EINA_INLIST_FOREACH(EINA_INLIST_GET(pd->items), ti)
{
Eina_Position2D child_pos = efl_gfx_entity_position_get(ti->object);
efl_gfx_entity_position_set(ti->object,
EINA_POSITION2D(pos.x - pd->last_pos.x + child_pos.x,
pos.y - pd->last_pos.y + child_pos.y));
}
pd->last_pos = pos;
efl_event_callback_call(ui_table, EFL_PACK_EVENT_LAYOUT_UPDATED, NULL);
}
void
_efl_ui_table_custom_layout(Efl_Ui_Table *ui_table, Efl_Ui_Table_Data *pd)
{
@ -231,14 +252,19 @@ _efl_ui_table_custom_layout(Efl_Ui_Table *ui_table, Efl_Ui_Table_Data *pd)
Eina_Bool do_free;
count = pd->count;
if (!count)
{
efl_gfx_hint_size_restricted_min_set(ui_table, EINA_SIZE2D(0, 0));
return;
}
if (!pd->full_recalc)
{
_efl_ui_table_layout_simple(ui_table, pd);
return;
}
_efl_ui_container_layout_init(ui_table, table_calc.layout_calc);
pd->last_pos.x = table_calc.layout_calc[0].pos - table_calc.layout_calc[0].margin[0];
pd->last_pos.y = table_calc.layout_calc[1].pos - table_calc.layout_calc[1].margin[0];
table_calc.want[0] = table_calc.want[1] = 0;
table_calc.weight_sum[0] = table_calc.weight_sum[1] = 0;
@ -391,6 +417,7 @@ _efl_ui_table_custom_layout(Efl_Ui_Table *ui_table, Efl_Ui_Table_Data *pd)
+ (table_calc.layout_calc[1].pad *
table_calc.cell_calc[1][rows - 1].index);
pd->full_recalc = EINA_FALSE;
efl_gfx_hint_size_restricted_min_set(ui_table,
EINA_SIZE2D(table_calc.want[0],
table_calc.want[1]));

View File

@ -44,11 +44,13 @@ struct _Efl_Ui_Table_Data
struct {
double h, v;
} align;
Eina_Position2D last_pos;
Eina_Bool cols_recalc : 1;
Eina_Bool rows_recalc : 1;
Eina_Bool linear_recalc : 1;
Eina_Bool homogeneoush : 1;
Eina_Bool homogeneousv : 1;
Eina_Bool full_recalc : 1; //whether to force full recalc
};
struct _Table_Item_Iterator