From 0c55e87d8fb70848eb59489550b80fce6dd49f84 Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Wed, 19 Feb 2020 17:34:49 -0800 Subject: [PATCH] cogl: reduce temporary allocations calculating redraw regions When calculating regions, a lot of temporary allocations are created. For the array of rects (which is often a short number of them) we can use stack allocations up to 1 page (256 cairo_rectangle_int_t). For building a region of rectangles, cairo and pixman are much faster if you have all of the rectangles up front or else it mallocs quite a bit of temporary memory. If we re-use the cairo_rectangle_int_t array we've already allocated (and preferably on the stack), we can delay the creation of regions until after the tight loop. Additionally, it requires fewer allocations to union two cairo_region_t than to incrementally union the rectangles into the region. Before (percentages are of total number of allocations) TOTAL FUNCTION [ 100.00%] [Everything] [ 100.00%] [gnome-shell --wayland --display-server] [ 99.67%] _start [ 99.67%] __libc_start_main [ 99.67%] main [ 98.60%] meta_run [ 96.90%] g_main_loop_run [ 96.90%] g_main_context_iterate.isra.0 [ 96.90%] g_main_context_dispatch [ 90.27%] clutter_clock_dispatch [ 86.54%] _clutter_stage_do_update [ 85.00%] clutter_stage_cogl_redraw [ 84.98%] clutter_stage_cogl_redraw_view [ 81.09%] cairo_region_union_rectangle After (overhead has much dropped) TOTAL FUNCTION [ 100.00%] [Everything] [ 99.80%] [gnome-shell --wayland --display-server] [ 99.48%] _start [ 99.48%] __libc_start_main [ 99.48%] main [ 92.37%] meta_run [ 81.49%] g_main_loop_run [ 81.49%] g_main_context_iterate.isra.0 [ 81.43%] g_main_context_dispatch [ 39.40%] clutter_clock_dispatch [ 26.93%] _clutter_stage_do_update [ 25.80%] clutter_stage_cogl_redraw [ 25.60%] clutter_stage_cogl_redraw_view https://gitlab.gnome.org/GNOME/mutter/merge_requests/1071 --- clutter/clutter/cogl/clutter-stage-cogl.c | 25 ++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c index 9b26d5553..b298398ec 100644 --- a/clutter/clutter/cogl/clutter-stage-cogl.c +++ b/clutter/clutter/cogl/clutter-stage-cogl.c @@ -49,6 +49,8 @@ #include "cogl/cogl-trace.h" +#define MAX_STACK_RECTS 256 + typedef struct _ClutterStageViewCoglPrivate { /* @@ -737,15 +739,17 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window, cogl_onscreen_get_frame_counter (COGL_ONSCREEN (fb)) > 3) { graphene_rect_t rect; + cairo_rectangle_int_t *freeme = NULL; cairo_rectangle_int_t *rects; int n_rects, i; may_use_clipped_redraw = TRUE; - fb_clip_region = cairo_region_create (); - n_rects = cairo_region_num_rectangles (redraw_clip); - rects = g_new (cairo_rectangle_int_t, n_rects); + if (n_rects < MAX_STACK_RECTS) + rects = g_newa (cairo_rectangle_int_t, n_rects); + else + rects = freeme = g_new (cairo_rectangle_int_t, n_rects); for (i = 0; i < n_rects; i++) { cairo_rectangle_int_t new_fb_clip_rect; @@ -756,9 +760,13 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window, graphene_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); + rects[i] = new_fb_clip_rect; } - g_free (rects); + if (n_rects == 0) + fb_clip_region = cairo_region_create (); + else + fb_clip_region = cairo_region_create_rectangles (rects, n_rects); + g_free (freeme); if (fb_scale != floorf (fb_scale)) { @@ -808,6 +816,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window, graphene_rect_t rect; cairo_rectangle_int_t damage_region; cairo_rectangle_int_t *rects; + cairo_region_t *add_clip; int n_rects, i; fill_current_damage_history (view, fb_clip_region); @@ -831,9 +840,11 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window, view_rect.x, view_rect.y, &damage_region); - cairo_region_union_rectangle (stage_cogl->redraw_clip, - &damage_region); + rects[i] = damage_region; } + add_clip = cairo_region_create_rectangles (rects, n_rects); + cairo_region_union (stage_cogl->redraw_clip, add_clip); + cairo_region_destroy (add_clip); CLUTTER_NOTE (CLIPPING, "Reusing back buffer(age=%d) - repairing region: num rects: %d\n", age,