1/* 2 * Copyright © 1998 Keith Packard 3 * Copyright © 2012 Intel Corporation 4 * 5 * Permission to use, copy, modify, distribute, and sell this software and its 6 * documentation for any purpose is hereby granted without fee, provided that 7 * the above copyright notice appear in all copies and that both that 8 * copyright notice and this permission notice appear in supporting 9 * documentation, and that the name of Keith Packard not be used in 10 * advertising or publicity pertaining to distribution of the software without 11 * specific, written prior permission. Keith Packard makes no 12 * representations about the suitability of this software for any purpose. It 13 * is provided "as is" without express or implied warranty. 14 * 15 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 17 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 21 * PERFORMANCE OF THIS SOFTWARE. 22 */ 23 24#include <string.h> 25#include "fb.h" 26 27typedef struct _mergeRopBits { 28 FbBits ca1, cx1, ca2, cx2; 29} FbMergeRopRec, *FbMergeRopPtr; 30 31#define O 0 32#define I FB_ALLONES 33 34static const FbMergeRopRec FbMergeRopBits[16] = { 35 {O, O, O, O}, /* clear 0x0 0 */ 36 {I, O, O, O}, /* and 0x1 src AND dst */ 37 {I, O, I, O}, /* andReverse 0x2 src AND NOT dst */ 38 {O, O, I, O}, /* copy 0x3 src */ 39 {I, I, O, O}, /* andInverted 0x4 NOT src AND dst */ 40 {O, I, O, O}, /* noop 0x5 dst */ 41 {O, I, I, O}, /* xor 0x6 src XOR dst */ 42 {I, I, I, O}, /* or 0x7 src OR dst */ 43 {I, I, I, I}, /* nor 0x8 NOT src AND NOT dst */ 44 {O, I, I, I}, /* equiv 0x9 NOT src XOR dst */ 45 {O, I, O, I}, /* invert 0xa NOT dst */ 46 {I, I, O, I}, /* orReverse 0xb src OR NOT dst */ 47 {O, O, I, I}, /* copyInverted 0xc NOT src */ 48 {I, O, I, I}, /* orInverted 0xd NOT src OR dst */ 49 {I, O, O, I}, /* nand 0xe NOT src OR NOT dst */ 50 {O, O, O, I}, /* set 0xf 1 */ 51}; 52 53#undef O 54#undef I 55 56#define FbDeclareMergeRop() FbBits _ca1, _cx1, _ca2, _cx2; 57#define FbDeclarePrebuiltMergeRop() FbBits _cca, _ccx; 58 59#define FbInitializeMergeRop(alu,pm) {\ 60 const FbMergeRopRec *_bits; \ 61 _bits = &FbMergeRopBits[alu]; \ 62 _ca1 = _bits->ca1 & pm; \ 63 _cx1 = _bits->cx1 | ~pm; \ 64 _ca2 = _bits->ca2 & pm; \ 65 _cx2 = _bits->cx2 & pm; \ 66} 67 68#define InitializeShifts(sx,dx,ls,rs) { \ 69 if (sx != dx) { \ 70 if (sx > dx) { \ 71 ls = sx - dx; \ 72 rs = FB_UNIT - ls; \ 73 } else { \ 74 rs = dx - sx; \ 75 ls = FB_UNIT - rs; \ 76 } \ 77 } \ 78} 79 80static void 81fbBlt__rop(FbBits *srcLine, FbStride srcStride, int srcX, 82 FbBits *dstLine, FbStride dstStride, int dstX, 83 int width, int height, 84 int alu, FbBits pm, int bpp, 85 Bool reverse, Bool upsidedown) 86{ 87 FbBits *src, *dst; 88 int leftShift, rightShift; 89 FbBits startmask, endmask; 90 FbBits bits, bits1; 91 int n, nmiddle; 92 Bool destInvarient; 93 int startbyte, endbyte; 94 95 FbDeclareMergeRop(); 96 97 FbInitializeMergeRop(alu, pm); 98 destInvarient = FbDestInvarientMergeRop(); 99 if (upsidedown) { 100 srcLine += (height - 1) * (srcStride); 101 dstLine += (height - 1) * (dstStride); 102 srcStride = -srcStride; 103 dstStride = -dstStride; 104 } 105 FbMaskBitsBytes(dstX, width, destInvarient, startmask, startbyte, 106 nmiddle, endmask, endbyte); 107 if (reverse) { 108 srcLine += ((srcX + width - 1) >> FB_SHIFT) + 1; 109 dstLine += ((dstX + width - 1) >> FB_SHIFT) + 1; 110 srcX = (srcX + width - 1) & FB_MASK; 111 dstX = (dstX + width - 1) & FB_MASK; 112 } else { 113 srcLine += srcX >> FB_SHIFT; 114 dstLine += dstX >> FB_SHIFT; 115 srcX &= FB_MASK; 116 dstX &= FB_MASK; 117 } 118 if (srcX == dstX) { 119 while (height--) { 120 src = srcLine; 121 srcLine += srcStride; 122 dst = dstLine; 123 dstLine += dstStride; 124 if (reverse) { 125 if (endmask) { 126 bits = READ(--src); 127 --dst; 128 FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask); 129 } 130 n = nmiddle; 131 if (destInvarient) { 132 while (n--) 133 WRITE(--dst, FbDoDestInvarientMergeRop(READ(--src))); 134 } else { 135 while (n--) { 136 bits = READ(--src); 137 --dst; 138 WRITE(dst, FbDoMergeRop(bits, READ(dst))); 139 } 140 } 141 if (startmask) { 142 bits = READ(--src); 143 --dst; 144 FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask); 145 } 146 } else { 147 if (startmask) { 148 bits = READ(src++); 149 FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask); 150 dst++; 151 } 152 n = nmiddle; 153 if (destInvarient) { 154 while (n--) 155 WRITE(dst++, FbDoDestInvarientMergeRop(READ(src++))); 156 } else { 157 while (n--) { 158 bits = READ(src++); 159 WRITE(dst, FbDoMergeRop(bits, READ(dst))); 160 dst++; 161 } 162 } 163 if (endmask) { 164 bits = READ(src); 165 FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask); 166 } 167 } 168 } 169 } else { 170 if (srcX > dstX) { 171 leftShift = srcX - dstX; 172 rightShift = FB_UNIT - leftShift; 173 } else { 174 rightShift = dstX - srcX; 175 leftShift = FB_UNIT - rightShift; 176 } 177 while (height--) { 178 src = srcLine; 179 srcLine += srcStride; 180 dst = dstLine; 181 dstLine += dstStride; 182 183 bits1 = 0; 184 if (reverse) { 185 if (srcX < dstX) 186 bits1 = READ(--src); 187 if (endmask) { 188 bits = FbScrRight(bits1, rightShift); 189 if (FbScrRight(endmask, leftShift)) { 190 bits1 = READ(--src); 191 bits |= FbScrLeft(bits1, leftShift); 192 } 193 --dst; 194 FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask); 195 } 196 n = nmiddle; 197 if (destInvarient) { 198 while (n--) { 199 bits = FbScrRight(bits1, rightShift); 200 bits1 = READ(--src); 201 bits |= FbScrLeft(bits1, leftShift); 202 --dst; 203 WRITE(dst, FbDoDestInvarientMergeRop(bits)); 204 } 205 } else { 206 while (n--) { 207 bits = FbScrRight(bits1, rightShift); 208 bits1 = READ(--src); 209 bits |= FbScrLeft(bits1, leftShift); 210 --dst; 211 WRITE(dst, FbDoMergeRop(bits, READ(dst))); 212 } 213 } 214 if (startmask) { 215 bits = FbScrRight(bits1, rightShift); 216 if (FbScrRight(startmask, leftShift)) { 217 bits1 = READ(--src); 218 bits |= FbScrLeft(bits1, leftShift); 219 } 220 --dst; 221 FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask); 222 } 223 } else { 224 if (srcX > dstX) 225 bits1 = READ(src++); 226 if (startmask) { 227 bits = FbScrLeft(bits1, leftShift); 228 if (FbScrLeft(startmask, rightShift)) { 229 bits1 = READ(src++); 230 bits |= FbScrRight(bits1, rightShift); 231 } 232 FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask); 233 dst++; 234 } 235 n = nmiddle; 236 if (destInvarient) { 237 while (n--) { 238 bits = FbScrLeft(bits1, leftShift); 239 bits1 = READ(src++); 240 bits |= FbScrRight(bits1, rightShift); 241 WRITE(dst, FbDoDestInvarientMergeRop(bits)); 242 dst++; 243 } 244 } else { 245 while (n--) { 246 bits = FbScrLeft(bits1, leftShift); 247 bits1 = READ(src++); 248 bits |= FbScrRight(bits1, rightShift); 249 WRITE(dst, FbDoMergeRop(bits, READ(dst))); 250 dst++; 251 } 252 } 253 if (endmask) { 254 bits = FbScrLeft(bits1, leftShift); 255 if (FbScrLeft(endmask, rightShift)) { 256 bits1 = READ(src); 257 bits |= FbScrRight(bits1, rightShift); 258 } 259 FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask); 260 } 261 } 262 } 263 } 264} 265 266void 267fbBlt(FbBits *srcLine, FbStride srcStride, int srcX, 268 FbBits *dstLine, FbStride dstStride, int dstX, 269 int width, int height, 270 int alu, FbBits pm, int bpp, 271 Bool reverse, Bool upsidedown) 272{ 273 DBG(("%s %dx%d, alu=%d, pm=%x, bpp=%d (reverse=%d, upsidedown=%d)\n", 274 __FUNCTION__, width, height, alu, pm, bpp, reverse, upsidedown)); 275 276 if (alu == GXcopy && pm == FB_ALLONES && ((srcX|dstX|width) & 7) == 0) { 277 CARD8 *s = (CARD8 *) srcLine; 278 CARD8 *d = (CARD8 *) dstLine; 279 void *(*func)(void *, const void *, size_t); 280 int i; 281 282 srcStride *= sizeof(FbBits); 283 dstStride *= sizeof(FbBits); 284 width >>= 3; 285 s += srcX >> 3; 286 d += dstX >> 3; 287 288 DBG(("%s fast blt, src_stride=%d, dst_stride=%d, width=%d (offset=%ld)\n", 289 __FUNCTION__, 290 srcStride, dstStride, width, (long)(s - d))); 291 292 if (width == srcStride && width == dstStride) { 293 width *= height; 294 height = 1; 295 } 296 297 if ((s < d && s + width > d) || (d < s && d + width > s)) 298 func = memmove; 299 else 300 func = memcpy; 301 if (!upsidedown) { 302 for (i = 0; i < height; i++) 303 func(d + i * dstStride, 304 s + i * srcStride, 305 width); 306 } else { 307 for (i = height; i--; ) 308 func(d + i * dstStride, 309 s + i * srcStride, 310 width); 311 } 312 313 return; 314 } 315 316 fbBlt__rop(srcLine, srcStride, srcX, 317 dstLine, dstStride, dstX, 318 width, height, 319 alu, pm, bpp, 320 reverse, upsidedown); 321} 322