clutter/actor: Use the new shallow relayout API

If an actor sets flag `CLUTTER_ACTOR_NO_LAYOUT` then that means it
is (or should be) unaffected by `queue_relayout` calls in its children.
So we can avoid propagating `queue_relayout` all the way up to the stage
and avoid a full stage relayout each time.

But those children whose parent has `CLUTTER_ACTOR_NO_LAYOUT` still need
to be allocated at some point. So we do it at the same point where it
happened before. Only we now queue a *shallow* relayout so the `allocate`
run on the next frame doesn't need to descend the whole actor tree anymore.
Only a subtree and hopefully very small.

For free-floating and top-level actors this provides a measurable
performance benefit. According to Google Profiler, calls to
`_clutter_stage_maybe_relayout` are now so cheap that they no longer show
up in performance profiles.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/575
This commit is contained in:
Daniel van Vugt 2019-05-10 16:06:18 +08:00 committed by verdre
parent 5257c6ecc2
commit 2731be6929

View File

@ -1778,6 +1778,15 @@ clutter_actor_unmap (ClutterActor *self)
clutter_actor_update_map_state (self, MAP_STATE_MAKE_UNMAPPED);
}
static void
clutter_actor_queue_shallow_relayout (ClutterActor *self)
{
ClutterActor *stage = _clutter_actor_get_stage_internal (self);
if (stage != NULL)
clutter_stage_queue_actor_relayout (CLUTTER_STAGE (stage), self);
}
static void
clutter_actor_real_show (ClutterActor *self)
{
@ -1811,6 +1820,11 @@ clutter_actor_real_show (ClutterActor *self)
clutter_actor_queue_relayout (self);
}
else /* but still don't leave the actor un-allocated before showing it */
{
clutter_actor_queue_shallow_relayout (self);
clutter_actor_queue_redraw (self);
}
}
static inline void
@ -2864,9 +2878,23 @@ clutter_actor_real_queue_relayout (ClutterActor *self)
memset (priv->height_requests, 0,
N_CACHED_SIZE_REQUESTS * sizeof (SizeRequest));
/* We need to go all the way up the hierarchy */
/* We may need to go all the way up the hierarchy */
if (priv->parent != NULL)
_clutter_actor_queue_only_relayout (priv->parent);
{
if (priv->parent->flags & CLUTTER_ACTOR_NO_LAYOUT)
{
clutter_actor_queue_shallow_relayout (self);
/* The above might have invalidated the parent's paint volume if self
* has moved or resized. DnD seems to require this...
*/
priv->parent->priv->needs_paint_volume_update = TRUE;
}
else
{
_clutter_actor_queue_only_relayout (priv->parent);
}
}
}
/**