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
This commit is contained in:
Christian Hergert 2020-02-19 17:34:49 -08:00 committed by Christian Hergert
parent 81d11ac0a8
commit 0c55e87d8f

View File

@ -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,