/* * * Copyright © 1998 Keith Packard * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Keith Packard not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. Keith Packard makes no * representations about the suitability of this software for any purpose. It * is provided "as is" without express or implied warranty. * * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifdef HAVE_DIX_CONFIG_H #include #endif #include "fb.h" /* * This is a slight abuse of the preprocessor to generate repetitive * code, the idea is to generate code for each case of a copy-mode * transparent stipple */ #define LaneCases1(c,a) case c: \ while (n--) { (void)FbLaneCase(c,a); a++; } \ break #define LaneCases2(c,a) LaneCases1(c,a); LaneCases1(c+1,a) #define LaneCases4(c,a) LaneCases2(c,a); LaneCases2(c+2,a) #define LaneCases8(c,a) LaneCases4(c,a); LaneCases4(c+4,a) #define LaneCases16(c,a) LaneCases8(c,a); LaneCases8(c+8,a) #define LaneCases32(c,a) LaneCases16(c,a); LaneCases16(c+16,a) #define LaneCases64(c,a) LaneCases32(c,a); LaneCases32(c+32,a) #define LaneCases128(c,a) LaneCases64(c,a); LaneCases64(c+64,a) #define LaneCases256(c,a) LaneCases128(c,a); LaneCases128(c+128,a) #if FB_SHIFT == 6 #define LaneCases(a) LaneCases256(0,a) #endif #if FB_SHIFT == 5 #define LaneCases(a) LaneCases16(0,a) #endif /* * Repeat a transparent stipple across a scanline n times */ void fbTransparentSpan(FbBits * dst, FbBits stip, FbBits fgxor, int n) { FbStip s; s = ((FbStip) (stip) & 0x01); s |= ((FbStip) (stip >> 8) & 0x02); s |= ((FbStip) (stip >> 16) & 0x04); s |= ((FbStip) (stip >> 24) & 0x08); #if FB_SHIFT > 5 s |= ((FbStip) (stip >> 32) & 0x10); s |= ((FbStip) (stip >> 40) & 0x20); s |= ((FbStip) (stip >> 48) & 0x40); s |= ((FbStip) (stip >> 56) & 0x80); #endif switch (s) { LaneCases(dst); } } void fbEvenStipple(FbBits * dst, FbStride dstStride, int dstX, int dstBpp, int width, int height, FbStip * stip, FbStride stipStride, int stipHeight, FbBits fgand, FbBits fgxor, FbBits bgand, FbBits bgxor, int xRot, int yRot) { FbBits startmask, endmask; FbBits mask, and, xor; int nmiddle, n; FbStip *s, *stipEnd, bits; int rot, stipX, stipY; int pixelsPerDst; const FbBits *fbBits; Bool transparent; int startbyte, endbyte; /* * Check for a transparent stipple (stencil) */ transparent = FALSE; if (dstBpp >= 8 && fgand == 0 && bgand == FB_ALLONES && bgxor == 0) transparent = TRUE; pixelsPerDst = FB_UNIT / dstBpp; /* * Adjust dest pointers */ dst += dstX >> FB_SHIFT; dstX &= FB_MASK; FbMaskBitsBytes(dstX, width, fgand == 0 && bgand == 0, startmask, startbyte, nmiddle, endmask, endbyte); if (startmask) dstStride--; dstStride -= nmiddle; xRot *= dstBpp; /* * Compute stip start scanline and rotation parameters */ stipEnd = stip + stipStride * stipHeight; modulus(-yRot, stipHeight, stipY); s = stip + stipStride * stipY; modulus(-xRot, FB_UNIT, stipX); rot = stipX; /* * Get pointer to stipple mask array for this depth */ /* fbStippleTable covers all valid bpp (4,8,16,32) */ fbBits = fbStippleTable[pixelsPerDst]; while (height--) { /* * Extract stipple bits for this scanline; */ bits = *s; s += stipStride; if (s == stipEnd) s = stip; #if FB_UNIT > 32 if (pixelsPerDst == 16) mask = FbStipple16Bits(FbLeftStipBits(bits, 16)); else #endif mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)]; /* * Rotate into position and compute reduced rop values */ mask = FbRotLeft(mask, rot); and = (fgand & mask) | (bgand & ~mask); xor = (fgxor & mask) | (bgxor & ~mask); if (transparent) { if (startmask) { fbTransparentSpan(dst, mask & startmask, fgxor, 1); dst++; } fbTransparentSpan(dst, mask, fgxor, nmiddle); dst += nmiddle; if (endmask) fbTransparentSpan(dst, mask & endmask, fgxor, 1); } else { /* * Fill scanline */ if (startmask) { FbDoLeftMaskByteRRop(dst, startbyte, startmask, and, xor); dst++; } n = nmiddle; if (!and) while (n--) *dst++ = xor; else { while (n--) { *dst = FbDoRRop(*dst, and, xor); dst++; } } if (endmask) FbDoRightMaskByteRRop(dst, endbyte, endmask, and, xor); } dst += dstStride; } } void fbOddStipple(FbBits * dst, FbStride dstStride, int dstX, int dstBpp, int width, int height, FbStip * stip, FbStride stipStride, int stipWidth, int stipHeight, FbBits fgand, FbBits fgxor, FbBits bgand, FbBits bgxor, int xRot, int yRot) { int stipX, stipY, sx; int widthTmp; int h, w; int x, y; modulus(-yRot, stipHeight, stipY); modulus(dstX / dstBpp - xRot, stipWidth, stipX); y = 0; while (height) { h = stipHeight - stipY; if (h > height) h = height; height -= h; widthTmp = width; x = dstX; sx = stipX; while (widthTmp) { w = (stipWidth - sx) * dstBpp; if (w > widthTmp) w = widthTmp; widthTmp -= w; fbBltOne(stip + stipY * stipStride, stipStride, sx, dst + y * dstStride, dstStride, x, dstBpp, w, h, fgand, fgxor, bgand, bgxor); x += w; sx = 0; } y += h; stipY = 0; } } void fbStipple(FbBits * dst, FbStride dstStride, int dstX, int dstBpp, int width, int height, FbStip * stip, FbStride stipStride, int stipWidth, int stipHeight, Bool even, FbBits fgand, FbBits fgxor, FbBits bgand, FbBits bgxor, int xRot, int yRot) { if (even) fbEvenStipple(dst, dstStride, dstX, dstBpp, width, height, stip, stipStride, stipHeight, fgand, fgxor, bgand, bgxor, xRot, yRot); else fbOddStipple(dst, dstStride, dstX, dstBpp, width, height, stip, stipStride, stipWidth, stipHeight, fgand, fgxor, bgand, bgxor, xRot, yRot); }