[clutter/wip/optimizations-2: 2/8] actor: Keep track of clones



commit b929021b68b612d51181eeb0e12aeab070884d93
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Thu Mar 7 18:09:33 2013 +0000

    actor: Keep track of clones
    
    Instead of using signal notifications, we should be able to keep track
    of the clones of an actor from within ClutterActor itself, using private
    API. There's no point in pretending that people can actually create a
    Clone class out of tree, given the amount of invariants we have to punch
    through in order to implement a proper replicator node of the scene
    graph, so we can just skip the signal emissions and just do the right
    thing at the right time.

 clutter/clutter-actor-private.h |    7 +++
 clutter/clutter-actor.c         |   80 ++++++++++++++++++++++++++++++++++++++-
 clutter/clutter-clone.c         |   30 ++------------
 3 files changed, 91 insertions(+), 26 deletions(-)
---
diff --git a/clutter/clutter-actor-private.h b/clutter/clutter-actor-private.h
index c5319e2..1c6f165 100644
--- a/clutter/clutter-actor-private.h
+++ b/clutter/clutter-actor-private.h
@@ -312,6 +312,13 @@ ClutterActorAlign               _clutter_actor_get_effective_x_align
 void                            _clutter_actor_handle_event                             (ClutterActor       
*actor,
                                                                                          const ClutterEvent 
*event);
 
+void                            _clutter_actor_attach_clone                             (ClutterActor *actor,
+                                                                                         ClutterActor 
*clone);
+void                            _clutter_actor_detach_clone                             (ClutterActor *actor,
+                                                                                         ClutterActor 
*clone);
+void                            _clutter_actor_queue_redraw_on_clones                   (ClutterActor 
*actor);
+void                            _clutter_actor_queue_relayout_on_clones                 (ClutterActor 
*actor);
+
 G_END_DECLS
 
 #endif /* __CLUTTER_ACTOR_PRIVATE_H__ */
diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c
index 5f868db..69c4fdf 100644
--- a/clutter/clutter-actor.c
+++ b/clutter/clutter-actor.c
@@ -771,7 +771,10 @@ struct _ClutterActorPrivate
   gchar *debug_name;
 #endif
 
-  /* bitfields */
+  /* a set of clones of the actor */
+  GHashTable *clones;
+
+  /* bitfields: KEEP AT THE END */
 
   /* fixed position and sizes */
   guint position_set                : 1;
@@ -2547,6 +2550,8 @@ _clutter_actor_signal_queue_redraw (ClutterActor *self,
    * receive the signal so it can queue its own redraw.
    */
 
+  _clutter_actor_queue_redraw_on_clones (self);
+
   /* calls klass->queue_redraw in default handler */
   g_signal_emit (self, actor_signals[QUEUE_REDRAW], 0, origin);
 }
@@ -5802,6 +5807,12 @@ clutter_actor_dispose (GObject *object)
       g_clear_object (&priv->content);
     }
 
+  if (priv->clones != NULL)
+    {
+      g_hash_table_unref (priv->clones);
+      priv->clones = NULL;
+    }
+
   G_OBJECT_CLASS (clutter_actor_parent_class)->dispose (object);
 }
 
@@ -8788,6 +8799,8 @@ _clutter_actor_queue_only_relayout (ClutterActor *self)
     }
 #endif /* CLUTTER_ENABLE_DEBUG */
 
+  _clutter_actor_queue_relayout_on_clones (self);
+
   g_signal_emit (self, actor_signals[QUEUE_RELAYOUT], 0);
 }
 
@@ -20113,3 +20126,68 @@ clutter_actor_get_child_transform (ClutterActor  *self,
   else
     clutter_matrix_init_identity (transform);
 }
+
+void
+_clutter_actor_attach_clone (ClutterActor *actor,
+                             ClutterActor *clone)
+{
+  ClutterActorPrivate *priv = actor->priv;
+
+  g_assert (clone != NULL);
+
+  if (priv->clones == NULL)
+    priv->clones = g_hash_table_new (NULL, NULL);
+
+  g_hash_table_add (priv->clones, clone);
+}
+
+void
+_clutter_actor_detach_clone (ClutterActor *actor,
+                             ClutterActor *clone)
+{
+  ClutterActorPrivate *priv = actor->priv;
+
+  g_assert (clone != NULL);
+
+  if (priv->clones == NULL ||
+      g_hash_table_lookup (priv->clones, clone) == NULL)
+    return;
+
+  g_hash_table_remove (priv->clones, clone);
+
+  if (g_hash_table_size (priv->clones) == 0)
+    {
+      g_hash_table_unref (priv->clones);
+      priv->clones = NULL;
+    }
+}
+
+void
+_clutter_actor_queue_redraw_on_clones (ClutterActor *self)
+{
+  ClutterActorPrivate *priv = self->priv;
+  GHashTableIter iter;
+  gpointer key;
+
+  if (priv->clones == NULL)
+    return;
+
+  g_hash_table_iter_init (&iter, priv->clones);
+  while (g_hash_table_iter_next (&iter, &key, NULL))
+    clutter_actor_queue_redraw (key);
+}
+
+void
+_clutter_actor_queue_relayout_on_clones (ClutterActor *self)
+{
+  ClutterActorPrivate *priv = self->priv;
+  GHashTableIter iter;
+  gpointer key;
+
+  if (priv->clones == NULL)
+    return;
+
+  g_hash_table_iter_init (&iter, priv->clones);
+  while (g_hash_table_iter_next (&iter, &key, NULL))
+    clutter_actor_queue_relayout (key);
+}
diff --git a/clutter/clutter-clone.c b/clutter/clutter-clone.c
index 6a82beb..1f94ab2 100644
--- a/clutter/clutter-clone.c
+++ b/clutter/clutter-clone.c
@@ -378,34 +378,17 @@ clutter_clone_new (ClutterActor *source)
 }
 
 static void
-clone_source_queue_redraw_cb (ClutterActor *source,
-                             ClutterActor *origin,
-                             ClutterClone *self)
-{
-  clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
-}
-
-static void
-clone_source_queue_relayout_cb (ClutterActor *source,
-                               ClutterClone *self)
-{
-  clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
-}
-
-static void
 clutter_clone_set_source_internal (ClutterClone *self,
                                   ClutterActor *source)
 {
   ClutterClonePrivate *priv = self->priv;
 
+  if (priv->clone_source == source)
+    return;
+
   if (priv->clone_source != NULL)
     {
-      g_signal_handlers_disconnect_by_func (priv->clone_source,
-                                            G_CALLBACK (clone_source_queue_redraw_cb),
-                                           self);
-      g_signal_handlers_disconnect_by_func (priv->clone_source,
-                                           G_CALLBACK (clone_source_queue_relayout_cb),
-                                           self);
+      _clutter_actor_detach_clone (priv->clone_source, CLUTTER_ACTOR (self));
       g_object_unref (priv->clone_source);
       priv->clone_source = NULL;
     }
@@ -413,10 +396,7 @@ clutter_clone_set_source_internal (ClutterClone *self,
   if (source != NULL)
     {
       priv->clone_source = g_object_ref (source);
-      g_signal_connect (priv->clone_source, "queue-redraw",
-                       G_CALLBACK (clone_source_queue_redraw_cb), self);
-      g_signal_connect (priv->clone_source, "queue-relayout",
-                       G_CALLBACK (clone_source_queue_relayout_cb), self);
+      _clutter_actor_attach_clone (priv->clone_source, CLUTTER_ACTOR (self));
     }
 
   g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SOURCE]);


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