From ba87f1324fda84ea816ad8f18442444c2ad1ed93 Mon Sep 17 00:00:00 2001 From: Billy Biggs Date: Mon, 1 Aug 2005 18:01:24 +0000 Subject: [PATCH] Optimize spans where the same value is being added to multiple pixels. This improves the speed of rasterizing wide trapezoids. Add an INLINE macro that matches the one from fbpict.h in xserver/fb. --- pixman/ChangeLog | 10 ++ pixman/src/fbedge.c | 230 +++++++++++++++++++++++++++++++++++++++----- pixman/src/icint.h | 6 ++ 3 files changed, 220 insertions(+), 26 deletions(-) diff --git a/pixman/ChangeLog b/pixman/ChangeLog index d9f1d9350..06402abd2 100644 --- a/pixman/ChangeLog +++ b/pixman/ChangeLog @@ -1,3 +1,13 @@ +2005-08-01 Billy Biggs + + * src/fbedge.c: (clip255), (add_saturate_8), + (fbRasterizeEdges8): Optimize spans where the same value is + being added to multiple pixels. This improves the speed of + rasterizing wide trapezoids. + + * src/icint.h: Add an INLINE macro that matches the one from + fbpict.h in xserver/fb. + 2005-08-01 Amaury Jacquot * NEWS: fix typo diff --git a/pixman/src/fbedge.c b/pixman/src/fbedge.c index 6839317d8..2ee6e6cdc 100644 --- a/pixman/src/fbedge.c +++ b/pixman/src/fbedge.c @@ -1,5 +1,5 @@ /* - * $Id: fbedge.c,v 1.2 2005-01-21 18:26:28 cworth Exp $ + * $Id: fbedge.c,v 1.3 2005-08-02 01:01:24 vektor Exp $ * * Copyright © 2004 Keith Packard * @@ -22,35 +22,11 @@ * PERFORMANCE OF THIS SOFTWARE. */ +#include #include "pixman-xserver-compat.h" #ifdef RENDER -/* - * 8 bit alpha - */ - -#define N_BITS 8 -#define rasterizeEdges fbRasterizeEdges8 - -#define DefineAlpha(line,x) \ - CARD8 *__ap = (CARD8 *) line + (x) - -#define StepAlpha __ap++ - -#define AddAlpha(a) { \ - CARD16 __a = a + *__ap; \ - *__ap = ((CARD8) ((__a) | (0 - ((__a) >> 8)))); \ -} - -#include "fbedgeimp.h" - -#undef AddAlpha -#undef StepAlpha -#undef DefineAlpha -#undef rasterizeEdges -#undef N_BITS - /* * 4 bit alpha */ @@ -100,6 +76,208 @@ #undef rasterizeEdges #undef N_BITS +/* + * 8 bit alpha + */ + +static INLINE CARD8 +clip255 (int x) +{ + if (x > 255) return 255; + return x; +} + +static INLINE void +add_saturate_8 (CARD8 *buf, int value, int length) +{ + while (length--) + { + *buf = clip255 (*buf + value); + buf++; + } +} + +/* + * We want to detect the case where we add the same value to a long + * span of pixels. The triangles on the end are filled in while we + * count how many sub-pixel scanlines contribute to the middle section. + * + * +--------------------------+ + * fill_height =| \ / + * +------------------+ + * |================| + * fill_start fill_end + */ +static void +fbRasterizeEdges8 (FbBits *buf, + int width, + int stride, + RenderEdge *l, + RenderEdge *r, + xFixed t, + xFixed b) +{ + xFixed y = t; + FbBits *line; + int fill_start = -1, fill_end = -1; + int fill_size = 0; + + line = buf + xFixedToInt (y) * stride; + + for (;;) + { + CARD8 *ap = (CARD8 *) line; + xFixed lx, rx; + int lxi, rxi; + + /* clip X */ + lx = l->x; + if (lx < 0) + lx = 0; + rx = r->x; + if (xFixedToInt (rx) >= width) + rx = IntToxFixed (width); + + /* Skip empty (or backwards) sections */ + if (rx > lx) + { + int lxs, rxs; + + /* Find pixel bounds for span. */ + lxi = xFixedToInt (lx); + rxi = xFixedToInt (rx); + + /* Sample coverage for edge pixels */ + lxs = RenderSamplesX (lx, 8); + rxs = RenderSamplesX (rx, 8); + + /* Add coverage across row */ + if (lxi == rxi) + { + ap[lxi] = clip255 (ap[lxi] + rxs - lxs); + } + else + { + ap[lxi] = clip255 (ap[lxi] + N_X_FRAC(8) - lxs); + + /* Move forward so that lxi/rxi is the pixel span */ + lxi++; + + /* Don't bother trying to optimize the fill unless + * the span is longer than 4 pixels. */ + if (rxi - lxi > 4) + { + if (fill_start < 0) + { + fill_start = lxi; + fill_end = rxi; + fill_size++; + } + else + { + if (lxi >= fill_end || rxi < fill_start) + { + /* We're beyond what we saved, just fill it */ + add_saturate_8 (ap + fill_start, + fill_size * N_X_FRAC(8), + fill_end - fill_start); + fill_start = lxi; + fill_end = rxi; + fill_size = 1; + } + else + { + /* Update fill_start */ + if (lxi > fill_start) + { + add_saturate_8 (ap + fill_start, + fill_size * N_X_FRAC(8), + lxi - fill_start); + fill_start = lxi; + } + else if (lxi < fill_start) + { + add_saturate_8 (ap + lxi, N_X_FRAC(8), + fill_start - lxi); + } + + /* Update fill_end */ + if (rxi < fill_end) + { + add_saturate_8 (ap + rxi, + fill_size * N_X_FRAC(8), + fill_end - rxi); + fill_end = rxi; + } + else if (fill_end < rxi) + { + add_saturate_8 (ap + fill_end, + N_X_FRAC(8), + rxi - fill_end); + } + fill_size++; + } + } + } + else + { + add_saturate_8 (ap + lxi, N_X_FRAC(8), rxi - lxi); + } + + /* Do not add in a 0 alpha here. This check is + * necessary to avoid a buffer overrun, (when rx + * is exactly on a pixel boundary). */ + if (rxs) + ap[rxi] = clip255 (ap[rxi] + rxs); + } + } + + if (y == b) { + /* We're done, make sure we clean up any remaining fill. */ + if (fill_start != fill_end) { + if (fill_size == N_Y_FRAC(8)) + { + memset (ap + fill_start, 0xff, fill_end - fill_start); + } + else + { + add_saturate_8 (ap + fill_start, fill_size * N_X_FRAC(8), + fill_end - fill_start); + } + } + break; + } + + if (xFixedFrac (y) != Y_FRAC_LAST(8)) + { + RenderEdgeStepSmall (l); + RenderEdgeStepSmall (r); + y += STEP_Y_SMALL(8); + } + else + { + RenderEdgeStepBig (l); + RenderEdgeStepBig (r); + y += STEP_Y_BIG(8); + if (fill_start != fill_end) + { + if (fill_size == N_Y_FRAC(8)) + { + memset (ap + fill_start, 0xff, fill_end - fill_start); + } + else + { + add_saturate_8 (ap + fill_start, fill_size * N_X_FRAC(8), + fill_end - fill_start); + } + fill_start = fill_end = -1; + fill_size = 0; + } + line += stride; + } + } +} + void fbRasterizeEdges (FbBits *buf, int bpp, diff --git a/pixman/src/icint.h b/pixman/src/icint.h index a5f0aff24..7567388f1 100644 --- a/pixman/src/icint.h +++ b/pixman/src/icint.h @@ -39,6 +39,12 @@ #define __inline #endif +#if defined(__GNUC__) +#define INLINE __inline__ +#else +#define INLINE +#endif + #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b))