[mutter] clutter/actor: Emit the queue-redraw signal right away
- From: Marge Bot <marge-bot src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] clutter/actor: Emit the queue-redraw signal right away
- Date: Tue, 24 Nov 2020 19:20:43 +0000 (UTC)
commit ce4c297cea62bd7d6aebfdd90be93a6690b72a07
Author: Jonas Dreßler <verdre v0yd nl>
Date: Mon Oct 19 16:48:53 2020 +0200
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>
clutter/clutter/clutter-actor.c | 70 ++++++++-----------------------
clutter/clutter/clutter-stage.c | 93 +++++++++++++++++------------------------
2 files changed, 55 insertions(+), 108 deletions(-)
---
diff --git a/clutter/clutter/clutter-actor.c b/clutter/clutter/clutter-actor.c
index 114d52a9be..678a3e6deb 100644
--- a/clutter/clutter/clutter-actor.c
+++ b/clutter/clutter/clutter-actor.c
@@ -8023,8 +8023,6 @@ _clutter_actor_finish_queue_redraw (ClutterActor *self)
later)
*/
priv->queue_redraw_entry = NULL;
-
- _clutter_actor_propagate_queue_redraw (self, self);
}
void
@@ -8041,63 +8039,26 @@ _clutter_actor_queue_redraw_full (ClutterActor *self,
* wrapper for this function. Additionally, an effect can queue a
* 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
* stage which is a list of actors that queued a redraw while
* updating the timelines, performing layouting and processing other
* 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
- * we iterate this list and actually emit the "queue-redraw" signals
- * for each of the listed actors which will bubble up to the stage
- * for each actor and at that point we will transform the actors
- * paint volume into screen coordinates to determine the clip region
- * for what needs to be redrawn in the next paint.
- *
- * Besides minimizing redundant work another reason for this
- * deferred design is that it's more likely we will be able to
- * determine the paint volume of an actor once we've finished
- * updating the scenegraph because its allocation should be up to
- * 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.
+ * we iterate this list and build the redraw clip of the stage by
+ * either using the clip that was supplied to
+ * _clutter_actor_queue_redraw_full() or by asking the actor for its
+ * redraw clip using clutter_actor_get_redraw_clip().
+ *
+ * Doing this later during the stage update instead of now is an
+ * important optimization, because later it's more likely we will be
+ * able to determine the paint volume of an actor (its allocation
+ * should be up to date).
*/
/* ignore queueing a redraw for actors being destroyed */
@@ -8179,6 +8140,9 @@ _clutter_actor_queue_redraw_full (ClutterActor *self,
}
priv->is_dirty = TRUE;
+
+ if (!priv->propagated_one_redraw)
+ _clutter_actor_propagate_queue_redraw (self, self);
}
/**
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index aa64c0277a..6afc40ea5c 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -2882,6 +2882,7 @@ void
clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage)
{
ClutterStagePrivate *priv = stage->priv;
+ GList *l;
COGL_TRACE_BEGIN_SCOPED (ClutterStageFinishQueueRedraws, "FinishQueueRedraws");
@@ -2890,68 +2891,50 @@ clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage)
priv->pending_finish_queue_redraws = FALSE;
- /* Note: we have to repeat until the pending_queue_redraws list is
- * 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)
+ for (l = priv->pending_queue_redraws; l; l = l->next)
{
- 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;
-
- /* NB: Entries may be invalidated if the actor gets destroyed */
- if (G_LIKELY (entry->actor != NULL))
- {
- ClutterPaintVolume old_actor_pv, new_actor_pv;
+ ClutterStageQueueRedrawEntry *entry = l->data;
- _clutter_actor_finish_queue_redraw (entry->actor);
+ /* NB: Entries may be invalidated if the actor gets destroyed */
+ if (G_LIKELY (entry->actor != NULL))
+ {
+ ClutterPaintVolume old_actor_pv, new_actor_pv;
- _clutter_paint_volume_init_static (&old_actor_pv, NULL);
- _clutter_paint_volume_init_static (&new_actor_pv, NULL);
-
- if (entry->has_clip)
- {
- add_to_stage_clip (stage, &entry->clip);
- }
- else if (clutter_actor_get_redraw_clip (entry->actor,
- &old_actor_pv,
- &new_actor_pv))
- {
- /* Add both the old paint volume of the actor (which is
- * currently visible on the screen) and the new paint volume
- * (which will be visible on the screen after this redraw)
- * to the redraw clip.
- * The former we do to ensure the old texture on the screen
- * will be fully painted over in case the actor was moved.
- */
- add_to_stage_clip (stage, &old_actor_pv);
- add_to_stage_clip (stage, &new_actor_pv);
- }
- else
- {
- /* If there's no clip we can use, we have to trigger an
- * unclipped full stage redraw.
- */
- add_to_stage_clip (stage, NULL);
- }
+ _clutter_paint_volume_init_static (&old_actor_pv, NULL);
+ _clutter_paint_volume_init_static (&new_actor_pv, NULL);
+ if (entry->has_clip)
+ {
+ add_to_stage_clip (stage, &entry->clip);
+ }
+ else if (clutter_actor_get_redraw_clip (entry->actor,
+ &old_actor_pv,
+ &new_actor_pv))
+ {
+ /* Add both the old paint volume of the actor (which is
+ * currently visible on the screen) and the new paint volume
+ * (which will be visible on the screen after this redraw)
+ * to the redraw clip.
+ * The former we do to ensure the old texture on the screen
+ * will be fully painted over in case the actor was moved.
+ */
+ add_to_stage_clip (stage, &old_actor_pv);
+ add_to_stage_clip (stage, &new_actor_pv);
+ }
+ else
+ {
+ /* If there's no clip we can use, we have to trigger an
+ * unclipped full stage redraw.
+ */
+ add_to_stage_clip (stage, NULL);
}
-
- free_queue_redraw_entry (entry);
}
- g_list_free (stolen_list);
+
+ free_queue_redraw_entry (entry);
}
+
+ g_list_free (priv->pending_queue_redraws);
+ priv->pending_queue_redraws = NULL;
}
/**
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]