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-shadow-factory-private.h"
|
||||||
#include "meta-window-actor-private.h"
|
#include "meta-window-actor-private.h"
|
||||||
#include "meta-texture-rectangle.h"
|
#include "meta-texture-rectangle.h"
|
||||||
|
#include "region-utils.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
POSITION_CHANGED,
|
POSITION_CHANGED,
|
||||||
@ -2058,14 +2059,15 @@ install_corners (MetaWindow *window,
|
|||||||
cairo_fill (cr);
|
cairo_fill (cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static cairo_region_t *
|
||||||
scan_visible_region (guchar *mask_data,
|
scan_visible_region (guchar *mask_data,
|
||||||
int stride,
|
int stride,
|
||||||
cairo_region_t *scan_area,
|
cairo_region_t *scan_area)
|
||||||
cairo_region_t *union_against)
|
|
||||||
{
|
{
|
||||||
int i, n_rects;
|
int i, n_rects = cairo_region_num_rectangles (scan_area);
|
||||||
n_rects = cairo_region_num_rectangles (scan_area);
|
MetaRegionBuilder builder;
|
||||||
|
|
||||||
|
meta_region_builder_init (&builder);
|
||||||
|
|
||||||
for (i = 0; i < n_rects; i++)
|
for (i = 0; i < n_rects; i++)
|
||||||
{
|
{
|
||||||
@ -2084,13 +2086,14 @@ scan_visible_region (guchar *mask_data,
|
|||||||
|
|
||||||
if (w > 0)
|
if (w > 0)
|
||||||
{
|
{
|
||||||
cairo_rectangle_int_t tmp = { x, y, w - x, 1 };
|
meta_region_builder_add_rectangle (&builder, x, y, w - x, 1);
|
||||||
cairo_region_union_rectangle (union_against, &tmp);
|
|
||||||
x = w;
|
x = w;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return meta_region_builder_finish (&builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -2131,7 +2134,7 @@ build_and_scan_frame_mask (MetaWindowActor *self,
|
|||||||
|
|
||||||
if (priv->window->frame != NULL)
|
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 };
|
cairo_rectangle_int_t rect = { 0, 0, tex_width, tex_height };
|
||||||
|
|
||||||
/* Make sure we don't paint the frame over the client window. */
|
/* 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);
|
install_corners (priv->window, borders, cr);
|
||||||
|
|
||||||
cairo_surface_flush (surface);
|
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);
|
cairo_destroy (cr);
|
||||||
|
@ -43,34 +43,17 @@
|
|||||||
/* Optimium performance seems to be with MAX_CHUNK_RECTANGLES=4; 8 is about 10% slower.
|
/* 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(). */
|
* But using 8 may be more robust to systems with slow malloc(). */
|
||||||
#define MAX_CHUNK_RECTANGLES 8
|
#define MAX_CHUNK_RECTANGLES 8
|
||||||
#define MAX_LEVELS 16
|
|
||||||
|
|
||||||
typedef struct
|
void
|
||||||
{
|
|
||||||
/* 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
|
|
||||||
meta_region_builder_init (MetaRegionBuilder *builder)
|
meta_region_builder_init (MetaRegionBuilder *builder)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < MAX_LEVELS; i++)
|
for (i = 0; i < META_REGION_BUILDER_MAX_LEVELS; i++)
|
||||||
builder->levels[i] = NULL;
|
builder->levels[i] = NULL;
|
||||||
builder->n_levels = 1;
|
builder->n_levels = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
meta_region_builder_add_rectangle (MetaRegionBuilder *builder,
|
meta_region_builder_add_rectangle (MetaRegionBuilder *builder,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
@ -95,7 +78,7 @@ meta_region_builder_add_rectangle (MetaRegionBuilder *builder,
|
|||||||
{
|
{
|
||||||
if (builder->levels[i] == NULL)
|
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] = builder->levels[i - 1];
|
||||||
builder->levels[i - 1] = NULL;
|
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)
|
meta_region_builder_finish (MetaRegionBuilder *builder)
|
||||||
{
|
{
|
||||||
cairo_region_t *result = NULL;
|
cairo_region_t *result = NULL;
|
||||||
|
@ -63,6 +63,32 @@ struct _MetaRegionIterator {
|
|||||||
cairo_rectangle_int_t next_rectangle;
|
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,
|
void meta_region_iterator_init (MetaRegionIterator *iter,
|
||||||
cairo_region_t *region);
|
cairo_region_t *region);
|
||||||
gboolean meta_region_iterator_at_end (MetaRegionIterator *iter);
|
gboolean meta_region_iterator_at_end (MetaRegionIterator *iter);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user