From e3e58123d36924c760ab6f58a7155a040422e91d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 6 Jul 2012 15:22:26 +0100 Subject: sna: Fixup fb wrapper To accommodate changes in the Xserver and avoid breakage; would have been much easier had the fb been exported in the first place. --- src/sna/fb/fbstipple.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 src/sna/fb/fbstipple.c (limited to 'src/sna/fb/fbstipple.c') diff --git a/src/sna/fb/fbstipple.c b/src/sna/fb/fbstipple.c new file mode 100644 index 00000000..d02970a0 --- /dev/null +++ b/src/sna/fb/fbstipple.c @@ -0,0 +1,223 @@ +/* + * Copyright © 1998 Keith Packard + * Copyright © 2012 Intel Corporation + * + * 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. + */ + +#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--) { 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 LaneCases(a) LaneCases16(0,a) + +/* + * 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); + switch (s) { + LaneCases(dst); + } +} + +static 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 = READ(s); + s += stipStride; + if (s == stipEnd) + s = stip; + 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--) + WRITE(dst++, xor); + else { + while (n--) { + WRITE(dst, FbDoRRop(READ(dst), and, xor)); + dst++; + } + } + if (endmask) + FbDoRightMaskByteRRop(dst, endbyte, endmask, and, xor); + } + dst += dstStride; + } +} + +static 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) +{ + DBG(("%s stipple=%dx%d, size=%dx%d\n", + __FUNCTION__, stipWidth, stipHeight, width, height)); + + 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); +} -- cgit v1.2.3