From 577c4711e15650a79cbaf8e1001d1e7482241d38 Mon Sep 17 00:00:00 2001 From: Erico Nunes Date: Wed, 22 Sep 2021 22:26:23 +0200 Subject: [PATCH] backends: Enable partial update on clipped redraws Mutter already calculates and tracks the damage rectangles to redraw only areas of the screen that change since the last time a buffer was used. This patch extends this by using the EGL_KHR_partial_update extension to inform the GPU in advance that only those areas will be changed, which may allow for further optimization. Part-of: --- src/backends/meta-stage-impl.c | 44 ++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/backends/meta-stage-impl.c b/src/backends/meta-stage-impl.c index 28534ec81..2990c8977 100644 --- a/src/backends/meta-stage-impl.c +++ b/src/backends/meta-stage-impl.c @@ -199,6 +199,48 @@ paint_damage_region (ClutterStageWindow *stage_window, cogl_framebuffer_pop_matrix (framebuffer); } +static void +queue_damage_region (ClutterStageWindow *stage_window, + ClutterStageView *stage_view, + cairo_region_t *damage_region) +{ + int *damage, n_rects, i; + g_autofree int *freeme = NULL; + CoglFramebuffer *framebuffer; + CoglOnscreen *onscreen; + + if (cairo_region_is_empty (damage_region)) + return; + + framebuffer = clutter_stage_view_get_onscreen (stage_view); + if (!COGL_IS_ONSCREEN (framebuffer)) + return; + + onscreen = COGL_ONSCREEN (framebuffer); + + n_rects = cairo_region_num_rectangles (damage_region); + + if (n_rects < MAX_STACK_RECTS) + damage = g_newa (int, n_rects * 4); + else + damage = freeme = g_new (int, n_rects * 4); + + for (i = 0; i < n_rects; i++) + { + cairo_rectangle_int_t rect; + int height = cogl_framebuffer_get_height (framebuffer); + + cairo_region_get_rectangle (damage_region, i, &rect); + damage[i * 4] = rect.x; + /* y coordinate needs to be flipped for OpenGL */ + damage[i * 4 + 1] = height - rect.y - rect.height; + damage[i * 4 + 2] = rect.width; + damage[i * 4 + 3] = rect.height; + } + + cogl_onscreen_queue_damage_region (onscreen, damage, n_rects); +} + static void swap_framebuffer (ClutterStageWindow *stage_window, ClutterStageView *stage_view, @@ -550,6 +592,8 @@ meta_stage_impl_redraw_view_primary (MetaStageImpl *stage_impl, } else if (use_clipped_redraw) { + queue_damage_region (stage_window, stage_view, fb_clip_region); + cogl_framebuffer_push_region_clip (fb, fb_clip_region); paint_stage (stage_impl, stage_view, redraw_clip);