mirror of
https://github.com/brl/mutter.git
synced 2024-11-21 23:50:41 -05:00
window-actor: Use MetaRegionBuilder when scanning the visible region
This gives a pretty solid performance improvement when resizing windows.
This commit is contained in:
parent
60c05a0dac
commit
ac18f41ed1
@ -26,6 +26,7 @@
|
||||
#include "meta-shadow-factory-private.h"
|
||||
#include "meta-window-actor-private.h"
|
||||
#include "meta-texture-rectangle.h"
|
||||
#include "region-utils.h"
|
||||
|
||||
enum {
|
||||
POSITION_CHANGED,
|
||||
@ -2058,14 +2059,15 @@ install_corners (MetaWindow *window,
|
||||
cairo_fill (cr);
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_region_t *
|
||||
scan_visible_region (guchar *mask_data,
|
||||
int stride,
|
||||
cairo_region_t *scan_area,
|
||||
cairo_region_t *union_against)
|
||||
cairo_region_t *scan_area)
|
||||
{
|
||||
int i, n_rects;
|
||||
n_rects = cairo_region_num_rectangles (scan_area);
|
||||
int i, n_rects = cairo_region_num_rectangles (scan_area);
|
||||
MetaRegionBuilder builder;
|
||||
|
||||
meta_region_builder_init (&builder);
|
||||
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
@ -2084,13 +2086,14 @@ scan_visible_region (guchar *mask_data,
|
||||
|
||||
if (w > 0)
|
||||
{
|
||||
cairo_rectangle_int_t tmp = { x, y, w - x, 1 };
|
||||
cairo_region_union_rectangle (union_against, &tmp);
|
||||
meta_region_builder_add_rectangle (&builder, x, y, w - x, 1);
|
||||
x = w;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return meta_region_builder_finish (&builder);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2131,7 +2134,7 @@ build_and_scan_frame_mask (MetaWindowActor *self,
|
||||
|
||||
if (priv->window->frame != NULL)
|
||||
{
|
||||
cairo_region_t *frame_paint_region;
|
||||
cairo_region_t *frame_paint_region, *scanned_region;
|
||||
cairo_rectangle_int_t rect = { 0, 0, tex_width, tex_height };
|
||||
|
||||
/* Make sure we don't paint the frame over the client window. */
|
||||
@ -2144,7 +2147,9 @@ build_and_scan_frame_mask (MetaWindowActor *self,
|
||||
install_corners (priv->window, borders, cr);
|
||||
|
||||
cairo_surface_flush (surface);
|
||||
scan_visible_region (mask_data, stride, frame_paint_region, shape_region);
|
||||
scanned_region = scan_visible_region (mask_data, stride, frame_paint_region);
|
||||
cairo_region_union (shape_region, scanned_region);
|
||||
cairo_region_destroy (scanned_region);
|
||||
}
|
||||
|
||||
cairo_destroy (cr);
|
||||
|
@ -43,34 +43,17 @@
|
||||
/* Optimium performance seems to be with MAX_CHUNK_RECTANGLES=4; 8 is about 10% slower.
|
||||
* But using 8 may be more robust to systems with slow malloc(). */
|
||||
#define MAX_CHUNK_RECTANGLES 8
|
||||
#define MAX_LEVELS 16
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* To merge regions in binary tree order, we need to keep track of
|
||||
* the regions that we've already merged together at different
|
||||
* levels of the tree. We fill in an array in the pattern:
|
||||
*
|
||||
* |a |
|
||||
* |b |a |
|
||||
* |c | |ab |
|
||||
* |d |c |ab |
|
||||
* |e | | |abcd|
|
||||
*/
|
||||
cairo_region_t *levels[MAX_LEVELS];
|
||||
int n_levels;
|
||||
} MetaRegionBuilder;
|
||||
|
||||
static void
|
||||
void
|
||||
meta_region_builder_init (MetaRegionBuilder *builder)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_LEVELS; i++)
|
||||
for (i = 0; i < META_REGION_BUILDER_MAX_LEVELS; i++)
|
||||
builder->levels[i] = NULL;
|
||||
builder->n_levels = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
meta_region_builder_add_rectangle (MetaRegionBuilder *builder,
|
||||
int x,
|
||||
int y,
|
||||
@ -95,7 +78,7 @@ meta_region_builder_add_rectangle (MetaRegionBuilder *builder,
|
||||
{
|
||||
if (builder->levels[i] == NULL)
|
||||
{
|
||||
if (i < MAX_LEVELS)
|
||||
if (i < META_REGION_BUILDER_MAX_LEVELS)
|
||||
{
|
||||
builder->levels[i] = builder->levels[i - 1];
|
||||
builder->levels[i - 1] = NULL;
|
||||
@ -115,7 +98,7 @@ meta_region_builder_add_rectangle (MetaRegionBuilder *builder,
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_region_t *
|
||||
cairo_region_t *
|
||||
meta_region_builder_finish (MetaRegionBuilder *builder)
|
||||
{
|
||||
cairo_region_t *result = NULL;
|
||||
|
@ -63,6 +63,32 @@ struct _MetaRegionIterator {
|
||||
cairo_rectangle_int_t next_rectangle;
|
||||
};
|
||||
|
||||
typedef struct _MetaRegionBuilder MetaRegionBuilder;
|
||||
|
||||
#define META_REGION_BUILDER_MAX_LEVELS 16
|
||||
struct _MetaRegionBuilder {
|
||||
/* To merge regions in binary tree order, we need to keep track of
|
||||
* the regions that we've already merged together at different
|
||||
* levels of the tree. We fill in an array in the pattern:
|
||||
*
|
||||
* |a |
|
||||
* |b |a |
|
||||
* |c | |ab |
|
||||
* |d |c |ab |
|
||||
* |e | | |abcd|
|
||||
*/
|
||||
cairo_region_t *levels[META_REGION_BUILDER_MAX_LEVELS];
|
||||
int n_levels;
|
||||
};
|
||||
|
||||
void meta_region_builder_init (MetaRegionBuilder *builder);
|
||||
void meta_region_builder_add_rectangle (MetaRegionBuilder *builder,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
cairo_region_t * meta_region_builder_finish (MetaRegionBuilder *builder);
|
||||
|
||||
void meta_region_iterator_init (MetaRegionIterator *iter,
|
||||
cairo_region_t *region);
|
||||
gboolean meta_region_iterator_at_end (MetaRegionIterator *iter);
|
||||
|
Loading…
Reference in New Issue
Block a user