123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278 |
- /*
- *
- * 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 <dix-config.h>
- #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);
- }
|