summaryrefslogtreecommitdiff
path: root/pixman/src/fbedge.c
diff options
context:
space:
mode:
Diffstat (limited to 'pixman/src/fbedge.c')
-rw-r--r--pixman/src/fbedge.c304
1 files changed, 304 insertions, 0 deletions
diff --git a/pixman/src/fbedge.c b/pixman/src/fbedge.c
new file mode 100644
index 0000000..15835f3
--- /dev/null
+++ b/pixman/src/fbedge.c
@@ -0,0 +1,304 @@
+/*
+ * $Id: fbedge.c,v 1.3 2005/08/02 01:01:24 vektor Exp $
+ *
+ * Copyright © 2004 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <string.h>
+#include "pixman-xserver-compat.h"
+
+#ifdef RENDER
+
+/*
+ * 4 bit alpha
+ */
+
+#define N_BITS 4
+#define rasterizeEdges fbRasterizeEdges4
+
+#if BITMAP_BIT_ORDER == LSBFirst
+#define Shift4(o) ((o) << 2)
+#else
+#define Shift4(o) ((1-(o)) << 2)
+#endif
+
+#define Get4(x,o) (((x) >> Shift4(o)) & 0xf)
+#define Put4(x,o,v) (((x) & ~(0xf << Shift4(o))) | (((v) & 0xf) << Shift4(o)))
+
+#define DefineAlpha(line,x) \
+ CARD8 *__ap = (CARD8 *) line + ((x) >> 1); \
+ int __ao = (x) & 1
+
+#define StepAlpha ((__ap += __ao), (__ao ^= 1))
+
+#define AddAlpha(a) { \
+ CARD8 __o = *__ap; \
+ CARD8 __a = (a) + Get4(__o, __ao); \
+ *__ap = Put4 (__o, __ao, __a | (0 - ((__a) >> 4))); \
+}
+
+#include "fbedgeimp.h"
+
+#undef AddAlpha
+#undef StepAlpha
+#undef DefineAlpha
+#undef rasterizeEdges
+#undef N_BITS
+
+
+/*
+ * 1 bit alpha
+ */
+
+#define N_BITS 1
+#define rasterizeEdges fbRasterizeEdges1
+
+#include "fbedgeimp.h"
+
+#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,
+ int width,
+ int stride,
+ RenderEdge *l,
+ RenderEdge *r,
+ xFixed t,
+ xFixed b)
+{
+ switch (bpp) {
+ case 1:
+ fbRasterizeEdges1 (buf, width, stride, l, r, t, b);
+ break;
+ case 4:
+ fbRasterizeEdges4 (buf, width, stride, l, r, t, b);
+ break;
+ case 8:
+ fbRasterizeEdges8 (buf, width, stride, l, r, t, b);
+ break;
+ }
+}
+
+#endif /* RENDER */