1428d7b3dSmrg/* 2428d7b3dSmrg * Copyright © 1998 Keith Packard 3428d7b3dSmrg * Copyright © 2012 Intel Corporation 4428d7b3dSmrg * 5428d7b3dSmrg * Permission to use, copy, modify, distribute, and sell this software and its 6428d7b3dSmrg * documentation for any purpose is hereby granted without fee, provided that 7428d7b3dSmrg * the above copyright notice appear in all copies and that both that 8428d7b3dSmrg * copyright notice and this permission notice appear in supporting 9428d7b3dSmrg * documentation, and that the name of Keith Packard not be used in 10428d7b3dSmrg * advertising or publicity pertaining to distribution of the software without 11428d7b3dSmrg * specific, written prior permission. Keith Packard makes no 12428d7b3dSmrg * representations about the suitability of this software for any purpose. It 13428d7b3dSmrg * is provided "as is" without express or implied warranty. 14428d7b3dSmrg * 15428d7b3dSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16428d7b3dSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 17428d7b3dSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 18428d7b3dSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 19428d7b3dSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 20428d7b3dSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 21428d7b3dSmrg * PERFORMANCE OF THIS SOFTWARE. 22428d7b3dSmrg */ 23428d7b3dSmrg 24428d7b3dSmrg#include "fb.h" 25428d7b3dSmrg 26428d7b3dSmrg/* 27428d7b3dSmrg * This is a slight abuse of the preprocessor to generate repetitive 28428d7b3dSmrg * code, the idea is to generate code for each case of a copy-mode 29428d7b3dSmrg * transparent stipple 30428d7b3dSmrg */ 31428d7b3dSmrg#define LaneCases1(c,a) \ 32428d7b3dSmrg case c: while (n--) { FbLaneCase(c,a); a++; } break 33428d7b3dSmrg#define LaneCases2(c,a) LaneCases1(c,a); LaneCases1(c+1,a) 34428d7b3dSmrg#define LaneCases4(c,a) LaneCases2(c,a); LaneCases2(c+2,a) 35428d7b3dSmrg#define LaneCases8(c,a) LaneCases4(c,a); LaneCases4(c+4,a) 36428d7b3dSmrg#define LaneCases16(c,a) LaneCases8(c,a); LaneCases8(c+8,a) 37428d7b3dSmrg 38428d7b3dSmrg#define LaneCases(a) LaneCases16(0,a) 39428d7b3dSmrg 40428d7b3dSmrg/* 41428d7b3dSmrg * Repeat a transparent stipple across a scanline n times 42428d7b3dSmrg */ 43428d7b3dSmrg 44428d7b3dSmrgvoid 45428d7b3dSmrgfbTransparentSpan(FbBits * dst, FbBits stip, FbBits fgxor, int n) 46428d7b3dSmrg{ 47428d7b3dSmrg FbStip s; 48428d7b3dSmrg 49428d7b3dSmrg s = ((FbStip) (stip) & 0x01); 50428d7b3dSmrg s |= ((FbStip) (stip >> 8) & 0x02); 51428d7b3dSmrg s |= ((FbStip) (stip >> 16) & 0x04); 52428d7b3dSmrg s |= ((FbStip) (stip >> 24) & 0x08); 53428d7b3dSmrg switch (s) { 54428d7b3dSmrg LaneCases(dst); 55428d7b3dSmrg } 56428d7b3dSmrg} 57428d7b3dSmrg 58428d7b3dSmrgstatic void 59428d7b3dSmrgfbEvenStipple(FbBits *dst, FbStride dstStride, int dstX, int dstBpp, 60428d7b3dSmrg int width, int height, 61428d7b3dSmrg FbStip *stip, FbStride stipStride, 62428d7b3dSmrg int stipHeight, 63428d7b3dSmrg FbBits fgand, FbBits fgxor, FbBits bgand, FbBits bgxor, 64428d7b3dSmrg int xRot, int yRot) 65428d7b3dSmrg{ 66428d7b3dSmrg FbBits startmask, endmask; 67428d7b3dSmrg FbBits mask, and, xor; 68428d7b3dSmrg int nmiddle, n; 69428d7b3dSmrg FbStip *s, *stipEnd, bits; 70428d7b3dSmrg int rot, stipX, stipY; 71428d7b3dSmrg int pixelsPerDst; 72428d7b3dSmrg const FbBits *fbBits; 73428d7b3dSmrg Bool transparent; 74428d7b3dSmrg int startbyte, endbyte; 75428d7b3dSmrg 76428d7b3dSmrg /* 77428d7b3dSmrg * Check for a transparent stipple (stencil) 78428d7b3dSmrg */ 79428d7b3dSmrg transparent = FALSE; 80428d7b3dSmrg if (dstBpp >= 8 && fgand == 0 && bgand == FB_ALLONES && bgxor == 0) 81428d7b3dSmrg transparent = TRUE; 82428d7b3dSmrg 83428d7b3dSmrg pixelsPerDst = FB_UNIT / dstBpp; 84428d7b3dSmrg /* 85428d7b3dSmrg * Adjust dest pointers 86428d7b3dSmrg */ 87428d7b3dSmrg dst += dstX >> FB_SHIFT; 88428d7b3dSmrg dstX &= FB_MASK; 89428d7b3dSmrg FbMaskBitsBytes(dstX, width, fgand == 0 && bgand == 0, 90428d7b3dSmrg startmask, startbyte, nmiddle, endmask, endbyte); 91428d7b3dSmrg 92428d7b3dSmrg if (startmask) 93428d7b3dSmrg dstStride--; 94428d7b3dSmrg dstStride -= nmiddle; 95428d7b3dSmrg 96428d7b3dSmrg xRot *= dstBpp; 97428d7b3dSmrg /* 98428d7b3dSmrg * Compute stip start scanline and rotation parameters 99428d7b3dSmrg */ 100428d7b3dSmrg stipEnd = stip + stipStride * stipHeight; 101428d7b3dSmrg modulus(-yRot, stipHeight, stipY); 102428d7b3dSmrg s = stip + stipStride * stipY; 103428d7b3dSmrg modulus(-xRot, FB_UNIT, stipX); 104428d7b3dSmrg rot = stipX; 105428d7b3dSmrg 106428d7b3dSmrg /* 107428d7b3dSmrg * Get pointer to stipple mask array for this depth 108428d7b3dSmrg */ 109428d7b3dSmrg /* fbStippleTable covers all valid bpp (4,8,16,32) */ 110428d7b3dSmrg fbBits = fbStippleTable[pixelsPerDst]; 111428d7b3dSmrg 112428d7b3dSmrg while (height--) { 113428d7b3dSmrg /* 114428d7b3dSmrg * Extract stipple bits for this scanline; 115428d7b3dSmrg */ 116428d7b3dSmrg bits = READ(s); 117428d7b3dSmrg s += stipStride; 118428d7b3dSmrg if (s == stipEnd) 119428d7b3dSmrg s = stip; 120428d7b3dSmrg mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)]; 121428d7b3dSmrg /* 122428d7b3dSmrg * Rotate into position and compute reduced rop values 123428d7b3dSmrg */ 124428d7b3dSmrg mask = FbRotLeft(mask, rot); 125428d7b3dSmrg and = (fgand & mask) | (bgand & ~mask); 126428d7b3dSmrg xor = (fgxor & mask) | (bgxor & ~mask); 127428d7b3dSmrg 128428d7b3dSmrg if (transparent) { 129428d7b3dSmrg if (startmask) { 130428d7b3dSmrg fbTransparentSpan(dst, mask & startmask, fgxor, 1); 131428d7b3dSmrg dst++; 132428d7b3dSmrg } 133428d7b3dSmrg fbTransparentSpan(dst, mask, fgxor, nmiddle); 134428d7b3dSmrg dst += nmiddle; 135428d7b3dSmrg if (endmask) 136428d7b3dSmrg fbTransparentSpan(dst, mask & endmask, fgxor, 1); 137428d7b3dSmrg } else { 138428d7b3dSmrg /* 139428d7b3dSmrg * Fill scanline 140428d7b3dSmrg */ 141428d7b3dSmrg if (startmask) { 142428d7b3dSmrg FbDoLeftMaskByteRRop(dst, startbyte, startmask, and, xor); 143428d7b3dSmrg dst++; 144428d7b3dSmrg } 145428d7b3dSmrg n = nmiddle; 146428d7b3dSmrg if (!and) 147428d7b3dSmrg while (n--) 148428d7b3dSmrg WRITE(dst++, xor); 149428d7b3dSmrg else { 150428d7b3dSmrg while (n--) { 151428d7b3dSmrg WRITE(dst, FbDoRRop(READ(dst), and, xor)); 152428d7b3dSmrg dst++; 153428d7b3dSmrg } 154428d7b3dSmrg } 155428d7b3dSmrg if (endmask) 156428d7b3dSmrg FbDoRightMaskByteRRop(dst, endbyte, endmask, and, xor); 157428d7b3dSmrg } 158428d7b3dSmrg dst += dstStride; 159428d7b3dSmrg } 160428d7b3dSmrg} 161428d7b3dSmrg 162428d7b3dSmrgstatic void 163428d7b3dSmrgfbOddStipple(FbBits *dst, FbStride dstStride, int dstX, int dstBpp, 164428d7b3dSmrg int width, int height, 165428d7b3dSmrg FbStip *stip, FbStride stipStride, 166428d7b3dSmrg int stipWidth, int stipHeight, 167428d7b3dSmrg FbBits fgand, FbBits fgxor, FbBits bgand, FbBits bgxor, 168428d7b3dSmrg int xRot, int yRot) 169428d7b3dSmrg{ 170428d7b3dSmrg int stipX, stipY, sx; 171428d7b3dSmrg int widthTmp; 172428d7b3dSmrg int h, w; 173428d7b3dSmrg int x, y; 174428d7b3dSmrg 175428d7b3dSmrg modulus(-yRot, stipHeight, stipY); 176428d7b3dSmrg modulus(dstX / dstBpp - xRot, stipWidth, stipX); 177428d7b3dSmrg y = 0; 178428d7b3dSmrg while (height) { 179428d7b3dSmrg h = stipHeight - stipY; 180428d7b3dSmrg if (h > height) 181428d7b3dSmrg h = height; 182428d7b3dSmrg height -= h; 183428d7b3dSmrg widthTmp = width; 184428d7b3dSmrg x = dstX; 185428d7b3dSmrg sx = stipX; 186428d7b3dSmrg while (widthTmp) { 187428d7b3dSmrg w = (stipWidth - sx) * dstBpp; 188428d7b3dSmrg if (w > widthTmp) 189428d7b3dSmrg w = widthTmp; 190428d7b3dSmrg widthTmp -= w; 191428d7b3dSmrg fbBltOne(stip + stipY * stipStride, 192428d7b3dSmrg stipStride, 193428d7b3dSmrg sx, 194428d7b3dSmrg dst + y * dstStride, 195428d7b3dSmrg dstStride, x, dstBpp, w, h, fgand, fgxor, bgand, bgxor); 196428d7b3dSmrg x += w; 197428d7b3dSmrg sx = 0; 198428d7b3dSmrg } 199428d7b3dSmrg y += h; 200428d7b3dSmrg stipY = 0; 201428d7b3dSmrg } 202428d7b3dSmrg} 203428d7b3dSmrg 204428d7b3dSmrgvoid 205428d7b3dSmrgfbStipple(FbBits *dst, FbStride dstStride, int dstX, int dstBpp, 206428d7b3dSmrg int width, int height, 207428d7b3dSmrg FbStip *stip, FbStride stipStride, 208428d7b3dSmrg int stipWidth, int stipHeight, Bool even, 209428d7b3dSmrg FbBits fgand, FbBits fgxor, FbBits bgand, FbBits bgxor, 210428d7b3dSmrg int xRot, int yRot) 211428d7b3dSmrg{ 212428d7b3dSmrg DBG(("%s stipple=%dx%d, size=%dx%d\n", 213428d7b3dSmrg __FUNCTION__, stipWidth, stipHeight, width, height)); 214428d7b3dSmrg 215428d7b3dSmrg if (even) 216428d7b3dSmrg fbEvenStipple(dst, dstStride, dstX, dstBpp, width, height, 217428d7b3dSmrg stip, stipStride, stipHeight, 218428d7b3dSmrg fgand, fgxor, bgand, bgxor, xRot, yRot); 219428d7b3dSmrg else 220428d7b3dSmrg fbOddStipple(dst, dstStride, dstX, dstBpp, width, height, 221428d7b3dSmrg stip, stipStride, stipWidth, stipHeight, 222428d7b3dSmrg fgand, fgxor, bgand, bgxor, xRot, yRot); 223428d7b3dSmrg} 224