summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJasper St. Pierre <jstpierre@mecheye.net>2012-04-29 07:10:15 -0400
committerJasper St. Pierre <jstpierre@mecheye.net>2012-05-25 17:31:06 -0400
commitac18f41ed187f52d148c448984cebe2ecfe96667 (patch)
tree4ab5277e189e7f42e51646c620853755157aaf6a
parent60c05a0dac2bbc7fa1aa5abde3d60c4a5749c1e4 (diff)
downloadmutter-ac18f41ed187f52d148c448984cebe2ecfe96667.tar.gz
window-actor: Use MetaRegionBuilder when scanning the visible region
This gives a pretty solid performance improvement when resizing windows.
-rw-r--r--src/compositor/meta-window-actor.c23
-rw-r--r--src/compositor/region-utils.c27
-rw-r--r--src/compositor/region-utils.h26
3 files changed, 45 insertions, 31 deletions
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);