[mutter] clutter: Move redraw clip management to views



commit 159c83b9145596f917003a4a8f47b9f30c6ed3cb
Author: Jonas Ådahl <jadahl gmail com>
Date:   Thu Feb 6 10:12:54 2020 +0100

    clutter: Move redraw clip management to views
    
    The stage window handled the redraw clip in a global manner; this would
    interfere if we want to paint views individually as it'd mean
    intersecting views (i.e. mirrored monitors) would loose the redraw clip
    once the first view was painted. It also is awkward to have a global
    state for something that is built up before redrawing, and only really
    valid during paint, due to buffer damage history.
    
    This commits removes all redraw clip management from the stage window,
    moving it all into the stage views. When a redraw clip is added to the
    stage, every affected view will get the same redraw clip added to it,
    and eventually when painted, the stage window (ClutterStageCogl) will
    retrieve the redraw clip for each view as it repaints them.
    
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/1042

 clutter/clutter/clutter-private.h            |   3 +
 clutter/clutter/clutter-stage-view-private.h |  12 ++-
 clutter/clutter/clutter-stage-view.c         |  86 ++++++++++++++++
 clutter/clutter/clutter-stage-window.c       |  71 -------------
 clutter/clutter/clutter-stage-window.h       |  12 ---
 clutter/clutter/clutter-stage.c              |  73 ++++++++++---
 clutter/clutter/clutter-util.c               |  10 ++
 clutter/clutter/cogl/clutter-stage-cogl.c    | 147 +++++----------------------
 clutter/clutter/cogl/clutter-stage-cogl.h    |   8 --
 9 files changed, 190 insertions(+), 232 deletions(-)
---
diff --git a/clutter/clutter/clutter-private.h b/clutter/clutter/clutter-private.h
index 94575f06b..e2a139f07 100644
--- a/clutter/clutter/clutter-private.h
+++ b/clutter/clutter/clutter-private.h
@@ -248,6 +248,9 @@ gboolean _clutter_util_rectangle_intersection (const cairo_rectangle_int_t *src1
                                                const cairo_rectangle_int_t *src2,
                                                cairo_rectangle_int_t       *dest);
 
+gboolean clutter_util_rectangle_equal (const cairo_rectangle_int_t *src1,
+                                       const cairo_rectangle_int_t *src2);
+
 
 struct _ClutterVertex4
 {
diff --git a/clutter/clutter/clutter-stage-view-private.h b/clutter/clutter/clutter-stage-view-private.h
index c63b62256..3b0d419fc 100644
--- a/clutter/clutter/clutter-stage-view-private.h
+++ b/clutter/clutter/clutter-stage-view-private.h
@@ -32,7 +32,15 @@ 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);
+void clutter_stage_view_add_redraw_clip (ClutterStageView            *view,
+                                         const cairo_rectangle_int_t *clip);
+
+gboolean clutter_stage_view_has_full_redraw_clip (ClutterStageView *view);
+
+gboolean clutter_stage_view_has_redraw_clip (ClutterStageView *view);
+
+const cairo_region_t * clutter_stage_view_peek_redraw_clip (ClutterStageView *view);
+
+cairo_region_t * clutter_stage_view_take_redraw_clip (ClutterStageView *view);
 
 #endif /* __CLUTTER_STAGE_VIEW_PRIVATE_H__ */
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
index 1fa7c5771..d93cf573f 100644
--- a/clutter/clutter/clutter-stage-view.c
+++ b/clutter/clutter/clutter-stage-view.c
@@ -23,6 +23,8 @@
 #include <cairo-gobject.h>
 #include <math.h>
 
+#include "clutter/clutter-private.h"
+
 enum
 {
   PROP_0,
@@ -50,6 +52,9 @@ typedef struct _ClutterStageViewPrivate
   CoglOffscreen *shadowfb;
   CoglPipeline *shadowfb_pipeline;
 
+  gboolean has_redraw_clip;
+  cairo_region_t *redraw_clip;
+
   guint dirty_viewport   : 1;
   guint dirty_projection : 1;
 } ClutterStageViewPrivate;
@@ -302,6 +307,86 @@ clutter_stage_view_get_offscreen_transformation_matrix (ClutterStageView *view,
   view_class->get_offscreen_transformation_matrix (view, matrix);
 }
 
+void
+clutter_stage_view_add_redraw_clip (ClutterStageView            *view,
+                                    const cairo_rectangle_int_t *clip)
+{
+  ClutterStageViewPrivate *priv =
+    clutter_stage_view_get_instance_private (view);
+
+  if (priv->has_redraw_clip && !priv->redraw_clip)
+    return;
+
+  if (!clip)
+    {
+      g_clear_pointer (&priv->redraw_clip, cairo_region_destroy);
+      priv->has_redraw_clip = TRUE;
+      return;
+    }
+
+  if (clip->width == 0 || clip->height == 0)
+    return;
+
+  if (!priv->redraw_clip)
+    {
+      if (!clutter_util_rectangle_equal (&priv->layout, clip))
+        priv->redraw_clip = cairo_region_create_rectangle (clip);
+    }
+  else
+    {
+      cairo_region_union_rectangle (priv->redraw_clip, clip);
+
+      if (cairo_region_num_rectangles (priv->redraw_clip) == 1)
+        {
+          cairo_rectangle_int_t redraw_clip_extents;
+
+          cairo_region_get_extents (priv->redraw_clip, &redraw_clip_extents);
+          if (clutter_util_rectangle_equal (&priv->layout, &redraw_clip_extents))
+            g_clear_pointer (&priv->redraw_clip, cairo_region_destroy);
+        }
+    }
+
+  priv->has_redraw_clip = TRUE;
+}
+
+gboolean
+clutter_stage_view_has_redraw_clip (ClutterStageView *view)
+{
+  ClutterStageViewPrivate *priv =
+    clutter_stage_view_get_instance_private (view);
+
+  return priv->has_redraw_clip;
+}
+
+gboolean
+clutter_stage_view_has_full_redraw_clip (ClutterStageView *view)
+{
+  ClutterStageViewPrivate *priv =
+    clutter_stage_view_get_instance_private (view);
+
+  return priv->has_redraw_clip && !priv->redraw_clip;
+}
+
+const cairo_region_t *
+clutter_stage_view_peek_redraw_clip (ClutterStageView *view)
+{
+  ClutterStageViewPrivate *priv =
+    clutter_stage_view_get_instance_private (view);
+
+  return priv->redraw_clip;
+}
+
+cairo_region_t *
+clutter_stage_view_take_redraw_clip (ClutterStageView *view)
+{
+  ClutterStageViewPrivate *priv =
+    clutter_stage_view_get_instance_private (view);
+
+  priv->has_redraw_clip = FALSE;
+
+  return g_steal_pointer (&priv->redraw_clip);
+}
+
 void
 clutter_stage_view_transform_to_onscreen (ClutterStageView *view,
                                           gfloat           *x,
@@ -414,6 +499,7 @@ clutter_stage_view_dispose (GObject *object)
   g_clear_pointer (&priv->offscreen, cogl_object_unref);
   g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref);
   g_clear_pointer (&priv->shadowfb_pipeline, cogl_object_unref);
+  g_clear_pointer (&priv->redraw_clip, cairo_region_destroy);
 
   G_OBJECT_CLASS (clutter_stage_view_parent_class)->dispose (object);
 }
diff --git a/clutter/clutter/clutter-stage-window.c b/clutter/clutter/clutter-stage-window.c
index 68a763d44..3c80124a9 100644
--- a/clutter/clutter/clutter-stage-window.c
+++ b/clutter/clutter/clutter-stage-window.c
@@ -178,77 +178,6 @@ _clutter_stage_window_clear_update_time (ClutterStageWindow *window)
   iface->clear_update_time (window);
 }
 
-void
-_clutter_stage_window_add_redraw_clip (ClutterStageWindow    *window,
-                                       cairo_rectangle_int_t *stage_clip)
-{
-  ClutterStageWindowInterface *iface;
-
-  g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window));
-
-  iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
-  if (iface->add_redraw_clip != NULL)
-    iface->add_redraw_clip (window, stage_clip);
-}
-
-/* Determines if the backend will clip the rendering of the next
- * frame.
- *
- * Note: at the start of each new frame there is an implied clip that
- * clips everything (i.e. nothing would be drawn) so this function
- * will return True at the start of a new frame if the backend
- * supports clipped redraws.
- */
-gboolean
-_clutter_stage_window_has_redraw_clips (ClutterStageWindow *window)
-{
-  ClutterStageWindowInterface *iface;
-
-  g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), FALSE);
-
-  iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
-  if (iface->has_redraw_clips != NULL)
-    return iface->has_redraw_clips (window);
-
-  return FALSE;
-}
-
-/* Determines if the backend will discard any additional redraw clips
- * and instead promote them to a full stage redraw.
- *
- * The ideas is that backend may have some heuristics that cause it to
- * give up tracking redraw clips so this can be used to avoid the cost
- * of calculating a redraw clip when we know it's going to be ignored
- * anyway.
- */
-gboolean
-_clutter_stage_window_ignoring_redraw_clips (ClutterStageWindow *window)
-{
-  ClutterStageWindowInterface *iface;
-
-  g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), FALSE);
-
-  iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
-  if (iface->ignoring_redraw_clips != NULL)
-    return iface->ignoring_redraw_clips (window);
-
-  return TRUE;
-}
-
-cairo_region_t *
-_clutter_stage_window_get_redraw_clip (ClutterStageWindow *window)
-{
-  ClutterStageWindowInterface *iface;
-
-  g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), FALSE);
-
-  iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
-  if (iface->get_redraw_clip != NULL)
-    return iface->get_redraw_clip (window);
-
-  return NULL;
-}
-
 void
 _clutter_stage_window_set_accept_focus (ClutterStageWindow *window,
                                         gboolean            accept_focus)
diff --git a/clutter/clutter/clutter-stage-window.h b/clutter/clutter/clutter-stage-window.h
index c99e9594d..eb529416e 100644
--- a/clutter/clutter/clutter-stage-window.h
+++ b/clutter/clutter/clutter-stage-window.h
@@ -51,12 +51,6 @@ struct _ClutterStageWindowInterface
   gint64            (* get_update_time)         (ClutterStageWindow *stage_window);
   void              (* clear_update_time)       (ClutterStageWindow *stage_window);
 
-  void              (* add_redraw_clip)         (ClutterStageWindow    *stage_window,
-                                                 cairo_rectangle_int_t *stage_rectangle);
-  gboolean          (* has_redraw_clips)        (ClutterStageWindow    *stage_window);
-  gboolean          (* ignoring_redraw_clips)   (ClutterStageWindow    *stage_window);
-  cairo_region_t *  (* get_redraw_clip)         (ClutterStageWindow    *stage_window);
-
   void              (* set_accept_focus)        (ClutterStageWindow *stage_window,
                                                  gboolean            accept_focus);
 
@@ -94,12 +88,6 @@ void              _clutter_stage_window_schedule_update         (ClutterStageWin
 gint64            _clutter_stage_window_get_update_time         (ClutterStageWindow *window);
 void              _clutter_stage_window_clear_update_time       (ClutterStageWindow *window);
 
-void              _clutter_stage_window_add_redraw_clip         (ClutterStageWindow    *window,
-                                                                 cairo_rectangle_int_t *stage_clip);
-gboolean          _clutter_stage_window_has_redraw_clips        (ClutterStageWindow    *window);
-gboolean          _clutter_stage_window_ignoring_redraw_clips   (ClutterStageWindow    *window);
-cairo_region_t *  _clutter_stage_window_get_redraw_clip         (ClutterStageWindow    *window);
-
 void              _clutter_stage_window_set_accept_focus        (ClutterStageWindow *window,
                                                                  gboolean            accept_focus);
 
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index ff7fed3bc..80061bba7 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -557,6 +557,33 @@ pick_record_contains_point (ClutterStage     *stage,
   return TRUE;
 }
 
+static void
+clutter_stage_add_redraw_clip (ClutterStage          *stage,
+                               cairo_rectangle_int_t *clip)
+{
+  GList *l;
+
+  for (l = _clutter_stage_peek_stage_views (stage); l; l = l->next)
+    {
+      ClutterStageView *view = l->data;
+
+      if (!clip)
+        {
+          clutter_stage_view_add_redraw_clip (view, NULL);
+        }
+      else
+        {
+          cairo_rectangle_int_t view_layout;
+          cairo_rectangle_int_t intersection;
+
+          clutter_stage_view_get_layout (view, &view_layout);
+          if (_clutter_util_rectangle_intersection (&view_layout, clip,
+                                                    &intersection))
+            clutter_stage_view_add_redraw_clip (view, &intersection);
+        }
+    }
+}
+
 static inline void
 queue_full_redraw (ClutterStage *stage)
 {
@@ -575,7 +602,7 @@ queue_full_redraw (ClutterStage *stage)
   if (stage_window == NULL)
     return;
 
-  _clutter_stage_window_add_redraw_clip (stage_window, NULL);
+  clutter_stage_add_redraw_clip (stage, NULL);
 }
 
 static gboolean
@@ -1413,16 +1440,12 @@ clutter_stage_do_redraw (ClutterStage *stage)
 static GSList *
 _clutter_stage_check_updated_pointers (ClutterStage *stage)
 {
-  ClutterStagePrivate *priv = stage->priv;
   ClutterBackend *backend;
   ClutterSeat *seat;
   GSList *updating = NULL;
   GList *l, *devices;
-  cairo_region_t *clip;
   graphene_point_t point;
 
-  clip = _clutter_stage_window_get_redraw_clip (priv->impl);
-
   backend = clutter_get_default_backend ();
   seat = clutter_backend_get_default_seat (backend);
   devices = clutter_seat_list_devices (seat);
@@ -1430,6 +1453,8 @@ _clutter_stage_check_updated_pointers (ClutterStage *stage)
   for (l = devices; l; l = l->next)
     {
       ClutterInputDevice *dev = l->data;
+      ClutterStageView *view;
+      const cairo_region_t *clip;
 
       if (clutter_input_device_get_device_mode (dev) !=
           CLUTTER_INPUT_MODE_MASTER)
@@ -1445,6 +1470,11 @@ _clutter_stage_check_updated_pointers (ClutterStage *stage)
           if (!clutter_input_device_get_coords (dev, NULL, &point))
             continue;
 
+          view = clutter_stage_get_view_at (stage, point.x, point.y);
+          if (!view)
+            continue;
+
+          clip = clutter_stage_view_peek_redraw_clip (view);
           if (!clip || cairo_region_contains_point (clip, point.x, point.y))
             updating = g_slist_prepend (updating, dev);
           break;
@@ -1554,6 +1584,22 @@ clutter_stage_real_queue_relayout (ClutterActor *self)
   parent_class->queue_relayout (self);
 }
 
+static gboolean
+is_full_stage_redraw_queued (ClutterStage *stage)
+{
+  GList *l;
+
+  for (l = _clutter_stage_peek_stage_views (stage); l; l = l->next)
+    {
+      ClutterStageView *view = l->data;
+
+      if (!clutter_stage_view_has_full_redraw_clip (view))
+        return FALSE;
+    }
+
+  return TRUE;
+}
+
 static gboolean
 clutter_stage_real_queue_redraw (ClutterActor       *actor,
                                  ClutterActor       *leaf,
@@ -1575,12 +1621,12 @@ clutter_stage_real_queue_redraw (ClutterActor       *actor,
   if (stage_window == NULL)
     return TRUE;
 
-  if (_clutter_stage_window_ignoring_redraw_clips (stage_window))
+  if (is_full_stage_redraw_queued (stage))
     return FALSE;
 
   if (redraw_clip == NULL)
     {
-      _clutter_stage_window_add_redraw_clip (stage_window, NULL);
+      clutter_stage_add_redraw_clip (stage, NULL);
       return FALSE;
     }
 
@@ -1612,23 +1658,20 @@ clutter_stage_real_queue_redraw (ClutterActor       *actor,
   stage_clip.width = intersection_box.x2 - stage_clip.x;
   stage_clip.height = intersection_box.y2 - stage_clip.y;
 
-  _clutter_stage_window_add_redraw_clip (stage_window, &stage_clip);
+  clutter_stage_add_redraw_clip (stage, &stage_clip);
   return FALSE;
 }
 
 gboolean
 _clutter_stage_has_full_redraw_queued (ClutterStage *stage)
 {
-  ClutterStageWindow *stage_window = _clutter_stage_get_window (stage);
-
-  if (CLUTTER_ACTOR_IN_DESTRUCTION (stage) || stage_window == NULL)
+  if (CLUTTER_ACTOR_IN_DESTRUCTION (stage))
     return FALSE;
 
-  if (stage->priv->redraw_pending &&
-      !_clutter_stage_window_has_redraw_clips (stage_window))
-    return TRUE;
-  else
+  if (!stage->priv->redraw_pending)
     return FALSE;
+
+  return is_full_stage_redraw_queued (stage);
 }
 
 static ClutterActor *
diff --git a/clutter/clutter/clutter-util.c b/clutter/clutter/clutter-util.c
index 885851240..6e59889a8 100644
--- a/clutter/clutter/clutter-util.c
+++ b/clutter/clutter/clutter-util.c
@@ -214,6 +214,16 @@ _clutter_util_rectangle_intersection (const cairo_rectangle_int_t *src1,
     }
 }
 
+gboolean
+clutter_util_rectangle_equal (const cairo_rectangle_int_t *src1,
+                              const cairo_rectangle_int_t *src2)
+{
+  return ((src1->x == src2->x) &&
+          (src1->y == src2->y) &&
+          (src1->width == src2->width) &&
+          (src1->height == src2->height));
+}
+
 float
 _clutter_util_matrix_determinant (const ClutterMatrix *matrix)
 {
diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c
index dcee3d4b8..36d1531cc 100644
--- a/clutter/clutter/cogl/clutter-stage-cogl.c
+++ b/clutter/clutter/cogl/clutter-stage-cogl.c
@@ -290,97 +290,6 @@ clutter_stage_cogl_resize (ClutterStageWindow *stage_window,
 {
 }
 
-static gboolean
-clutter_stage_cogl_has_redraw_clips (ClutterStageWindow *stage_window)
-{
-  ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
-
-  /* NB: at the start of each new frame there is an implied clip that
-   * clips everything (i.e. nothing would be drawn) so we need to make
-   * sure we return True in the un-initialized case here.
-   */
-  if (!stage_cogl->initialized_redraw_clip ||
-      (stage_cogl->initialized_redraw_clip &&
-       stage_cogl->redraw_clip))
-    return TRUE;
-  else
-    return FALSE;
-}
-
-static gboolean
-clutter_stage_cogl_ignoring_redraw_clips (ClutterStageWindow *stage_window)
-{
-  ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
-
-  /* NB: a NULL clip means a full stage redraw is required */
-  if (stage_cogl->initialized_redraw_clip &&
-      !stage_cogl->redraw_clip)
-    return TRUE;
-  else
-    return FALSE;
-}
-
-/* A redraw clip represents (in stage coordinates) the bounding box of
- * something that needs to be redrawn. Typically they are added to the
- * StageWindow as a result of clutter_actor_queue_clipped_redraw() by
- * actors such as ClutterGLXTexturePixmap. All redraw clips are
- * discarded after the next paint.
- *
- * A NULL stage_clip means the whole stage needs to be redrawn.
- *
- * What we do with this information:
- * - we keep track of the bounding box for all redraw clips
- * - when we come to redraw; we scissor the redraw to that box and use
- *   glBlitFramebuffer to present the redraw to the front
- *   buffer.
- */
-static void
-clutter_stage_cogl_add_redraw_clip (ClutterStageWindow    *stage_window,
-                                    cairo_rectangle_int_t *stage_clip)
-{
-  ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
-
-  /* If we are already forced to do a full stage redraw then bail early */
-  if (clutter_stage_cogl_ignoring_redraw_clips (stage_window))
-    return;
-
-  /* A NULL stage clip means a full stage redraw has been queued and
-   * we keep track of this by setting a NULL redraw_clip.
-   */
-  if (stage_clip == NULL)
-    {
-      g_clear_pointer (&stage_cogl->redraw_clip, cairo_region_destroy);
-      stage_cogl->initialized_redraw_clip = TRUE;
-      return;
-    }
-
-  /* Ignore requests to add degenerate/empty clip rectangles */
-  if (stage_clip->width == 0 || stage_clip->height == 0)
-    return;
-
-  if (!stage_cogl->redraw_clip)
-    {
-      stage_cogl->redraw_clip = cairo_region_create_rectangle (stage_clip);
-    }
-  else
-    {
-      cairo_region_union_rectangle (stage_cogl->redraw_clip, stage_clip);
-    }
-
-  stage_cogl->initialized_redraw_clip = TRUE;
-}
-
-static cairo_region_t *
-clutter_stage_cogl_get_redraw_clip (ClutterStageWindow *stage_window)
-{
-  ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
-
-  if (stage_cogl->using_clipped_redraw && stage_cogl->redraw_clip)
-    return cairo_region_copy (stage_cogl->redraw_clip);
-
-  return NULL;
-}
-
 static inline gboolean
 valid_buffer_age (ClutterStageViewCogl *view_cogl,
                   int                   age)
@@ -397,7 +306,8 @@ valid_buffer_age (ClutterStageViewCogl *view_cogl,
 static void
 paint_damage_region (ClutterStageWindow *stage_window,
                      ClutterStageView   *view,
-                     cairo_region_t     *swap_region)
+                     cairo_region_t     *swap_region,
+                     cairo_region_t     *queued_redraw_clip)
 {
   CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (view);
   CoglContext *ctx = cogl_framebuffer_get_context (framebuffer);
@@ -434,8 +344,7 @@ paint_damage_region (ClutterStageWindow *stage_window,
     }
 
   /* Red for the clip */
-  if (stage_cogl->initialized_redraw_clip &&
-      stage_cogl->redraw_clip)
+  if (queued_redraw_clip)
     {
       static CoglPipeline *overlay_red = NULL;
 
@@ -445,13 +354,13 @@ paint_damage_region (ClutterStageWindow *stage_window,
           cogl_pipeline_set_color4ub (overlay_red, 0x33, 0x00, 0x00, 0x33);
         }
 
-      n_rects = cairo_region_num_rectangles (stage_cogl->redraw_clip);
+      n_rects = cairo_region_num_rectangles (queued_redraw_clip);
       for (i = 0; i < n_rects; i++)
         {
           cairo_rectangle_int_t rect;
           float x_1, x_2, y_1, y_2;
 
-          cairo_region_get_rectangle (stage_cogl->redraw_clip, i, &rect);
+          cairo_region_get_rectangle (queued_redraw_clip, i, &rect);
           x_1 = rect.x;
           x_2 = rect.x + rect.width;
           y_1 = rect.y;
@@ -468,13 +377,14 @@ static gboolean
 swap_framebuffer (ClutterStageWindow *stage_window,
                   ClutterStageView   *view,
                   cairo_region_t     *swap_region,
-                  gboolean            swap_with_damage)
+                  gboolean            swap_with_damage,
+                  cairo_region_t     *queued_redraw_clip)
 {
   CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (view);
   int *damage, n_rects, i;
 
   if (G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DAMAGE_REGION)))
-    paint_damage_region (stage_window, view, swap_region);
+    paint_damage_region (stage_window, view, swap_region, queued_redraw_clip);
 
   n_rects = cairo_region_num_rectangles (swap_region);
   damage = g_newa (int, n_rects * 4);
@@ -711,7 +621,8 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
   gboolean do_swap_buffer;
   gboolean swap_with_damage;
   ClutterActor *wrapper;
-  cairo_region_t *redraw_clip = NULL;
+  cairo_region_t *redraw_clip;
+  cairo_region_t *queued_redraw_clip;
   cairo_region_t *fb_clip_region;
   cairo_region_t *swap_region;
   cairo_rectangle_int_t redraw_rect;
@@ -733,20 +644,13 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
 
   has_buffer_age = cogl_is_onscreen (fb) && is_buffer_age_enabled ();
 
+  redraw_clip = clutter_stage_view_take_redraw_clip (view);
+
   /* NB: a NULL redraw clip == full stage redraw */
-  if (!stage_cogl->redraw_clip)
+  if (!redraw_clip)
     is_full_redraw = TRUE;
   else
-    {
-      cairo_region_t *view_region;
-      redraw_clip = cairo_region_copy (stage_cogl->redraw_clip);
-
-      view_region = cairo_region_create_rectangle (&view_rect);
-      cairo_region_intersect (redraw_clip, view_region);
-
-      is_full_redraw = cairo_region_equal (redraw_clip, view_region);
-      cairo_region_destroy (view_region);
-    }
+    is_full_redraw = FALSE;
 
   may_use_clipped_redraw = FALSE;
   if (_clutter_stage_window_can_clip_redraws (stage_window) &&
@@ -798,6 +702,8 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
       redraw_clip = cairo_region_create_rectangle (&view_rect);
     }
 
+  queued_redraw_clip = cairo_region_copy (redraw_clip);
+
   if (may_use_clipped_redraw &&
       G_LIKELY (!(clutter_paint_debug_flags & CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS)))
     use_clipped_redraw = TRUE;
@@ -845,7 +751,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
               cairo_region_intersect_rectangle (view_damage, &view_rect);
 
               /* Update the redraw clip region with the extra damage. */
-              cairo_region_union (stage_cogl->redraw_clip, view_damage);
+              cairo_region_union (redraw_clip, view_damage);
               cairo_region_union (redraw_clip, view_damage);
 
               cairo_region_destroy (view_damage);
@@ -894,8 +800,6 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
       cairo_rectangle_int_t clip_rect;
       cairo_rectangle_int_t scissor_rect;
 
-      stage_cogl->using_clipped_redraw = TRUE;
-
       if (cairo_region_num_rectangles (fb_clip_region) == 1)
         {
           cairo_region_get_extents (fb_clip_region, &clip_rect);
@@ -926,8 +830,6 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
       paint_stage (stage_cogl, view, redraw_clip);
 
       cogl_framebuffer_pop_clip (fb);
-
-      stage_cogl->using_clipped_redraw = FALSE;
     }
   else
     {
@@ -1033,6 +935,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
     }
 
   g_clear_pointer (&redraw_clip, cairo_region_destroy);
+  g_clear_pointer (&queued_redraw_clip, cairo_region_destroy);
   g_clear_pointer (&fb_clip_region, cairo_region_destroy);
 
   if (do_swap_buffer)
@@ -1056,7 +959,8 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
       res = swap_framebuffer (stage_window,
                               view,
                               swap_region,
-                              swap_with_damage);
+                              swap_with_damage,
+                              queued_redraw_clip);
 
       cairo_region_destroy (swap_region);
 
@@ -1081,6 +985,9 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
     {
       ClutterStageView *view = l->data;
 
+      if (!clutter_stage_view_has_redraw_clip (view))
+        continue;
+
       swap_event |= clutter_stage_cogl_redraw_view (stage_window, view);
     }
 
@@ -1097,10 +1004,6 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
         stage_cogl->pending_swaps++;
     }
 
-  /* reset the redraw clipping for the next paint... */
-  stage_cogl->initialized_redraw_clip = FALSE;
-  g_clear_pointer (&stage_cogl->redraw_clip, cairo_region_destroy);
-
   stage_cogl->frame_count++;
 
   COGL_TRACE_END (ClutterStageCoglRedraw);
@@ -1118,10 +1021,6 @@ clutter_stage_window_iface_init (ClutterStageWindowInterface *iface)
   iface->schedule_update = clutter_stage_cogl_schedule_update;
   iface->get_update_time = clutter_stage_cogl_get_update_time;
   iface->clear_update_time = clutter_stage_cogl_clear_update_time;
-  iface->add_redraw_clip = clutter_stage_cogl_add_redraw_clip;
-  iface->has_redraw_clips = clutter_stage_cogl_has_redraw_clips;
-  iface->ignoring_redraw_clips = clutter_stage_cogl_ignoring_redraw_clips;
-  iface->get_redraw_clip = clutter_stage_cogl_get_redraw_clip;
   iface->redraw = clutter_stage_cogl_redraw;
 }
 
diff --git a/clutter/clutter/cogl/clutter-stage-cogl.h b/clutter/clutter/cogl/clutter-stage-cogl.h
index 3ad658bc5..1eaa02e8f 100644
--- a/clutter/clutter/cogl/clutter-stage-cogl.h
+++ b/clutter/clutter/cogl/clutter-stage-cogl.h
@@ -55,14 +55,6 @@ struct _ClutterStageCogl
   unsigned int frame_count;
 
   gint last_sync_delay;
-
-  cairo_region_t *redraw_clip;
-
-  guint initialized_redraw_clip : 1;
-
-  /* TRUE if the current paint cycle has a clipped redraw. In that
-     case bounding_redraw_clip specifies the the bounds. */
-  guint using_clipped_redraw : 1;
 };
 
 struct _ClutterStageCoglClass


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