791 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			791 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * Copyright © 1998 Keith Packard
 | |
|  *
 | |
|  * 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.
 | |
|  */
 | |
| 
 | |
| #ifdef HAVE_DIX_CONFIG_H
 | |
| #include <dix-config.h>
 | |
| #endif
 | |
| 
 | |
| #include <string.h>
 | |
| #include "fb.h"
 | |
| 
 | |
| #define InitializeShifts(sx,dx,ls,rs) { \
 | |
|     if (sx != dx) { \
 | |
| 	if (sx > dx) { \
 | |
| 	    ls = sx - dx; \
 | |
| 	    rs = FB_UNIT - ls; \
 | |
| 	} else { \
 | |
| 	    rs = dx - sx; \
 | |
| 	    ls = FB_UNIT - rs; \
 | |
| 	} \
 | |
|     } \
 | |
| }
 | |
| 
 | |
| void
 | |
| fbBlt(FbBits * srcLine,
 | |
|       FbStride srcStride,
 | |
|       int srcX,
 | |
|       FbBits * dstLine,
 | |
|       FbStride dstStride,
 | |
|       int dstX,
 | |
|       int width,
 | |
|       int height, int alu, FbBits pm, int bpp, Bool reverse, Bool upsidedown)
 | |
| {
 | |
|     FbBits *src, *dst;
 | |
|     int leftShift, rightShift;
 | |
|     FbBits startmask, endmask;
 | |
|     FbBits bits, bits1;
 | |
|     int n, nmiddle;
 | |
|     Bool destInvarient;
 | |
|     int startbyte, endbyte;
 | |
|     int careful;
 | |
| 
 | |
|     FbDeclareMergeRop();
 | |
| 
 | |
|     if (bpp == 24 && !FbCheck24Pix(pm)) {
 | |
|         fbBlt24(srcLine, srcStride, srcX, dstLine, dstStride, dstX,
 | |
|                 width, height, alu, pm, reverse, upsidedown);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     careful = !((srcLine < dstLine && srcLine + width * (bpp >> 3) > dstLine) ||
 | |
|                 (dstLine < srcLine && dstLine + width * (bpp >> 3) > srcLine))
 | |
|         || (bpp & 7);
 | |
| 
 | |
|     if (alu == GXcopy && pm == FB_ALLONES && !careful &&
 | |
|         !(srcX & 7) && !(dstX & 7) && !(width & 7)) {
 | |
|         int i;
 | |
|         CARD8 *tmpsrc = (CARD8 *) srcLine;
 | |
|         CARD8 *tmpdst = (CARD8 *) dstLine;
 | |
| 
 | |
|         srcStride *= sizeof(FbBits);
 | |
|         dstStride *= sizeof(FbBits);
 | |
|         width >>= 3;
 | |
|         tmpsrc += (srcX >> 3);
 | |
|         tmpdst += (dstX >> 3);
 | |
| 
 | |
|         if (!upsidedown)
 | |
|             for (i = 0; i < height; i++)
 | |
|                 MEMCPY_WRAPPED(tmpdst + i * dstStride, tmpsrc + i * srcStride, width);
 | |
|         else
 | |
|             for (i = height - 1; i >= 0; i--)
 | |
|                 MEMCPY_WRAPPED(tmpdst + i * dstStride, tmpsrc + i * srcStride, width);
 | |
| 
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     FbInitializeMergeRop(alu, pm);
 | |
|     destInvarient = FbDestInvarientMergeRop();
 | |
|     if (upsidedown) {
 | |
|         srcLine += (height - 1) * (srcStride);
 | |
|         dstLine += (height - 1) * (dstStride);
 | |
|         srcStride = -srcStride;
 | |
|         dstStride = -dstStride;
 | |
|     }
 | |
|     FbMaskBitsBytes(dstX, width, destInvarient, startmask, startbyte,
 | |
|                     nmiddle, endmask, endbyte);
 | |
|     if (reverse) {
 | |
|         srcLine += ((srcX + width - 1) >> FB_SHIFT) + 1;
 | |
|         dstLine += ((dstX + width - 1) >> FB_SHIFT) + 1;
 | |
|         srcX = (srcX + width - 1) & FB_MASK;
 | |
|         dstX = (dstX + width - 1) & FB_MASK;
 | |
|     }
 | |
|     else {
 | |
|         srcLine += srcX >> FB_SHIFT;
 | |
|         dstLine += dstX >> FB_SHIFT;
 | |
|         srcX &= FB_MASK;
 | |
|         dstX &= FB_MASK;
 | |
|     }
 | |
|     if (srcX == dstX) {
 | |
|         while (height--) {
 | |
|             src = srcLine;
 | |
|             srcLine += srcStride;
 | |
|             dst = dstLine;
 | |
|             dstLine += dstStride;
 | |
|             if (reverse) {
 | |
|                 if (endmask) {
 | |
|                     bits = READ(--src);
 | |
|                     --dst;
 | |
|                     FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask);
 | |
|                 }
 | |
|                 n = nmiddle;
 | |
|                 if (destInvarient) {
 | |
|                     while (n--)
 | |
|                         WRITE(--dst, FbDoDestInvarientMergeRop(READ(--src)));
 | |
|                 }
 | |
|                 else {
 | |
|                     while (n--) {
 | |
|                         bits = READ(--src);
 | |
|                         --dst;
 | |
|                         WRITE(dst, FbDoMergeRop(bits, READ(dst)));
 | |
|                     }
 | |
|                 }
 | |
|                 if (startmask) {
 | |
|                     bits = READ(--src);
 | |
|                     --dst;
 | |
|                     FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask);
 | |
|                 }
 | |
|             }
 | |
|             else {
 | |
|                 if (startmask) {
 | |
|                     bits = READ(src++);
 | |
|                     FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask);
 | |
|                     dst++;
 | |
|                 }
 | |
|                 n = nmiddle;
 | |
|                 if (destInvarient) {
 | |
| #if 0
 | |
|                     /*
 | |
|                      * This provides some speedup on screen->screen blts
 | |
|                      * over the PCI bus, usually about 10%.  But fb
 | |
|                      * isn't usually used for this operation...
 | |
|                      */
 | |
|                     if (_ca2 + 1 == 0 && _cx2 == 0) {
 | |
|                         FbBits t1, t2, t3, t4;
 | |
| 
 | |
|                         while (n >= 4) {
 | |
|                             t1 = *src++;
 | |
|                             t2 = *src++;
 | |
|                             t3 = *src++;
 | |
|                             t4 = *src++;
 | |
|                             *dst++ = t1;
 | |
|                             *dst++ = t2;
 | |
|                             *dst++ = t3;
 | |
|                             *dst++ = t4;
 | |
|                             n -= 4;
 | |
|                         }
 | |
|                     }
 | |
| #endif
 | |
|                     while (n--)
 | |
|                         WRITE(dst++, FbDoDestInvarientMergeRop(READ(src++)));
 | |
|                 }
 | |
|                 else {
 | |
|                     while (n--) {
 | |
|                         bits = READ(src++);
 | |
|                         WRITE(dst, FbDoMergeRop(bits, READ(dst)));
 | |
|                         dst++;
 | |
|                     }
 | |
|                 }
 | |
|                 if (endmask) {
 | |
|                     bits = READ(src);
 | |
|                     FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     else {
 | |
|         if (srcX > dstX) {
 | |
|             leftShift = srcX - dstX;
 | |
|             rightShift = FB_UNIT - leftShift;
 | |
|         }
 | |
|         else {
 | |
|             rightShift = dstX - srcX;
 | |
|             leftShift = FB_UNIT - rightShift;
 | |
|         }
 | |
|         while (height--) {
 | |
|             src = srcLine;
 | |
|             srcLine += srcStride;
 | |
|             dst = dstLine;
 | |
|             dstLine += dstStride;
 | |
| 
 | |
|             bits1 = 0;
 | |
|             if (reverse) {
 | |
|                 if (srcX < dstX)
 | |
|                     bits1 = READ(--src);
 | |
|                 if (endmask) {
 | |
|                     bits = FbScrRight(bits1, rightShift);
 | |
|                     if (FbScrRight(endmask, leftShift)) {
 | |
|                         bits1 = READ(--src);
 | |
|                         bits |= FbScrLeft(bits1, leftShift);
 | |
|                     }
 | |
|                     --dst;
 | |
|                     FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask);
 | |
|                 }
 | |
|                 n = nmiddle;
 | |
|                 if (destInvarient) {
 | |
|                     while (n--) {
 | |
|                         bits = FbScrRight(bits1, rightShift);
 | |
|                         bits1 = READ(--src);
 | |
|                         bits |= FbScrLeft(bits1, leftShift);
 | |
|                         --dst;
 | |
|                         WRITE(dst, FbDoDestInvarientMergeRop(bits));
 | |
|                     }
 | |
|                 }
 | |
|                 else {
 | |
|                     while (n--) {
 | |
|                         bits = FbScrRight(bits1, rightShift);
 | |
|                         bits1 = READ(--src);
 | |
|                         bits |= FbScrLeft(bits1, leftShift);
 | |
|                         --dst;
 | |
|                         WRITE(dst, FbDoMergeRop(bits, READ(dst)));
 | |
|                     }
 | |
|                 }
 | |
|                 if (startmask) {
 | |
|                     bits = FbScrRight(bits1, rightShift);
 | |
|                     if (FbScrRight(startmask, leftShift)) {
 | |
|                         bits1 = READ(--src);
 | |
|                         bits |= FbScrLeft(bits1, leftShift);
 | |
|                     }
 | |
|                     --dst;
 | |
|                     FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask);
 | |
|                 }
 | |
|             }
 | |
|             else {
 | |
|                 if (srcX > dstX)
 | |
|                     bits1 = READ(src++);
 | |
|                 if (startmask) {
 | |
|                     bits = FbScrLeft(bits1, leftShift);
 | |
|                     if (FbScrLeft(startmask, rightShift)) {
 | |
|                         bits1 = READ(src++);
 | |
|                         bits |= FbScrRight(bits1, rightShift);
 | |
|                     }
 | |
|                     FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask);
 | |
|                     dst++;
 | |
|                 }
 | |
|                 n = nmiddle;
 | |
|                 if (destInvarient) {
 | |
|                     while (n--) {
 | |
|                         bits = FbScrLeft(bits1, leftShift);
 | |
|                         bits1 = READ(src++);
 | |
|                         bits |= FbScrRight(bits1, rightShift);
 | |
|                         WRITE(dst, FbDoDestInvarientMergeRop(bits));
 | |
|                         dst++;
 | |
|                     }
 | |
|                 }
 | |
|                 else {
 | |
|                     while (n--) {
 | |
|                         bits = FbScrLeft(bits1, leftShift);
 | |
|                         bits1 = READ(src++);
 | |
|                         bits |= FbScrRight(bits1, rightShift);
 | |
|                         WRITE(dst, FbDoMergeRop(bits, READ(dst)));
 | |
|                         dst++;
 | |
|                     }
 | |
|                 }
 | |
|                 if (endmask) {
 | |
|                     bits = FbScrLeft(bits1, leftShift);
 | |
|                     if (FbScrLeft(endmask, rightShift)) {
 | |
|                         bits1 = READ(src);
 | |
|                         bits |= FbScrRight(bits1, rightShift);
 | |
|                     }
 | |
|                     FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| #undef DEBUG_BLT24
 | |
| #ifdef DEBUG_BLT24
 | |
| 
 | |
| static unsigned long
 | |
| getPixel(char *src, int x)
 | |
| {
 | |
|     unsigned long l;
 | |
| 
 | |
|     l = 0;
 | |
|     memcpy(&l, src + x * 3, 3);
 | |
|     return l;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| static void
 | |
| fbBlt24Line(FbBits * src,
 | |
|             int srcX,
 | |
|             FbBits * dst, int dstX, int width, int alu, FbBits pm, Bool reverse)
 | |
| {
 | |
| #ifdef DEBUG_BLT24
 | |
|     char *origDst = (char *) dst;
 | |
|     FbBits *origLine = dst + ((dstX >> FB_SHIFT) - 1);
 | |
|     int origNlw = ((width + FB_MASK) >> FB_SHIFT) + 3;
 | |
|     int origX = dstX / 24;
 | |
| #endif
 | |
| 
 | |
|     int leftShift, rightShift;
 | |
|     FbBits startmask, endmask;
 | |
|     int n;
 | |
| 
 | |
|     FbBits bits, bits1;
 | |
|     FbBits mask;
 | |
| 
 | |
|     int rot;
 | |
| 
 | |
|     FbDeclareMergeRop();
 | |
| 
 | |
|     FbInitializeMergeRop(alu, FB_ALLONES);
 | |
|     FbMaskBits(dstX, width, startmask, n, endmask);
 | |
| #ifdef DEBUG_BLT24
 | |
|     ErrorF("dstX %d width %d reverse %d\n", dstX, width, reverse);
 | |
| #endif
 | |
|     if (reverse) {
 | |
|         src += ((srcX + width - 1) >> FB_SHIFT) + 1;
 | |
|         dst += ((dstX + width - 1) >> FB_SHIFT) + 1;
 | |
|         rot = FbFirst24Rot(((dstX + width - 8) & FB_MASK));
 | |
|         rot = FbPrev24Rot(rot);
 | |
| #ifdef DEBUG_BLT24
 | |
|         ErrorF("dstX + width - 8: %d rot: %d\n", (dstX + width - 8) & FB_MASK,
 | |
|                rot);
 | |
| #endif
 | |
|         srcX = (srcX + width - 1) & FB_MASK;
 | |
|         dstX = (dstX + width - 1) & FB_MASK;
 | |
|     }
 | |
|     else {
 | |
|         src += srcX >> FB_SHIFT;
 | |
|         dst += dstX >> FB_SHIFT;
 | |
|         srcX &= FB_MASK;
 | |
|         dstX &= FB_MASK;
 | |
|         rot = FbFirst24Rot(dstX);
 | |
| #ifdef DEBUG_BLT24
 | |
|         ErrorF("dstX: %d rot: %d\n", dstX, rot);
 | |
| #endif
 | |
|     }
 | |
|     mask = FbRot24(pm, rot);
 | |
| #ifdef DEBUG_BLT24
 | |
|     ErrorF("pm 0x%x mask 0x%x\n", pm, mask);
 | |
| #endif
 | |
|     if (srcX == dstX) {
 | |
|         if (reverse) {
 | |
|             if (endmask) {
 | |
|                 bits = READ(--src);
 | |
|                 --dst;
 | |
|                 WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask & endmask));
 | |
|                 mask = FbPrev24Pix(mask);
 | |
|             }
 | |
|             while (n--) {
 | |
|                 bits = READ(--src);
 | |
|                 --dst;
 | |
|                 WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask));
 | |
|                 mask = FbPrev24Pix(mask);
 | |
|             }
 | |
|             if (startmask) {
 | |
|                 bits = READ(--src);
 | |
|                 --dst;
 | |
|                 WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask & startmask));
 | |
|             }
 | |
|         }
 | |
|         else {
 | |
|             if (startmask) {
 | |
|                 bits = READ(src++);
 | |
|                 WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask & startmask));
 | |
|                 dst++;
 | |
|                 mask = FbNext24Pix(mask);
 | |
|             }
 | |
|             while (n--) {
 | |
|                 bits = READ(src++);
 | |
|                 WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask));
 | |
|                 dst++;
 | |
|                 mask = FbNext24Pix(mask);
 | |
|             }
 | |
|             if (endmask) {
 | |
|                 bits = READ(src);
 | |
|                 WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask & endmask));
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     else {
 | |
|         if (srcX > dstX) {
 | |
|             leftShift = srcX - dstX;
 | |
|             rightShift = FB_UNIT - leftShift;
 | |
|         }
 | |
|         else {
 | |
|             rightShift = dstX - srcX;
 | |
|             leftShift = FB_UNIT - rightShift;
 | |
|         }
 | |
| 
 | |
|         bits1 = 0;
 | |
|         if (reverse) {
 | |
|             if (srcX < dstX)
 | |
|                 bits1 = READ(--src);
 | |
|             if (endmask) {
 | |
|                 bits = FbScrRight(bits1, rightShift);
 | |
|                 if (FbScrRight(endmask, leftShift)) {
 | |
|                     bits1 = READ(--src);
 | |
|                     bits |= FbScrLeft(bits1, leftShift);
 | |
|                 }
 | |
|                 --dst;
 | |
|                 WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask & endmask));
 | |
|                 mask = FbPrev24Pix(mask);
 | |
|             }
 | |
|             while (n--) {
 | |
|                 bits = FbScrRight(bits1, rightShift);
 | |
|                 bits1 = READ(--src);
 | |
|                 bits |= FbScrLeft(bits1, leftShift);
 | |
|                 --dst;
 | |
|                 WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask));
 | |
|                 mask = FbPrev24Pix(mask);
 | |
|             }
 | |
|             if (startmask) {
 | |
|                 bits = FbScrRight(bits1, rightShift);
 | |
|                 if (FbScrRight(startmask, leftShift)) {
 | |
|                     bits1 = READ(--src);
 | |
|                     bits |= FbScrLeft(bits1, leftShift);
 | |
|                 }
 | |
|                 --dst;
 | |
|                 WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask & startmask));
 | |
|             }
 | |
|         }
 | |
|         else {
 | |
|             if (srcX > dstX)
 | |
|                 bits1 = READ(src++);
 | |
|             if (startmask) {
 | |
|                 bits = FbScrLeft(bits1, leftShift);
 | |
|                 bits1 = READ(src++);
 | |
|                 bits |= FbScrRight(bits1, rightShift);
 | |
|                 WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask & startmask));
 | |
|                 dst++;
 | |
|                 mask = FbNext24Pix(mask);
 | |
|             }
 | |
|             while (n--) {
 | |
|                 bits = FbScrLeft(bits1, leftShift);
 | |
|                 bits1 = READ(src++);
 | |
|                 bits |= FbScrRight(bits1, rightShift);
 | |
|                 WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask));
 | |
|                 dst++;
 | |
|                 mask = FbNext24Pix(mask);
 | |
|             }
 | |
|             if (endmask) {
 | |
|                 bits = FbScrLeft(bits1, leftShift);
 | |
|                 if (FbScrLeft(endmask, rightShift)) {
 | |
|                     bits1 = READ(src);
 | |
|                     bits |= FbScrRight(bits1, rightShift);
 | |
|                 }
 | |
|                 WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask & endmask));
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| #ifdef DEBUG_BLT24
 | |
|     {
 | |
|         int firstx, lastx, x;
 | |
| 
 | |
|         firstx = origX;
 | |
|         if (firstx)
 | |
|             firstx--;
 | |
|         lastx = origX + width / 24 + 1;
 | |
|         for (x = firstx; x <= lastx; x++)
 | |
|             ErrorF("%06x ", getPixel(origDst, x));
 | |
|         ErrorF("\n");
 | |
|         while (origNlw--)
 | |
|             ErrorF("%08x ", *origLine++);
 | |
|         ErrorF("\n");
 | |
|     }
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void
 | |
| fbBlt24(FbBits * srcLine,
 | |
|         FbStride srcStride,
 | |
|         int srcX,
 | |
|         FbBits * dstLine,
 | |
|         FbStride dstStride,
 | |
|         int dstX,
 | |
|         int width,
 | |
|         int height, int alu, FbBits pm, Bool reverse, Bool upsidedown)
 | |
| {
 | |
|     if (upsidedown) {
 | |
|         srcLine += (height - 1) * srcStride;
 | |
|         dstLine += (height - 1) * dstStride;
 | |
|         srcStride = -srcStride;
 | |
|         dstStride = -dstStride;
 | |
|     }
 | |
|     while (height--) {
 | |
|         fbBlt24Line(srcLine, srcX, dstLine, dstX, width, alu, pm, reverse);
 | |
|         srcLine += srcStride;
 | |
|         dstLine += dstStride;
 | |
|     }
 | |
| #ifdef DEBUG_BLT24
 | |
|     ErrorF("\n");
 | |
| #endif
 | |
| }
 | |
| 
 | |
| #if FB_SHIFT == FB_STIP_SHIFT + 1
 | |
| 
 | |
| /*
 | |
|  * Could be generalized to FB_SHIFT > FB_STIP_SHIFT + 1 by
 | |
|  * creating an ring of values stepped through for each line
 | |
|  */
 | |
| 
 | |
| void
 | |
| fbBltOdd(FbBits * srcLine,
 | |
|          FbStride srcStrideEven,
 | |
|          FbStride srcStrideOdd,
 | |
|          int srcXEven,
 | |
|          int srcXOdd,
 | |
|          FbBits * dstLine,
 | |
|          FbStride dstStrideEven,
 | |
|          FbStride dstStrideOdd,
 | |
|          int dstXEven,
 | |
|          int dstXOdd, int width, int height, int alu, FbBits pm, int bpp)
 | |
| {
 | |
|     FbBits *src;
 | |
|     int leftShiftEven, rightShiftEven;
 | |
|     FbBits startmaskEven, endmaskEven;
 | |
|     int nmiddleEven;
 | |
| 
 | |
|     FbBits *dst;
 | |
|     int leftShiftOdd, rightShiftOdd;
 | |
|     FbBits startmaskOdd, endmaskOdd;
 | |
|     int nmiddleOdd;
 | |
| 
 | |
|     int leftShift, rightShift;
 | |
|     FbBits startmask, endmask;
 | |
|     int nmiddle;
 | |
| 
 | |
|     int srcX, dstX;
 | |
| 
 | |
|     FbBits bits, bits1;
 | |
|     int n;
 | |
| 
 | |
|     Bool destInvarient;
 | |
|     Bool even;
 | |
| 
 | |
|     FbDeclareMergeRop();
 | |
| 
 | |
|     FbInitializeMergeRop(alu, pm);
 | |
|     destInvarient = FbDestInvarientMergeRop();
 | |
| 
 | |
|     srcLine += srcXEven >> FB_SHIFT;
 | |
|     dstLine += dstXEven >> FB_SHIFT;
 | |
|     srcXEven &= FB_MASK;
 | |
|     dstXEven &= FB_MASK;
 | |
|     srcXOdd &= FB_MASK;
 | |
|     dstXOdd &= FB_MASK;
 | |
| 
 | |
|     FbMaskBits(dstXEven, width, startmaskEven, nmiddleEven, endmaskEven);
 | |
|     FbMaskBits(dstXOdd, width, startmaskOdd, nmiddleOdd, endmaskOdd);
 | |
| 
 | |
|     even = TRUE;
 | |
|     InitializeShifts(srcXEven, dstXEven, leftShiftEven, rightShiftEven);
 | |
|     InitializeShifts(srcXOdd, dstXOdd, leftShiftOdd, rightShiftOdd);
 | |
|     while (height--) {
 | |
|         src = srcLine;
 | |
|         dst = dstLine;
 | |
|         if (even) {
 | |
|             srcX = srcXEven;
 | |
|             dstX = dstXEven;
 | |
|             startmask = startmaskEven;
 | |
|             endmask = endmaskEven;
 | |
|             nmiddle = nmiddleEven;
 | |
|             leftShift = leftShiftEven;
 | |
|             rightShift = rightShiftEven;
 | |
|             srcLine += srcStrideEven;
 | |
|             dstLine += dstStrideEven;
 | |
|             even = FALSE;
 | |
|         }
 | |
|         else {
 | |
|             srcX = srcXOdd;
 | |
|             dstX = dstXOdd;
 | |
|             startmask = startmaskOdd;
 | |
|             endmask = endmaskOdd;
 | |
|             nmiddle = nmiddleOdd;
 | |
|             leftShift = leftShiftOdd;
 | |
|             rightShift = rightShiftOdd;
 | |
|             srcLine += srcStrideOdd;
 | |
|             dstLine += dstStrideOdd;
 | |
|             even = TRUE;
 | |
|         }
 | |
|         if (srcX == dstX) {
 | |
|             if (startmask) {
 | |
|                 bits = READ(src++);
 | |
|                 WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), startmask));
 | |
|                 dst++;
 | |
|             }
 | |
|             n = nmiddle;
 | |
|             if (destInvarient) {
 | |
|                 while (n--) {
 | |
|                     bits = READ(src++);
 | |
|                     WRITE(dst, FbDoDestInvarientMergeRop(bits));
 | |
|                     dst++;
 | |
|                 }
 | |
|             }
 | |
|             else {
 | |
|                 while (n--) {
 | |
|                     bits = READ(src++);
 | |
|                     WRITE(dst, FbDoMergeRop(bits, READ(dst)));
 | |
|                     dst++;
 | |
|                 }
 | |
|             }
 | |
|             if (endmask) {
 | |
|                 bits = READ(src);
 | |
|                 WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), endmask));
 | |
|             }
 | |
|         }
 | |
|         else {
 | |
|             bits = 0;
 | |
|             if (srcX > dstX)
 | |
|                 bits = READ(src++);
 | |
|             if (startmask) {
 | |
|                 bits1 = FbScrLeft(bits, leftShift);
 | |
|                 bits = READ(src++);
 | |
|                 bits1 |= FbScrRight(bits, rightShift);
 | |
|                 WRITE(dst, FbDoMaskMergeRop(bits1, READ(dst), startmask));
 | |
|                 dst++;
 | |
|             }
 | |
|             n = nmiddle;
 | |
|             if (destInvarient) {
 | |
|                 while (n--) {
 | |
|                     bits1 = FbScrLeft(bits, leftShift);
 | |
|                     bits = READ(src++);
 | |
|                     bits1 |= FbScrRight(bits, rightShift);
 | |
|                     WRITE(dst, FbDoDestInvarientMergeRop(bits1));
 | |
|                     dst++;
 | |
|                 }
 | |
|             }
 | |
|             else {
 | |
|                 while (n--) {
 | |
|                     bits1 = FbScrLeft(bits, leftShift);
 | |
|                     bits = READ(src++);
 | |
|                     bits1 |= FbScrRight(bits, rightShift);
 | |
|                     WRITE(dst, FbDoMergeRop(bits1, READ(dst)));
 | |
|                     dst++;
 | |
|                 }
 | |
|             }
 | |
|             if (endmask) {
 | |
|                 bits1 = FbScrLeft(bits, leftShift);
 | |
|                 if (FbScrLeft(endmask, rightShift)) {
 | |
|                     bits = READ(src);
 | |
|                     bits1 |= FbScrRight(bits, rightShift);
 | |
|                 }
 | |
|                 WRITE(dst, FbDoMaskMergeRop(bits1, READ(dst), endmask));
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| fbBltOdd24(FbBits * srcLine,
 | |
|            FbStride srcStrideEven,
 | |
|            FbStride srcStrideOdd,
 | |
|            int srcXEven,
 | |
|            int srcXOdd,
 | |
|            FbBits * dstLine,
 | |
|            FbStride dstStrideEven,
 | |
|            FbStride dstStrideOdd,
 | |
|            int dstXEven, int dstXOdd, int width, int height, int alu, FbBits pm)
 | |
| {
 | |
|     Bool even = TRUE;
 | |
| 
 | |
|     while (height--) {
 | |
|         if (even) {
 | |
|             fbBlt24Line(srcLine, srcXEven, dstLine, dstXEven,
 | |
|                         width, alu, pm, FALSE);
 | |
|             srcLine += srcStrideEven;
 | |
|             dstLine += dstStrideEven;
 | |
|             even = FALSE;
 | |
|         }
 | |
|         else {
 | |
|             fbBlt24Line(srcLine, srcXOdd, dstLine, dstXOdd,
 | |
|                         width, alu, pm, FALSE);
 | |
|             srcLine += srcStrideOdd;
 | |
|             dstLine += dstStrideOdd;
 | |
|             even = TRUE;
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| #if FB_STIP_SHIFT != FB_SHIFT
 | |
| void
 | |
| fbSetBltOdd(FbStip * stip,
 | |
|             FbStride stipStride,
 | |
|             int srcX,
 | |
|             FbBits ** bits,
 | |
|             FbStride * strideEven,
 | |
|             FbStride * strideOdd, int *srcXEven, int *srcXOdd)
 | |
| {
 | |
|     int srcAdjust;
 | |
|     int strideAdjust;
 | |
| 
 | |
|     /*
 | |
|      * bytes needed to align source
 | |
|      */
 | |
|     srcAdjust = (((int) stip) & (FB_MASK >> 3));
 | |
|     /*
 | |
|      * FbStip units needed to align stride
 | |
|      */
 | |
|     strideAdjust = stipStride & (FB_MASK >> FB_STIP_SHIFT);
 | |
| 
 | |
|     *bits = (FbBits *) ((char *) stip - srcAdjust);
 | |
|     if (srcAdjust) {
 | |
|         *strideEven = FbStipStrideToBitsStride(stipStride + 1);
 | |
|         *strideOdd = FbStipStrideToBitsStride(stipStride);
 | |
| 
 | |
|         *srcXEven = srcX + (srcAdjust << 3);
 | |
|         *srcXOdd = srcX + (srcAdjust << 3) - (strideAdjust << FB_STIP_SHIFT);
 | |
|     }
 | |
|     else {
 | |
|         *strideEven = FbStipStrideToBitsStride(stipStride);
 | |
|         *strideOdd = FbStipStrideToBitsStride(stipStride + 1);
 | |
| 
 | |
|         *srcXEven = srcX;
 | |
|         *srcXOdd = srcX + (strideAdjust << FB_STIP_SHIFT);
 | |
|     }
 | |
| }
 | |
| #endif
 | |
| 
 | |
| void
 | |
| fbBltStip(FbStip * src, FbStride srcStride,     /* in FbStip units, not FbBits units */
 | |
|           int srcX, FbStip * dst, FbStride dstStride,   /* in FbStip units, not FbBits units */
 | |
|           int dstX, int width, int height, int alu, FbBits pm, int bpp)
 | |
| {
 | |
| #if FB_STIP_SHIFT != FB_SHIFT
 | |
|     if (FB_STIP_ODDSTRIDE(srcStride) || FB_STIP_ODDPTR(src) ||
 | |
|         FB_STIP_ODDSTRIDE(dstStride) || FB_STIP_ODDPTR(dst)) {
 | |
|         FbStride srcStrideEven, srcStrideOdd;
 | |
|         FbStride dstStrideEven, dstStrideOdd;
 | |
|         int srcXEven, srcXOdd;
 | |
|         int dstXEven, dstXOdd;
 | |
|         FbBits *s, *d;
 | |
|         int sx, dx;
 | |
| 
 | |
|         src += srcX >> FB_STIP_SHIFT;
 | |
|         srcX &= FB_STIP_MASK;
 | |
|         dst += dstX >> FB_STIP_SHIFT;
 | |
|         dstX &= FB_STIP_MASK;
 | |
| 
 | |
|         fbSetBltOdd(src, srcStride, srcX,
 | |
|                     &s, &srcStrideEven, &srcStrideOdd, &srcXEven, &srcXOdd);
 | |
| 
 | |
|         fbSetBltOdd(dst, dstStride, dstX,
 | |
|                     &d, &dstStrideEven, &dstStrideOdd, &dstXEven, &dstXOdd);
 | |
| 
 | |
|         if (bpp == 24 && !FbCheck24Pix(pm)) {
 | |
|             fbBltOdd24(s, srcStrideEven, srcStrideOdd,
 | |
|                        srcXEven, srcXOdd,
 | |
|                        d, dstStrideEven, dstStrideOdd,
 | |
|                        dstXEven, dstXOdd, width, height, alu, pm);
 | |
|         }
 | |
|         else {
 | |
|             fbBltOdd(s, srcStrideEven, srcStrideOdd,
 | |
|                      srcXEven, srcXOdd,
 | |
|                      d, dstStrideEven, dstStrideOdd,
 | |
|                      dstXEven, dstXOdd, width, height, alu, pm, bpp);
 | |
|         }
 | |
|     }
 | |
|     else
 | |
| #endif
 | |
|     {
 | |
|         fbBlt((FbBits *) src, FbStipStrideToBitsStride(srcStride),
 | |
|               srcX,
 | |
|               (FbBits *) dst, FbStipStrideToBitsStride(dstStride),
 | |
|               dstX, width, height, alu, pm, bpp, FALSE, FALSE);
 | |
|     }
 | |
| }
 |