[mutter/wip/carlosg/clip-regions: 1/6] ClutterStage: Store clip area as a region



commit d0c810a2a33b190e5d4a9d9238585454e7f384c8
Author: Carlos Garnacho <carlosg gnome org>
Date:   Sat Jul 20 17:52:11 2019 +0200

    ClutterStage: Store clip area as a region
    
    This will allow drawing optimizations as a region is more concrete
    than the bounding rectangle.
    
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/692

 clutter/clutter/clutter-stage-window.c    |  26 ++-
 clutter/clutter/clutter-stage-window.h    |   5 +-
 clutter/clutter/clutter-stage.c           |  25 +++
 clutter/clutter/clutter-stage.h           |   2 +
 clutter/clutter/cogl/clutter-stage-cogl.c | 305 ++++++++++++++++++------------
 clutter/clutter/cogl/clutter-stage-cogl.h |   2 +-
 6 files changed, 240 insertions(+), 125 deletions(-)
---
diff --git a/clutter/clutter/clutter-stage-window.c b/clutter/clutter/clutter-stage-window.c
index 76421d6a0..a526f54fe 100644
--- a/clutter/clutter/clutter-stage-window.c
+++ b/clutter/clutter/clutter-stage-window.c
@@ -235,19 +235,35 @@ _clutter_stage_window_ignoring_redraw_clips (ClutterStageWindow *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;
+}
+
 gboolean
 _clutter_stage_window_get_redraw_clip_bounds (ClutterStageWindow    *window,
                                               cairo_rectangle_int_t *stage_clip)
 {
-  ClutterStageWindowInterface *iface;
+  cairo_region_t *redraw_clip;
 
   g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), FALSE);
 
-  iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
-  if (iface->get_redraw_clip_bounds != NULL)
-    return iface->get_redraw_clip_bounds (window, stage_clip);
+  redraw_clip = _clutter_stage_window_get_redraw_clip (window);
+  if (!redraw_clip)
+    return FALSE;
 
-  return FALSE;
+  cairo_region_get_extents (redraw_clip, stage_clip);
+  cairo_region_destroy (redraw_clip);
+  return TRUE;
 }
 
 void
diff --git a/clutter/clutter/clutter-stage-window.h b/clutter/clutter/clutter-stage-window.h
index 389ed0596..992389e78 100644
--- a/clutter/clutter/clutter-stage-window.h
+++ b/clutter/clutter/clutter-stage-window.h
@@ -55,9 +55,7 @@ struct _ClutterStageWindowInterface
                                                  cairo_rectangle_int_t *stage_rectangle);
   gboolean          (* has_redraw_clips)        (ClutterStageWindow    *stage_window);
   gboolean          (* ignoring_redraw_clips)   (ClutterStageWindow    *stage_window);
-  gboolean          (* get_redraw_clip_bounds)  (ClutterStageWindow    *stage_window,
-                                                 cairo_rectangle_int_t *clip);
-
+  cairo_region_t *  (* get_redraw_clip)         (ClutterStageWindow    *stage_window);
 
   void              (* set_accept_focus)        (ClutterStageWindow *stage_window,
                                                  gboolean            accept_focus);
@@ -105,6 +103,7 @@ gboolean          _clutter_stage_window_has_redraw_clips        (ClutterStageWin
 gboolean          _clutter_stage_window_ignoring_redraw_clips   (ClutterStageWindow    *window);
 gboolean          _clutter_stage_window_get_redraw_clip_bounds  (ClutterStageWindow    *window,
                                                                  cairo_rectangle_int_t *clip);
+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 3a4e56f5a..c9a45646a 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -1350,6 +1350,31 @@ _clutter_stage_has_full_redraw_queued (ClutterStage *stage)
     return FALSE;
 }
 
+cairo_region_t *
+clutter_stage_get_redraw_clip (ClutterStage *stage)
+{
+  ClutterStagePrivate *priv;
+  cairo_rectangle_int_t clip;
+  cairo_region_t *region;
+
+  g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
+
+  priv = stage->priv;
+
+  region = _clutter_stage_window_get_redraw_clip (priv->impl);
+  if (region)
+    return region;
+
+  if (!region)
+    {
+      /* Set clip to the full extents of the stage */
+      _clutter_stage_window_get_geometry (priv->impl, &clip);
+      region = cairo_region_create_rectangle (&clip);
+    }
+
+  return region;
+}
+
 /**
  * clutter_stage_get_redraw_clip_bounds:
  * @stage: A #ClutterStage
diff --git a/clutter/clutter/clutter-stage.h b/clutter/clutter/clutter-stage.h
index c28904bd0..e896fb275 100644
--- a/clutter/clutter/clutter-stage.h
+++ b/clutter/clutter/clutter-stage.h
@@ -236,6 +236,8 @@ CLUTTER_EXPORT
 void            clutter_stage_get_redraw_clip_bounds            (ClutterStage          *stage,
                                                                  cairo_rectangle_int_t *clip);
 CLUTTER_EXPORT
+cairo_region_t * clutter_stage_get_redraw_clip                  (ClutterStage          *stage);
+CLUTTER_EXPORT
 void            clutter_stage_ensure_viewport                   (ClutterStage          *stage);
 CLUTTER_EXPORT
 void            clutter_stage_ensure_redraw                     (ClutterStage          *stage);
diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c
index 8f97a5fa6..19291fb73 100644
--- a/clutter/clutter/cogl/clutter-stage-cogl.c
+++ b/clutter/clutter/cogl/clutter-stage-cogl.c
@@ -56,7 +56,7 @@ typedef struct _ClutterStageViewCoglPrivate
    */
 #define DAMAGE_HISTORY_MAX 16
 #define DAMAGE_HISTORY(x) ((x) & (DAMAGE_HISTORY_MAX - 1))
-  cairo_rectangle_int_t damage_history[DAMAGE_HISTORY_MAX];
+  cairo_region_t * damage_history[DAMAGE_HISTORY_MAX];
   unsigned int damage_index;
 } ClutterStageViewCoglPrivate;
 
@@ -296,13 +296,10 @@ clutter_stage_cogl_has_redraw_clips (ClutterStageWindow *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.
-   *
-   * NB: a clip width of 0 means a full stage redraw has been queued
-   * so we effectively don't have any redraw clips in that case.
    */
   if (!stage_cogl->initialized_redraw_clip ||
       (stage_cogl->initialized_redraw_clip &&
-       stage_cogl->bounding_redraw_clip.width != 0))
+       stage_cogl->redraw_clip))
     return TRUE;
   else
     return FALSE;
@@ -313,9 +310,9 @@ clutter_stage_cogl_ignoring_redraw_clips (ClutterStageWindow *stage_window)
 {
   ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
 
-  /* NB: a clip width of 0 means a full stage redraw is required */
+  /* NB: a NULL clip means a full stage redraw is required */
   if (stage_cogl->initialized_redraw_clip &&
-      stage_cogl->bounding_redraw_clip.width == 0)
+      !stage_cogl->redraw_clip)
     return TRUE;
   else
     return FALSE;
@@ -346,11 +343,11 @@ clutter_stage_cogl_add_redraw_clip (ClutterStageWindow    *stage_window,
     return;
 
   /* A NULL stage clip means a full stage redraw has been queued and
-   * we keep track of this by setting a zero width
-   * stage_cogl->bounding_redraw_clip */
+   * we keep track of this by setting a NULL redraw_clip.
+   */
   if (stage_clip == NULL)
     {
-      stage_cogl->bounding_redraw_clip.width = 0;
+      g_clear_pointer (&stage_cogl->redraw_clip, cairo_region_destroy);
       stage_cogl->initialized_redraw_clip = TRUE;
       return;
     }
@@ -359,34 +356,27 @@ clutter_stage_cogl_add_redraw_clip (ClutterStageWindow    *stage_window,
   if (stage_clip->width == 0 || stage_clip->height == 0)
     return;
 
-  if (!stage_cogl->initialized_redraw_clip)
+  if (!stage_cogl->redraw_clip)
     {
-      stage_cogl->bounding_redraw_clip = *stage_clip;
+      stage_cogl->redraw_clip = cairo_region_create_rectangle (stage_clip);
     }
-  else if (stage_cogl->bounding_redraw_clip.width > 0)
+  else
     {
-      _clutter_util_rectangle_union (&stage_cogl->bounding_redraw_clip,
-                                     stage_clip,
-                                     &stage_cogl->bounding_redraw_clip);
+      cairo_region_union_rectangle (stage_cogl->redraw_clip, stage_clip);
     }
 
   stage_cogl->initialized_redraw_clip = TRUE;
 }
 
-static gboolean
-clutter_stage_cogl_get_redraw_clip_bounds (ClutterStageWindow    *stage_window,
-                                           cairo_rectangle_int_t *stage_clip)
+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_clip = stage_cogl->bounding_redraw_clip;
+  if (stage_cogl->using_clipped_redraw && stage_cogl->redraw_clip)
+    return cairo_region_copy (stage_cogl->redraw_clip);
 
-      return TRUE;
-    }
-
-  return FALSE;
+  return NULL;
 }
 
 static inline gboolean
@@ -433,9 +423,12 @@ paint_damage_region (ClutterStageWindow    *stage_window,
   cogl_framebuffer_draw_rectangle (framebuffer, overlay_blue, x_1, y_1, x_2, y_2);
 
   /* Red for the clip */
-  if (stage_cogl->initialized_redraw_clip)
+  if (stage_cogl->initialized_redraw_clip &&
+      stage_cogl->redraw_clip)
     {
       static CoglPipeline *overlay_red = NULL;
+      cairo_rectangle_int_t *rects;
+      int n_rects, i;
 
       if (G_UNLIKELY (overlay_red == NULL))
         {
@@ -443,12 +436,19 @@ paint_damage_region (ClutterStageWindow    *stage_window,
           cogl_pipeline_set_color4ub (overlay_red, 0x33, 0x00, 0x00, 0x33);
         }
 
-      x_1 = stage_cogl->bounding_redraw_clip.x;
-      x_2 = stage_cogl->bounding_redraw_clip.x + stage_cogl->bounding_redraw_clip.width;
-      y_1 = stage_cogl->bounding_redraw_clip.y;
-      y_2 = stage_cogl->bounding_redraw_clip.y + stage_cogl->bounding_redraw_clip.height;
+      n_rects = cairo_region_num_rectangles (stage_cogl->redraw_clip);
+      rects = g_malloc (sizeof(cairo_rectangle_int_t) * n_rects);
+      for (i = 0; i < n_rects; i++)
+        {
+          cairo_region_get_rectangle (stage_cogl->redraw_clip, i, &rects[i]);
+          x_1 = rects[i].x;
+          x_2 = rects[i].x + rects[i].width;
+          y_1 = rects[i].y;
+          y_2 = rects[i].y + rects[i].height;
 
-      cogl_framebuffer_draw_rectangle (framebuffer, overlay_red, x_1, y_1, x_2, y_2);
+          cogl_framebuffer_draw_rectangle (framebuffer, overlay_red, x_1, y_1, x_2, y_2);
+        }
+      g_free (rects);
     }
 
   cogl_framebuffer_pop_matrix (framebuffer);
@@ -519,44 +519,51 @@ swap_framebuffer (ClutterStageWindow    *stage_window,
 static void
 paint_stage (ClutterStageCogl            *stage_cogl,
              ClutterStageView            *view,
-             const cairo_rectangle_int_t *clip)
+             cairo_region_t              *clip)
 {
   ClutterStage *stage = stage_cogl->wrapper;
+  cairo_rectangle_int_t clip_rect;
+
+  cairo_region_get_extents (clip, &clip_rect);
 
   _clutter_stage_maybe_setup_viewport (stage, view);
-  _clutter_stage_paint_view (stage, view, clip);
+  _clutter_stage_paint_view (stage, view, &clip_rect);
 
   if (clutter_stage_view_get_onscreen (view) !=
       clutter_stage_view_get_framebuffer (view))
     {
-      clutter_stage_view_blit_offscreen (view, clip);
+      clutter_stage_view_blit_offscreen (view, &clip_rect);
     }
 }
 
 static void
-fill_current_damage_history_and_step (ClutterStageView *view)
+fill_current_damage_history (ClutterStageView *view,
+                             cairo_region_t   *damage)
 {
   ClutterStageViewCogl *view_cogl = CLUTTER_STAGE_VIEW_COGL (view);
   ClutterStageViewCoglPrivate *view_priv =
     clutter_stage_view_cogl_get_instance_private (view_cogl);
-  cairo_rectangle_int_t view_rect;
-  float fb_scale;
-  cairo_rectangle_int_t *current_fb_damage;
+  cairo_region_t **current_fb_damage;
 
   current_fb_damage =
     &view_priv->damage_history[DAMAGE_HISTORY (view_priv->damage_index)];
-  clutter_stage_view_get_layout (view, &view_rect);
-  fb_scale = clutter_stage_view_get_scale (view);
 
-  *current_fb_damage = (cairo_rectangle_int_t) {
-    .x = 0,
-    .y = 0,
-    .width = ceilf (view_rect.width * fb_scale),
-    .height = ceilf (view_rect.height * fb_scale)
-  };
+  g_clear_pointer (current_fb_damage, cairo_region_destroy);
+  *current_fb_damage = cairo_region_copy (damage);
   view_priv->damage_index++;
 }
 
+static void
+fill_current_damage_history_rectangle (ClutterStageView            *view,
+                                       const cairo_rectangle_int_t *rect)
+{
+  cairo_region_t *damage;
+
+  damage = cairo_region_create_rectangle (rect);
+  fill_current_damage_history (view, damage);
+  cairo_region_destroy (damage);
+}
+
 static void
 transform_swap_region_to_onscreen (ClutterStageView      *view,
                                    cairo_rectangle_int_t *swap_region)
@@ -654,9 +661,11 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
   gboolean do_swap_buffer;
   gboolean swap_with_damage;
   ClutterActor *wrapper;
-  cairo_rectangle_int_t redraw_clip;
+  cairo_region_t *redraw_clip;
+  cairo_region_t *fb_clip_region;
   cairo_rectangle_int_t swap_region;
-  cairo_rectangle_int_t fb_clip_region;
+  cairo_rectangle_int_t clip_rect;
+  cairo_rectangle_int_t redraw_rect;
   gboolean clip_region_empty;
   float fb_scale;
   int subpixel_compensation = 0;
@@ -675,20 +684,19 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
 
   has_buffer_age = cogl_is_onscreen (fb) && is_buffer_age_enabled ();
 
-  /* NB: a zero width redraw clip == full stage redraw */
-  if (stage_cogl->bounding_redraw_clip.width == 0)
+  /* NB: a NULL redraw clip == full stage redraw */
+  if (!stage_cogl->redraw_clip)
     have_clip = FALSE;
   else
     {
-      redraw_clip = stage_cogl->bounding_redraw_clip;
-      _clutter_util_rectangle_intersection (&redraw_clip,
-                                            &view_rect,
-                                            &redraw_clip);
-
-      have_clip = !(redraw_clip.x == view_rect.x &&
-                    redraw_clip.y == view_rect.y &&
-                    redraw_clip.width == view_rect.width &&
-                    redraw_clip.height == view_rect.height);
+      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);
+
+      have_clip = !cairo_region_equal (redraw_clip, view_region);
+      cairo_region_destroy (view_region);
     }
 
   may_use_clipped_redraw = FALSE;
@@ -700,25 +708,54 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
       cogl_onscreen_get_frame_counter (COGL_ONSCREEN (fb)) > 3)
     {
       ClutterRect rect;
+      cairo_rectangle_int_t *rects;
+      int n_rects, i;
 
       may_use_clipped_redraw = TRUE;
 
-      _clutter_util_rect_from_rectangle (&redraw_clip, &rect);
-      clutter_rect_offset (&rect, -view_rect.x, -view_rect.y);
-      scale_and_clamp_rect (&rect, fb_scale, &fb_clip_region);
+      fb_clip_region = cairo_region_create ();
+
+      n_rects = cairo_region_num_rectangles (redraw_clip);
+      rects = g_malloc (sizeof(cairo_rectangle_int_t) * n_rects);
+      for (i = 0; i < n_rects; i++)
+        {
+          cairo_rectangle_int_t new_fb_clip_rect;
+
+          cairo_region_get_rectangle (redraw_clip, i, &rects[i]);
+
+          _clutter_util_rect_from_rectangle (&rects[i], &rect);
+          clutter_rect_offset (&rect, -view_rect.x, -view_rect.y);
+          scale_and_clamp_rect (&rect, fb_scale, &new_fb_clip_rect);
+
+          cairo_region_union_rectangle (fb_clip_region, &new_fb_clip_rect);
+        }
+      g_free (rects);
+
+
 
       if (fb_scale != floorf (fb_scale))
         {
           subpixel_compensation = ceilf (fb_scale);
-          fb_clip_region.x -= subpixel_compensation;
-          fb_clip_region.y -= subpixel_compensation;
-          fb_clip_region.width += 2 * subpixel_compensation;
-          fb_clip_region.height += 2 * subpixel_compensation;
+
+          n_rects = cairo_region_num_rectangles (fb_clip_region);
+          rects = g_malloc (sizeof(cairo_rectangle_int_t) * n_rects);
+          for (i = 0; i < n_rects; i++)
+            {
+              cairo_region_get_rectangle (fb_clip_region, i, &rects[i]);
+              rects[i].x -= subpixel_compensation;
+              rects[i].y -= subpixel_compensation;
+              rects[i].width += 2 * subpixel_compensation;
+              rects[i].height += 2 * subpixel_compensation;
+            }
+          cairo_region_destroy (fb_clip_region);
+          fb_clip_region = cairo_region_create_rectangles (rects, n_rects);
+          g_free (rects);
         }
     }
   else
     {
-      fb_clip_region = (cairo_rectangle_int_t) { 0 };
+      fb_clip_region = cairo_region_create ();
+      redraw_clip = cairo_region_reference (fb_clip_region);
     }
 
   if (may_use_clipped_redraw &&
@@ -727,16 +764,14 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
   else
     use_clipped_redraw = FALSE;
 
-  clip_region_empty = may_use_clipped_redraw && fb_clip_region.width == 0;
+  clip_region_empty = may_use_clipped_redraw && cairo_region_is_empty (fb_clip_region);
 
   swap_with_damage = FALSE;
   if (has_buffer_age)
     {
       if (use_clipped_redraw && !clip_region_empty)
         {
-          int age, i;
-          cairo_rectangle_int_t *current_fb_damage =
-            &view_priv->damage_history[DAMAGE_HISTORY (view_priv->damage_index++)];
+          int age;
 
           age = cogl_onscreen_get_buffer_age (COGL_ONSCREEN (fb));
 
@@ -744,57 +779,73 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
             {
               ClutterRect rect;
               cairo_rectangle_int_t damage_region;
+              cairo_rectangle_int_t *rects;
+              int n_rects, i;
 
-              *current_fb_damage = fb_clip_region;
+              fill_current_damage_history (view, fb_clip_region);
 
               for (i = 1; i <= age; i++)
                 {
-                  cairo_rectangle_int_t *fb_damage =
-                    &view_priv->damage_history[DAMAGE_HISTORY (view_priv->damage_index - i - 1)];
+                  cairo_region_t *fb_damage =
+                    view_priv->damage_history[DAMAGE_HISTORY (view_priv->damage_index - i - 1)];
+                  cairo_region_union (fb_clip_region, fb_damage);
+                }
 
-                  _clutter_util_rectangle_union (&fb_clip_region,
-                                                 fb_damage,
-                                                 &fb_clip_region);
+              /* Update the redraw clip state with the extra damage. */
+              n_rects = cairo_region_num_rectangles (fb_clip_region);
+              rects = g_malloc (sizeof(cairo_rectangle_int_t) * n_rects);
+              for (i = 0; i < n_rects; i++)
+                {
+                  cairo_region_get_rectangle (fb_clip_region, i, &rects[i]);
+                  _clutter_util_rect_from_rectangle (&rects[i], &rect);
+                  scale_and_clamp_rect (&rect, 1.0f / fb_scale, &damage_region);
+                  _clutter_util_rectangle_offset (&damage_region,
+                                                  view_rect.x,
+                                                  view_rect.y,
+                                                  &damage_region);
+                  cairo_region_union_rectangle (stage_cogl->redraw_clip,
+                                                &damage_region);
                 }
+              g_free (rects);
 
-              /* Update the bounding redraw clip state with the extra damage. */
-              _clutter_util_rect_from_rectangle (&fb_clip_region, &rect);
-              scale_and_clamp_rect (&rect, 1.0f / fb_scale, &damage_region);
-              _clutter_util_rectangle_offset (&damage_region,
-                                              view_rect.x,
-                                              view_rect.y,
-                                              &damage_region);
-              _clutter_util_rectangle_union (&stage_cogl->bounding_redraw_clip,
-                                             &damage_region,
-                                             &stage_cogl->bounding_redraw_clip);
-
-              CLUTTER_NOTE (CLIPPING, "Reusing back buffer(age=%d) - repairing region: x=%d, y=%d, width=%d, 
height=%d\n",
+
+              CLUTTER_NOTE (CLIPPING, "Reusing back buffer(age=%d) - repairing region: num rects: %d\n",
                             age,
-                            fb_clip_region.x,
-                            fb_clip_region.y,
-                            fb_clip_region.width,
-                            fb_clip_region.height);
+                            cairo_region_num_rectangles (fb_clip_region));
 
               swap_with_damage = TRUE;
             }
           else
             {
+              cairo_rectangle_int_t fb_damage;
+
               CLUTTER_NOTE (CLIPPING, "Invalid back buffer(age=%d): forcing full redraw\n", age);
               use_clipped_redraw = FALSE;
-              *current_fb_damage = (cairo_rectangle_int_t) {
+              fb_damage = (cairo_rectangle_int_t) {
                 .x = 0,
                 .y = 0,
-                .width = view_rect.width * fb_scale,
-                .height = view_rect.height * fb_scale
+                .width = ceilf (view_rect.width * fb_scale),
+                .height = ceilf (view_rect.height * fb_scale)
               };
+              fill_current_damage_history_rectangle (view, &fb_damage);
             }
         }
       else if (!use_clipped_redraw)
         {
-          fill_current_damage_history_and_step (view);
+          cairo_rectangle_int_t fb_damage;
+
+          fb_damage = (cairo_rectangle_int_t) {
+            .x = 0,
+            .y = 0,
+            .width = ceilf (view_rect.width * fb_scale),
+            .height = ceilf (view_rect.height * fb_scale)
+          };
+          fill_current_damage_history_rectangle (view, &fb_damage);
         }
     }
 
+  cairo_region_get_extents (fb_clip_region, &clip_rect);
+
   cogl_push_framebuffer (fb);
   if (use_clipped_redraw && clip_region_empty)
     {
@@ -803,10 +854,11 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
   else if (use_clipped_redraw)
     {
       ClutterRect rect;
+      cairo_region_t *paint_region;
       cairo_rectangle_int_t scissor_rect;
       cairo_rectangle_int_t paint_rect;
 
-      calculate_scissor_region (&fb_clip_region,
+      calculate_scissor_region (&clip_rect,
                                 subpixel_compensation,
                                 fb_width, fb_height,
                                 &scissor_rect);
@@ -826,14 +878,16 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
                                           scissor_rect.width,
                                           scissor_rect.height);
 
-      _clutter_util_rect_from_rectangle (&fb_clip_region, &rect);
+      _clutter_util_rect_from_rectangle (&clip_rect, &rect);
       scale_and_clamp_rect (&rect, 1.0f / fb_scale, &paint_rect);
       _clutter_util_rectangle_offset (&paint_rect,
                                       view_rect.x,
                                       view_rect.y,
                                       &paint_rect);
 
-      paint_stage (stage_cogl, view, &paint_rect);
+      paint_region = cairo_region_create_rectangle (&paint_rect);
+      paint_stage (stage_cogl, view, paint_region);
+      cairo_region_destroy (paint_region);
       cogl_framebuffer_pop_clip (fb);
 
       stage_cogl->using_clipped_redraw = FALSE;
@@ -843,16 +897,17 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
       CLUTTER_NOTE (CLIPPING, "Unclipped stage paint\n");
 
       /* If we are trying to debug redraw issues then we want to pass
-       * the bounding_redraw_clip so it can be visualized */
+       * the redraw_clip so it can be visualized */
       if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS) &&
           may_use_clipped_redraw &&
           !clip_region_empty)
         {
           ClutterRect rect;
+          cairo_region_t *paint_region;
           cairo_rectangle_int_t scissor_rect;
           cairo_rectangle_int_t paint_rect;
 
-          calculate_scissor_region (&fb_clip_region,
+          calculate_scissor_region (&clip_rect,
                                     subpixel_compensation,
                                     fb_width, fb_height,
                                     &scissor_rect);
@@ -863,31 +918,41 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
                                               scissor_rect.width,
                                               scissor_rect.height);
 
-          _clutter_util_rect_from_rectangle (&fb_clip_region, &rect);
+          _clutter_util_rect_from_rectangle (&clip_rect, &rect);
           scale_and_clamp_rect (&rect, 1.0f / fb_scale, &paint_rect);
           _clutter_util_rectangle_offset (&paint_rect,
                                           view_rect.x,
                                           view_rect.y,
                                           &paint_rect);
 
-          paint_stage (stage_cogl, view, &paint_rect);
+          paint_region = cairo_region_create_rectangle (&paint_rect);
+          paint_stage (stage_cogl, view, paint_region);
+          cairo_region_destroy (paint_region);
           cogl_framebuffer_pop_clip (fb);
         }
       else
-        paint_stage (stage_cogl, view, &view_rect);
+        {
+          cairo_region_t *view_region;
+
+          view_region = cairo_region_create_rectangle (&view_rect);
+          paint_stage (stage_cogl, view, view_region);
+          cairo_region_destroy (view_region);
+        }
     }
   cogl_pop_framebuffer ();
 
+  cairo_region_get_extents (redraw_clip, &redraw_rect);
+
   if (may_use_clipped_redraw &&
       G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_REDRAWS)))
     {
       CoglContext *ctx = cogl_framebuffer_get_context (fb);
       static CoglPipeline *outline = NULL;
       ClutterActor *actor = CLUTTER_ACTOR (wrapper);
-      float x_1 = redraw_clip.x;
-      float x_2 = redraw_clip.x + redraw_clip.width;
-      float y_1 = redraw_clip.y;
-      float y_2 = redraw_clip.y + redraw_clip.height;
+      float x_1 = redraw_rect.x;
+      float x_2 = redraw_rect.x + redraw_rect.width;
+      float y_1 = redraw_rect.y;
+      float y_2 = redraw_rect.y + redraw_rect.height;
       CoglVertexP2 quad[4] = {
         { x_1, y_1 },
         { x_2, y_1 },
@@ -933,7 +998,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
         }
       else
         {
-          swap_region = fb_clip_region;
+          cairo_region_get_extents (fb_clip_region, &swap_region);
           g_assert (swap_region.width > 0);
           do_swap_buffer = TRUE;
         }
@@ -944,6 +1009,11 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
       do_swap_buffer = TRUE;
     }
 
+  if (redraw_clip)
+    cairo_region_destroy (redraw_clip);
+  if (fb_clip_region)
+    cairo_region_destroy (fb_clip_region);
+
   if (do_swap_buffer)
     {
       COGL_TRACE_BEGIN_SCOPED (ClutterStageCoglRedrawViewSwapFramebuffer,
@@ -998,6 +1068,7 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
 
   /* 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++;
 
@@ -1043,13 +1114,15 @@ clutter_stage_cogl_get_dirty_pixel (ClutterStageWindow *stage_window,
       ClutterStageViewCoglPrivate *view_priv =
         clutter_stage_view_cogl_get_instance_private (view_cogl);
       cairo_rectangle_int_t view_layout;
-      cairo_rectangle_int_t *fb_damage;
+      cairo_region_t *fb_damage;
+      cairo_rectangle_int_t fb_damage_rect;
 
       clutter_stage_view_get_layout (view, &view_layout);
 
-      fb_damage = &view_priv->damage_history[DAMAGE_HISTORY (view_priv->damage_index - 1)];
-      *x = fb_damage->x / fb_scale;
-      *y = fb_damage->y / fb_scale;
+      fb_damage = view_priv->damage_history[DAMAGE_HISTORY (view_priv->damage_index - 1)];
+      cairo_region_get_extents (fb_damage, &fb_damage_rect);
+      *x = fb_damage_rect.x / fb_scale;
+      *y = fb_damage_rect.y / fb_scale;
     }
 }
 
@@ -1068,7 +1141,7 @@ clutter_stage_window_iface_init (ClutterStageWindowInterface *iface)
   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_bounds = clutter_stage_cogl_get_redraw_clip_bounds;
+  iface->get_redraw_clip = clutter_stage_cogl_get_redraw_clip;
   iface->redraw = clutter_stage_cogl_redraw;
   iface->get_dirty_pixel = clutter_stage_cogl_get_dirty_pixel;
 }
diff --git a/clutter/clutter/cogl/clutter-stage-cogl.h b/clutter/clutter/cogl/clutter-stage-cogl.h
index a69c424eb..084788790 100644
--- a/clutter/clutter/cogl/clutter-stage-cogl.h
+++ b/clutter/clutter/cogl/clutter-stage-cogl.h
@@ -62,7 +62,7 @@ struct _ClutterStageCogl
 
   gint last_sync_delay;
 
-  cairo_rectangle_int_t bounding_redraw_clip;
+  cairo_region_t *redraw_clip;
 
   guint initialized_redraw_clip : 1;
 


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