Pixman uses y-x banded rectangles to represent regions.  We use these
y-x banded rectangles to generate triangle fans, resulting in more
geometry than strictly necessary to draw the screen.

This patch combines the bands to reduce geometry for complex scenes.
---
 src/gl-renderer.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 64 insertions(+), 3 deletions(-)

diff --git a/src/gl-renderer.c b/src/gl-renderer.c
index 076c242..40447c7 100644
--- a/src/gl-renderer.c
+++ b/src/gl-renderer.c
@@ -25,6 +25,7 @@
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
 
+#include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
@@ -296,6 +297,55 @@ calculate_edges(struct weston_view *ev, pixman_box32_t 
*rect,
        return n;
 }
 
+static bool
+merge_down(pixman_box32_t *a, pixman_box32_t *b, pixman_box32_t *merge)
+{
+       if (a->x1 == b->x1 && a->x2 == b->x2 && a->y1 == b->y2) {
+               merge->x1 = a->x1;
+               merge->x2 = a->x2;
+               merge->y1 = b->y1;
+               merge->y2 = a->y2;
+               return true;
+       }
+       return false;
+}
+
+static int
+compress_bands(pixman_box32_t *inrects, int nrects,
+                  pixman_box32_t **outrects)
+{
+       bool merged;
+       pixman_box32_t *out, merge_rect;
+       int i, j, nout;
+
+       if (!nrects) {
+               *outrects = NULL;
+               return 0;
+       }
+
+       /* nrects is an upper bound - we're not too worried about
+        * allocating a little extra
+        */
+       out = malloc(sizeof(pixman_box32_t) * nrects);
+       out[0] = inrects[0];
+       nout = 1;
+       for (i = 1; i < nrects; i++) {
+               for (j = 0; j < nout; j++) {
+                       merged = merge_down(&inrects[i], &out[j], &merge_rect);
+                       if (merged) {
+                               out[j] = merge_rect;
+                               break;
+                       }
+               }
+               if (!merged) {
+                       out[nout] = inrects[i];
+                       nout++;
+               }
+       }
+       *outrects = out;
+       return nout;
+}
+
 static int
 texture_region(struct weston_view *ev, pixman_region32_t *region,
                pixman_region32_t *surf_region)
@@ -306,11 +356,20 @@ texture_region(struct weston_view *ev, pixman_region32_t 
*region,
        GLfloat *v, inv_width, inv_height;
        unsigned int *vtxcnt, nvtx = 0;
        pixman_box32_t *rects, *surf_rects;
-       int i, j, k, nrects, nsurf;
-
-       rects = pixman_region32_rectangles(region, &nrects);
+       pixman_box32_t *raw_rects;
+       int i, j, k, nrects, nsurf, raw_nrects;
+       bool used_band_compression;
+       raw_rects = pixman_region32_rectangles(region, &raw_nrects);
        surf_rects = pixman_region32_rectangles(surf_region, &nsurf);
 
+       if (raw_nrects < 4) {
+               used_band_compression = false;
+               nrects = raw_nrects;
+               rects = raw_rects;
+       } else {
+               nrects = compress_bands(raw_rects, raw_nrects, &rects);
+               used_band_compression = true;
+       }
        /* worst case we can have 8 vertices per rect (ie. clipped into
         * an octagon):
         */
@@ -369,6 +428,8 @@ texture_region(struct weston_view *ev, pixman_region32_t 
*region,
                }
        }
 
+       if (used_band_compression)
+               free(rects);
        return nvtx;
 }
 
-- 
2.1.1

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to