[mutter] clutter: Introduce paint contexts



commit 49c8d423171d10b4a4b5560af8df7667d9275001
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Wed Nov 13 22:21:58 2019 +0100

    clutter: Introduce paint contexts
    
    When painting, actors rely on semi global state tracked by the state to
    get various things needed for painting, such as the current draw
    framebuffer. Having state hidden in such ways can be very deceiving as
    it's hard to follow changes spread out, and adding more and more state
    that should be tracked during a paint gets annoying as they will not
    change in isolation but one by one in their own places. To do this
    better, introduce a paint context that is passed along in paint calls
    that contains the necessary state needed during painting.
    
    The paint context implements a framebuffer stack just as Cogl works,
    which is currently needed for offscreen rendering used by clutter.
    
    The same context is passed around for paint nodes, contents and effects
    as well.
    
    In this commit, the context is only introduced, but not used. It aims to
    replace the Cogl framebuffer stack, and will allow actors to know what
    view it is currently painted on.
    
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/935

 clutter/clutter/clutter-actor.c                    |  34 ++---
 clutter/clutter/clutter-actor.h                    |  10 +-
 clutter/clutter/clutter-autocleanups.h             |   1 +
 clutter/clutter/clutter-blur-effect.c              |   8 +-
 .../clutter/clutter-brightness-contrast-effect.c   |   8 +-
 clutter/clutter/clutter-canvas.c                   |   7 +-
 clutter/clutter/clutter-clone.c                    |   5 +-
 clutter/clutter/clutter-colorize-effect.c          |   8 +-
 clutter/clutter/clutter-content-private.h          |   7 +-
 clutter/clutter/clutter-content.c                  |  20 +--
 clutter/clutter/clutter-content.h                  |   7 +-
 clutter/clutter/clutter-deform-effect.c            |   3 +-
 clutter/clutter/clutter-desaturate-effect.c        |   8 +-
 clutter/clutter/clutter-effect-private.h           |   7 +-
 clutter/clutter/clutter-effect.c                   |  26 ++--
 clutter/clutter/clutter-effect.h                   |   8 +-
 clutter/clutter/clutter-image.c                    |   7 +-
 clutter/clutter/clutter-offscreen-effect.c         |  28 +++--
 clutter/clutter/clutter-offscreen-effect.h         |   6 +-
 clutter/clutter/clutter-paint-context-private.h    |  30 +++++
 clutter/clutter/clutter-paint-context.c            | 139 +++++++++++++++++++++
 clutter/clutter/clutter-paint-context.h            |  55 ++++++++
 clutter/clutter/clutter-paint-node-private.h       |  10 +-
 clutter/clutter/clutter-paint-node.c               |  20 +--
 clutter/clutter/clutter-paint-node.h               |   3 +-
 clutter/clutter/clutter-paint-nodes.c              |  53 +++++---
 clutter/clutter/clutter-shader-effect.c            |   5 +-
 clutter/clutter/clutter-stage-view-private.h       |   2 +
 clutter/clutter/clutter-stage.c                    |  14 ++-
 clutter/clutter/clutter-text.c                     |   3 +-
 clutter/clutter/deprecated/clutter-group.c         |   5 +-
 clutter/clutter/deprecated/clutter-rectangle.c     |   3 +-
 clutter/clutter/meson.build                        |   3 +
 cogl/tests/conform/test-materials.c                |   4 +-
 cogl/tests/conform/test-multitexture.c             |   4 +-
 cogl/tests/conform/test-readpixels.c               |   4 +-
 cogl/tests/conform/test-texture-mipmaps.c          |   4 +-
 cogl/tests/conform/test-texture-pixmap-x11.c       |   4 +-
 cogl/tests/conform/test-vertex-buffer-contiguous.c |   4 +-
 cogl/tests/conform/test-vertex-buffer-interleved.c |   4 +-
 cogl/tests/conform/test-viewport.c                 |   4 +-
 src/backends/meta-stage.c                          |   5 +-
 src/compositor/meta-background-actor.c             |   3 +-
 src/compositor/meta-shaped-texture.c               |  13 +-
 src/compositor/meta-surface-actor-wayland.c        |   6 +-
 src/compositor/meta-surface-actor.c                |   6 +-
 src/compositor/meta-window-actor-x11.c             |   6 +-
 src/compositor/meta-window-actor.c                 |   5 +-
 src/compositor/meta-window-group.c                 |   9 +-
 .../clutter/conform/actor-offscreen-redirect.c     |   3 +-
 src/tests/clutter/conform/actor-shader-effect.c    |  10 +-
 src/tests/clutter/conform/binding-pool.c           |   5 +-
 src/tests/clutter/conform/text-cache.c             |   4 +-
 src/tests/clutter/interactive/test-binding-pool.c  |   5 +-
 .../clutter/interactive/test-cogl-multitexture.c   |   4 +-
 .../clutter/interactive/test-cogl-offscreen.c      |   3 +-
 .../clutter/interactive/test-cogl-point-sprites.c  |   4 +-
 .../clutter/interactive/test-cogl-tex-convert.c    |   3 +-
 .../clutter/interactive/test-cogl-tex-polygon.c    |   3 +-
 src/tests/clutter/interactive/test-cogl-tex-tile.c |   3 +-
 .../clutter/interactive/test-cogl-vertex-buffer.c  |   4 +-
 src/tests/clutter/interactive/test-content.c       |   7 +-
 src/tests/clutter/interactive/test-image.c         |   7 +-
 src/tests/clutter/interactive/test-paint-wrapper.c |  10 +-
 src/tests/clutter/micro-bench/test-cogl-perf.c     |   4 +-
 src/tests/clutter/micro-bench/test-picking.c       |   4 +-
 src/tests/clutter/micro-bench/test-text-perf.c     |   4 +-
 src/tests/clutter/micro-bench/test-text.c          |   4 +-
 src/tests/clutter/performance/test-common.h        |   9 +-
 69 files changed, 563 insertions(+), 175 deletions(-)
---
diff --git a/clutter/clutter/clutter-actor.c b/clutter/clutter/clutter-actor.c
index 1ad9061f7..95b7b1f15 100644
--- a/clutter/clutter/clutter-actor.c
+++ b/clutter/clutter/clutter-actor.c
@@ -3760,7 +3760,8 @@ add_or_remove_flatten_effect (ClutterActor *self)
 }
 
 static void
-clutter_actor_real_paint (ClutterActor *actor)
+clutter_actor_real_paint (ClutterActor        *actor,
+                          ClutterPaintContext *paint_context)
 {
   ClutterActorPrivate *priv = actor->priv;
   ClutterActor *iter;
@@ -3777,13 +3778,14 @@ clutter_actor_real_paint (ClutterActor *actor)
                     iter->priv->allocation.x2 - iter->priv->allocation.x1,
                     iter->priv->allocation.y2 - iter->priv->allocation.y1);
 
-      clutter_actor_paint (iter);
+      clutter_actor_paint (iter, paint_context);
     }
 }
 
 static gboolean
-clutter_actor_paint_node (ClutterActor     *actor,
-                          ClutterPaintNode *root)
+clutter_actor_paint_node (ClutterActor        *actor,
+                          ClutterPaintNode    *root,
+                          ClutterPaintContext *paint_context)
 {
   ClutterActorPrivate *priv = actor->priv;
   ClutterActorBox box;
@@ -3847,7 +3849,7 @@ clutter_actor_paint_node (ClutterActor     *actor,
     }
 
   if (priv->content != NULL)
-    _clutter_content_paint_content (priv->content, actor, root);
+    _clutter_content_paint_content (priv->content, actor, root, paint_context);
 
   if (CLUTTER_ACTOR_GET_CLASS (actor)->paint_node != NULL)
     CLUTTER_ACTOR_GET_CLASS (actor)->paint_node (actor, root);
@@ -3863,7 +3865,7 @@ clutter_actor_paint_node (ClutterActor     *actor,
     }
 #endif /* CLUTTER_ENABLE_DEBUG */
 
-  clutter_paint_node_paint (root);
+  clutter_paint_node_paint (root, paint_context);
 
   return TRUE;
 }
@@ -3887,7 +3889,8 @@ clutter_actor_paint_node (ClutterActor     *actor,
  * unless it is performing a pick paint.
  */
 void
-clutter_actor_paint (ClutterActor *self)
+clutter_actor_paint (ClutterActor        *self,
+                     ClutterPaintContext *paint_context)
 {
   g_autoptr (ClutterPaintNode) actor_node = NULL;
   g_autoptr (ClutterPaintNode) root_node = NULL;
@@ -4069,7 +4072,7 @@ clutter_actor_paint (ClutterActor *self)
   if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_VOLUMES))
     _clutter_actor_draw_paint_volume (self, actor_node);
 
-  clutter_paint_node_paint (root_node);
+  clutter_paint_node_paint (root_node, paint_context);
 
   /* If we make it here then the actor has run through a complete
      paint run including all the effects so it's no longer dirty */
@@ -4089,7 +4092,8 @@ clutter_actor_paint (ClutterActor *self)
  * Since: 1.8
  */
 void
-clutter_actor_continue_paint (ClutterActor *self)
+clutter_actor_continue_paint (ClutterActor        *self,
+                              ClutterPaintContext *paint_context)
 {
   ClutterActorPrivate *priv;
 
@@ -4122,15 +4126,15 @@ clutter_actor_continue_paint (ClutterActor *self)
       /* XXX - for 1.12, we use the return value of paint_node() to
        * decide whether we should emit the ::paint signal.
        */
-      clutter_actor_paint_node (self, dummy);
+      clutter_actor_paint_node (self, dummy, paint_context);
       clutter_paint_node_unref (dummy);
 
       /* XXX:2.0 - Call the paint() virtual directly */
       if (g_signal_has_handler_pending (self, actor_signals[PAINT],
                                         0, TRUE))
-        g_signal_emit (self, actor_signals[PAINT], 0);
+        g_signal_emit (self, actor_signals[PAINT], 0, paint_context);
       else
-        CLUTTER_ACTOR_GET_CLASS (self)->paint (self);
+        CLUTTER_ACTOR_GET_CLASS (self)->paint (self, paint_context);
     }
   else
     {
@@ -4157,7 +4161,7 @@ clutter_actor_continue_paint (ClutterActor *self)
             run_flags |= CLUTTER_EFFECT_PAINT_ACTOR_DIRTY;
         }
 
-      _clutter_effect_paint (priv->current_effect, run_flags);
+      _clutter_effect_paint (priv->current_effect, paint_context, run_flags);
 
       priv->current_effect = old_current_effect;
     }
@@ -8534,6 +8538,7 @@ clutter_actor_class_init (ClutterActorClass *klass)
   /**
    * ClutterActor::paint:
    * @actor: the #ClutterActor that received the signal
+   * @paint_context: a #ClutterPaintContext
    *
    * The ::paint signal is emitted each time an actor is being painted.
    *
@@ -8561,7 +8566,8 @@ clutter_actor_class_init (ClutterActorClass *klass)
                   G_SIGNAL_DEPRECATED,
                   G_STRUCT_OFFSET (ClutterActorClass, paint),
                   NULL, NULL, NULL,
-                  G_TYPE_NONE, 0);
+                  G_TYPE_NONE, 1,
+                  CLUTTER_TYPE_PAINT_CONTEXT);
   /**
    * ClutterActor::realize:
    * @actor: the #ClutterActor that received the signal
diff --git a/clutter/clutter/clutter-actor.h b/clutter/clutter/clutter-actor.h
index efe919ec8..41082cf61 100644
--- a/clutter/clutter/clutter-actor.h
+++ b/clutter/clutter/clutter-actor.h
@@ -39,6 +39,7 @@
 
 #include <clutter/clutter-types.h>
 #include <clutter/clutter-event.h>
+#include <clutter/clutter-paint-context.h>
 
 G_BEGIN_DECLS
 
@@ -228,7 +229,8 @@ struct _ClutterActorClass
   void (* unrealize)            (ClutterActor          *self);
   void (* map)                  (ClutterActor          *self);
   void (* unmap)                (ClutterActor          *self);
-  void (* paint)                (ClutterActor          *self);
+  void (* paint)                (ClutterActor          *self,
+                                 ClutterPaintContext   *paint_context);
   void (* parent_set)           (ClutterActor          *actor,
                                  ClutterActor          *old_parent);
 
@@ -349,9 +351,11 @@ void                            clutter_actor_map
 CLUTTER_EXPORT
 void                            clutter_actor_unmap                             (ClutterActor                
*self);
 CLUTTER_EXPORT
-void                            clutter_actor_paint                             (ClutterActor                
*self);
+void                            clutter_actor_paint                             (ClutterActor                
*self,
+                                                                                 ClutterPaintContext         
*paint_context);
 CLUTTER_EXPORT
-void                            clutter_actor_continue_paint                    (ClutterActor                
*self);
+void                            clutter_actor_continue_paint                    (ClutterActor                
*self,
+                                                                                 ClutterPaintContext         
*paint_context);
 CLUTTER_EXPORT
 void                            clutter_actor_pick                              (ClutterActor                
*actor);
 CLUTTER_EXPORT
diff --git a/clutter/clutter/clutter-autocleanups.h b/clutter/clutter/clutter-autocleanups.h
index 4d6aa0541..8e17d002e 100644
--- a/clutter/clutter/clutter-autocleanups.h
+++ b/clutter/clutter/clutter-autocleanups.h
@@ -90,6 +90,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterActorBox, clutter_actor_box_free)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterColor, clutter_color_free)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterMargin, clutter_margin_free)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterMatrix, clutter_matrix_free)
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPaintContext, clutter_paint_context_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPaintNode, clutter_paint_node_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPaintVolume, clutter_paint_volume_free)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPathNode, clutter_path_node_free)
diff --git a/clutter/clutter/clutter-blur-effect.c b/clutter/clutter/clutter-blur-effect.c
index 06a7b2d4b..c2a739eb7 100644
--- a/clutter/clutter/clutter-blur-effect.c
+++ b/clutter/clutter/clutter-blur-effect.c
@@ -99,7 +99,8 @@ G_DEFINE_TYPE (ClutterBlurEffect,
                CLUTTER_TYPE_OFFSCREEN_EFFECT);
 
 static gboolean
-clutter_blur_effect_pre_paint (ClutterEffect *effect)
+clutter_blur_effect_pre_paint (ClutterEffect       *effect,
+                               ClutterPaintContext *paint_context)
 {
   ClutterBlurEffect *self = CLUTTER_BLUR_EFFECT (effect);
   ClutterEffectClass *parent_class;
@@ -124,7 +125,7 @@ clutter_blur_effect_pre_paint (ClutterEffect *effect)
     }
 
   parent_class = CLUTTER_EFFECT_CLASS (clutter_blur_effect_parent_class);
-  if (parent_class->pre_paint (effect))
+  if (parent_class->pre_paint (effect, paint_context))
     {
       ClutterOffscreenEffect *offscreen_effect =
         CLUTTER_OFFSCREEN_EFFECT (effect);
@@ -157,7 +158,8 @@ clutter_blur_effect_pre_paint (ClutterEffect *effect)
 }
 
 static void
-clutter_blur_effect_paint_target (ClutterOffscreenEffect *effect)
+clutter_blur_effect_paint_target (ClutterOffscreenEffect *effect,
+                                  ClutterPaintContext    *paint_context)
 {
   ClutterBlurEffect *self = CLUTTER_BLUR_EFFECT (effect);
   CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
diff --git a/clutter/clutter/clutter-brightness-contrast-effect.c 
b/clutter/clutter/clutter-brightness-contrast-effect.c
index 9bb3d9760..01d43f1fa 100644
--- a/clutter/clutter/clutter-brightness-contrast-effect.c
+++ b/clutter/clutter/clutter-brightness-contrast-effect.c
@@ -130,7 +130,8 @@ will_have_no_effect (ClutterBrightnessContrastEffect *self)
 }
 
 static gboolean
-clutter_brightness_contrast_effect_pre_paint (ClutterEffect *effect)
+clutter_brightness_contrast_effect_pre_paint (ClutterEffect       *effect,
+                                              ClutterPaintContext *paint_context)
 {
   ClutterBrightnessContrastEffect *self = CLUTTER_BRIGHTNESS_CONTRAST_EFFECT (effect);
   ClutterEffectClass *parent_class;
@@ -156,7 +157,7 @@ clutter_brightness_contrast_effect_pre_paint (ClutterEffect *effect)
 
   parent_class =
     CLUTTER_EFFECT_CLASS (clutter_brightness_contrast_effect_parent_class);
-  if (parent_class->pre_paint (effect))
+  if (parent_class->pre_paint (effect, paint_context))
     {
       ClutterOffscreenEffect *offscreen_effect =
         CLUTTER_OFFSCREEN_EFFECT (effect);
@@ -175,7 +176,8 @@ clutter_brightness_contrast_effect_pre_paint (ClutterEffect *effect)
 }
 
 static void
-clutter_brightness_contrast_effect_paint_target (ClutterOffscreenEffect *effect)
+clutter_brightness_contrast_effect_paint_target (ClutterOffscreenEffect *effect,
+                                                 ClutterPaintContext    *paint_context)
 {
   ClutterBrightnessContrastEffect *self = CLUTTER_BRIGHTNESS_CONTRAST_EFFECT (effect);
   CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
diff --git a/clutter/clutter/clutter-canvas.c b/clutter/clutter/clutter-canvas.c
index b0f1f080c..2502586a3 100644
--- a/clutter/clutter/clutter-canvas.c
+++ b/clutter/clutter/clutter-canvas.c
@@ -328,9 +328,10 @@ clutter_canvas_init (ClutterCanvas *self)
 }
 
 static void
-clutter_canvas_paint_content (ClutterContent   *content,
-                              ClutterActor     *actor,
-                              ClutterPaintNode *root)
+clutter_canvas_paint_content (ClutterContent      *content,
+                              ClutterActor        *actor,
+                              ClutterPaintNode    *root,
+                              ClutterPaintContext *paint_context)
 {
   ClutterCanvas *self = CLUTTER_CANVAS (content);
   ClutterCanvasPrivate *priv = self->priv;
diff --git a/clutter/clutter/clutter-clone.c b/clutter/clutter/clutter-clone.c
index 53fd1e657..8c805725a 100644
--- a/clutter/clutter/clutter-clone.c
+++ b/clutter/clutter/clutter-clone.c
@@ -152,7 +152,8 @@ clutter_clone_apply_transform (ClutterActor *self, CoglMatrix *matrix)
 }
 
 static void
-clutter_clone_paint (ClutterActor *actor)
+clutter_clone_paint (ClutterActor        *actor,
+                     ClutterPaintContext *paint_context)
 {
   ClutterClone *self = CLUTTER_CLONE (actor);
   ClutterClonePrivate *priv = self->priv;
@@ -189,7 +190,7 @@ clutter_clone_paint (ClutterActor *actor)
   if (clutter_actor_is_realized (priv->clone_source))
     {
       _clutter_actor_push_clone_paint ();
-      clutter_actor_paint (priv->clone_source);
+      clutter_actor_paint (priv->clone_source, paint_context);
       _clutter_actor_pop_clone_paint ();
     }
 
diff --git a/clutter/clutter/clutter-colorize-effect.c b/clutter/clutter/clutter-colorize-effect.c
index 73bd31949..811787036 100644
--- a/clutter/clutter/clutter-colorize-effect.c
+++ b/clutter/clutter/clutter-colorize-effect.c
@@ -105,7 +105,8 @@ G_DEFINE_TYPE (ClutterColorizeEffect,
                CLUTTER_TYPE_OFFSCREEN_EFFECT);
 
 static gboolean
-clutter_colorize_effect_pre_paint (ClutterEffect *effect)
+clutter_colorize_effect_pre_paint (ClutterEffect       *effect,
+                                   ClutterPaintContext *paint_context)
 {
   ClutterColorizeEffect *self = CLUTTER_COLORIZE_EFFECT (effect);
   ClutterEffectClass *parent_class;
@@ -126,7 +127,7 @@ clutter_colorize_effect_pre_paint (ClutterEffect *effect)
     }
 
   parent_class = CLUTTER_EFFECT_CLASS (clutter_colorize_effect_parent_class);
-  if (parent_class->pre_paint (effect))
+  if (parent_class->pre_paint (effect, paint_context))
     {
       ClutterOffscreenEffect *offscreen_effect =
         CLUTTER_OFFSCREEN_EFFECT (effect);
@@ -145,7 +146,8 @@ clutter_colorize_effect_pre_paint (ClutterEffect *effect)
 }
 
 static void
-clutter_colorize_effect_paint_target (ClutterOffscreenEffect *effect)
+clutter_colorize_effect_paint_target (ClutterOffscreenEffect *effect,
+                                      ClutterPaintContext    *paint_context)
 {
   ClutterColorizeEffect *self = CLUTTER_COLORIZE_EFFECT (effect);
   CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
diff --git a/clutter/clutter/clutter-content-private.h b/clutter/clutter/clutter-content-private.h
index 009ae41c8..1654b3bbf 100644
--- a/clutter/clutter/clutter-content-private.h
+++ b/clutter/clutter/clutter-content-private.h
@@ -34,9 +34,10 @@ void            _clutter_content_attached               (ClutterContent   *conte
 void            _clutter_content_detached               (ClutterContent   *content,
                                                          ClutterActor     *actor);
 
-void            _clutter_content_paint_content          (ClutterContent   *content,
-                                                         ClutterActor     *actor,
-                                                         ClutterPaintNode *node);
+void            _clutter_content_paint_content          (ClutterContent      *content,
+                                                         ClutterActor        *actor,
+                                                         ClutterPaintNode    *node,
+                                                         ClutterPaintContext *paint_context);
 
 G_END_DECLS
 
diff --git a/clutter/clutter/clutter-content.c b/clutter/clutter/clutter-content.c
index 4516280ce..31abd1135 100644
--- a/clutter/clutter/clutter-content.c
+++ b/clutter/clutter/clutter-content.c
@@ -96,9 +96,10 @@ clutter_content_real_invalidate_size (ClutterContent *content)
 }
 
 static void
-clutter_content_real_paint_content (ClutterContent   *content,
-                                    ClutterActor     *actor,
-                                    ClutterPaintNode *context)
+clutter_content_real_paint_content (ClutterContent      *content,
+                                    ClutterActor        *actor,
+                                    ClutterPaintNode    *context,
+                                    ClutterPaintContext *paint_context)
 {
 }
 
@@ -300,7 +301,8 @@ _clutter_content_detached (ClutterContent *content,
  * _clutter_content_paint_content:
  * @content: a #ClutterContent
  * @actor: a #ClutterActor
- * @context: a #ClutterPaintNode
+ * @node: a #ClutterPaintNode
+ * @paint_context: a #ClutterPaintContext
  *
  * Creates the render tree for the @content and @actor.
  *
@@ -308,11 +310,13 @@ _clutter_content_detached (ClutterContent *content,
  * virtual function.
  */
 void
-_clutter_content_paint_content (ClutterContent   *content,
-                                ClutterActor     *actor,
-                                ClutterPaintNode *node)
+_clutter_content_paint_content (ClutterContent      *content,
+                                ClutterActor        *actor,
+                                ClutterPaintNode    *node,
+                                ClutterPaintContext *paint_context)
 {
-  CLUTTER_CONTENT_GET_IFACE (content)->paint_content (content, actor, node);
+  CLUTTER_CONTENT_GET_IFACE (content)->paint_content (content, actor, node,
+                                                      paint_context);
 }
 
 /**
diff --git a/clutter/clutter/clutter-content.h b/clutter/clutter/clutter-content.h
index 4e2e1f58f..77b44dc3f 100644
--- a/clutter/clutter/clutter-content.h
+++ b/clutter/clutter/clutter-content.h
@@ -65,9 +65,10 @@ struct _ClutterContentInterface
   gboolean      (* get_preferred_size)  (ClutterContent   *content,
                                          gfloat           *width,
                                          gfloat           *height);
-  void          (* paint_content)       (ClutterContent   *content,
-                                         ClutterActor     *actor,
-                                         ClutterPaintNode *node);
+  void          (* paint_content)       (ClutterContent      *content,
+                                         ClutterActor        *actor,
+                                         ClutterPaintNode    *node,
+                                         ClutterPaintContext *paint_context);
 
   void          (* attached)            (ClutterContent   *content,
                                          ClutterActor     *actor);
diff --git a/clutter/clutter/clutter-deform-effect.c b/clutter/clutter/clutter-deform-effect.c
index 50e2f5c91..4dbf76af2 100644
--- a/clutter/clutter/clutter-deform-effect.c
+++ b/clutter/clutter/clutter-deform-effect.c
@@ -166,7 +166,8 @@ clutter_deform_effect_set_actor (ClutterActorMeta *meta,
 }
 
 static void
-clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect)
+clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect,
+                                    ClutterPaintContext    *paint_context)
 {
   ClutterDeformEffect *self= CLUTTER_DEFORM_EFFECT (effect);
   ClutterDeformEffectPrivate *priv = self->priv;
diff --git a/clutter/clutter/clutter-desaturate-effect.c b/clutter/clutter/clutter-desaturate-effect.c
index bc691d5d0..4ed522e0c 100644
--- a/clutter/clutter/clutter-desaturate-effect.c
+++ b/clutter/clutter/clutter-desaturate-effect.c
@@ -112,7 +112,8 @@ G_DEFINE_TYPE (ClutterDesaturateEffect,
                CLUTTER_TYPE_OFFSCREEN_EFFECT);
 
 static gboolean
-clutter_desaturate_effect_pre_paint (ClutterEffect *effect)
+clutter_desaturate_effect_pre_paint (ClutterEffect       *effect,
+                                     ClutterPaintContext *paint_context)
 {
   ClutterDesaturateEffect *self = CLUTTER_DESATURATE_EFFECT (effect);
   ClutterEffectClass *parent_class;
@@ -133,7 +134,7 @@ clutter_desaturate_effect_pre_paint (ClutterEffect *effect)
     }
 
   parent_class = CLUTTER_EFFECT_CLASS (clutter_desaturate_effect_parent_class);
-  if (parent_class->pre_paint (effect))
+  if (parent_class->pre_paint (effect, paint_context))
     {
       ClutterOffscreenEffect *offscreen_effect =
         CLUTTER_OFFSCREEN_EFFECT (effect);
@@ -152,7 +153,8 @@ clutter_desaturate_effect_pre_paint (ClutterEffect *effect)
 }
 
 static void
-clutter_desaturate_effect_paint_target (ClutterOffscreenEffect *effect)
+clutter_desaturate_effect_paint_target (ClutterOffscreenEffect *effect,
+                                        ClutterPaintContext    *paint_context)
 {
   ClutterDesaturateEffect *self = CLUTTER_DESATURATE_EFFECT (effect);
   CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
diff --git a/clutter/clutter/clutter-effect-private.h b/clutter/clutter/clutter-effect-private.h
index 15901bcfb..5b3874613 100644
--- a/clutter/clutter/clutter-effect-private.h
+++ b/clutter/clutter/clutter-effect-private.h
@@ -5,12 +5,15 @@
 
 G_BEGIN_DECLS
 
-gboolean        _clutter_effect_pre_paint               (ClutterEffect           *effect);
-void            _clutter_effect_post_paint              (ClutterEffect           *effect);
+gboolean        _clutter_effect_pre_paint               (ClutterEffect           *effect,
+                                                         ClutterPaintContext     *paint_context);
+void            _clutter_effect_post_paint              (ClutterEffect           *effect,
+                                                         ClutterPaintContext     *paint_context);
 gboolean        _clutter_effect_modify_paint_volume     (ClutterEffect           *effect,
                                                          ClutterPaintVolume      *volume);
 gboolean        _clutter_effect_has_custom_paint_volume (ClutterEffect           *effect);
 void            _clutter_effect_paint                   (ClutterEffect           *effect,
+                                                         ClutterPaintContext     *paint_context,
                                                          ClutterEffectPaintFlags  flags);
 void            _clutter_effect_pick                    (ClutterEffect           *effect);
 
diff --git a/clutter/clutter/clutter-effect.c b/clutter/clutter/clutter-effect.c
index 5cc64da66..fe355d24e 100644
--- a/clutter/clutter/clutter-effect.c
+++ b/clutter/clutter/clutter-effect.c
@@ -177,13 +177,15 @@ G_DEFINE_ABSTRACT_TYPE (ClutterEffect,
                         CLUTTER_TYPE_ACTOR_META);
 
 static gboolean
-clutter_effect_real_pre_paint (ClutterEffect *effect)
+clutter_effect_real_pre_paint (ClutterEffect       *effect,
+                               ClutterPaintContext *paint_context)
 {
   return TRUE;
 }
 
 static void
-clutter_effect_real_post_paint (ClutterEffect *effect)
+clutter_effect_real_post_paint (ClutterEffect       *effect,
+                                ClutterPaintContext *paint_context)
 {
 }
 
@@ -196,6 +198,7 @@ clutter_effect_real_modify_paint_volume (ClutterEffect      *effect,
 
 static void
 clutter_effect_real_paint (ClutterEffect           *effect,
+                           ClutterPaintContext     *paint_context,
                            ClutterEffectPaintFlags  flags)
 {
   ClutterActorMeta *actor_meta = CLUTTER_ACTOR_META (effect);
@@ -206,13 +209,13 @@ clutter_effect_real_paint (ClutterEffect           *effect,
      effects that haven't migrated to use the 'paint' virtual yet. This
      just calls the old pre and post virtuals before chaining on */
 
-  pre_paint_succeeded = _clutter_effect_pre_paint (effect);
+  pre_paint_succeeded = _clutter_effect_pre_paint (effect, paint_context);
 
   actor = clutter_actor_meta_get_actor (actor_meta);
-  clutter_actor_continue_paint (actor);
+  clutter_actor_continue_paint (actor, paint_context);
 
   if (pre_paint_succeeded)
-    _clutter_effect_post_paint (effect);
+    _clutter_effect_post_paint (effect, paint_context);
 }
 
 static void
@@ -262,28 +265,31 @@ clutter_effect_init (ClutterEffect *self)
 }
 
 gboolean
-_clutter_effect_pre_paint (ClutterEffect *effect)
+_clutter_effect_pre_paint (ClutterEffect       *effect,
+                           ClutterPaintContext *paint_context)
 {
   g_return_val_if_fail (CLUTTER_IS_EFFECT (effect), FALSE);
 
-  return CLUTTER_EFFECT_GET_CLASS (effect)->pre_paint (effect);
+  return CLUTTER_EFFECT_GET_CLASS (effect)->pre_paint (effect, paint_context);
 }
 
 void
-_clutter_effect_post_paint (ClutterEffect *effect)
+_clutter_effect_post_paint (ClutterEffect       *effect,
+                            ClutterPaintContext *paint_context)
 {
   g_return_if_fail (CLUTTER_IS_EFFECT (effect));
 
-  CLUTTER_EFFECT_GET_CLASS (effect)->post_paint (effect);
+  CLUTTER_EFFECT_GET_CLASS (effect)->post_paint (effect, paint_context);
 }
 
 void
 _clutter_effect_paint (ClutterEffect           *effect,
+                       ClutterPaintContext     *paint_context,
                        ClutterEffectPaintFlags  flags)
 {
   g_return_if_fail (CLUTTER_IS_EFFECT (effect));
 
-  CLUTTER_EFFECT_GET_CLASS (effect)->paint (effect, flags);
+  CLUTTER_EFFECT_GET_CLASS (effect)->paint (effect, paint_context, flags);
 }
 
 void
diff --git a/clutter/clutter/clutter-effect.h b/clutter/clutter/clutter-effect.h
index 0e9de2f36..50e06f889 100644
--- a/clutter/clutter/clutter-effect.h
+++ b/clutter/clutter/clutter-effect.h
@@ -30,6 +30,7 @@
 #endif
 
 #include <clutter/clutter-actor-meta.h>
+#include <clutter/clutter-paint-context.h>
 
 G_BEGIN_DECLS
 
@@ -74,13 +75,16 @@ struct _ClutterEffectClass
   ClutterActorMetaClass parent_class;
 
   /*< public >*/
-  gboolean (* pre_paint)           (ClutterEffect           *effect);
-  void     (* post_paint)          (ClutterEffect           *effect);
+  gboolean (* pre_paint)           (ClutterEffect           *effect,
+                                    ClutterPaintContext     *paint_context);
+  void     (* post_paint)          (ClutterEffect           *effect,
+                                    ClutterPaintContext     *paint_context);
 
   gboolean (* modify_paint_volume) (ClutterEffect           *effect,
                                     ClutterPaintVolume      *volume);
 
   void     (* paint)               (ClutterEffect           *effect,
+                                    ClutterPaintContext     *paint_context,
                                     ClutterEffectPaintFlags  flags);
   void     (* pick)                (ClutterEffect           *effect);
 
diff --git a/clutter/clutter/clutter-image.c b/clutter/clutter/clutter-image.c
index 61ad78c62..c5a1c51ac 100644
--- a/clutter/clutter/clutter-image.c
+++ b/clutter/clutter/clutter-image.c
@@ -118,9 +118,10 @@ clutter_image_init (ClutterImage *self)
 }
 
 static void
-clutter_image_paint_content (ClutterContent   *content,
-                             ClutterActor     *actor,
-                             ClutterPaintNode *root)
+clutter_image_paint_content (ClutterContent      *content,
+                             ClutterActor        *actor,
+                             ClutterPaintNode    *root,
+                             ClutterPaintContext *paint_context)
 {
   ClutterImagePrivate *priv = CLUTTER_IMAGE (content)->priv;
   ClutterPaintNode *node;
diff --git a/clutter/clutter/clutter-offscreen-effect.c b/clutter/clutter/clutter-offscreen-effect.c
index cc3150d44..18744f4fc 100644
--- a/clutter/clutter/clutter-offscreen-effect.c
+++ b/clutter/clutter/clutter-offscreen-effect.c
@@ -237,7 +237,8 @@ update_fbo (ClutterEffect *effect,
 }
 
 static gboolean
-clutter_offscreen_effect_pre_paint (ClutterEffect *effect)
+clutter_offscreen_effect_pre_paint (ClutterEffect       *effect,
+                                    ClutterPaintContext *paint_context)
 {
   ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect);
   ClutterOffscreenEffectPrivate *priv = self->priv;
@@ -378,7 +379,8 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect)
 }
 
 static void
-clutter_offscreen_effect_real_paint_target (ClutterOffscreenEffect *effect)
+clutter_offscreen_effect_real_paint_target (ClutterOffscreenEffect *effect,
+                                            ClutterPaintContext    *paint_context)
 {
   ClutterOffscreenEffectPrivate *priv = effect->priv;
   CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
@@ -407,7 +409,8 @@ clutter_offscreen_effect_real_paint_target (ClutterOffscreenEffect *effect)
 }
 
 static void
-clutter_offscreen_effect_paint_texture (ClutterOffscreenEffect *effect)
+clutter_offscreen_effect_paint_texture (ClutterOffscreenEffect *effect,
+                                        ClutterPaintContext    *paint_context)
 {
   ClutterOffscreenEffectPrivate *priv = effect->priv;
   CoglMatrix modelview;
@@ -436,13 +439,14 @@ clutter_offscreen_effect_paint_texture (ClutterOffscreenEffect *effect)
   /* paint the target material; this is virtualized for
    * sub-classes that require special hand-holding
    */
-  clutter_offscreen_effect_paint_target (effect);
+  clutter_offscreen_effect_paint_target (effect, paint_context);
 
   cogl_pop_matrix ();
 }
 
 static void
-clutter_offscreen_effect_post_paint (ClutterEffect *effect)
+clutter_offscreen_effect_post_paint (ClutterEffect       *effect,
+                                     ClutterPaintContext *paint_context)
 {
   ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect);
   ClutterOffscreenEffectPrivate *priv = self->priv;
@@ -458,11 +462,12 @@ clutter_offscreen_effect_post_paint (ClutterEffect *effect)
   cogl_pop_matrix ();
   cogl_pop_framebuffer ();
 
-  clutter_offscreen_effect_paint_texture (self);
+  clutter_offscreen_effect_paint_texture (self, paint_context);
 }
 
 static void
 clutter_offscreen_effect_paint (ClutterEffect           *effect,
+                                ClutterPaintContext     *paint_context,
                                 ClutterEffectPaintFlags  flags)
 {
   ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect);
@@ -476,10 +481,10 @@ clutter_offscreen_effect_paint (ClutterEffect           *effect,
       /* Chain up to the parent paint method which will call the pre and
          post paint functions to update the image */
       CLUTTER_EFFECT_CLASS (clutter_offscreen_effect_parent_class)->
-        paint (effect, flags);
+        paint (effect, paint_context, flags);
     }
   else
-    clutter_offscreen_effect_paint_texture (self);
+    clutter_offscreen_effect_paint_texture (self, paint_context);
 }
 
 static void
@@ -582,17 +587,20 @@ clutter_offscreen_effect_get_target (ClutterOffscreenEffect *effect)
 /**
  * clutter_offscreen_effect_paint_target:
  * @effect: a #ClutterOffscreenEffect
+ * @paint_context: a #ClutterPaintContext
  *
  * Calls the paint_target() virtual function of the @effect
  *
  * Since: 1.4
  */
 void
-clutter_offscreen_effect_paint_target (ClutterOffscreenEffect *effect)
+clutter_offscreen_effect_paint_target (ClutterOffscreenEffect *effect,
+                                       ClutterPaintContext    *paint_context)
 {
   g_return_if_fail (CLUTTER_IS_OFFSCREEN_EFFECT (effect));
 
-  CLUTTER_OFFSCREEN_EFFECT_GET_CLASS (effect)->paint_target (effect);
+  CLUTTER_OFFSCREEN_EFFECT_GET_CLASS (effect)->paint_target (effect,
+                                                             paint_context);
 }
 
 /**
diff --git a/clutter/clutter/clutter-offscreen-effect.h b/clutter/clutter/clutter-offscreen-effect.h
index 6ab1637ae..2de98bb0a 100644
--- a/clutter/clutter/clutter-offscreen-effect.h
+++ b/clutter/clutter/clutter-offscreen-effect.h
@@ -79,7 +79,8 @@ struct _ClutterOffscreenEffectClass
   CoglHandle (* create_texture) (ClutterOffscreenEffect *effect,
                                  gfloat                  width,
                                  gfloat                  height);
-  void       (* paint_target)   (ClutterOffscreenEffect *effect);
+  void       (* paint_target)   (ClutterOffscreenEffect *effect,
+                                 ClutterPaintContext    *paint_context);
 
   /*< private >*/
   void (* _clutter_offscreen1) (void);
@@ -101,7 +102,8 @@ CLUTTER_EXPORT
 CoglHandle      clutter_offscreen_effect_get_texture            (ClutterOffscreenEffect *effect);
 
 CLUTTER_EXPORT
-void            clutter_offscreen_effect_paint_target           (ClutterOffscreenEffect *effect);
+void            clutter_offscreen_effect_paint_target           (ClutterOffscreenEffect *effect,
+                                                                 ClutterPaintContext    *paint_context);
 CLUTTER_EXPORT
 CoglHandle      clutter_offscreen_effect_create_texture         (ClutterOffscreenEffect *effect,
                                                                  gfloat                  width,
diff --git a/clutter/clutter/clutter-paint-context-private.h b/clutter/clutter/clutter-paint-context-private.h
new file mode 100644
index 000000000..8d8986ca1
--- /dev/null
+++ b/clutter/clutter/clutter-paint-context-private.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2019 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CLUTTER_PAINT_CONTEXT_PRIVATE_H
+#define CLUTTER_PAINT_CONTEXT_PRIVATE_H
+
+#include "clutter-paint-context.h"
+
+ClutterPaintContext * clutter_paint_context_new_for_view (ClutterStageView *view);
+
+void clutter_paint_context_push_framebuffer (ClutterPaintContext *paint_context,
+                                             CoglFramebuffer     *framebuffer);
+
+void clutter_paint_context_pop_framebuffer (ClutterPaintContext *paint_context);
+
+#endif /* CLUTTER_PAINT_CONTEXT_PRIVATE_H */
diff --git a/clutter/clutter/clutter-paint-context.c b/clutter/clutter/clutter-paint-context.c
new file mode 100644
index 000000000..51f73b9a5
--- /dev/null
+++ b/clutter/clutter/clutter-paint-context.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2019 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "clutter-build-config.h"
+
+#include "clutter-paint-context-private.h"
+
+struct _ClutterPaintContext
+{
+  grefcount ref_count;
+
+  GList *framebuffers;
+
+  ClutterStageView *view;
+};
+
+G_DEFINE_BOXED_TYPE (ClutterPaintContext, clutter_paint_context,
+                     clutter_paint_context_ref,
+                     clutter_paint_context_unref)
+
+ClutterPaintContext *
+clutter_paint_context_new_for_view (ClutterStageView *view)
+{
+  ClutterPaintContext *paint_context;
+  CoglFramebuffer *framebuffer;
+
+  paint_context = g_new0 (ClutterPaintContext, 1);
+  g_ref_count_init (&paint_context->ref_count);
+  paint_context->view = view;
+
+  framebuffer = clutter_stage_view_get_framebuffer (view);
+  clutter_paint_context_push_framebuffer (paint_context, framebuffer);
+
+  return paint_context;
+}
+
+/**
+ * clutter_paint_context_new_for_framebuffer: (skip)
+ */
+ClutterPaintContext *
+clutter_paint_context_new_for_framebuffer (CoglFramebuffer *framebuffer)
+{
+  ClutterPaintContext *paint_context;
+
+  paint_context = g_new0 (ClutterPaintContext, 1);
+  g_ref_count_init (&paint_context->ref_count);
+
+  clutter_paint_context_push_framebuffer (paint_context, framebuffer);
+
+  return paint_context;
+}
+
+ClutterPaintContext *
+clutter_paint_context_ref (ClutterPaintContext *paint_context)
+{
+  g_ref_count_inc (&paint_context->ref_count);
+  return paint_context;
+}
+
+static void
+clutter_paint_context_dispose (ClutterPaintContext *paint_context)
+{
+  g_list_free_full (paint_context->framebuffers,
+                    cogl_object_unref);
+  paint_context->framebuffers = NULL;
+}
+
+void
+clutter_paint_context_unref (ClutterPaintContext *paint_context)
+{
+  if (g_ref_count_dec (&paint_context->ref_count))
+    {
+      clutter_paint_context_dispose (paint_context);
+      g_free (paint_context);
+    }
+}
+
+void
+clutter_paint_context_destroy (ClutterPaintContext *paint_context)
+{
+  clutter_paint_context_dispose (paint_context);
+  clutter_paint_context_unref (paint_context);
+}
+
+void
+clutter_paint_context_push_framebuffer (ClutterPaintContext *paint_context,
+                                        CoglFramebuffer     *framebuffer)
+{
+  paint_context->framebuffers = g_list_prepend (paint_context->framebuffers,
+                                                cogl_object_ref (framebuffer));
+}
+
+void
+clutter_paint_context_pop_framebuffer (ClutterPaintContext *paint_context)
+{
+  g_return_if_fail (paint_context->framebuffers);
+
+  cogl_object_unref (paint_context->framebuffers->data);
+  paint_context->framebuffers =
+    g_list_delete_link (paint_context->framebuffers,
+                        paint_context->framebuffers);
+}
+
+/**
+ * clutter_paint_context_get_framebuffer:
+ * @paint_context: The #ClutterPaintContext
+ *
+ * Returns: (transfer none): The #CoglFramebuffer used for drawing
+ */
+CoglFramebuffer *
+clutter_paint_context_get_framebuffer (ClutterPaintContext *paint_context)
+{
+  g_return_val_if_fail (paint_context->framebuffers, NULL);
+
+  return paint_context->framebuffers->data;
+}
+
+/**
+ * clutter_paint_context_get_stage_view: (skip)
+ */
+ClutterStageView *
+clutter_paint_context_get_stage_view (ClutterPaintContext *paint_context)
+{
+  return paint_context->view;
+}
diff --git a/clutter/clutter/clutter-paint-context.h b/clutter/clutter/clutter-paint-context.h
new file mode 100644
index 000000000..e7e52331a
--- /dev/null
+++ b/clutter/clutter/clutter-paint-context.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CLUTTER_PAINT_CONTEXT_H
+#define CLUTTER_PAINT_CONTEXT_H
+
+#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
+#error "Only <clutter/clutter.h> can be included directly."
+#endif
+
+#include <glib-object.h>
+
+#include "clutter-macros.h"
+#include "clutter-stage-view.h"
+
+typedef struct _ClutterPaintContext ClutterPaintContext;
+
+#define CLUTTER_TYPE_PAINT_CONTEXT (clutter_paint_context_get_type ())
+
+CLUTTER_EXPORT
+GType clutter_paint_context_get_type (void);
+
+CLUTTER_EXPORT
+ClutterPaintContext * clutter_paint_context_new_for_framebuffer (CoglFramebuffer *framebuffer);
+
+CLUTTER_EXPORT
+ClutterPaintContext * clutter_paint_context_ref (ClutterPaintContext *paint_context);
+
+CLUTTER_EXPORT
+void clutter_paint_context_unref (ClutterPaintContext *paint_context);
+
+CLUTTER_EXPORT
+void clutter_paint_context_destroy (ClutterPaintContext *paint_context);
+
+CLUTTER_EXPORT
+CoglFramebuffer * clutter_paint_context_get_framebuffer (ClutterPaintContext *paint_context);
+
+CLUTTER_EXPORT
+ClutterStageView * clutter_paint_context_get_stage_view (ClutterPaintContext *paint_context);
+
+#endif /* CLUTTER_PAINT_CONTEXT_H */
diff --git a/clutter/clutter/clutter-paint-node-private.h b/clutter/clutter/clutter-paint-node-private.h
index fa555a478..8d81ad184 100644
--- a/clutter/clutter/clutter-paint-node-private.h
+++ b/clutter/clutter/clutter-paint-node-private.h
@@ -27,6 +27,7 @@
 
 #include <glib-object.h>
 #include <json-glib/json-glib.h>
+#include <clutter/clutter-paint-context.h>
 #include <clutter/clutter-paint-node.h>
 
 G_BEGIN_DECLS
@@ -63,9 +64,12 @@ struct _ClutterPaintNodeClass
 
   void     (* finalize)  (ClutterPaintNode *node);
 
-  gboolean (* pre_draw)  (ClutterPaintNode *node);
-  void     (* draw)      (ClutterPaintNode *node);
-  void     (* post_draw) (ClutterPaintNode *node);
+  gboolean (* pre_draw)  (ClutterPaintNode    *node,
+                          ClutterPaintContext *paint_context);
+  void     (* draw)      (ClutterPaintNode    *node,
+                          ClutterPaintContext *paint_context);
+  void     (* post_draw) (ClutterPaintNode    *node,
+                          ClutterPaintContext *paint_context);
 
   JsonNode*(* serialize) (ClutterPaintNode *node);
 
diff --git a/clutter/clutter/clutter-paint-node.c b/clutter/clutter/clutter-paint-node.c
index af098e1ca..bb23486ad 100644
--- a/clutter/clutter/clutter-paint-node.c
+++ b/clutter/clutter/clutter-paint-node.c
@@ -202,18 +202,21 @@ clutter_paint_node_real_finalize (ClutterPaintNode *node)
 }
 
 static gboolean
-clutter_paint_node_real_pre_draw (ClutterPaintNode *node)
+clutter_paint_node_real_pre_draw (ClutterPaintNode    *node,
+                                  ClutterPaintContext *paint_context)
 {
   return FALSE;
 }
 
 static void
-clutter_paint_node_real_draw (ClutterPaintNode *node)
+clutter_paint_node_real_draw (ClutterPaintNode    *node,
+                              ClutterPaintContext *paint_context)
 {
 }
 
 static void
-clutter_paint_node_real_post_draw (ClutterPaintNode *node)
+clutter_paint_node_real_post_draw (ClutterPaintNode    *node,
+                                   ClutterPaintContext *paint_context)
 {
 }
 
@@ -997,29 +1000,30 @@ clutter_paint_node_add_primitive (ClutterPaintNode *node,
  * its children, if any.
  */
 void
-clutter_paint_node_paint (ClutterPaintNode *node)
+clutter_paint_node_paint (ClutterPaintNode    *node,
+                          ClutterPaintContext *paint_context)
 {
   ClutterPaintNodeClass *klass = CLUTTER_PAINT_NODE_GET_CLASS (node);
   ClutterPaintNode *iter;
   gboolean res;
 
-  res = klass->pre_draw (node);
+  res = klass->pre_draw (node, paint_context);
 
   if (res)
     {
-      klass->draw (node);
+      klass->draw (node, paint_context);
     }
 
   for (iter = node->first_child;
        iter != NULL;
        iter = iter->next_sibling)
     {
-      clutter_paint_node_paint (iter);
+      clutter_paint_node_paint (iter, paint_context);
     }
 
   if (res)
     {
-      klass->post_draw (node);
+      klass->post_draw (node, paint_context);
     }
 }
 
diff --git a/clutter/clutter/clutter-paint-node.h b/clutter/clutter/clutter-paint-node.h
index cd22e431e..49722edd9 100644
--- a/clutter/clutter/clutter-paint-node.h
+++ b/clutter/clutter/clutter-paint-node.h
@@ -50,7 +50,8 @@ CLUTTER_EXPORT
 void                    clutter_paint_node_unref                        (ClutterPaintNode      *node);
 
 CLUTTER_EXPORT
-void                    clutter_paint_node_paint                        (ClutterPaintNode      *node);
+void                    clutter_paint_node_paint                        (ClutterPaintNode      *node,
+                                                                         ClutterPaintContext   
*paint_context);
 
 CLUTTER_EXPORT
 void                    clutter_paint_node_set_name                     (ClutterPaintNode      *node,
diff --git a/clutter/clutter/clutter-paint-nodes.c b/clutter/clutter/clutter-paint-nodes.c
index 4c5b23ba5..f95580f33 100644
--- a/clutter/clutter/clutter-paint-nodes.c
+++ b/clutter/clutter/clutter-paint-nodes.c
@@ -103,7 +103,8 @@ struct _ClutterRootNode
 G_DEFINE_TYPE (ClutterRootNode, clutter_root_node, CLUTTER_TYPE_PAINT_NODE)
 
 static gboolean
-clutter_root_node_pre_draw (ClutterPaintNode *node)
+clutter_root_node_pre_draw (ClutterPaintNode    *node,
+                            ClutterPaintContext *paint_context)
 {
   ClutterRootNode *rnode = (ClutterRootNode *) node;
 
@@ -117,7 +118,8 @@ clutter_root_node_pre_draw (ClutterPaintNode *node)
 }
 
 static void
-clutter_root_node_post_draw (ClutterPaintNode *node)
+clutter_root_node_post_draw (ClutterPaintNode    *node,
+                             ClutterPaintContext *paint_context)
 {
   cogl_pop_framebuffer ();
 }
@@ -201,7 +203,8 @@ struct _ClutterTransformNodeClass
 G_DEFINE_TYPE (ClutterTransformNode, clutter_transform_node, CLUTTER_TYPE_PAINT_NODE)
 
 static gboolean
-clutter_transform_node_pre_draw (ClutterPaintNode *node)
+clutter_transform_node_pre_draw (ClutterPaintNode    *node,
+                                 ClutterPaintContext *paint_context)
 {
   ClutterTransformNode *transform_node = (ClutterTransformNode *) node;
   CoglFramebuffer *fb = cogl_get_draw_framebuffer ();
@@ -213,7 +216,8 @@ clutter_transform_node_pre_draw (ClutterPaintNode *node)
 }
 
 static void
-clutter_transform_node_post_draw (ClutterPaintNode *node)
+clutter_transform_node_post_draw (ClutterPaintNode    *node,
+                                  ClutterPaintContext *paint_context)
 {
   CoglFramebuffer *fb = cogl_get_draw_framebuffer ();
 
@@ -278,7 +282,8 @@ struct _ClutterDummyNode
 G_DEFINE_TYPE (ClutterDummyNode, clutter_dummy_node, CLUTTER_TYPE_PAINT_NODE)
 
 static gboolean
-clutter_dummy_node_pre_draw (ClutterPaintNode *node)
+clutter_dummy_node_pre_draw (ClutterPaintNode    *node,
+                             ClutterPaintContext *paint_context)
 {
   return TRUE;
 }
@@ -383,7 +388,8 @@ clutter_pipeline_node_finalize (ClutterPaintNode *node)
 }
 
 static gboolean
-clutter_pipeline_node_pre_draw (ClutterPaintNode *node)
+clutter_pipeline_node_pre_draw (ClutterPaintNode    *node,
+                                ClutterPaintContext *paint_context)
 {
   ClutterPipelineNode *pnode = CLUTTER_PIPELINE_NODE (node);
 
@@ -398,7 +404,8 @@ clutter_pipeline_node_pre_draw (ClutterPaintNode *node)
 }
 
 static void
-clutter_pipeline_node_draw (ClutterPaintNode *node)
+clutter_pipeline_node_draw (ClutterPaintNode    *node,
+                            ClutterPaintContext *paint_context)
 {
   ClutterPipelineNode *pnode = CLUTTER_PIPELINE_NODE (node);
   CoglFramebuffer *fb;
@@ -459,7 +466,8 @@ clutter_pipeline_node_draw (ClutterPaintNode *node)
 }
 
 static void
-clutter_pipeline_node_post_draw (ClutterPaintNode *node)
+clutter_pipeline_node_post_draw (ClutterPaintNode    *node,
+                                 ClutterPaintContext *paint_context)
 {
   cogl_pop_source ();
 }
@@ -780,7 +788,8 @@ clutter_text_node_finalize (ClutterPaintNode *node)
 }
 
 static gboolean
-clutter_text_node_pre_draw (ClutterPaintNode *node)
+clutter_text_node_pre_draw (ClutterPaintNode    *node,
+                            ClutterPaintContext *paint_context)
 {
   ClutterTextNode *tnode = CLUTTER_TEXT_NODE (node);
 
@@ -788,7 +797,8 @@ clutter_text_node_pre_draw (ClutterPaintNode *node)
 }
 
 static void
-clutter_text_node_draw (ClutterPaintNode *node)
+clutter_text_node_draw (ClutterPaintNode    *node,
+                        ClutterPaintContext *paint_context)
 {
   ClutterTextNode *tnode = CLUTTER_TEXT_NODE (node);
   PangoRectangle extents;
@@ -974,7 +984,8 @@ struct _ClutterClipNodeClass
 G_DEFINE_TYPE (ClutterClipNode, clutter_clip_node, CLUTTER_TYPE_PAINT_NODE)
 
 static gboolean
-clutter_clip_node_pre_draw (ClutterPaintNode *node)
+clutter_clip_node_pre_draw (ClutterPaintNode    *node,
+                            ClutterPaintContext *paint_context)
 {
   gboolean retval = FALSE;
   CoglFramebuffer *fb;
@@ -1018,7 +1029,8 @@ clutter_clip_node_pre_draw (ClutterPaintNode *node)
 }
 
 static void
-clutter_clip_node_post_draw (ClutterPaintNode *node)
+clutter_clip_node_post_draw (ClutterPaintNode    *node,
+                             ClutterPaintContext *paint_context)
 {
   CoglFramebuffer *fb;
   guint i;
@@ -1100,7 +1112,8 @@ struct _ClutterActorNodeClass
 G_DEFINE_TYPE (ClutterActorNode, clutter_actor_node, CLUTTER_TYPE_PAINT_NODE)
 
 static gboolean
-clutter_actor_node_pre_draw (ClutterPaintNode *node)
+clutter_actor_node_pre_draw (ClutterPaintNode    *node,
+                             ClutterPaintContext *paint_context)
 {
   ClutterActorNode *actor_node = CLUTTER_ACTOR_NODE (node);
 
@@ -1110,15 +1123,17 @@ clutter_actor_node_pre_draw (ClutterPaintNode *node)
 }
 
 static void
-clutter_actor_node_draw (ClutterPaintNode *node)
+clutter_actor_node_draw (ClutterPaintNode    *node,
+                         ClutterPaintContext *paint_context)
 {
   ClutterActorNode *actor_node = CLUTTER_ACTOR_NODE (node);
 
-  clutter_actor_continue_paint (actor_node->actor);
+  clutter_actor_continue_paint (actor_node->actor, paint_context);
 }
 
 static void
-clutter_actor_node_post_draw (ClutterPaintNode *node)
+clutter_actor_node_post_draw (ClutterPaintNode    *node,
+                              ClutterPaintContext *paint_context)
 {
   ClutterActorNode *actor_node = CLUTTER_ACTOR_NODE (node);
 
@@ -1217,7 +1232,8 @@ struct _ClutterLayerNodeClass
 G_DEFINE_TYPE (ClutterLayerNode, clutter_layer_node, CLUTTER_TYPE_PAINT_NODE)
 
 static gboolean
-clutter_layer_node_pre_draw (ClutterPaintNode *node)
+clutter_layer_node_pre_draw (ClutterPaintNode *node,
+                             ClutterPaintContext *paint_context)
 {
   ClutterLayerNode *lnode = (ClutterLayerNode *) node;
   CoglMatrix matrix;
@@ -1265,7 +1281,8 @@ clutter_layer_node_pre_draw (ClutterPaintNode *node)
 }
 
 static void
-clutter_layer_node_post_draw (ClutterPaintNode *node)
+clutter_layer_node_post_draw (ClutterPaintNode    *node,
+                              ClutterPaintContext *paint_context)
 {
   ClutterLayerNode *lnode = CLUTTER_LAYER_NODE (node);
   CoglFramebuffer *fb;
diff --git a/clutter/clutter/clutter-shader-effect.c b/clutter/clutter/clutter-shader-effect.c
index 2d98d1bb6..f61f37e8f 100644
--- a/clutter/clutter/clutter-shader-effect.c
+++ b/clutter/clutter/clutter-shader-effect.c
@@ -395,7 +395,8 @@ clutter_shader_effect_try_static_source (ClutterShaderEffect *self)
 }
 
 static void
-clutter_shader_effect_paint_target (ClutterOffscreenEffect *effect)
+clutter_shader_effect_paint_target (ClutterOffscreenEffect *effect,
+                                    ClutterPaintContext    *paint_context)
 {
   ClutterShaderEffect *self = CLUTTER_SHADER_EFFECT (effect);
   ClutterShaderEffectPrivate *priv = self->priv;
@@ -425,7 +426,7 @@ clutter_shader_effect_paint_target (ClutterOffscreenEffect *effect)
 out:
   /* paint the offscreen buffer */
   parent = CLUTTER_OFFSCREEN_EFFECT_CLASS (clutter_shader_effect_parent_class);
-  parent->paint_target (effect);
+  parent->paint_target (effect, paint_context);
 
 }
 
diff --git a/clutter/clutter/clutter-stage-view-private.h b/clutter/clutter/clutter-stage-view-private.h
index 9fcbadba5..bbdcbaef8 100644
--- a/clutter/clutter/clutter-stage-view-private.h
+++ b/clutter/clutter/clutter-stage-view-private.h
@@ -33,5 +33,7 @@ gboolean clutter_stage_view_is_dirty_projection (ClutterStageView *view);
 void clutter_stage_view_set_dirty_projection (ClutterStageView *view,
                                               gboolean          dirty);
 
+void clutter_stage_view_add_redraw_clip (ClutterStageView      *view,
+                                         cairo_rectangle_int_t *clip);
 
 #endif /* __CLUTTER_STAGE_VIEW_PRIVATE_H__ */
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index 02377867a..ba573a08b 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -68,6 +68,7 @@
 #include "clutter-marshal.h"
 #include "clutter-master-clock.h"
 #include "clutter-mutter.h"
+#include "clutter-paint-context-private.h"
 #include "clutter-paint-volume-private.h"
 #include "clutter-private.h"
 #include "clutter-stage-manager-private.h"
@@ -922,8 +923,13 @@ clutter_stage_do_paint_view (ClutterStage                *stage,
                              ClutterStageView            *view,
                              const cairo_rectangle_int_t *clip)
 {
+  ClutterPaintContext *paint_context;
+
+  paint_context = clutter_paint_context_new_for_view (view);
+
   setup_view_for_pick_or_paint (stage, view, clip);
-  clutter_actor_paint (CLUTTER_ACTOR (stage));
+  clutter_actor_paint (CLUTTER_ACTOR (stage), paint_context);
+  clutter_paint_context_destroy (paint_context);
 }
 
 /* This provides a common point of entry for painting the scenegraph
@@ -963,14 +969,15 @@ _clutter_stage_emit_after_paint (ClutterStage *stage)
  * respect the Z order as it uses our empty sort_depth_order.
  */
 static void
-clutter_stage_paint (ClutterActor *self)
+clutter_stage_paint (ClutterActor        *self,
+                     ClutterPaintContext *paint_context)
 {
   ClutterActorIter iter;
   ClutterActor *child;
 
   clutter_actor_iter_init (&iter, self);
   while (clutter_actor_iter_next (&iter, &child))
-    clutter_actor_paint (child);
+    clutter_actor_paint (child, paint_context);
 }
 
 static void
@@ -2165,6 +2172,7 @@ clutter_stage_class_init (ClutterStageClass *klass)
   /**
    * ClutterStage::after-paint:
    * @stage: the stage that received the event
+   * @paint_Context: the paint context
    *
    * The ::after-paint signal is emitted after the stage is painted,
    * but before the results are displayed on the screen.
diff --git a/clutter/clutter/clutter-text.c b/clutter/clutter/clutter-text.c
index b4dea0f6b..33d30f01e 100644
--- a/clutter/clutter/clutter-text.c
+++ b/clutter/clutter/clutter-text.c
@@ -2548,7 +2548,8 @@ clutter_text_compute_layout_offsets (ClutterText           *self,
 #define TEXT_PADDING    2
 
 static void
-clutter_text_paint (ClutterActor *self)
+clutter_text_paint (ClutterActor        *self,
+                    ClutterPaintContext *paint_context)
 {
   ClutterText *text = CLUTTER_TEXT (self);
   ClutterTextPrivate *priv = text->priv;
diff --git a/clutter/clutter/deprecated/clutter-group.c b/clutter/clutter/deprecated/clutter-group.c
index 519fded14..ac52916dd 100644
--- a/clutter/clutter/deprecated/clutter-group.c
+++ b/clutter/clutter/deprecated/clutter-group.c
@@ -277,14 +277,15 @@ clutter_container_iface_init (ClutterContainerIface *iface)
 }
 
 static void
-clutter_group_real_paint (ClutterActor *actor)
+clutter_group_real_paint (ClutterActor        *actor,
+                          ClutterPaintContext *paint_context)
 {
   ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv;
 
   CLUTTER_NOTE (PAINT, "ClutterGroup paint enter '%s'",
                 _clutter_actor_get_debug_name (actor));
 
-  g_list_foreach (priv->children, (GFunc) clutter_actor_paint, NULL);
+  g_list_foreach (priv->children, (GFunc) clutter_actor_paint, paint_context);
 
   CLUTTER_NOTE (PAINT, "ClutterGroup paint leave '%s'",
                 _clutter_actor_get_debug_name (actor));
diff --git a/clutter/clutter/deprecated/clutter-rectangle.c b/clutter/clutter/deprecated/clutter-rectangle.c
index da9f5014f..bd2fc599d 100644
--- a/clutter/clutter/deprecated/clutter-rectangle.c
+++ b/clutter/clutter/deprecated/clutter-rectangle.c
@@ -78,7 +78,8 @@ static const ClutterColor default_border_color = {   0,   0,   0, 255 };
 G_DEFINE_TYPE_WITH_PRIVATE (ClutterRectangle, clutter_rectangle, CLUTTER_TYPE_ACTOR)
 
 static void
-clutter_rectangle_paint (ClutterActor *self)
+clutter_rectangle_paint (ClutterActor        *self,
+                         ClutterPaintContext *paint_context)
 {
   ClutterRectanglePrivate *priv = CLUTTER_RECTANGLE (self)->priv;
   CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
diff --git a/clutter/clutter/meson.build b/clutter/clutter/meson.build
index 567f5fc23..2a2e0a103 100644
--- a/clutter/clutter/meson.build
+++ b/clutter/clutter/meson.build
@@ -58,6 +58,7 @@ clutter_headers = [
   'clutter-mutter.h',
   'clutter-offscreen-effect.h',
   'clutter-page-turn-effect.h',
+  'clutter-paint-context.h',
   'clutter-paint-nodes.h',
   'clutter-paint-node.h',
   'clutter-pan-action.h',
@@ -146,6 +147,7 @@ clutter_sources = [
   'clutter-master-clock-default.c',
   'clutter-offscreen-effect.c',
   'clutter-page-turn-effect.c',
+  'clutter-paint-context.c',
   'clutter-paint-nodes.c',
   'clutter-paint-node.c',
   'clutter-pan-action.c',
@@ -200,6 +202,7 @@ clutter_private_headers = [
   'clutter-master-clock.h',
   'clutter-master-clock-default.h',
   'clutter-offscreen-effect-private.h',
+  'clutter-paint-context-private.h',
   'clutter-paint-node-private.h',
   'clutter-paint-volume-private.h',
   'clutter-private.h',
diff --git a/cogl/tests/conform/test-materials.c b/cogl/tests/conform/test-materials.c
index b6d66ebf9..ef38cd613 100644
--- a/cogl/tests/conform/test-materials.c
+++ b/cogl/tests/conform/test-materials.c
@@ -191,7 +191,9 @@ test_invalid_texture_layers_with_constant_colors (TestState *state,
 }
 
 static void
-on_paint (ClutterActor *actor, TestState *state)
+on_paint (ClutterActor        *actor,
+          ClutterPaintContext *paint_context,
+          TestState           *state)
 {
   test_invalid_texture_layers (state,
                                0, 0 /* position */
diff --git a/cogl/tests/conform/test-multitexture.c b/cogl/tests/conform/test-multitexture.c
index d87a88d2c..5a7a4eca2 100644
--- a/cogl/tests/conform/test-multitexture.c
+++ b/cogl/tests/conform/test-multitexture.c
@@ -99,7 +99,9 @@ make_texture (guchar ref)
 }
 
 static void
-on_paint (ClutterActor *actor, TestState *state)
+on_paint (ClutterActor        *actor,
+          ClutterPaintContext *paint_context,
+          TestState           *state)
 {
   CoglHandle tex0, tex1;
   CoglHandle material;
diff --git a/cogl/tests/conform/test-readpixels.c b/cogl/tests/conform/test-readpixels.c
index 42951dad5..4e861afc4 100644
--- a/cogl/tests/conform/test-readpixels.c
+++ b/cogl/tests/conform/test-readpixels.c
@@ -15,7 +15,9 @@ static const ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff };
 
 
 static void
-on_paint (ClutterActor *actor, void *state)
+on_paint (ClutterActor        *actor,
+          ClutterPaintContext *paint_context,
+          void                *state)
 {
   float saved_viewport[4];
   CoglMatrix saved_projection;
diff --git a/cogl/tests/conform/test-texture-mipmaps.c b/cogl/tests/conform/test-texture-mipmaps.c
index d4edbb1bd..8db876315 100644
--- a/cogl/tests/conform/test-texture-mipmaps.c
+++ b/cogl/tests/conform/test-texture-mipmaps.c
@@ -45,7 +45,9 @@ make_texture (void)
 }
 
 static void
-on_paint (ClutterActor *actor, TestState *state)
+on_paint (ClutterActor        *actor,
+          ClutterPaintContext *paint_context,
+          TestState           *state)
 {
   CoglHandle tex;
   CoglHandle material;
diff --git a/cogl/tests/conform/test-texture-pixmap-x11.c b/cogl/tests/conform/test-texture-pixmap-x11.c
index 4424a60db..d2b9d7ae5 100644
--- a/cogl/tests/conform/test-texture-pixmap-x11.c
+++ b/cogl/tests/conform/test-texture-pixmap-x11.c
@@ -140,7 +140,9 @@ check_paint (TestState *state, int x, int y, int scale)
 #define FRAME_COUNT_UPDATED 8
 
 static void
-on_paint (ClutterActor *actor, TestState *state)
+on_paint (ClutterActor        *actor,
+          ClutterPaintContext *paint_context,
+          TestState           *state)
 {
   CoglHandle material;
 
diff --git a/cogl/tests/conform/test-vertex-buffer-contiguous.c 
b/cogl/tests/conform/test-vertex-buffer-contiguous.c
index 2bc89fa1c..f74e3ac7a 100644
--- a/cogl/tests/conform/test-vertex-buffer-contiguous.c
+++ b/cogl/tests/conform/test-vertex-buffer-contiguous.c
@@ -96,7 +96,9 @@ validate_result (TestState *state)
 }
 
 static void
-on_paint (ClutterActor *actor, TestState *state)
+on_paint (ClutterActor        *actor,
+          ClutterPaintContext *paint_context,
+          TestState           *state)
 {
   /* Draw a faded blue triangle */
   cogl_vertex_buffer_enable (state->buffer, "gl_Color::blue");
diff --git a/cogl/tests/conform/test-vertex-buffer-interleved.c 
b/cogl/tests/conform/test-vertex-buffer-interleved.c
index c1696e97a..057adc94a 100644
--- a/cogl/tests/conform/test-vertex-buffer-interleved.c
+++ b/cogl/tests/conform/test-vertex-buffer-interleved.c
@@ -63,7 +63,9 @@ validate_result (TestState *state)
 }
 
 static void
-on_paint (ClutterActor *actor, TestState *state)
+on_paint (ClutterActor        *actor,
+          ClutterPaintContext *paint_context,
+          TestState           *state)
 {
   /* Draw a faded blue triangle */
   cogl_vertex_buffer_draw (state->buffer,
diff --git a/cogl/tests/conform/test-viewport.c b/cogl/tests/conform/test-viewport.c
index 9d9af0e02..1b2582954 100644
--- a/cogl/tests/conform/test-viewport.c
+++ b/cogl/tests/conform/test-viewport.c
@@ -66,7 +66,9 @@ assert_rectangle_color_and_black_border (int x,
 
 
 static void
-on_paint (ClutterActor *actor, void *state)
+on_paint (ClutterActor        *actor,
+          ClutterPaintContext *paint_context,
+          void                *state)
 {
   float saved_viewport[4];
   CoglMatrix saved_projection;
diff --git a/src/backends/meta-stage.c b/src/backends/meta-stage.c
index b80431bff..939ca809e 100644
--- a/src/backends/meta-stage.c
+++ b/src/backends/meta-stage.c
@@ -184,12 +184,13 @@ notify_watchers_for_mode (MetaStage           *stage,
 }
 
 static void
-meta_stage_paint (ClutterActor *actor)
+meta_stage_paint (ClutterActor        *actor,
+                  ClutterPaintContext *paint_context)
 {
   MetaStage *stage = META_STAGE (actor);
   GList *l;
 
-  CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor);
+  CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor, paint_context);
 
   notify_watchers_for_mode (stage, stage->current_view,
                             META_STAGE_WATCH_AFTER_ACTOR_PAINT);
diff --git a/src/compositor/meta-background-actor.c b/src/compositor/meta-background-actor.c
index 961f6721b..46cf3e9e4 100644
--- a/src/compositor/meta-background-actor.c
+++ b/src/compositor/meta-background-actor.c
@@ -507,7 +507,8 @@ meta_background_actor_get_paint_volume (ClutterActor       *actor,
 }
 
 static void
-meta_background_actor_paint (ClutterActor *actor)
+meta_background_actor_paint (ClutterActor        *actor,
+                             ClutterPaintContext *paint_context)
 {
   MetaBackgroundActor *self = META_BACKGROUND_ACTOR (actor);
   ClutterActorBox actor_box;
diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c
index eccee6eb3..ec02667ac 100644
--- a/src/compositor/meta-shaped-texture.c
+++ b/src/compositor/meta-shaped-texture.c
@@ -716,9 +716,10 @@ select_texture_for_paint (MetaShapedTexture *stex)
 }
 
 static void
-meta_shaped_texture_paint_content (ClutterContent   *content,
-                                   ClutterActor     *actor,
-                                   ClutterPaintNode *root_node)
+meta_shaped_texture_paint_content (ClutterContent      *content,
+                                   ClutterActor        *actor,
+                                   ClutterPaintNode    *root_node,
+                                   ClutterPaintContext *paint_context)
 {
   MetaShapedTexture *stex = META_SHAPED_TEXTURE (content);
   ClutterActorBox alloc;
@@ -1184,6 +1185,7 @@ get_image_via_offscreen (MetaShapedTexture     *stex,
   CoglMatrix projection_matrix;
   cairo_rectangle_int_t fallback_clip;
   ClutterColor clear_color;
+  ClutterPaintContext *paint_context;
   cairo_surface_t *surface;
 
   if (!clip)
@@ -1234,6 +1236,8 @@ get_image_via_offscreen (MetaShapedTexture     *stex,
   root_node = clutter_root_node_new (fb, &clear_color, COGL_BUFFER_BIT_COLOR);
   clutter_paint_node_set_name (root_node, "MetaShapedTexture.offscreen");
 
+  paint_context = clutter_paint_context_new_for_framebuffer (fb);
+
   do_paint_content (stex, root_node,
                     stex->texture,
                     &(ClutterActorBox) {
@@ -1243,7 +1247,8 @@ get_image_via_offscreen (MetaShapedTexture     *stex,
                     },
                     255);
 
-  clutter_paint_node_paint (root_node);
+  clutter_paint_node_paint (root_node, paint_context);
+  clutter_paint_context_destroy (paint_context);
 
   surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
                                         clip->width, clip->height);
diff --git a/src/compositor/meta-surface-actor-wayland.c b/src/compositor/meta-surface-actor-wayland.c
index c91dd8222..0308010f5 100644
--- a/src/compositor/meta-surface-actor-wayland.c
+++ b/src/compositor/meta-surface-actor-wayland.c
@@ -99,7 +99,8 @@ meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor)
 }
 
 static void
-meta_surface_actor_wayland_paint (ClutterActor *actor)
+meta_surface_actor_wayland_paint (ClutterActor        *actor,
+                                  ClutterPaintContext *paint_context)
 {
   MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor);
 
@@ -112,7 +113,8 @@ meta_surface_actor_wayland_paint (ClutterActor *actor)
       wl_list_init (&self->frame_callback_list);
     }
 
-  CLUTTER_ACTOR_CLASS (meta_surface_actor_wayland_parent_class)->paint (actor);
+  CLUTTER_ACTOR_CLASS (meta_surface_actor_wayland_parent_class)->paint (actor,
+                                                                        paint_context);
 }
 
 static void
diff --git a/src/compositor/meta-surface-actor.c b/src/compositor/meta-surface-actor.c
index 5046a70fa..a2f95ef26 100644
--- a/src/compositor/meta-surface-actor.c
+++ b/src/compositor/meta-surface-actor.c
@@ -116,7 +116,8 @@ set_clip_region (MetaSurfaceActor *surface_actor,
 }
 
 static void
-meta_surface_actor_paint (ClutterActor *actor)
+meta_surface_actor_paint (ClutterActor        *actor,
+                          ClutterPaintContext *paint_context)
 {
   MetaSurfaceActor *surface_actor = META_SURFACE_ACTOR (actor);
   MetaSurfaceActorPrivate *priv =
@@ -125,7 +126,8 @@ meta_surface_actor_paint (ClutterActor *actor)
   if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
     return;
 
-  CLUTTER_ACTOR_CLASS (meta_surface_actor_parent_class)->paint (actor);
+  CLUTTER_ACTOR_CLASS (meta_surface_actor_parent_class)->paint (actor,
+                                                                paint_context);
 }
 
 static void
diff --git a/src/compositor/meta-window-actor-x11.c b/src/compositor/meta-window-actor-x11.c
index 2800ffb04..957525ec7 100644
--- a/src/compositor/meta-window-actor-x11.c
+++ b/src/compositor/meta-window-actor-x11.c
@@ -1140,7 +1140,8 @@ meta_window_actor_x11_pre_paint (MetaWindowActor *actor)
 }
 
 static void
-meta_window_actor_x11_paint (ClutterActor *actor)
+meta_window_actor_x11_paint (ClutterActor        *actor,
+                             ClutterPaintContext *paint_context)
 {
   MetaWindowActorX11 *actor_x11 = META_WINDOW_ACTOR_X11 (actor);
   MetaWindow *window;
@@ -1202,7 +1203,8 @@ meta_window_actor_x11_paint (ClutterActor *actor)
         cairo_region_destroy (clip);
     }
 
-  CLUTTER_ACTOR_CLASS (meta_window_actor_x11_parent_class)->paint (actor);
+  CLUTTER_ACTOR_CLASS (meta_window_actor_x11_parent_class)->paint (actor,
+                                                                   paint_context);
 }
 
 static void
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index 6e86424dc..00ba043f9 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -1338,6 +1338,7 @@ meta_window_actor_get_image (MetaWindowActor *self,
   CoglColor clear_color;
   float x, y;
   MetaRectangle scaled_clip;
+  ClutterPaintContext *paint_context;
   cairo_surface_t *surface;
 
   if (!priv->surface)
@@ -1409,7 +1410,9 @@ meta_window_actor_get_image (MetaWindowActor *self,
   cogl_framebuffer_scale (framebuffer, resource_scale, resource_scale, 1);
   cogl_framebuffer_translate (framebuffer, -x, -y, 0);
 
-  clutter_actor_paint (actor);
+  paint_context = clutter_paint_context_new_for_framebuffer (framebuffer);
+  clutter_actor_paint (actor, paint_context);
+  clutter_paint_context_destroy (paint_context);
 
   cogl_pop_framebuffer ();
 
diff --git a/src/compositor/meta-window-group.c b/src/compositor/meta-window-group.c
index b8a33cc30..7d35becf6 100644
--- a/src/compositor/meta-window-group.c
+++ b/src/compositor/meta-window-group.c
@@ -52,7 +52,8 @@ cullable_iface_init (MetaCullableInterface *iface)
 }
 
 static void
-meta_window_group_paint (ClutterActor *actor)
+meta_window_group_paint (ClutterActor        *actor,
+                         ClutterPaintContext *paint_context)
 {
   cairo_region_t *clip_region;
   cairo_region_t *unobscured_region;
@@ -90,7 +91,8 @@ meta_window_group_paint (ClutterActor *actor)
                                               &paint_y_origin) ||
           !meta_actor_is_untransformed (actor, NULL, NULL))
         {
-          CLUTTER_ACTOR_CLASS (meta_window_group_parent_class)->paint (actor);
+          CLUTTER_ACTOR_CLASS (meta_window_group_parent_class)->paint (actor,
+                                                                       paint_context);
           return;
         }
     }
@@ -121,7 +123,8 @@ meta_window_group_paint (ClutterActor *actor)
   cairo_region_destroy (unobscured_region);
   cairo_region_destroy (clip_region);
 
-  CLUTTER_ACTOR_CLASS (meta_window_group_parent_class)->paint (actor);
+  CLUTTER_ACTOR_CLASS (meta_window_group_parent_class)->paint (actor,
+                                                               paint_context);
 
   meta_cullable_reset_culling (META_CULLABLE (window_group));
 }
diff --git a/src/tests/clutter/conform/actor-offscreen-redirect.c 
b/src/tests/clutter/conform/actor-offscreen-redirect.c
index a51509ce8..e10141d9c 100644
--- a/src/tests/clutter/conform/actor-offscreen-redirect.c
+++ b/src/tests/clutter/conform/actor-offscreen-redirect.c
@@ -37,7 +37,8 @@ G_DEFINE_TYPE (FooActor, foo_actor, CLUTTER_TYPE_ACTOR);
 static gboolean group_has_overlaps;
 
 static void
-foo_actor_paint (ClutterActor *actor)
+foo_actor_paint (ClutterActor        *actor,
+                 ClutterPaintContext *paint_context)
 {
   FooActor *foo_actor = (FooActor *) actor;
   ClutterActorBox allocation;
diff --git a/src/tests/clutter/conform/actor-shader-effect.c b/src/tests/clutter/conform/actor-shader-effect.c
index 5cbe51f06..58d0a30b7 100644
--- a/src/tests/clutter/conform/actor-shader-effect.c
+++ b/src/tests/clutter/conform/actor-shader-effect.c
@@ -36,7 +36,8 @@ G_DEFINE_TYPE (FooOldShaderEffect,
                CLUTTER_TYPE_SHADER_EFFECT);
 
 static void
-foo_old_shader_effect_paint_target (ClutterOffscreenEffect *effect)
+foo_old_shader_effect_paint_target (ClutterOffscreenEffect *effect,
+                                    ClutterPaintContext    *paint_context)
 {
   clutter_shader_effect_set_shader_source (CLUTTER_SHADER_EFFECT (effect),
                                            old_shader_effect_source);
@@ -46,7 +47,7 @@ foo_old_shader_effect_paint_target (ClutterOffscreenEffect *effect)
                                      1.0f, 0.0f, 0.0f);
 
   CLUTTER_OFFSCREEN_EFFECT_CLASS (foo_old_shader_effect_parent_class)->
-    paint_target (effect);
+    paint_target (effect, paint_context);
 }
 
 static void
@@ -110,7 +111,8 @@ foo_new_shader_effect_get_static_source (ClutterShaderEffect *effect)
 }
 
 static void
-foo_new_shader_effect_paint_target (ClutterOffscreenEffect *effect)
+foo_new_shader_effect_paint_target (ClutterOffscreenEffect *effect,
+                                    ClutterPaintContext    *paint_context)
 {
   clutter_shader_effect_set_uniform (CLUTTER_SHADER_EFFECT (effect),
                                      "override_color",
@@ -118,7 +120,7 @@ foo_new_shader_effect_paint_target (ClutterOffscreenEffect *effect)
                                      0.0f, 1.0f, 0.0f);
 
   CLUTTER_OFFSCREEN_EFFECT_CLASS (foo_new_shader_effect_parent_class)->
-    paint_target (effect);
+    paint_target (effect, paint_context);
 }
 
 static void
diff --git a/src/tests/clutter/conform/binding-pool.c b/src/tests/clutter/conform/binding-pool.c
index 7c9bbc1a1..849b12c1f 100644
--- a/src/tests/clutter/conform/binding-pool.c
+++ b/src/tests/clutter/conform/binding-pool.c
@@ -132,7 +132,8 @@ key_group_key_press (ClutterActor    *actor,
 }
 
 static void
-key_group_paint (ClutterActor *actor)
+key_group_paint (ClutterActor        *actor,
+                 ClutterPaintContext *paint_context)
 {
   KeyGroup *self = KEY_GROUP (actor);
   ClutterActorIter iter;
@@ -158,7 +159,7 @@ key_group_paint (ClutterActor *actor)
           cogl_rectangle (box.x1, box.y1, box.x2, box.y2);
         }
 
-      clutter_actor_paint (child);
+      clutter_actor_paint (child, paint_context);
     }
 }
 
diff --git a/src/tests/clutter/conform/text-cache.c b/src/tests/clutter/conform/text-cache.c
index 6b4bddf78..748101eab 100644
--- a/src/tests/clutter/conform/text-cache.c
+++ b/src/tests/clutter/conform/text-cache.c
@@ -28,7 +28,9 @@ struct _CallbackData
 };
 
 static void
-on_paint (ClutterActor *stage, CallbackData *data)
+on_paint (ClutterActor        *stage,
+          ClutterPaintContext *paint_context,
+          CallbackData        *data)
 {
   PangoLayout *new_layout;
 
diff --git a/src/tests/clutter/interactive/test-binding-pool.c 
b/src/tests/clutter/interactive/test-binding-pool.c
index b33eebd42..330ea89e4 100644
--- a/src/tests/clutter/interactive/test-binding-pool.c
+++ b/src/tests/clutter/interactive/test-binding-pool.c
@@ -150,7 +150,8 @@ key_group_key_press (ClutterActor    *actor,
 }
 
 static void
-key_group_paint (ClutterActor *actor)
+key_group_paint (ClutterActor        *actor,
+                 ClutterPaintContext *paint_context)
 {
   KeyGroup *self = KEY_GROUP (actor);
   ClutterActorIter iter;
@@ -176,7 +177,7 @@ key_group_paint (ClutterActor *actor)
           cogl_rectangle (box.x1, box.y1, box.x2, box.y2);
         }
 
-      clutter_actor_paint (child);
+      clutter_actor_paint (child, paint_context);
 
       i += 1;
     }
diff --git a/src/tests/clutter/interactive/test-cogl-multitexture.c 
b/src/tests/clutter/interactive/test-cogl-multitexture.c
index e877d2b73..de2b17d2c 100644
--- a/src/tests/clutter/interactive/test-cogl-multitexture.c
+++ b/src/tests/clutter/interactive/test-cogl-multitexture.c
@@ -55,7 +55,9 @@ frame_cb (ClutterTimeline  *timeline,
 }
 
 static void
-material_rectangle_paint (ClutterActor *actor, gpointer data)
+material_rectangle_paint (ClutterActor        *actor,
+                          ClutterPaintContext *paint_context,
+                          gpointer             data)
 {
   TestMultiLayerMaterialState *state = data;
 
diff --git a/src/tests/clutter/interactive/test-cogl-offscreen.c 
b/src/tests/clutter/interactive/test-cogl-offscreen.c
index b06e6d7f3..2720679c0 100644
--- a/src/tests/clutter/interactive/test-cogl-offscreen.c
+++ b/src/tests/clutter/interactive/test-cogl-offscreen.c
@@ -83,7 +83,8 @@ G_DEFINE_TYPE_WITH_PRIVATE (TestCoglbox, test_coglbox, CLUTTER_TYPE_ACTOR);
  *--------------------------------------------------*/
 
 static void
-test_coglbox_paint (ClutterActor *self)
+test_coglbox_paint (ClutterActor        *self,
+                    ClutterPaintContext *paint_context)
 {
   TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (self);
   gfloat texcoords[4] = { 0, 0, 1, 1 };
diff --git a/src/tests/clutter/interactive/test-cogl-point-sprites.c 
b/src/tests/clutter/interactive/test-cogl-point-sprites.c
index 9cca9df78..453d6fffe 100644
--- a/src/tests/clutter/interactive/test-cogl-point-sprites.c
+++ b/src/tests/clutter/interactive/test-cogl-point-sprites.c
@@ -95,7 +95,9 @@ generate_round_texture (void)
 }
 
 static void
-paint_cb (ClutterActor *stage, Data *data)
+paint_cb (ClutterActor        *stage,
+          ClutterPaintContext *paint_context,
+          Data                *data)
 {
   CoglMatrix old_matrix, new_matrix;
   int i;
diff --git a/src/tests/clutter/interactive/test-cogl-tex-convert.c 
b/src/tests/clutter/interactive/test-cogl-tex-convert.c
index 0e975a8c1..799ab7bb3 100644
--- a/src/tests/clutter/interactive/test-cogl-tex-convert.c
+++ b/src/tests/clutter/interactive/test-cogl-tex-convert.c
@@ -82,7 +82,8 @@ G_DEFINE_TYPE_WITH_PRIVATE (TestCoglbox, test_coglbox, CLUTTER_TYPE_ACTOR);
  *--------------------------------------------------*/
 
 static void
-test_coglbox_paint(ClutterActor *self)
+test_coglbox_paint (ClutterActor        *self,
+                    ClutterPaintContext *paint_context)
 {
   TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (self);
   gfloat texcoords[4] = { 0.0, 0.0, 1.0, 1.0 };
diff --git a/src/tests/clutter/interactive/test-cogl-tex-polygon.c 
b/src/tests/clutter/interactive/test-cogl-tex-polygon.c
index 3eb5d574c..904092a59 100644
--- a/src/tests/clutter/interactive/test-cogl-tex-polygon.c
+++ b/src/tests/clutter/interactive/test-cogl-tex-polygon.c
@@ -166,7 +166,8 @@ test_coglbox_triangle_texture (int    tex_width,
 }
 
 static void
-test_coglbox_paint (ClutterActor *self)
+test_coglbox_paint (ClutterActor        *self,
+                    ClutterPaintContext *paint_context)
 {
   TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (self);
   CoglHandle tex_handle = priv->use_sliced ? priv->sliced_tex
diff --git a/src/tests/clutter/interactive/test-cogl-tex-tile.c 
b/src/tests/clutter/interactive/test-cogl-tex-tile.c
index 518e4f0f6..94fa3c199 100644
--- a/src/tests/clutter/interactive/test-cogl-tex-tile.c
+++ b/src/tests/clutter/interactive/test-cogl-tex-tile.c
@@ -83,7 +83,8 @@ G_DEFINE_TYPE_WITH_PRIVATE (TestCoglbox, test_coglbox, CLUTTER_TYPE_ACTOR);
  *--------------------------------------------------*/
 
 static void
-test_coglbox_paint (ClutterActor *self)
+test_coglbox_paint (ClutterActor        *self,
+                    ClutterPaintContext *paint_context)
 {
   TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (self);
   gfloat texcoords[4] = { 0.0f, 0.0f, 1.0f, 1.0f };
diff --git a/src/tests/clutter/interactive/test-cogl-vertex-buffer.c 
b/src/tests/clutter/interactive/test-cogl-vertex-buffer.c
index 65ae9d3c6..33dbbc3e1 100644
--- a/src/tests/clutter/interactive/test-cogl-vertex-buffer.c
+++ b/src/tests/clutter/interactive/test-cogl-vertex-buffer.c
@@ -145,7 +145,9 @@ frame_cb (ClutterTimeline *timeline,
 }
 
 static void
-on_paint (ClutterActor *actor, TestState *state)
+on_paint (ClutterActor        *actor,
+          ClutterPaintContext *paint_context,
+          TestState           *state)
 {
   cogl_set_source_color4ub (0xff, 0x00, 0x00, 0xff);
   cogl_vertex_buffer_draw_elements (state->buffer,
diff --git a/src/tests/clutter/interactive/test-content.c b/src/tests/clutter/interactive/test-content.c
index fa0ac3a2f..ede6db591 100644
--- a/src/tests/clutter/interactive/test-content.c
+++ b/src/tests/clutter/interactive/test-content.c
@@ -32,9 +32,10 @@ G_DEFINE_TYPE_WITH_CODE (ColorContent, color_content, G_TYPE_OBJECT,
                                                 clutter_content_iface_init))
 
 static void
-color_content_paint_content (ClutterContent   *content,
-                             ClutterActor     *actor,
-                             ClutterPaintNode *root)
+color_content_paint_content (ClutterContent      *content,
+                             ClutterActor        *actor,
+                             ClutterPaintNode    *root,
+                             ClutterPaintContext *paint_context)
 {
   ColorContent *self = (ColorContent *) content;
   ClutterActorBox box, content_box;
diff --git a/src/tests/clutter/interactive/test-image.c b/src/tests/clutter/interactive/test-image.c
index a3dc28c26..81fd3c36d 100644
--- a/src/tests/clutter/interactive/test-image.c
+++ b/src/tests/clutter/interactive/test-image.c
@@ -33,9 +33,10 @@ G_DEFINE_TYPE_WITH_CODE (SolidContent, solid_content, G_TYPE_OBJECT,
                                                 clutter_content_iface_init))
 
 static void
-solid_content_paint_content (ClutterContent   *content,
-                             ClutterActor     *actor,
-                             ClutterPaintNode *root)
+solid_content_paint_content (ClutterContent      *content,
+                             ClutterActor        *actor,
+                             ClutterPaintNode    *root,
+                             ClutterPaintContext *paint_context)
 {
   SolidContent *self = (SolidContent *) content;
   ClutterActorBox box, content_box;
diff --git a/src/tests/clutter/interactive/test-paint-wrapper.c 
b/src/tests/clutter/interactive/test-paint-wrapper.c
index a08a33d1b..47eb50ca5 100644
--- a/src/tests/clutter/interactive/test-paint-wrapper.c
+++ b/src/tests/clutter/interactive/test-paint-wrapper.c
@@ -144,8 +144,9 @@ frame_cb (ClutterTimeline *timeline,
 }
 
 static void
-hand_pre_paint (ClutterActor *actor,
-                gpointer      user_data)
+hand_pre_paint (ClutterActor        *actor,
+                ClutterPaintContext *paint_context,
+                gpointer             user_data)
 {
   SuperOH *oh = user_data;
   gfloat w, h;
@@ -165,8 +166,9 @@ hand_pre_paint (ClutterActor *actor,
 }
 
 static void
-hand_post_paint (ClutterActor *actor,
-                 gpointer      user_data)
+hand_post_paint (ClutterActor        *actor,
+                 ClutterPaintContext *paint_context,
+                 gpointer             user_data)
 {
   SuperOH *oh = user_data;
   gfloat w, h;
diff --git a/src/tests/clutter/micro-bench/test-cogl-perf.c b/src/tests/clutter/micro-bench/test-cogl-perf.c
index 0b92219c5..09fb549cf 100644
--- a/src/tests/clutter/micro-bench/test-cogl-perf.c
+++ b/src/tests/clutter/micro-bench/test-cogl-perf.c
@@ -98,7 +98,9 @@ TestCallback tests[] =
 };
 
 static void
-on_paint (ClutterActor *actor, TestState *state)
+on_paint (ClutterActor        *actor,
+          ClutterPaintContext *paint_context,
+          TestState           *state)
 {
   tests[state->current_test] (state);
 }
diff --git a/src/tests/clutter/micro-bench/test-picking.c b/src/tests/clutter/micro-bench/test-picking.c
index 845e600d9..942e161f7 100644
--- a/src/tests/clutter/micro-bench/test-picking.c
+++ b/src/tests/clutter/micro-bench/test-picking.c
@@ -54,7 +54,9 @@ do_events (ClutterActor *stage)
 }
 
 static void
-on_paint (ClutterActor *stage, gconstpointer *data)
+on_paint (ClutterActor        *stage,
+          ClutterPaintContext *paint_context,
+          gconstpointer       *data)
 {
   do_events (stage);
 }
diff --git a/src/tests/clutter/micro-bench/test-text-perf.c b/src/tests/clutter/micro-bench/test-text-perf.c
index 710c83e27..76084c4ff 100644
--- a/src/tests/clutter/micro-bench/test-text-perf.c
+++ b/src/tests/clutter/micro-bench/test-text-perf.c
@@ -11,7 +11,9 @@ static int n_chars;
 static int rows, cols;
 
 static void
-on_paint (ClutterActor *actor, gconstpointer *data)
+on_paint (ClutterActor        *actor,
+          ClutterPaintContext *paint_context,
+          gconstpointer       *data)
 {
   static GTimer *timer = NULL;
   static int fps = 0;
diff --git a/src/tests/clutter/micro-bench/test-text.c b/src/tests/clutter/micro-bench/test-text.c
index d79bfd65a..18bd841eb 100644
--- a/src/tests/clutter/micro-bench/test-text.c
+++ b/src/tests/clutter/micro-bench/test-text.c
@@ -10,7 +10,9 @@
 #define ROWS 20
 
 static void
-on_paint (ClutterActor *actor, gconstpointer *data)
+on_paint (ClutterActor        *actor,
+          ClutterPaintContext *paint_context,
+          gconstpointer       *data)
 {
   static GTimer *timer = NULL;
   static int fps = 0;
diff --git a/src/tests/clutter/performance/test-common.h b/src/tests/clutter/performance/test-common.h
index 8c07389aa..aae2b3cd3 100644
--- a/src/tests/clutter/performance/test-common.h
+++ b/src/tests/clutter/performance/test-common.h
@@ -25,7 +25,9 @@ clutter_perf_fps_init (void)
   g_random_set_seed (12345678);
 }
 
-static void perf_stage_paint_cb (ClutterStage *stage, gpointer *data);
+static void perf_stage_paint_cb (ClutterStage        *stage,
+                                 ClutterPaintContext *paint_context,
+                                 gpointer            *data);
 static gboolean perf_fake_mouse_cb (gpointer stage);
 
 static inline void
@@ -47,7 +49,10 @@ clutter_perf_fps_report (const gchar *id)
        id, testframes / g_timer_elapsed (testtimer, NULL));
 }
 
-static void perf_stage_paint_cb (ClutterStage *stage, gpointer *data)
+static void
+perf_stage_paint_cb (ClutterStage        *stage,
+                     ClutterPaintContext *paint_context,
+                     gpointer            *data)
 {
   if (!testtimer)
     testtimer = g_timer_new ();



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