aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/fb/fbblt.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/fb/fbblt.c')
-rw-r--r--xorg-server/fb/fbblt.c1896
1 files changed, 948 insertions, 948 deletions
diff --git a/xorg-server/fb/fbblt.c b/xorg-server/fb/fbblt.c
index 6b5327080..680940467 100644
--- a/xorg-server/fb/fbblt.c
+++ b/xorg-server/fb/fbblt.c
@@ -1,948 +1,948 @@
-/*
- * 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 *src = (CARD8 *) srcLine;
- CARD8 *dst = (CARD8 *) dstLine;
-
- srcStride *= sizeof(FbBits);
- dstStride *= sizeof(FbBits);
- width >>= 3;
- src += (srcX >> 3);
- dst += (dstX >> 3);
-
- if (!upsidedown)
- for (i = 0; i < height; i++)
- MEMCPY_WRAPPED(dst + i * dstStride, src + i * srcStride, width);
- else
- for (i = height - 1; i >= 0; i--)
- MEMCPY_WRAPPED(dst + i * dstStride, src + 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);
- }
-}
+/*
+ * 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 *src = (CARD8 *) srcLine;
+ CARD8 *dst = (CARD8 *) dstLine;
+
+ srcStride *= sizeof(FbBits);
+ dstStride *= sizeof(FbBits);
+ width >>= 3;
+ src += (srcX >> 3);
+ dst += (dstX >> 3);
+
+ if (!upsidedown)
+ for (i = 0; i < height; i++)
+ MEMCPY_WRAPPED(dst + i * dstStride, src + i * srcStride, width);
+ else
+ for (i = height - 1; i >= 0; i--)
+ MEMCPY_WRAPPED(dst + i * dstStride, src + 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);
+ }
+}