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 <string.h> 25428d7b3dSmrg#include "fb.h" 26428d7b3dSmrg 27428d7b3dSmrgtypedef struct _mergeRopBits { 28428d7b3dSmrg FbBits ca1, cx1, ca2, cx2; 29428d7b3dSmrg} FbMergeRopRec, *FbMergeRopPtr; 30428d7b3dSmrg 31428d7b3dSmrg#define O 0 32428d7b3dSmrg#define I FB_ALLONES 33428d7b3dSmrg 34428d7b3dSmrgstatic const FbMergeRopRec FbMergeRopBits[16] = { 35428d7b3dSmrg {O, O, O, O}, /* clear 0x0 0 */ 36428d7b3dSmrg {I, O, O, O}, /* and 0x1 src AND dst */ 37428d7b3dSmrg {I, O, I, O}, /* andReverse 0x2 src AND NOT dst */ 38428d7b3dSmrg {O, O, I, O}, /* copy 0x3 src */ 39428d7b3dSmrg {I, I, O, O}, /* andInverted 0x4 NOT src AND dst */ 40428d7b3dSmrg {O, I, O, O}, /* noop 0x5 dst */ 41428d7b3dSmrg {O, I, I, O}, /* xor 0x6 src XOR dst */ 42428d7b3dSmrg {I, I, I, O}, /* or 0x7 src OR dst */ 43428d7b3dSmrg {I, I, I, I}, /* nor 0x8 NOT src AND NOT dst */ 44428d7b3dSmrg {O, I, I, I}, /* equiv 0x9 NOT src XOR dst */ 45428d7b3dSmrg {O, I, O, I}, /* invert 0xa NOT dst */ 46428d7b3dSmrg {I, I, O, I}, /* orReverse 0xb src OR NOT dst */ 47428d7b3dSmrg {O, O, I, I}, /* copyInverted 0xc NOT src */ 48428d7b3dSmrg {I, O, I, I}, /* orInverted 0xd NOT src OR dst */ 49428d7b3dSmrg {I, O, O, I}, /* nand 0xe NOT src OR NOT dst */ 50428d7b3dSmrg {O, O, O, I}, /* set 0xf 1 */ 51428d7b3dSmrg}; 52428d7b3dSmrg 53428d7b3dSmrg#undef O 54428d7b3dSmrg#undef I 55428d7b3dSmrg 56428d7b3dSmrg#define FbDeclareMergeRop() FbBits _ca1, _cx1, _ca2, _cx2; 57428d7b3dSmrg#define FbDeclarePrebuiltMergeRop() FbBits _cca, _ccx; 58428d7b3dSmrg 59428d7b3dSmrg#define FbInitializeMergeRop(alu,pm) {\ 60428d7b3dSmrg const FbMergeRopRec *_bits; \ 61428d7b3dSmrg _bits = &FbMergeRopBits[alu]; \ 62428d7b3dSmrg _ca1 = _bits->ca1 & pm; \ 63428d7b3dSmrg _cx1 = _bits->cx1 | ~pm; \ 64428d7b3dSmrg _ca2 = _bits->ca2 & pm; \ 65428d7b3dSmrg _cx2 = _bits->cx2 & pm; \ 66428d7b3dSmrg} 67428d7b3dSmrg 68428d7b3dSmrg#define InitializeShifts(sx,dx,ls,rs) { \ 69428d7b3dSmrg if (sx != dx) { \ 70428d7b3dSmrg if (sx > dx) { \ 71428d7b3dSmrg ls = sx - dx; \ 72428d7b3dSmrg rs = FB_UNIT - ls; \ 73428d7b3dSmrg } else { \ 74428d7b3dSmrg rs = dx - sx; \ 75428d7b3dSmrg ls = FB_UNIT - rs; \ 76428d7b3dSmrg } \ 77428d7b3dSmrg } \ 78428d7b3dSmrg} 79428d7b3dSmrg 80428d7b3dSmrgstatic void 81428d7b3dSmrgfbBlt__rop(FbBits *srcLine, FbStride srcStride, int srcX, 82428d7b3dSmrg FbBits *dstLine, FbStride dstStride, int dstX, 83428d7b3dSmrg int width, int height, 84428d7b3dSmrg int alu, FbBits pm, int bpp, 85428d7b3dSmrg Bool reverse, Bool upsidedown) 86428d7b3dSmrg{ 87428d7b3dSmrg FbBits *src, *dst; 88428d7b3dSmrg int leftShift, rightShift; 89428d7b3dSmrg FbBits startmask, endmask; 90428d7b3dSmrg FbBits bits, bits1; 91428d7b3dSmrg int n, nmiddle; 92428d7b3dSmrg Bool destInvarient; 93428d7b3dSmrg int startbyte, endbyte; 94428d7b3dSmrg 95428d7b3dSmrg FbDeclareMergeRop(); 96428d7b3dSmrg 97428d7b3dSmrg FbInitializeMergeRop(alu, pm); 98428d7b3dSmrg destInvarient = FbDestInvarientMergeRop(); 99428d7b3dSmrg if (upsidedown) { 100428d7b3dSmrg srcLine += (height - 1) * (srcStride); 101428d7b3dSmrg dstLine += (height - 1) * (dstStride); 102428d7b3dSmrg srcStride = -srcStride; 103428d7b3dSmrg dstStride = -dstStride; 104428d7b3dSmrg } 105428d7b3dSmrg FbMaskBitsBytes(dstX, width, destInvarient, startmask, startbyte, 106428d7b3dSmrg nmiddle, endmask, endbyte); 107428d7b3dSmrg if (reverse) { 108428d7b3dSmrg srcLine += ((srcX + width - 1) >> FB_SHIFT) + 1; 109428d7b3dSmrg dstLine += ((dstX + width - 1) >> FB_SHIFT) + 1; 110428d7b3dSmrg srcX = (srcX + width - 1) & FB_MASK; 111428d7b3dSmrg dstX = (dstX + width - 1) & FB_MASK; 112428d7b3dSmrg } else { 113428d7b3dSmrg srcLine += srcX >> FB_SHIFT; 114428d7b3dSmrg dstLine += dstX >> FB_SHIFT; 115428d7b3dSmrg srcX &= FB_MASK; 116428d7b3dSmrg dstX &= FB_MASK; 117428d7b3dSmrg } 118428d7b3dSmrg if (srcX == dstX) { 119428d7b3dSmrg while (height--) { 120428d7b3dSmrg src = srcLine; 121428d7b3dSmrg srcLine += srcStride; 122428d7b3dSmrg dst = dstLine; 123428d7b3dSmrg dstLine += dstStride; 124428d7b3dSmrg if (reverse) { 125428d7b3dSmrg if (endmask) { 126428d7b3dSmrg bits = READ(--src); 127428d7b3dSmrg --dst; 128428d7b3dSmrg FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask); 129428d7b3dSmrg } 130428d7b3dSmrg n = nmiddle; 131428d7b3dSmrg if (destInvarient) { 132428d7b3dSmrg while (n--) 133428d7b3dSmrg WRITE(--dst, FbDoDestInvarientMergeRop(READ(--src))); 134428d7b3dSmrg } else { 135428d7b3dSmrg while (n--) { 136428d7b3dSmrg bits = READ(--src); 137428d7b3dSmrg --dst; 138428d7b3dSmrg WRITE(dst, FbDoMergeRop(bits, READ(dst))); 139428d7b3dSmrg } 140428d7b3dSmrg } 141428d7b3dSmrg if (startmask) { 142428d7b3dSmrg bits = READ(--src); 143428d7b3dSmrg --dst; 144428d7b3dSmrg FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask); 145428d7b3dSmrg } 146428d7b3dSmrg } else { 147428d7b3dSmrg if (startmask) { 148428d7b3dSmrg bits = READ(src++); 149428d7b3dSmrg FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask); 150428d7b3dSmrg dst++; 151428d7b3dSmrg } 152428d7b3dSmrg n = nmiddle; 153428d7b3dSmrg if (destInvarient) { 154428d7b3dSmrg while (n--) 155428d7b3dSmrg WRITE(dst++, FbDoDestInvarientMergeRop(READ(src++))); 156428d7b3dSmrg } else { 157428d7b3dSmrg while (n--) { 158428d7b3dSmrg bits = READ(src++); 159428d7b3dSmrg WRITE(dst, FbDoMergeRop(bits, READ(dst))); 160428d7b3dSmrg dst++; 161428d7b3dSmrg } 162428d7b3dSmrg } 163428d7b3dSmrg if (endmask) { 164428d7b3dSmrg bits = READ(src); 165428d7b3dSmrg FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask); 166428d7b3dSmrg } 167428d7b3dSmrg } 168428d7b3dSmrg } 169428d7b3dSmrg } else { 170428d7b3dSmrg if (srcX > dstX) { 171428d7b3dSmrg leftShift = srcX - dstX; 172428d7b3dSmrg rightShift = FB_UNIT - leftShift; 173428d7b3dSmrg } else { 174428d7b3dSmrg rightShift = dstX - srcX; 175428d7b3dSmrg leftShift = FB_UNIT - rightShift; 176428d7b3dSmrg } 177428d7b3dSmrg while (height--) { 178428d7b3dSmrg src = srcLine; 179428d7b3dSmrg srcLine += srcStride; 180428d7b3dSmrg dst = dstLine; 181428d7b3dSmrg dstLine += dstStride; 182428d7b3dSmrg 183428d7b3dSmrg bits1 = 0; 184428d7b3dSmrg if (reverse) { 185428d7b3dSmrg if (srcX < dstX) 186428d7b3dSmrg bits1 = READ(--src); 187428d7b3dSmrg if (endmask) { 188428d7b3dSmrg bits = FbScrRight(bits1, rightShift); 189428d7b3dSmrg if (FbScrRight(endmask, leftShift)) { 190428d7b3dSmrg bits1 = READ(--src); 191428d7b3dSmrg bits |= FbScrLeft(bits1, leftShift); 192428d7b3dSmrg } 193428d7b3dSmrg --dst; 194428d7b3dSmrg FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask); 195428d7b3dSmrg } 196428d7b3dSmrg n = nmiddle; 197428d7b3dSmrg if (destInvarient) { 198428d7b3dSmrg while (n--) { 199428d7b3dSmrg bits = FbScrRight(bits1, rightShift); 200428d7b3dSmrg bits1 = READ(--src); 201428d7b3dSmrg bits |= FbScrLeft(bits1, leftShift); 202428d7b3dSmrg --dst; 203428d7b3dSmrg WRITE(dst, FbDoDestInvarientMergeRop(bits)); 204428d7b3dSmrg } 205428d7b3dSmrg } else { 206428d7b3dSmrg while (n--) { 207428d7b3dSmrg bits = FbScrRight(bits1, rightShift); 208428d7b3dSmrg bits1 = READ(--src); 209428d7b3dSmrg bits |= FbScrLeft(bits1, leftShift); 210428d7b3dSmrg --dst; 211428d7b3dSmrg WRITE(dst, FbDoMergeRop(bits, READ(dst))); 212428d7b3dSmrg } 213428d7b3dSmrg } 214428d7b3dSmrg if (startmask) { 215428d7b3dSmrg bits = FbScrRight(bits1, rightShift); 216428d7b3dSmrg if (FbScrRight(startmask, leftShift)) { 217428d7b3dSmrg bits1 = READ(--src); 218428d7b3dSmrg bits |= FbScrLeft(bits1, leftShift); 219428d7b3dSmrg } 220428d7b3dSmrg --dst; 221428d7b3dSmrg FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask); 222428d7b3dSmrg } 223428d7b3dSmrg } else { 224428d7b3dSmrg if (srcX > dstX) 225428d7b3dSmrg bits1 = READ(src++); 226428d7b3dSmrg if (startmask) { 227428d7b3dSmrg bits = FbScrLeft(bits1, leftShift); 228428d7b3dSmrg if (FbScrLeft(startmask, rightShift)) { 229428d7b3dSmrg bits1 = READ(src++); 230428d7b3dSmrg bits |= FbScrRight(bits1, rightShift); 231428d7b3dSmrg } 232428d7b3dSmrg FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask); 233428d7b3dSmrg dst++; 234428d7b3dSmrg } 235428d7b3dSmrg n = nmiddle; 236428d7b3dSmrg if (destInvarient) { 237428d7b3dSmrg while (n--) { 238428d7b3dSmrg bits = FbScrLeft(bits1, leftShift); 239428d7b3dSmrg bits1 = READ(src++); 240428d7b3dSmrg bits |= FbScrRight(bits1, rightShift); 241428d7b3dSmrg WRITE(dst, FbDoDestInvarientMergeRop(bits)); 242428d7b3dSmrg dst++; 243428d7b3dSmrg } 244428d7b3dSmrg } else { 245428d7b3dSmrg while (n--) { 246428d7b3dSmrg bits = FbScrLeft(bits1, leftShift); 247428d7b3dSmrg bits1 = READ(src++); 248428d7b3dSmrg bits |= FbScrRight(bits1, rightShift); 249428d7b3dSmrg WRITE(dst, FbDoMergeRop(bits, READ(dst))); 250428d7b3dSmrg dst++; 251428d7b3dSmrg } 252428d7b3dSmrg } 253428d7b3dSmrg if (endmask) { 254428d7b3dSmrg bits = FbScrLeft(bits1, leftShift); 255428d7b3dSmrg if (FbScrLeft(endmask, rightShift)) { 256428d7b3dSmrg bits1 = READ(src); 257428d7b3dSmrg bits |= FbScrRight(bits1, rightShift); 258428d7b3dSmrg } 259428d7b3dSmrg FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask); 260428d7b3dSmrg } 261428d7b3dSmrg } 262428d7b3dSmrg } 263428d7b3dSmrg } 264428d7b3dSmrg} 265428d7b3dSmrg 266428d7b3dSmrgvoid 267428d7b3dSmrgfbBlt(FbBits *srcLine, FbStride srcStride, int srcX, 268428d7b3dSmrg FbBits *dstLine, FbStride dstStride, int dstX, 269428d7b3dSmrg int width, int height, 270428d7b3dSmrg int alu, FbBits pm, int bpp, 271428d7b3dSmrg Bool reverse, Bool upsidedown) 272428d7b3dSmrg{ 273428d7b3dSmrg DBG(("%s %dx%d, alu=%d, pm=%x, bpp=%d (reverse=%d, upsidedown=%d)\n", 274428d7b3dSmrg __FUNCTION__, width, height, alu, pm, bpp, reverse, upsidedown)); 275428d7b3dSmrg 276428d7b3dSmrg if (alu == GXcopy && pm == FB_ALLONES && ((srcX|dstX|width) & 7) == 0) { 277428d7b3dSmrg CARD8 *s = (CARD8 *) srcLine; 278428d7b3dSmrg CARD8 *d = (CARD8 *) dstLine; 279428d7b3dSmrg void *(*func)(void *, const void *, size_t); 280428d7b3dSmrg int i; 281428d7b3dSmrg 282428d7b3dSmrg srcStride *= sizeof(FbBits); 283428d7b3dSmrg dstStride *= sizeof(FbBits); 284428d7b3dSmrg width >>= 3; 285428d7b3dSmrg s += srcX >> 3; 286428d7b3dSmrg d += dstX >> 3; 287428d7b3dSmrg 288428d7b3dSmrg DBG(("%s fast blt, src_stride=%d, dst_stride=%d, width=%d (offset=%ld)\n", 289428d7b3dSmrg __FUNCTION__, 290428d7b3dSmrg srcStride, dstStride, width, (long)(s - d))); 291428d7b3dSmrg 292428d7b3dSmrg if (width == srcStride && width == dstStride) { 293428d7b3dSmrg width *= height; 294428d7b3dSmrg height = 1; 295428d7b3dSmrg } 296428d7b3dSmrg 297428d7b3dSmrg if ((s < d && s + width > d) || (d < s && d + width > s)) 298428d7b3dSmrg func = memmove; 299428d7b3dSmrg else 300428d7b3dSmrg func = memcpy; 301428d7b3dSmrg if (!upsidedown) { 302428d7b3dSmrg for (i = 0; i < height; i++) 303428d7b3dSmrg func(d + i * dstStride, 304428d7b3dSmrg s + i * srcStride, 305428d7b3dSmrg width); 306428d7b3dSmrg } else { 307428d7b3dSmrg for (i = height; i--; ) 308428d7b3dSmrg func(d + i * dstStride, 309428d7b3dSmrg s + i * srcStride, 310428d7b3dSmrg width); 311428d7b3dSmrg } 312428d7b3dSmrg 313428d7b3dSmrg return; 314428d7b3dSmrg } 315428d7b3dSmrg 316428d7b3dSmrg fbBlt__rop(srcLine, srcStride, srcX, 317428d7b3dSmrg dstLine, dstStride, dstX, 318428d7b3dSmrg width, height, 319428d7b3dSmrg alu, pm, bpp, 320428d7b3dSmrg reverse, upsidedown); 321428d7b3dSmrg} 322