1/* 2 * Copyright © 1998 Keith Packard 3 * Copyright © 2012 Intel Corporation 4 * 5 * Permission to use, copy, modify, distribute, and sell this software and its 6 * documentation for any purpose is hereby granted without fee, provided that 7 * the above copyright notice appear in all copies and that both that 8 * copyright notice and this permission notice appear in supporting 9 * documentation, and that the name of Keith Packard not be used in 10 * advertising or publicity pertaining to distribution of the software without 11 * specific, written prior permission. Keith Packard makes no 12 * representations about the suitability of this software for any purpose. It 13 * is provided "as is" without express or implied warranty. 14 * 15 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 17 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 21 * PERFORMANCE OF THIS SOFTWARE. 22 */ 23 24#include "fb.h" 25 26/* 27 * This is a slight abuse of the preprocessor to generate repetitive 28 * code, the idea is to generate code for each case of a copy-mode 29 * transparent stipple 30 */ 31#define LaneCases1(c,a) \ 32 case c: while (n--) { FbLaneCase(c,a); a++; } break 33#define LaneCases2(c,a) LaneCases1(c,a); LaneCases1(c+1,a) 34#define LaneCases4(c,a) LaneCases2(c,a); LaneCases2(c+2,a) 35#define LaneCases8(c,a) LaneCases4(c,a); LaneCases4(c+4,a) 36#define LaneCases16(c,a) LaneCases8(c,a); LaneCases8(c+8,a) 37 38#define LaneCases(a) LaneCases16(0,a) 39 40/* 41 * Repeat a transparent stipple across a scanline n times 42 */ 43 44void 45fbTransparentSpan(FbBits * dst, FbBits stip, FbBits fgxor, int n) 46{ 47 FbStip s; 48 49 s = ((FbStip) (stip) & 0x01); 50 s |= ((FbStip) (stip >> 8) & 0x02); 51 s |= ((FbStip) (stip >> 16) & 0x04); 52 s |= ((FbStip) (stip >> 24) & 0x08); 53 switch (s) { 54 LaneCases(dst); 55 } 56} 57 58static void 59fbEvenStipple(FbBits *dst, FbStride dstStride, int dstX, int dstBpp, 60 int width, int height, 61 FbStip *stip, FbStride stipStride, 62 int stipHeight, 63 FbBits fgand, FbBits fgxor, FbBits bgand, FbBits bgxor, 64 int xRot, int yRot) 65{ 66 FbBits startmask, endmask; 67 FbBits mask, and, xor; 68 int nmiddle, n; 69 FbStip *s, *stipEnd, bits; 70 int rot, stipX, stipY; 71 int pixelsPerDst; 72 const FbBits *fbBits; 73 Bool transparent; 74 int startbyte, endbyte; 75 76 /* 77 * Check for a transparent stipple (stencil) 78 */ 79 transparent = FALSE; 80 if (dstBpp >= 8 && fgand == 0 && bgand == FB_ALLONES && bgxor == 0) 81 transparent = TRUE; 82 83 pixelsPerDst = FB_UNIT / dstBpp; 84 /* 85 * Adjust dest pointers 86 */ 87 dst += dstX >> FB_SHIFT; 88 dstX &= FB_MASK; 89 FbMaskBitsBytes(dstX, width, fgand == 0 && bgand == 0, 90 startmask, startbyte, nmiddle, endmask, endbyte); 91 92 if (startmask) 93 dstStride--; 94 dstStride -= nmiddle; 95 96 xRot *= dstBpp; 97 /* 98 * Compute stip start scanline and rotation parameters 99 */ 100 stipEnd = stip + stipStride * stipHeight; 101 modulus(-yRot, stipHeight, stipY); 102 s = stip + stipStride * stipY; 103 modulus(-xRot, FB_UNIT, stipX); 104 rot = stipX; 105 106 /* 107 * Get pointer to stipple mask array for this depth 108 */ 109 /* fbStippleTable covers all valid bpp (4,8,16,32) */ 110 fbBits = fbStippleTable[pixelsPerDst]; 111 112 while (height--) { 113 /* 114 * Extract stipple bits for this scanline; 115 */ 116 bits = READ(s); 117 s += stipStride; 118 if (s == stipEnd) 119 s = stip; 120 mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)]; 121 /* 122 * Rotate into position and compute reduced rop values 123 */ 124 mask = FbRotLeft(mask, rot); 125 and = (fgand & mask) | (bgand & ~mask); 126 xor = (fgxor & mask) | (bgxor & ~mask); 127 128 if (transparent) { 129 if (startmask) { 130 fbTransparentSpan(dst, mask & startmask, fgxor, 1); 131 dst++; 132 } 133 fbTransparentSpan(dst, mask, fgxor, nmiddle); 134 dst += nmiddle; 135 if (endmask) 136 fbTransparentSpan(dst, mask & endmask, fgxor, 1); 137 } else { 138 /* 139 * Fill scanline 140 */ 141 if (startmask) { 142 FbDoLeftMaskByteRRop(dst, startbyte, startmask, and, xor); 143 dst++; 144 } 145 n = nmiddle; 146 if (!and) 147 while (n--) 148 WRITE(dst++, xor); 149 else { 150 while (n--) { 151 WRITE(dst, FbDoRRop(READ(dst), and, xor)); 152 dst++; 153 } 154 } 155 if (endmask) 156 FbDoRightMaskByteRRop(dst, endbyte, endmask, and, xor); 157 } 158 dst += dstStride; 159 } 160} 161 162static void 163fbOddStipple(FbBits *dst, FbStride dstStride, int dstX, int dstBpp, 164 int width, int height, 165 FbStip *stip, FbStride stipStride, 166 int stipWidth, int stipHeight, 167 FbBits fgand, FbBits fgxor, FbBits bgand, FbBits bgxor, 168 int xRot, int yRot) 169{ 170 int stipX, stipY, sx; 171 int widthTmp; 172 int h, w; 173 int x, y; 174 175 modulus(-yRot, stipHeight, stipY); 176 modulus(dstX / dstBpp - xRot, stipWidth, stipX); 177 y = 0; 178 while (height) { 179 h = stipHeight - stipY; 180 if (h > height) 181 h = height; 182 height -= h; 183 widthTmp = width; 184 x = dstX; 185 sx = stipX; 186 while (widthTmp) { 187 w = (stipWidth - sx) * dstBpp; 188 if (w > widthTmp) 189 w = widthTmp; 190 widthTmp -= w; 191 fbBltOne(stip + stipY * stipStride, 192 stipStride, 193 sx, 194 dst + y * dstStride, 195 dstStride, x, dstBpp, w, h, fgand, fgxor, bgand, bgxor); 196 x += w; 197 sx = 0; 198 } 199 y += h; 200 stipY = 0; 201 } 202} 203 204void 205fbStipple(FbBits *dst, FbStride dstStride, int dstX, int dstBpp, 206 int width, int height, 207 FbStip *stip, FbStride stipStride, 208 int stipWidth, int stipHeight, Bool even, 209 FbBits fgand, FbBits fgxor, FbBits bgand, FbBits bgxor, 210 int xRot, int yRot) 211{ 212 DBG(("%s stipple=%dx%d, size=%dx%d\n", 213 __FUNCTION__, stipWidth, stipHeight, width, height)); 214 215 if (even) 216 fbEvenStipple(dst, dstStride, dstX, dstBpp, width, height, 217 stip, stipStride, stipHeight, 218 fgand, fgxor, bgand, bgxor, xRot, yRot); 219 else 220 fbOddStipple(dst, dstStride, dstX, dstBpp, width, height, 221 stip, stipStride, stipWidth, stipHeight, 222 fgand, fgxor, bgand, bgxor, xRot, yRot); 223} 224