11176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/*
21176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Copyright © 2004 Keith Packard
31176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *
41176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Permission to use, copy, modify, distribute, and sell this software and its
51176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * documentation for any purpose is hereby granted without fee, provided that
61176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * the above copyright notice appear in all copies and that both that
71176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * copyright notice and this permission notice appear in supporting
81176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * documentation, and that the name of Keith Packard not be used in
91176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * advertising or publicity pertaining to distribution of the software without
101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * specific, written prior permission.  Keith Packard makes no
111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * representations about the suitability of this software for any purpose.  It
121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * is provided "as is" without express or implied warranty.
131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *
141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * PERFORMANCE OF THIS SOFTWARE.
211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */
221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifndef rasterize_span
241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
261176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic void
271176bdada62cabc6ec4b0308a930e83b679d5d36John ReckRASTERIZE_EDGES (pixman_image_t  *image,
281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		pixman_edge_t	*l,
291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		pixman_edge_t	*r,
301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		pixman_fixed_t		t,
311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		pixman_fixed_t		b)
321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{
331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    pixman_fixed_t  y = t;
341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t  *line;
351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    uint32_t *buf = (image)->bits.bits;
361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int stride = (image)->bits.rowstride;
371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    int width = (image)->bits.width;
381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    line = buf + pixman_fixed_to_int (y) * stride;
401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    for (;;)
421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    {
431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	pixman_fixed_t	lx;
441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	pixman_fixed_t      rx;
451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	int	lxi;
461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	int rxi;
471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	lx = l->x;
491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	rx = r->x;
501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#if N_BITS == 1
511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	/* For the non-antialiased case, round the coordinates up, in effect
521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	 * sampling just slightly to the left of the pixel. This is so that
531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	 * when the sample point lies exactly on the line, we round towards
541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	 * north-west.
551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	 *
561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	 * (The AA case does a similar  adjustment in RENDER_SAMPLES_X)
571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	 */
581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	lx += X_FRAC_FIRST(1) - pixman_fixed_e;
591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	rx += X_FRAC_FIRST(1) - pixman_fixed_e;
601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	/* clip X */
621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (lx < 0)
631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    lx = 0;
641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (pixman_fixed_to_int (rx) >= width)
651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#if N_BITS == 1
661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    rx = pixman_int_to_fixed (width);
671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#else
681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    /* Use the last pixel of the scanline, covered 100%.
691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	     * We can't use the first pixel following the scanline,
701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	     * because accessing it could result in a buffer overrun.
711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	     */
721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    rx = pixman_int_to_fixed (width) - 1;
731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	/* Skip empty (or backwards) sections */
761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (rx > lx)
771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    /* Find pixel bounds for span */
801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    lxi = pixman_fixed_to_int (lx);
811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    rxi = pixman_fixed_to_int (rx);
821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#if N_BITS == 1
841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    {
851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#define LEFT_MASK(x)							\
871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		(((x) & 0x1f) ?						\
881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		 SCREEN_SHIFT_RIGHT (0xffffffff, (x) & 0x1f) : 0)
891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#define RIGHT_MASK(x)							\
901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		(((32 - (x)) & 0x1f) ?					\
911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		 SCREEN_SHIFT_LEFT (0xffffffff, (32 - (x)) & 0x1f) : 0)
921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#define MASK_BITS(x,w,l,n,r) {						\
941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    n = (w);						\
951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    r = RIGHT_MASK ((x) + n);				\
961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    l = LEFT_MASK (x);					\
971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    if (l) {						\
981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			n -= 32 - ((x) & 0x1f);				\
991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			if (n < 0) {					\
1001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    n = 0;					\
1011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    l &= r;					\
1021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			    r = 0;					\
1031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			}						\
1041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    }							\
1051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    n >>= 5;						\
1061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		}
1071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		uint32_t  *a = line;
1091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		uint32_t  startmask;
1101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		uint32_t  endmask;
1111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		int	    nmiddle;
1121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		int	    width = rxi - lxi;
1131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		int	    x = lxi;
1141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		a += x >> 5;
1161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		x &= 0x1f;
1171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		MASK_BITS (x, width, startmask, nmiddle, endmask);
1191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		if (startmask) {
1211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    WRITE(image, a, READ(image, a) | startmask);
1221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    a++;
1231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		}
1241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		while (nmiddle--)
1251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    WRITE(image, a++, 0xffffffff);
1261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		if (endmask)
1271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    WRITE(image, a, READ(image, a) | endmask);
1281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    }
1291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#else
1301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    {
1311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		DEFINE_ALPHA(line,lxi);
1321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		int	    lxs;
1331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		int     rxs;
1341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		/* Sample coverage for edge pixels */
1361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		lxs = RENDER_SAMPLES_X (lx, N_BITS);
1371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		rxs = RENDER_SAMPLES_X (rx, N_BITS);
1381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		/* Add coverage across row */
1401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		if (lxi == rxi)
1411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		{
1421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    ADD_ALPHA (rxs - lxs);
1431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		}
1441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		else
1451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		{
1461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    int	xi;
1471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    ADD_ALPHA (N_X_FRAC(N_BITS) - lxs);
1491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    STEP_ALPHA;
1501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    for (xi = lxi + 1; xi < rxi; xi++)
1511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    {
1521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			ADD_ALPHA (N_X_FRAC(N_BITS));
1531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck			STEP_ALPHA;
1541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    }
1551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		    ADD_ALPHA (rxs);
1561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck		}
1571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    }
1581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
1591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
1601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (y == b)
1621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    break;
1631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#if N_BITS > 1
1651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	if (pixman_fixed_frac (y) != Y_FRAC_LAST(N_BITS))
1661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
1671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    RENDER_EDGE_STEP_SMALL (l);
1681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    RENDER_EDGE_STEP_SMALL (r);
1691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    y += STEP_Y_SMALL(N_BITS);
1701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
1711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	else
1721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif
1731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	{
1741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    RENDER_EDGE_STEP_BIG (l);
1751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    RENDER_EDGE_STEP_BIG (r);
1761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    y += STEP_Y_BIG(N_BITS);
1771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	    line += stride;
1781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck	}
1791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck    }
1801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}
1811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck
1821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#undef rasterize_span
183