mirror of
https://github.com/brl/mutter.git
synced 2024-11-29 03:20:46 -05:00
clutter/actor: Emit the queue-redraw signal right away
Since we now decoupled the "queue-redraw" signal from creating the stage clip, we can move signal emission into _clutter_actor_queue_redraw_full() and emit the signal right away when queueing a redraw on an actor. With that we now no longer have to accommodate for the stage pending_queue_redraws list changing while iterating over it. To ensure we don't emit the signal too often when multiple redraws are queued on one actor, use the propagated_one_redraw flag to limit the number of emissions to a single one for every update cycle. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1511>
This commit is contained in:
parent
9b16eff784
commit
ce4c297cea
@ -8023,8 +8023,6 @@ _clutter_actor_finish_queue_redraw (ClutterActor *self)
|
|||||||
later)
|
later)
|
||||||
*/
|
*/
|
||||||
priv->queue_redraw_entry = NULL;
|
priv->queue_redraw_entry = NULL;
|
||||||
|
|
||||||
_clutter_actor_propagate_queue_redraw (self, self);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -8041,63 +8039,26 @@ _clutter_actor_queue_redraw_full (ClutterActor *self,
|
|||||||
* wrapper for this function. Additionally, an effect can queue a
|
* wrapper for this function. Additionally, an effect can queue a
|
||||||
* redraw by wrapping this function in clutter_effect_queue_repaint().
|
* redraw by wrapping this function in clutter_effect_queue_repaint().
|
||||||
*
|
*
|
||||||
|
* This function will emit the "queue-redraw" signal for each actor
|
||||||
|
* up the actor-tree, allowing to track redraws queued by children
|
||||||
|
* or to queue a redraw of a different actor (like a clone) in
|
||||||
|
* response to this one.
|
||||||
|
*
|
||||||
* This functions queues an entry in a list associated with the
|
* This functions queues an entry in a list associated with the
|
||||||
* stage which is a list of actors that queued a redraw while
|
* stage which is a list of actors that queued a redraw while
|
||||||
* updating the timelines, performing layouting and processing other
|
* updating the timelines, performing layouting and processing other
|
||||||
* mainloop sources before the next paint starts.
|
* mainloop sources before the next paint starts.
|
||||||
*
|
*
|
||||||
* We aim to minimize the processing done at this point because
|
|
||||||
* there is a good chance other events will happen while updating
|
|
||||||
* the scenegraph that would invalidate any expensive work we might
|
|
||||||
* otherwise try to do here. For example we don't try and resolve
|
|
||||||
* the screen space bounding box of an actor at this stage so as to
|
|
||||||
* minimize how much of the screen redraw because it's possible
|
|
||||||
* something else will happen which will force a full redraw anyway.
|
|
||||||
*
|
|
||||||
* When all updates are complete and we come to paint the stage then
|
* When all updates are complete and we come to paint the stage then
|
||||||
* we iterate this list and actually emit the "queue-redraw" signals
|
* we iterate this list and build the redraw clip of the stage by
|
||||||
* for each of the listed actors which will bubble up to the stage
|
* either using the clip that was supplied to
|
||||||
* for each actor and at that point we will transform the actors
|
* _clutter_actor_queue_redraw_full() or by asking the actor for its
|
||||||
* paint volume into screen coordinates to determine the clip region
|
* redraw clip using clutter_actor_get_redraw_clip().
|
||||||
* for what needs to be redrawn in the next paint.
|
|
||||||
*
|
*
|
||||||
* Besides minimizing redundant work another reason for this
|
* Doing this later during the stage update instead of now is an
|
||||||
* deferred design is that it's more likely we will be able to
|
* important optimization, because later it's more likely we will be
|
||||||
* determine the paint volume of an actor once we've finished
|
* able to determine the paint volume of an actor (its allocation
|
||||||
* updating the scenegraph because its allocation should be up to
|
* should be up to date).
|
||||||
* date. NB: If we can't determine an actors paint volume then we
|
|
||||||
* can't automatically queue a clipped redraw which can make a big
|
|
||||||
* difference to performance.
|
|
||||||
*
|
|
||||||
* So the control flow goes like this:
|
|
||||||
* One of clutter_actor_queue_redraw(),
|
|
||||||
* or clutter_effect_queue_repaint()
|
|
||||||
*
|
|
||||||
* then control moves to:
|
|
||||||
* _clutter_stage_queue_actor_redraw()
|
|
||||||
*
|
|
||||||
* later during _clutter_stage_do_update(), once relayouting is done
|
|
||||||
* and the scenegraph has been updated we will call:
|
|
||||||
* clutter_stage_maybe_finish_queue_redraws().
|
|
||||||
*
|
|
||||||
* clutter_stage_maybe_finish_queue_redraws() will call
|
|
||||||
* _clutter_actor_finish_queue_redraw() for each listed actor.
|
|
||||||
*
|
|
||||||
* Note: actors *are* allowed to queue further redraws during this
|
|
||||||
* process (considering clone actors or texture_new_from_actor which
|
|
||||||
* respond to their source queueing a redraw by queuing a redraw
|
|
||||||
* themselves). We repeat the process until the list is empty.
|
|
||||||
*
|
|
||||||
* This will result in the "queue-redraw" signal being fired for
|
|
||||||
* each actor which will pass control to the default signal handler:
|
|
||||||
* clutter_actor_real_queue_redraw()
|
|
||||||
*
|
|
||||||
* This will bubble up to the stages handler:
|
|
||||||
* clutter_stage_real_queue_redraw()
|
|
||||||
*
|
|
||||||
* clutter_stage_real_queue_redraw() will transform the actors paint
|
|
||||||
* volume into screen space and add it as a clip region for the next
|
|
||||||
* paint.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* ignore queueing a redraw for actors being destroyed */
|
/* ignore queueing a redraw for actors being destroyed */
|
||||||
@ -8179,6 +8140,9 @@ _clutter_actor_queue_redraw_full (ClutterActor *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
priv->is_dirty = TRUE;
|
priv->is_dirty = TRUE;
|
||||||
|
|
||||||
|
if (!priv->propagated_one_redraw)
|
||||||
|
_clutter_actor_propagate_queue_redraw (self, self);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2882,6 +2882,7 @@ void
|
|||||||
clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage)
|
clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage)
|
||||||
{
|
{
|
||||||
ClutterStagePrivate *priv = stage->priv;
|
ClutterStagePrivate *priv = stage->priv;
|
||||||
|
GList *l;
|
||||||
|
|
||||||
COGL_TRACE_BEGIN_SCOPED (ClutterStageFinishQueueRedraws, "FinishQueueRedraws");
|
COGL_TRACE_BEGIN_SCOPED (ClutterStageFinishQueueRedraws, "FinishQueueRedraws");
|
||||||
|
|
||||||
@ -2890,23 +2891,7 @@ clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage)
|
|||||||
|
|
||||||
priv->pending_finish_queue_redraws = FALSE;
|
priv->pending_finish_queue_redraws = FALSE;
|
||||||
|
|
||||||
/* Note: we have to repeat until the pending_queue_redraws list is
|
for (l = priv->pending_queue_redraws; l; l = l->next)
|
||||||
* empty because actors are allowed to queue redraws in response to
|
|
||||||
* the queue-redraw signal. For example Clone actors or
|
|
||||||
* texture_new_from_actor actors will have to queue a redraw if
|
|
||||||
* their source queues a redraw.
|
|
||||||
*/
|
|
||||||
while (stage->priv->pending_queue_redraws)
|
|
||||||
{
|
|
||||||
GList *l;
|
|
||||||
/* XXX: we need to allow stage->priv->pending_queue_redraws to
|
|
||||||
* be updated while we process the current entries in the list
|
|
||||||
* so we steal the list pointer and then reset it to an empty
|
|
||||||
* list before processing... */
|
|
||||||
GList *stolen_list = stage->priv->pending_queue_redraws;
|
|
||||||
stage->priv->pending_queue_redraws = NULL;
|
|
||||||
|
|
||||||
for (l = stolen_list; l; l = l->next)
|
|
||||||
{
|
{
|
||||||
ClutterStageQueueRedrawEntry *entry = l->data;
|
ClutterStageQueueRedrawEntry *entry = l->data;
|
||||||
|
|
||||||
@ -2915,8 +2900,6 @@ clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage)
|
|||||||
{
|
{
|
||||||
ClutterPaintVolume old_actor_pv, new_actor_pv;
|
ClutterPaintVolume old_actor_pv, new_actor_pv;
|
||||||
|
|
||||||
_clutter_actor_finish_queue_redraw (entry->actor);
|
|
||||||
|
|
||||||
_clutter_paint_volume_init_static (&old_actor_pv, NULL);
|
_clutter_paint_volume_init_static (&old_actor_pv, NULL);
|
||||||
_clutter_paint_volume_init_static (&new_actor_pv, NULL);
|
_clutter_paint_volume_init_static (&new_actor_pv, NULL);
|
||||||
|
|
||||||
@ -2945,13 +2928,13 @@ clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage)
|
|||||||
*/
|
*/
|
||||||
add_to_stage_clip (stage, NULL);
|
add_to_stage_clip (stage, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free_queue_redraw_entry (entry);
|
free_queue_redraw_entry (entry);
|
||||||
}
|
}
|
||||||
g_list_free (stolen_list);
|
|
||||||
}
|
g_list_free (priv->pending_queue_redraws);
|
||||||
|
priv->pending_queue_redraws = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user