[PATCH weston] gl-renderer: compress pixman bands to simplify geometry

Derek Foreman derekf at osg.samsung.com
Thu Oct 16 14:37:02 PDT 2014


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



More information about the wayland-devel mailing list