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