diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c index 0ebea5383..fb5b0c887 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -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); diff --git a/src/compositor/region-utils.c b/src/compositor/region-utils.c index cf3c64ec7..34e1d4d58 100644 --- a/src/compositor/region-utils.c +++ b/src/compositor/region-utils.c @@ -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; diff --git a/src/compositor/region-utils.h b/src/compositor/region-utils.h index d20105c99..c494e97c5 100644 --- a/src/compositor/region-utils.h +++ b/src/compositor/region-utils.h @@ -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);