[mutter] window-actor: Use MetaRegionBuilder when scanning the visible region



commit ac18f41ed187f52d148c448984cebe2ecfe96667
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Sun Apr 29 07:10:15 2012 -0400

    window-actor: Use MetaRegionBuilder when scanning the visible region
    
    This gives a pretty solid performance improvement when resizing windows.

 src/compositor/meta-window-actor.c |   23 ++++++++++++++---------
 src/compositor/region-utils.c      |   27 +++++----------------------
 src/compositor/region-utils.h      |   26 ++++++++++++++++++++++++++
 3 files changed, 45 insertions(+), 31 deletions(-)
---
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index 0ebea53..fb5b0c8 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 cf3c64e..34e1d4d 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 d20105c..c494e97 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);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]