[mutter] clutter/stage-cogl: Ensure redraw_clip is a superset of fb_clip_region



commit 88600c89850c47dd9def1afd29c137e6809918a6
Author: Daniel van Vugt <daniel van vugt canonical com>
Date:   Mon Nov 9 15:39:40 2020 +0800

    clutter/stage-cogl: Ensure redraw_clip is a superset of fb_clip_region
    
    Initially we generate the new part of fb_clip_region from the new part
    of redraw_clip, scale it up and clamp. But the clamping means the new
    part of fb_clip_region might now represent a slightly larger area than
    the new part of redraw_clip, by one pixel.
    
    In some rare cases where a foreground actor honours redraw_clip, but
    the background actor does not (meaning it might fill all fb_clip_region),
    you could find 1px rendering glitches in that gap as the background
    actor paints there but the foreground actor does not.
    
    To ensure such glitches can never happen we now regenerate the final
    redraw_clip as a clamped superset of the final fb_clip_region. That's
    the minimum area we must paint to ensure no gaps appear inside
    fb_clip_region.
    
    Although the fix here sounds like the intent of the old code, the old
    code forgot to include the new part of fb_clip_region in the clamping
    of the final redraw_clip. So the new part of redraw_clip was sometimes
    kept too small for the new part of fb_clip_region.
    
    We also move the code to the main path because technically it's also
    needed when `has_buffer_age == FALSE`.
    
    Fixes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1500
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1554>

 clutter/clutter/cogl/clutter-stage-cogl.c | 27 +++++++++++++++++----------
 1 file changed, 17 insertions(+), 10 deletions(-)
---
diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c
index 2e14ec9ebc..410421b569 100644
--- a/clutter/clutter/cogl/clutter-stage-cogl.c
+++ b/clutter/clutter/cogl/clutter-stage-cogl.c
@@ -549,7 +549,6 @@ clutter_stage_cogl_redraw_view_primary (ClutterStageCogl *stage_cogl,
       if (use_clipped_redraw)
         {
           cairo_region_t *fb_damage;
-          cairo_region_t *view_damage;
           int age;
 
           fb_damage = cairo_region_create ();
@@ -566,15 +565,6 @@ clutter_stage_cogl_redraw_view_primary (ClutterStageCogl *stage_cogl,
           /* Update the fb clip region with the extra damage. */
           cairo_region_union (fb_clip_region, fb_damage);
 
-          /* Update the redraw clip with the extra damage done to the view */
-          view_damage = scale_offset_and_clamp_region (fb_damage,
-                                                       1.0f / fb_scale,
-                                                       view_rect.x,
-                                                       view_rect.y);
-
-          cairo_region_union (redraw_clip, view_damage);
-
-          cairo_region_destroy (view_damage);
           cairo_region_destroy (fb_damage);
 
           CLUTTER_NOTE (CLIPPING, "Reusing back buffer(age=%d) - repairing region: num rects: %d\n",
@@ -587,6 +577,23 @@ clutter_stage_cogl_redraw_view_primary (ClutterStageCogl *stage_cogl,
       clutter_damage_history_step (view_priv->damage_history);
     }
 
+  if (use_clipped_redraw)
+    {
+      /* Regenerate redraw_clip because:
+       *  1. It's missing the regions added from damage_history above; and
+       *  2. If using fractional scaling then it might be a fraction of a
+       *     logical pixel (or one physical pixel) smaller than
+       *     fb_clip_region, due to the clamping from
+       *     offset_scale_and_clamp_region. So we need to ensure redraw_clip
+       *     is a superset of fb_clip_region to avoid such gaps.
+       */
+      cairo_region_destroy (redraw_clip);
+      redraw_clip = scale_offset_and_clamp_region (fb_clip_region,
+                                                   1.0 / fb_scale,
+                                                   view_rect.x,
+                                                   view_rect.y);
+    }
+
   if (clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DAMAGE_REGION)
     {
       cairo_region_t *debug_redraw_clip;


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