gl-renderer: compress pixman bands to simplify geometry

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.

Acked-by: "Jasper St. Pierre" <jstpierre@mecheye.net>
Tested-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
dev
Derek Foreman 10 years ago committed by Pekka Paalanen
parent 64a3df086e
commit f81809864e
  1. 67
      src/gl-renderer.c

@ -25,6 +25,7 @@
#include <GLES2/gl2.h> #include <GLES2/gl2.h>
#include <GLES2/gl2ext.h> #include <GLES2/gl2ext.h>
#include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
@ -296,6 +297,55 @@ calculate_edges(struct weston_view *ev, pixman_box32_t *rect,
return n; 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 static int
texture_region(struct weston_view *ev, pixman_region32_t *region, texture_region(struct weston_view *ev, pixman_region32_t *region,
pixman_region32_t *surf_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; GLfloat *v, inv_width, inv_height;
unsigned int *vtxcnt, nvtx = 0; unsigned int *vtxcnt, nvtx = 0;
pixman_box32_t *rects, *surf_rects; pixman_box32_t *rects, *surf_rects;
int i, j, k, nrects, nsurf; pixman_box32_t *raw_rects;
int i, j, k, nrects, nsurf, raw_nrects;
rects = pixman_region32_rectangles(region, &nrects); bool used_band_compression;
raw_rects = pixman_region32_rectangles(region, &raw_nrects);
surf_rects = pixman_region32_rectangles(surf_region, &nsurf); 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 /* worst case we can have 8 vertices per rect (ie. clipped into
* an octagon): * an octagon):
*/ */
@ -369,6 +428,8 @@ texture_region(struct weston_view *ev, pixman_region32_t *region,
} }
} }
if (used_band_compression)
free(rects);
return nvtx; return nvtx;
} }

Loading…
Cancel
Save