From 8e6fac38fa73ec4c8a67835a1128e6b1a9889302 Mon Sep 17 00:00:00 2001
From: "Owen W. Taylor" <otaylor@fishsoup.net>
Date: Sat, 13 Nov 2010 11:29:49 -0500
Subject: [PATCH] Don't update or use last_paint_box when painting inside a
 clone

The last_paint_box for an actor represents its "normal" position - we
shouldn't update it or use it to cull drawing if we are painting
a clone of the actor. Tracking whether we are painting a clone is
done by adding  _clutter_actor_push/pop_clone_paint() and a global
"clone paint level".

http://bugzilla.clutter-project.org/show_bug.cgi?id=2396
---
 clutter/clutter-actor-private.h |  3 +++
 clutter/clutter-actor.c         | 42 +++++++++++++++++++++++++++------
 clutter/clutter-clone.c         |  2 ++
 3 files changed, 40 insertions(+), 7 deletions(-)

diff --git a/clutter/clutter-actor-private.h b/clutter/clutter-actor-private.h
index 2c1cc3342..716234682 100644
--- a/clutter/clutter-actor-private.h
+++ b/clutter/clutter-actor-private.h
@@ -115,6 +115,9 @@ gboolean           _clutter_actor_set_default_paint_volume (ClutterActor *self,
 
 G_CONST_RETURN gchar *_clutter_actor_get_debug_name (ClutterActor *self);
 
+void _clutter_actor_push_clone_paint (void);
+void _clutter_actor_pop_clone_paint  (void);
+
 G_END_DECLS
 
 #endif /* __CLUTTER_ACTOR_PRIVATE_H__ */
diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c
index 553b112c5..4bf713bca 100644
--- a/clutter/clutter-actor.c
+++ b/clutter/clutter-actor.c
@@ -2465,6 +2465,26 @@ _clutter_actor_draw_paint_volume (ClutterActor *self)
     clutter_paint_volume_free (&fake_pv);
 }
 
+static int clone_paint_level = 0;
+
+void
+_clutter_actor_push_clone_paint (void)
+{
+  clone_paint_level++;
+}
+
+void
+_clutter_actor_pop_clone_paint (void)
+{
+  clone_paint_level--;
+}
+
+static gboolean
+in_clone_paint (void)
+{
+  return clone_paint_level > 0;
+}
+
 /* Returns TRUE if the actor can be ignored */
 static gboolean
 cull_actor (ClutterActor *self)
@@ -2619,6 +2639,11 @@ clutter_actor_paint (ClutterActor *self)
        * We also fetch the current paint box to perform culling so we
        * can avoid painting actors outside the current clip region.
        *
+       * If we are painting inside a clone, we should neither update
+       * the paint box or use it to cull painting, since the paint
+       * box represents the location of the source actor on the
+       * screen.
+       *
        * XXX: We are starting to do a lot of vertex transforms on
        * the CPU in a typical paint, so at some point we should
        * audit these and consider caching some things.
@@ -2636,14 +2661,17 @@ clutter_actor_paint (ClutterActor *self)
        *   or we'd need to be able to invalidate paint-volumes on
        *   projection changes.
        */
-      if (G_LIKELY (need_paint_box) &&
-          clutter_actor_get_paint_box (self, &priv->last_paint_box))
-        priv->last_paint_box_valid = TRUE;
-      else
-        priv->last_paint_box_valid = FALSE;
+      if (!in_clone_paint ())
+	{
+          if (G_LIKELY (need_paint_box) &&
+              clutter_actor_get_paint_box (self, &priv->last_paint_box))
+            priv->last_paint_box_valid = TRUE;
+          else
+            priv->last_paint_box_valid = FALSE;
 
-      if (cull_actor (self))
-        goto done;
+	  if (cull_actor (self))
+	    goto done;
+	}
 
       if (priv->effects != NULL)
         effect_painted = _clutter_actor_effects_pre_paint (self);
diff --git a/clutter/clutter-clone.c b/clutter/clutter-clone.c
index cb5027328..ed3348908 100644
--- a/clutter/clutter-clone.c
+++ b/clutter/clutter-clone.c
@@ -184,7 +184,9 @@ clutter_clone_paint (ClutterActor *self)
       was_unmapped = TRUE;
     }
 
+  _clutter_actor_push_clone_paint ();
   clutter_actor_paint (priv->clone_source);
+  _clutter_actor_pop_clone_paint ();
 
   if (was_unmapped)
     _clutter_actor_set_enable_paint_unmapped (priv->clone_source, FALSE);