[clutter] actor: Skip transitions on invisible actors



commit 8f032d595263a2f4fdb057ae5d954ee8236e96cf
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Thu Mar 7 19:33:59 2013 +0000

    actor: Skip transitions on invisible actors
    
    If an actor has not been painted yet, or it's not going to be painted,
    we can ignore transitions queued on it.
    
    By ignoring transitions on actors that have not been painted yet, we can
    avoid doing work during the set up phase of the scene graph, as well as
    avoiding actors "flying in" from nowhere.
    
    Obviously, we have to take into account potential clones, so we need to
    check that the actor is not part of a cloned branch of the scene graph,
    as well as checking if the actor has mapped clones.

 clutter/clutter-actor.c |   52 ++++++++++++++++++++++++++++++++++++----------
 1 files changed, 40 insertions(+), 12 deletions(-)
---
diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c
index a275da8..46001e3 100644
--- a/clutter/clutter-actor.c
+++ b/clutter/clutter-actor.c
@@ -816,6 +816,7 @@ struct _ClutterActorPrivate
   guint needs_compute_expand        : 1;
   guint needs_x_expand              : 1;
   guint needs_y_expand              : 1;
+  guint was_painted                 : 1;
 };
 
 enum
@@ -1487,6 +1488,12 @@ clutter_actor_real_map (ClutterActor *self)
   stage = _clutter_actor_get_stage_internal (self);
   priv->pick_id = _clutter_stage_acquire_pick_id (CLUTTER_STAGE (stage), self);
 
+  /* reset the was_painted flag here: unmapped actors are not going to
+   * be painted in any case, and this allows us to catch the case of
+   * cloned actors.
+   */
+  priv->was_painted = FALSE;
+
   CLUTTER_NOTE (ACTOR, "Pick id '%d' for actor '%s'",
                 priv->pick_id,
                 _clutter_actor_get_debug_name (self));
@@ -3892,6 +3899,9 @@ clutter_actor_continue_paint (ClutterActor *self)
 
           /* XXX:2.0 - Call the paint() virtual directly */
           g_signal_emit (self, actor_signals[PAINT], 0);
+
+          /* the actor was painted at least once */
+          priv->was_painted = TRUE;
         }
       else
         {
@@ -8611,14 +8621,26 @@ _clutter_actor_queue_redraw_full (ClutterActor       *self,
     return;
 
   /* we can ignore unmapped actors, unless they have at least one
-   * mapped clone, as unmapped actors will simply be left unpainted;
+   * mapped clone or they are inside a cloned branch of the scene
+   * graph, as unmapped actors will simply be left unpainted.
+   *
    * this allows us to ignore redraws queued on leaf nodes when one
    * of their parents has been hidden
    */
   if (!CLUTTER_ACTOR_IS_MAPPED (self) &&
-      !clutter_actor_has_mapped_clones (self) &&
-      self->priv->in_cloned_branch == 0)
-    return;
+      self->priv->in_cloned_branch == 0 &&
+      !clutter_actor_has_mapped_clones (self))
+    {
+      CLUTTER_NOTE (PAINT,
+                    "Skipping queue_redraw('%s'): mapped=%s, "
+                    "mapped_clones=%s, "
+                    "in_cloned_branch=%s\n",
+                    _clutter_actor_get_debug_name (self),
+                    CLUTTER_ACTOR_IS_MAPPED (self) ? "yes" : "no",
+                    clutter_actor_has_mapped_clones (self) ? "yes" : "no",
+                    self->priv->in_cloned_branch != 0 ? "yes" : "no");
+      return;
+    }
 
   /* given the check above we could end up queueing a redraw on an
    * unmapped actor with mapped clones, so we cannot assume that
@@ -18761,15 +18783,21 @@ _clutter_actor_create_transition (ClutterActor *actor,
       goto out;
     }
 
-  /* if the current easing state has a duration of 0, then we don't
-   * bother to create the transition, and we just set the final value
-   * directly on the actor; we don't go through the Animatable
-   * interface because we know we got here through an animatable
-   * property.
-   */
-  if (info->cur_state->easing_duration == 0)
+  if (info->cur_state->easing_duration == 0 ||
+      !actor->priv->was_painted ||
+      (!CLUTTER_ACTOR_IS_MAPPED (actor) &&
+       actor->priv->in_cloned_branch == 0 &&
+       !clutter_actor_has_mapped_clones (actor)))
     {
-      CLUTTER_NOTE (ANIMATION, "Easing duration=0, immediate set for '%s::%s'",
+      /* don't bother creating the transition if one is not necessary
+       * because the actor doesn't want one, or if the actor is not
+       * visible: we just set the final value directly on the actor.
+       *
+       * we also don't go through the Animatable interface because we
+       * already know we got here through an animatable property.
+       */
+      CLUTTER_NOTE (ANIMATION, "Easing duration=0 was_painted=%s, immediate set for '%s::%s'",
+                    actor->priv->was_painted ? "yes" : "no",
                     _clutter_actor_get_debug_name (actor),
                     pspec->name);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]