fbblt.c revision 1b5d61b8
1/* 2 * Copyright © 1998 Keith Packard 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that 7 * copyright notice and this permission notice appear in supporting 8 * documentation, and that the name of Keith Packard not be used in 9 * advertising or publicity pertaining to distribution of the software without 10 * specific, written prior permission. Keith Packard makes no 11 * representations about the suitability of this software for any purpose. It 12 * is provided "as is" without express or implied warranty. 13 * 14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 * PERFORMANCE OF THIS SOFTWARE. 21 */ 22 23#ifdef HAVE_DIX_CONFIG_H 24#include <dix-config.h> 25#endif 26 27#include <string.h> 28#include "fb.h" 29 30#define InitializeShifts(sx,dx,ls,rs) { \ 31 if (sx != dx) { \ 32 if (sx > dx) { \ 33 ls = sx - dx; \ 34 rs = FB_UNIT - ls; \ 35 } else { \ 36 rs = dx - sx; \ 37 ls = FB_UNIT - rs; \ 38 } \ 39 } \ 40} 41 42void 43fbBlt(FbBits * srcLine, 44 FbStride srcStride, 45 int srcX, 46 FbBits * dstLine, 47 FbStride dstStride, 48 int dstX, 49 int width, 50 int height, int alu, FbBits pm, int bpp, Bool reverse, Bool upsidedown) 51{ 52 FbBits *src, *dst; 53 int leftShift, rightShift; 54 FbBits startmask, endmask; 55 FbBits bits, bits1; 56 int n, nmiddle; 57 Bool destInvarient; 58 int startbyte, endbyte; 59 60 FbDeclareMergeRop(); 61 62 if (alu == GXcopy && pm == FB_ALLONES && 63 !(srcX & 7) && !(dstX & 7) && !(width & 7)) 64 { 65 CARD8 *src_byte = (CARD8 *) srcLine + (srcX >> 3); 66 CARD8 *dst_byte = (CARD8 *) dstLine + (dstX >> 3); 67 FbStride src_byte_stride = srcStride << (FB_SHIFT - 3); 68 FbStride dst_byte_stride = dstStride << (FB_SHIFT - 3); 69 int width_byte = (width >> 3); 70 71 /* Make sure there's no overlap; we can't use memcpy in that 72 * case as it's not well defined, so fall through to the 73 * general code 74 */ 75 if (src_byte + width_byte <= dst_byte || 76 dst_byte + width_byte <= src_byte) 77 { 78 int i; 79 80 if (!upsidedown) 81 for (i = 0; i < height; i++) 82 MEMCPY_WRAPPED(dst_byte + i * dst_byte_stride, 83 src_byte + i * src_byte_stride, 84 width_byte); 85 else 86 for (i = height - 1; i >= 0; i--) 87 MEMCPY_WRAPPED(dst_byte + i * dst_byte_stride, 88 src_byte + i * src_byte_stride, 89 width_byte); 90 91 return; 92 } 93 } 94 95 FbInitializeMergeRop(alu, pm); 96 destInvarient = FbDestInvarientMergeRop(); 97 if (upsidedown) { 98 srcLine += (height - 1) * (srcStride); 99 dstLine += (height - 1) * (dstStride); 100 srcStride = -srcStride; 101 dstStride = -dstStride; 102 } 103 FbMaskBitsBytes(dstX, width, destInvarient, startmask, startbyte, 104 nmiddle, endmask, endbyte); 105 if (reverse) { 106 srcLine += ((srcX + width - 1) >> FB_SHIFT) + 1; 107 dstLine += ((dstX + width - 1) >> FB_SHIFT) + 1; 108 srcX = (srcX + width - 1) & FB_MASK; 109 dstX = (dstX + width - 1) & FB_MASK; 110 } 111 else { 112 srcLine += srcX >> FB_SHIFT; 113 dstLine += dstX >> FB_SHIFT; 114 srcX &= FB_MASK; 115 dstX &= FB_MASK; 116 } 117 if (srcX == dstX) { 118 while (height--) { 119 src = srcLine; 120 srcLine += srcStride; 121 dst = dstLine; 122 dstLine += dstStride; 123 if (reverse) { 124 if (endmask) { 125 bits = READ(--src); 126 --dst; 127 FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask); 128 } 129 n = nmiddle; 130 if (destInvarient) { 131 while (n--) 132 WRITE(--dst, FbDoDestInvarientMergeRop(READ(--src))); 133 } 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 } 147 else { 148 if (startmask) { 149 bits = READ(src++); 150 FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask); 151 dst++; 152 } 153 n = nmiddle; 154 if (destInvarient) { 155#if 0 156 /* 157 * This provides some speedup on screen->screen blts 158 * over the PCI bus, usually about 10%. But fb 159 * isn't usually used for this operation... 160 */ 161 if (_ca2 + 1 == 0 && _cx2 == 0) { 162 FbBits t1, t2, t3, t4; 163 164 while (n >= 4) { 165 t1 = *src++; 166 t2 = *src++; 167 t3 = *src++; 168 t4 = *src++; 169 *dst++ = t1; 170 *dst++ = t2; 171 *dst++ = t3; 172 *dst++ = t4; 173 n -= 4; 174 } 175 } 176#endif 177 while (n--) 178 WRITE(dst++, FbDoDestInvarientMergeRop(READ(src++))); 179 } 180 else { 181 while (n--) { 182 bits = READ(src++); 183 WRITE(dst, FbDoMergeRop(bits, READ(dst))); 184 dst++; 185 } 186 } 187 if (endmask) { 188 bits = READ(src); 189 FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask); 190 } 191 } 192 } 193 } 194 else { 195 if (srcX > dstX) { 196 leftShift = srcX - dstX; 197 rightShift = FB_UNIT - leftShift; 198 } 199 else { 200 rightShift = dstX - srcX; 201 leftShift = FB_UNIT - rightShift; 202 } 203 while (height--) { 204 src = srcLine; 205 srcLine += srcStride; 206 dst = dstLine; 207 dstLine += dstStride; 208 209 bits1 = 0; 210 if (reverse) { 211 if (srcX < dstX) 212 bits1 = READ(--src); 213 if (endmask) { 214 bits = FbScrRight(bits1, rightShift); 215 if (FbScrRight(endmask, leftShift)) { 216 bits1 = READ(--src); 217 bits |= FbScrLeft(bits1, leftShift); 218 } 219 --dst; 220 FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask); 221 } 222 n = nmiddle; 223 if (destInvarient) { 224 while (n--) { 225 bits = FbScrRight(bits1, rightShift); 226 bits1 = READ(--src); 227 bits |= FbScrLeft(bits1, leftShift); 228 --dst; 229 WRITE(dst, FbDoDestInvarientMergeRop(bits)); 230 } 231 } 232 else { 233 while (n--) { 234 bits = FbScrRight(bits1, rightShift); 235 bits1 = READ(--src); 236 bits |= FbScrLeft(bits1, leftShift); 237 --dst; 238 WRITE(dst, FbDoMergeRop(bits, READ(dst))); 239 } 240 } 241 if (startmask) { 242 bits = FbScrRight(bits1, rightShift); 243 if (FbScrRight(startmask, leftShift)) { 244 bits1 = READ(--src); 245 bits |= FbScrLeft(bits1, leftShift); 246 } 247 --dst; 248 FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask); 249 } 250 } 251 else { 252 if (srcX > dstX) 253 bits1 = READ(src++); 254 if (startmask) { 255 bits = FbScrLeft(bits1, leftShift); 256 if (FbScrLeft(startmask, rightShift)) { 257 bits1 = READ(src++); 258 bits |= FbScrRight(bits1, rightShift); 259 } 260 FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask); 261 dst++; 262 } 263 n = nmiddle; 264 if (destInvarient) { 265 while (n--) { 266 bits = FbScrLeft(bits1, leftShift); 267 bits1 = READ(src++); 268 bits |= FbScrRight(bits1, rightShift); 269 WRITE(dst, FbDoDestInvarientMergeRop(bits)); 270 dst++; 271 } 272 } 273 else { 274 while (n--) { 275 bits = FbScrLeft(bits1, leftShift); 276 bits1 = READ(src++); 277 bits |= FbScrRight(bits1, rightShift); 278 WRITE(dst, FbDoMergeRop(bits, READ(dst))); 279 dst++; 280 } 281 } 282 if (endmask) { 283 bits = FbScrLeft(bits1, leftShift); 284 if (FbScrLeft(endmask, rightShift)) { 285 bits1 = READ(src); 286 bits |= FbScrRight(bits1, rightShift); 287 } 288 FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask); 289 } 290 } 291 } 292 } 293} 294 295void 296fbBltStip(FbStip * src, FbStride srcStride, /* in FbStip units, not FbBits units */ 297 int srcX, FbStip * dst, FbStride dstStride, /* in FbStip units, not FbBits units */ 298 int dstX, int width, int height, int alu, FbBits pm, int bpp) 299{ 300 fbBlt((FbBits *) src, FbStipStrideToBitsStride(srcStride), srcX, 301 (FbBits *) dst, FbStipStrideToBitsStride(dstStride), dstX, 302 width, height, alu, pm, bpp, FALSE, FALSE); 303} 304