From 92710d8f895188ffee99a50079c96f2a2354eebd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= Date: Thu, 19 Mar 2020 22:30:06 +0100 Subject: [PATCH] clutter/stage-cogl: Check for buffer age early Fix a regression that got introduced with c483b52d240136cf49b358cde2c0d2c0ed237e51 where we started passing the redraw_clip to paint_stage() instead of creating a temporary view_region for unclipped redraws: In case we detect an invalid buffer age, we fall back to doing an unclipped redraw after we passed the first check setting up may_use_clipped_redraw. That means we didn't reset the redraw_clip to the view_rect, and we're now going to redraw the stage using the original redraw clip even though we're swapping the full framebuffer without damage. To fix that, check for the buffer age before setting up the fb_clip_region and the redraw_clip and set may_use_clipped_redraw to FALSE if the buffer age is invalid, too. This ensures the redraw_clip is always going to be correctly set to the view rect when we want to force a full redraw. Fixes https://gitlab.gnome.org/GNOME/mutter/issues/1128 --- clutter/clutter/cogl/clutter-stage-cogl.c | 112 ++++++++++------------ 1 file changed, 51 insertions(+), 61 deletions(-) diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c index f345313cf..d48e97641 100644 --- a/clutter/clutter/cogl/clutter-stage-cogl.c +++ b/clutter/clutter/cogl/clutter-stage-cogl.c @@ -628,6 +628,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window, float fb_scale; int subpixel_compensation = 0; int fb_width, fb_height; + int buffer_age; wrapper = CLUTTER_ACTOR (stage_cogl->wrapper); @@ -650,16 +651,26 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window, else is_full_redraw = FALSE; - may_use_clipped_redraw = FALSE; - if (_clutter_stage_window_can_clip_redraws (stage_window) && - (can_blit_sub_buffer || has_buffer_age) && - !is_full_redraw && - /* some drivers struggle to get going and produce some junk - * frames when starting up... */ - cogl_onscreen_get_frame_counter (COGL_ONSCREEN (fb)) > 3) - { - may_use_clipped_redraw = TRUE; + may_use_clipped_redraw = + _clutter_stage_window_can_clip_redraws (stage_window) && + (can_blit_sub_buffer || has_buffer_age) && + !is_full_redraw && + /* some drivers struggle to get going and produce some junk + * frames when starting up... */ + cogl_onscreen_get_frame_counter (COGL_ONSCREEN (fb)) > 3; + if (has_buffer_age) + { + buffer_age = cogl_onscreen_get_buffer_age (COGL_ONSCREEN (fb)); + if (!valid_buffer_age (view_cogl, buffer_age)) + { + CLUTTER_NOTE (CLIPPING, "Invalid back buffer(age=%d): forcing full redraw\n", buffer_age); + may_use_clipped_redraw = FALSE; + } + } + + if (may_use_clipped_redraw) + { fb_clip_region = offset_scale_and_clamp_region (redraw_clip, -view_rect.x, -view_rect.y, @@ -715,64 +726,43 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window, { if (use_clipped_redraw && !clip_region_empty) { - int age; + cairo_region_t *fb_damage; + cairo_region_t *view_damage; + int i; - age = cogl_onscreen_get_buffer_age (COGL_ONSCREEN (fb)); + fill_current_damage_history (view, fb_clip_region); - if (valid_buffer_age (view_cogl, age)) + fb_damage = cairo_region_create (); + + for (i = 1; i <= buffer_age; i++) { - cairo_region_t *fb_damage; - cairo_region_t *view_damage; - int i; + int damage_index; - fill_current_damage_history (view, fb_clip_region); - - fb_damage = cairo_region_create (); - - for (i = 1; i <= age; i++) - { - int damage_index; - - damage_index = DAMAGE_HISTORY (view_priv->damage_index - i - 1); - cairo_region_union (fb_damage, - view_priv->damage_history[damage_index]); - } - - /* Update the fb clip region with the extra damage. */ - cairo_region_union (fb_clip_region, fb_damage); - - view_damage = offset_scale_and_clamp_region (fb_damage, - 0, 0, - 1.0f / fb_scale); - cairo_region_translate (view_damage, view_rect.x, view_rect.y); - cairo_region_intersect_rectangle (view_damage, &view_rect); - - /* Update the redraw clip region with the extra damage. */ - 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", - age, - cairo_region_num_rectangles (fb_clip_region)); - - swap_with_damage = TRUE; + damage_index = DAMAGE_HISTORY (view_priv->damage_index - i - 1); + cairo_region_union (fb_damage, + view_priv->damage_history[damage_index]); } - else - { - cairo_rectangle_int_t fb_damage; - CLUTTER_NOTE (CLIPPING, "Invalid back buffer(age=%d): forcing full redraw\n", age); - use_clipped_redraw = FALSE; - 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); - } + /* Update the fb clip region with the extra damage. */ + cairo_region_union (fb_clip_region, fb_damage); + + view_damage = offset_scale_and_clamp_region (fb_damage, + 0, 0, + 1.0f / fb_scale); + cairo_region_translate (view_damage, view_rect.x, view_rect.y); + cairo_region_intersect_rectangle (view_damage, &view_rect); + + /* Update the redraw clip region with the extra damage. */ + 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", + buffer_age, + cairo_region_num_rectangles (fb_clip_region)); + + swap_with_damage = TRUE; } else if (!use_clipped_redraw) {