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