fbstipple.c revision 428d7b3d
11.14Smsaitoh/*
21.1Schristos * Copyright © 1998 Keith Packard
31.1Schristos * Copyright © 2012 Intel Corporation
41.7Ssimonb *
51.1Schristos * Permission to use, copy, modify, distribute, and sell this software and its
61.1Schristos * documentation for any purpose is hereby granted without fee, provided that
71.1Schristos * the above copyright notice appear in all copies and that both that
81.1Schristos * copyright notice and this permission notice appear in supporting
91.1Schristos * documentation, and that the name of Keith Packard not be used in
101.1Schristos * advertising or publicity pertaining to distribution of the software without
111.1Schristos * specific, written prior permission.  Keith Packard makes no
121.1Schristos * representations about the suitability of this software for any purpose.  It
131.1Schristos * is provided "as is" without express or implied warranty.
141.1Schristos *
151.1Schristos * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
161.1Schristos * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
171.1Schristos * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
181.1Schristos * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
191.1Schristos * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
201.1Schristos * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
211.1Schristos * PERFORMANCE OF THIS SOFTWARE.
221.1Schristos */
231.1Schristos
241.1Schristos#include "fb.h"
251.1Schristos
261.1Schristos/*
271.1Schristos * This is a slight abuse of the preprocessor to generate repetitive
281.1Schristos * code, the idea is to generate code for each case of a copy-mode
291.1Schristos * transparent stipple
301.1Schristos */
311.1Schristos#define LaneCases1(c,a) \
321.14Smsaitoh	case c: while (n--) { FbLaneCase(c,a); a++; } break
331.1Schristos#define LaneCases2(c,a)	    LaneCases1(c,a); LaneCases1(c+1,a)
341.1Schristos#define LaneCases4(c,a)	    LaneCases2(c,a); LaneCases2(c+2,a)
351.7Ssimonb#define LaneCases8(c,a)	    LaneCases4(c,a); LaneCases4(c+4,a)
361.7Ssimonb#define LaneCases16(c,a)    LaneCases8(c,a); LaneCases8(c+8,a)
371.1Schristos
381.1Schristos#define LaneCases(a)	    LaneCases16(0,a)
391.1Schristos
401.1Schristos/*
411.1Schristos * Repeat a transparent stipple across a scanline n times
421.1Schristos */
431.1Schristos
441.1Schristosvoid
451.2SpgoyettefbTransparentSpan(FbBits * dst, FbBits stip, FbBits fgxor, int n)
461.1Schristos{
471.1Schristos	FbStip s;
481.1Schristos
491.1Schristos	s = ((FbStip) (stip) & 0x01);
501.1Schristos	s |= ((FbStip) (stip >> 8) & 0x02);
511.1Schristos	s |= ((FbStip) (stip >> 16) & 0x04);
521.1Schristos	s |= ((FbStip) (stip >> 24) & 0x08);
531.1Schristos	switch (s) {
541.2Spgoyette		LaneCases(dst);
551.1Schristos	}
561.7Ssimonb}
571.7Ssimonb
581.7Ssimonbstatic void
591.7SsimonbfbEvenStipple(FbBits *dst, FbStride dstStride, int dstX, int dstBpp,
601.1Schristos              int width, int height,
611.1Schristos              FbStip *stip, FbStride stipStride,
621.1Schristos              int stipHeight,
631.7Ssimonb              FbBits fgand, FbBits fgxor, FbBits bgand, FbBits bgxor,
641.7Ssimonb	      int xRot, int yRot)
651.1Schristos{
661.1Schristos	FbBits startmask, endmask;
671.1Schristos	FbBits mask, and, xor;
681.1Schristos	int nmiddle, n;
691.1Schristos	FbStip *s, *stipEnd, bits;
701.4Smsaitoh	int rot, stipX, stipY;
711.4Smsaitoh	int pixelsPerDst;
721.7Ssimonb	const FbBits *fbBits;
731.7Ssimonb	Bool transparent;
741.4Smsaitoh	int startbyte, endbyte;
751.7Ssimonb
761.13Smsaitoh	/*
771.7Ssimonb	 * Check for a transparent stipple (stencil)
781.7Ssimonb	 */
791.7Ssimonb	transparent = FALSE;
801.7Ssimonb	if (dstBpp >= 8 && fgand == 0 && bgand == FB_ALLONES && bgxor == 0)
811.7Ssimonb		transparent = TRUE;
821.7Ssimonb
831.7Ssimonb	pixelsPerDst = FB_UNIT / dstBpp;
841.7Ssimonb	/*
851.7Ssimonb	 * Adjust dest pointers
861.7Ssimonb	 */
871.7Ssimonb	dst += dstX >> FB_SHIFT;
881.7Ssimonb	dstX &= FB_MASK;
891.7Ssimonb	FbMaskBitsBytes(dstX, width, fgand == 0 && bgand == 0,
901.7Ssimonb			startmask, startbyte, nmiddle, endmask, endbyte);
911.14Smsaitoh
921.14Smsaitoh	if (startmask)
931.14Smsaitoh		dstStride--;
941.14Smsaitoh	dstStride -= nmiddle;
951.14Smsaitoh
961.7Ssimonb	xRot *= dstBpp;
971.7Ssimonb	/*
981.7Ssimonb	 * Compute stip start scanline and rotation parameters
991.7Ssimonb	 */
1001.14Smsaitoh	stipEnd = stip + stipStride * stipHeight;
1011.14Smsaitoh	modulus(-yRot, stipHeight, stipY);
1021.14Smsaitoh	s = stip + stipStride * stipY;
1031.14Smsaitoh	modulus(-xRot, FB_UNIT, stipX);
1041.14Smsaitoh	rot = stipX;
1051.4Smsaitoh
1061.4Smsaitoh	/*
1071.1Schristos	 * Get pointer to stipple mask array for this depth
1081.1Schristos	 */
1091.2Spgoyette	/* fbStippleTable covers all valid bpp (4,8,16,32) */
1101.1Schristos	fbBits = fbStippleTable[pixelsPerDst];
1111.1Schristos
1121.1Schristos	while (height--) {
1131.2Spgoyette		/*
1141.2Spgoyette		 * Extract stipple bits for this scanline;
1151.6Smsaitoh		 */
1161.1Schristos		bits = READ(s);
1171.6Smsaitoh		s += stipStride;
1181.1Schristos		if (s == stipEnd)
1191.1Schristos			s = stip;
1201.9Ssimonb		mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)];
1211.4Smsaitoh		/*
1221.4Smsaitoh		 * Rotate into position and compute reduced rop values
1231.4Smsaitoh		 */
1241.4Smsaitoh		mask = FbRotLeft(mask, rot);
1251.5Smsaitoh		and = (fgand & mask) | (bgand & ~mask);
1261.4Smsaitoh		xor = (fgxor & mask) | (bgxor & ~mask);
1271.4Smsaitoh
1281.4Smsaitoh		if (transparent) {
1291.4Smsaitoh			if (startmask) {
1301.1Schristos				fbTransparentSpan(dst, mask & startmask, fgxor, 1);
1311.1Schristos				dst++;
1321.6Smsaitoh			}
1331.6Smsaitoh			fbTransparentSpan(dst, mask, fgxor, nmiddle);
1341.1Schristos			dst += nmiddle;
1351.11Sthorpej			if (endmask)
1361.11Sthorpej				fbTransparentSpan(dst, mask & endmask, fgxor, 1);
1371.12Sthorpej		} else {
1381.1Schristos			/*
1391.1Schristos			 * Fill scanline
1401.1Schristos			 */
1411.1Schristos			if (startmask) {
1421.6Smsaitoh				FbDoLeftMaskByteRRop(dst, startbyte, startmask, and, xor);
1431.6Smsaitoh				dst++;
1441.1Schristos			}
1451.1Schristos			n = nmiddle;
1461.1Schristos			if (!and)
1471.8Sjoerg				while (n--)
1481.1Schristos					WRITE(dst++, xor);
1491.1Schristos			else {
1501.1Schristos				while (n--) {
1511.1Schristos					WRITE(dst, FbDoRRop(READ(dst), and, xor));
1521.1Schristos					dst++;
1531.7Ssimonb				}
1541.7Ssimonb			}
1551.7Ssimonb			if (endmask)
1561.7Ssimonb				FbDoRightMaskByteRRop(dst, endbyte, endmask, and, xor);
1571.7Ssimonb		}
1581.7Ssimonb		dst += dstStride;
1591.7Ssimonb	}
1601.7Ssimonb}
1611.7Ssimonb
1621.11Sthorpejstatic void
1631.2SpgoyettefbOddStipple(FbBits *dst, FbStride dstStride, int dstX, int dstBpp,
1641.2Spgoyette             int width, int height,
1651.2Spgoyette             FbStip *stip, FbStride stipStride,
1661.11Sthorpej             int stipWidth, int stipHeight,
1671.2Spgoyette             FbBits fgand, FbBits fgxor, FbBits bgand, FbBits bgxor,
1681.2Spgoyette	     int xRot, int yRot)
1691.2Spgoyette{
1701.11Sthorpej	int stipX, stipY, sx;
1711.12Sthorpej	int widthTmp;
1721.2Spgoyette	int h, w;
1731.2Spgoyette	int x, y;
1741.1Schristos
1751.1Schristos	modulus(-yRot, stipHeight, stipY);
1761.1Schristos	modulus(dstX / dstBpp - xRot, stipWidth, stipX);
1771.6Smsaitoh	y = 0;
1781.1Schristos	while (height) {
1791.1Schristos		h = stipHeight - stipY;
1801.1Schristos		if (h > height)
1811.1Schristos			h = height;
1821.1Schristos		height -= h;
1831.1Schristos		widthTmp = width;
1841.1Schristos		x = dstX;
1851.1Schristos		sx = stipX;
1861.1Schristos		while (widthTmp) {
1871.1Schristos			w = (stipWidth - sx) * dstBpp;
1881.1Schristos			if (w > widthTmp)
1891.1Schristos				w = widthTmp;
1901.1Schristos			widthTmp -= w;
1911.1Schristos			fbBltOne(stip + stipY * stipStride,
1921.1Schristos				 stipStride,
1931.7Ssimonb				 sx,
1941.7Ssimonb				 dst + y * dstStride,
1951.1Schristos				 dstStride, x, dstBpp, w, h, fgand, fgxor, bgand, bgxor);
1961.1Schristos			x += w;
1971.1Schristos			sx = 0;
1981.1Schristos		}
1991.1Schristos		y += h;
2001.1Schristos		stipY = 0;
2011.1Schristos	}
2021.1Schristos}
2031.1Schristos
2041.1Schristosvoid
2051.1SchristosfbStipple(FbBits *dst, FbStride dstStride, int dstX, int dstBpp,
2061.7Ssimonb          int width, int height,
2071.7Ssimonb          FbStip *stip, FbStride stipStride,
2081.1Schristos          int stipWidth, int stipHeight, Bool even,
2091.1Schristos          FbBits fgand, FbBits fgxor, FbBits bgand, FbBits bgxor,
2101.1Schristos	  int xRot, int yRot)
2111.1Schristos{
2121.2Spgoyette	DBG(("%s stipple=%dx%d, size=%dx%d\n",
2131.2Spgoyette	     __FUNCTION__, stipWidth, stipHeight, width, height));
2141.2Spgoyette
2151.2Spgoyette	if (even)
2161.2Spgoyette		fbEvenStipple(dst, dstStride, dstX, dstBpp, width, height,
2171.2Spgoyette			      stip, stipStride, stipHeight,
2181.2Spgoyette			      fgand, fgxor, bgand, bgxor, xRot, yRot);
2191.2Spgoyette	else
2201.2Spgoyette		fbOddStipple(dst, dstStride, dstX, dstBpp, width, height,
2211.2Spgoyette			     stip, stipStride, stipWidth, stipHeight,
2221.2Spgoyette			     fgand, fgxor, bgand, bgxor, xRot, yRot);
2231.2Spgoyette}
2241.2Spgoyette