[clutter] actor: Ignore redraws queued on unmapped actors



commit 0e0db890e1552ce2d3c00ecc9b68c24876d84fec
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Thu Mar 7 18:20:48 2013 +0000

    actor: Ignore redraws queued on unmapped actors
    
    If an actor is unmapped then it won't be painted, so we can safely
    short-circuit out of _clutter_actor_queue_redraw_full() if the mapped
    flag is not set.
    
    We need, on the other hand, make an exception for Clones, otherwise
    they won't receive notification that the source actor has changed
    and they won't be painted.
    
    This allows us to ignore redraws queued on children of invisible
    parents, and avoid traversing the scene graph.

 clutter/clutter-actor.c |   67 +++++++++++++++++++++++++++++++++++-----------
 1 files changed, 51 insertions(+), 16 deletions(-)
---
diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c
index b02a106..ec511d8 100644
--- a/clutter/clutter-actor.c
+++ b/clutter/clutter-actor.c
@@ -1062,6 +1062,8 @@ static void clutter_actor_set_transform_internal (ClutterActor        *self,
 static void clutter_actor_set_child_transform_internal (ClutterActor        *self,
                                                         const ClutterMatrix *transform);
 
+static inline gboolean clutter_actor_has_mapped_clones (ClutterActor *self);
+
 /* Helper macro which translates by the anchor coord, applies the
    given transformation and then translates back */
 #define TRANSFORM_ABOUT_ANCHOR_COORD(a,m,c,_transform)  G_STMT_START { \
@@ -8532,11 +8534,12 @@ _clutter_actor_queue_redraw_full (ClutterActor       *self,
    *
    * The process starts in one of the following two functions which
    * are wrappers for this function:
-   * clutter_actor_queue_redraw
-   * _clutter_actor_queue_redraw_with_clip
+   *
+   *   clutter_actor_queue_redraw()
+   *   _clutter_actor_queue_redraw_with_clip()
    *
    * additionally, an effect can queue a redraw by wrapping this
-   * function in clutter_effect_queue_rerun
+   * function in clutter_effect_queue_repaint().
    *
    * This functions queues an entry in a list associated with the
    * stage which is a list of actors that queued a redraw while
@@ -8567,19 +8570,20 @@ _clutter_actor_queue_redraw_full (ClutterActor       *self,
    * difference to performance.
    *
    * So the control flow goes like this:
-   * One of clutter_actor_queue_redraw,
-   *        _clutter_actor_queue_redraw_with_clip
-   *     or clutter_effect_queue_rerun
+   * One of clutter_actor_queue_redraw(),
+   *        _clutter_actor_queue_redraw_with_clip(),
+   *     or clutter_effect_queue_repaint()
    *
    * then control moves to:
-   *   _clutter_stage_queue_actor_redraw
+   *   _clutter_stage_queue_actor_redraw()
    *
-   * later during _clutter_stage_do_update, once relayouting is done
+   * later during _clutter_stage_do_update(), once relayouting is done
    * and the scenegraph has been updated we will call:
-   * _clutter_stage_finish_queue_redraws
+   * _clutter_stage_finish_queue_redraws().
+   *
+   * _clutter_stage_finish_queue_redraws() will call
+   * _clutter_actor_finish_queue_redraw() for each listed actor.
    *
-   * _clutter_stage_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
@@ -8587,12 +8591,12 @@ _clutter_actor_queue_redraw_full (ClutterActor       *self,
    *
    * 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
+   * clutter_actor_real_queue_redraw()
    *
    * This will bubble up to the stages handler:
-   * clutter_stage_real_queue_redraw
+   * clutter_stage_real_queue_redraw()
    *
-   * clutter_stage_real_queue_redraw will transform the actors paint
+   * 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.
    */
@@ -8601,9 +8605,20 @@ _clutter_actor_queue_redraw_full (ClutterActor       *self,
   if (CLUTTER_ACTOR_IN_DESTRUCTION (self))
     return;
 
-  stage = _clutter_actor_get_stage_internal (self);
+  /* we can ignore unmapped actors, unless they have at least one
+   * mapped clone, 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))
+    return;
 
-  /* Ignore queueing a redraw for actors not descended from a stage */
+  /* given the check above we could end up queueing a redraw on an
+   * unmapped actor with mapped clones, so we cannot assume that
+   * get_stage() will return a Stage
+   */
+  stage = _clutter_actor_get_stage_internal (self);
   if (stage == NULL)
     return;
 
@@ -20206,3 +20221,23 @@ _clutter_actor_queue_relayout_on_clones (ClutterActor *self)
   while (g_hash_table_iter_next (&iter, &key, NULL))
     clutter_actor_queue_relayout (key);
 }
+
+static inline gboolean
+clutter_actor_has_mapped_clones (ClutterActor *self)
+{
+  ClutterActorPrivate *priv = self->priv;
+  GHashTableIter iter;
+  gpointer key;
+
+  if (priv->clones == NULL)
+    return FALSE;
+
+  g_hash_table_iter_init (&iter, priv->clones);
+  while (g_hash_table_iter_next (&iter, &key, NULL))
+    {
+      if (CLUTTER_ACTOR_IS_MAPPED (key))
+        return TRUE;
+    }
+
+  return FALSE;
+}


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