957 lines
20 KiB
C
957 lines
20 KiB
C
/*
|
|
* Id: fbblt.c,v 1.1 1999/11/02 03:54:45 keithp Exp $
|
|
*
|
|
* 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;
|
|
FbDeclareMergeRop ();
|
|
|
|
#ifdef FB_24BIT
|
|
if (bpp == 24 && !FbCheck24Pix (pm))
|
|
{
|
|
fbBlt24 (srcLine, srcStride, srcX, dstLine, dstStride, dstX,
|
|
width, height, alu, pm, reverse, upsidedown);
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if (alu == GXcopy && pm == FB_ALLONES && !reverse &&
|
|
!(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(dst + i * dstStride, src + i * srcStride, width);
|
|
else
|
|
for (i = height - 1; i >= 0; i--)
|
|
memcpy(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 = *--src;
|
|
--dst;
|
|
FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask);
|
|
}
|
|
n = nmiddle;
|
|
if (destInvarient)
|
|
{
|
|
while (n--)
|
|
*--dst = FbDoDestInvarientMergeRop(*--src);
|
|
}
|
|
else
|
|
{
|
|
while (n--)
|
|
{
|
|
bits = *--src;
|
|
--dst;
|
|
*dst = FbDoMergeRop (bits, *dst);
|
|
}
|
|
}
|
|
if (startmask)
|
|
{
|
|
bits = *--src;
|
|
--dst;
|
|
FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (startmask)
|
|
{
|
|
bits = *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--)
|
|
*dst++ = FbDoDestInvarientMergeRop(*src++);
|
|
}
|
|
else
|
|
{
|
|
while (n--)
|
|
{
|
|
bits = *src++;
|
|
*dst = FbDoMergeRop (bits, *dst);
|
|
dst++;
|
|
}
|
|
}
|
|
if (endmask)
|
|
{
|
|
bits = *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 = *--src;
|
|
if (endmask)
|
|
{
|
|
bits = FbScrRight(bits1, rightShift);
|
|
if (FbScrRight(endmask, leftShift))
|
|
{
|
|
bits1 = *--src;
|
|
bits |= FbScrLeft(bits1, leftShift);
|
|
}
|
|
--dst;
|
|
FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask);
|
|
}
|
|
n = nmiddle;
|
|
if (destInvarient)
|
|
{
|
|
while (n--)
|
|
{
|
|
bits = FbScrRight(bits1, rightShift);
|
|
bits1 = *--src;
|
|
bits |= FbScrLeft(bits1, leftShift);
|
|
--dst;
|
|
*dst = FbDoDestInvarientMergeRop(bits);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (n--)
|
|
{
|
|
bits = FbScrRight(bits1, rightShift);
|
|
bits1 = *--src;
|
|
bits |= FbScrLeft(bits1, leftShift);
|
|
--dst;
|
|
*dst = FbDoMergeRop(bits, *dst);
|
|
}
|
|
}
|
|
if (startmask)
|
|
{
|
|
bits = FbScrRight(bits1, rightShift);
|
|
if (FbScrRight(startmask, leftShift))
|
|
{
|
|
bits1 = *--src;
|
|
bits |= FbScrLeft(bits1, leftShift);
|
|
}
|
|
--dst;
|
|
FbDoLeftMaskByteMergeRop (dst, bits, startbyte, startmask);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (srcX > dstX)
|
|
bits1 = *src++;
|
|
if (startmask)
|
|
{
|
|
bits = FbScrLeft(bits1, leftShift);
|
|
if (FbScrLeft(startmask, rightShift))
|
|
{
|
|
bits1 = *src++;
|
|
bits |= FbScrRight(bits1, rightShift);
|
|
}
|
|
FbDoLeftMaskByteMergeRop (dst, bits, startbyte, startmask);
|
|
dst++;
|
|
}
|
|
n = nmiddle;
|
|
if (destInvarient)
|
|
{
|
|
while (n--)
|
|
{
|
|
bits = FbScrLeft(bits1, leftShift);
|
|
bits1 = *src++;
|
|
bits |= FbScrRight(bits1, rightShift);
|
|
*dst = FbDoDestInvarientMergeRop(bits);
|
|
dst++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (n--)
|
|
{
|
|
bits = FbScrLeft(bits1, leftShift);
|
|
bits1 = *src++;
|
|
bits |= FbScrRight(bits1, rightShift);
|
|
*dst = FbDoMergeRop(bits, *dst);
|
|
dst++;
|
|
}
|
|
}
|
|
if (endmask)
|
|
{
|
|
bits = FbScrLeft(bits1, leftShift);
|
|
if (FbScrLeft(endmask, rightShift))
|
|
{
|
|
bits1 = *src;
|
|
bits |= FbScrRight(bits1, rightShift);
|
|
}
|
|
FbDoRightMaskByteMergeRop (dst, bits, endbyte, endmask);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef FB_24BIT
|
|
|
|
#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 = *--src;
|
|
--dst;
|
|
*dst = FbDoMaskMergeRop (bits, *dst, mask & endmask);
|
|
mask = FbPrev24Pix (mask);
|
|
}
|
|
while (n--)
|
|
{
|
|
bits = *--src;
|
|
--dst;
|
|
*dst = FbDoMaskMergeRop (bits, *dst, mask);
|
|
mask = FbPrev24Pix (mask);
|
|
}
|
|
if (startmask)
|
|
{
|
|
bits = *--src;
|
|
--dst;
|
|
*dst = FbDoMaskMergeRop(bits, *dst, mask & startmask);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (startmask)
|
|
{
|
|
bits = *src++;
|
|
*dst = FbDoMaskMergeRop (bits, *dst, mask & startmask);
|
|
dst++;
|
|
mask = FbNext24Pix(mask);
|
|
}
|
|
while (n--)
|
|
{
|
|
bits = *src++;
|
|
*dst = FbDoMaskMergeRop (bits, *dst, mask);
|
|
dst++;
|
|
mask = FbNext24Pix(mask);
|
|
}
|
|
if (endmask)
|
|
{
|
|
bits = *src;
|
|
*dst = FbDoMaskMergeRop(bits, *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 = *--src;
|
|
if (endmask)
|
|
{
|
|
bits = FbScrRight(bits1, rightShift);
|
|
if (FbScrRight(endmask, leftShift))
|
|
{
|
|
bits1 = *--src;
|
|
bits |= FbScrLeft(bits1, leftShift);
|
|
}
|
|
--dst;
|
|
*dst = FbDoMaskMergeRop (bits, *dst, mask & endmask);
|
|
mask = FbPrev24Pix(mask);
|
|
}
|
|
while (n--)
|
|
{
|
|
bits = FbScrRight(bits1, rightShift);
|
|
bits1 = *--src;
|
|
bits |= FbScrLeft(bits1, leftShift);
|
|
--dst;
|
|
*dst = FbDoMaskMergeRop(bits, *dst, mask);
|
|
mask = FbPrev24Pix(mask);
|
|
}
|
|
if (startmask)
|
|
{
|
|
bits = FbScrRight(bits1, rightShift);
|
|
if (FbScrRight(startmask, leftShift))
|
|
{
|
|
bits1 = *--src;
|
|
bits |= FbScrLeft(bits1, leftShift);
|
|
}
|
|
--dst;
|
|
*dst = FbDoMaskMergeRop (bits, *dst, mask & startmask);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (srcX > dstX)
|
|
bits1 = *src++;
|
|
if (startmask)
|
|
{
|
|
bits = FbScrLeft(bits1, leftShift);
|
|
bits1 = *src++;
|
|
bits |= FbScrRight(bits1, rightShift);
|
|
*dst = FbDoMaskMergeRop (bits, *dst, mask & startmask);
|
|
dst++;
|
|
mask = FbNext24Pix(mask);
|
|
}
|
|
while (n--)
|
|
{
|
|
bits = FbScrLeft(bits1, leftShift);
|
|
bits1 = *src++;
|
|
bits |= FbScrRight(bits1, rightShift);
|
|
*dst = FbDoMaskMergeRop(bits, *dst, mask);
|
|
dst++;
|
|
mask = FbNext24Pix(mask);
|
|
}
|
|
if (endmask)
|
|
{
|
|
bits = FbScrLeft(bits1, leftShift);
|
|
if (FbScrLeft(endmask, rightShift))
|
|
{
|
|
bits1 = *src;
|
|
bits |= FbScrRight(bits1, rightShift);
|
|
}
|
|
*dst = FbDoMaskMergeRop (bits, *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
|
|
}
|
|
#endif /* FB_24BIT */
|
|
|
|
#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 = *src++;
|
|
*dst = FbDoMaskMergeRop (bits, *dst, startmask);
|
|
dst++;
|
|
}
|
|
n = nmiddle;
|
|
if (destInvarient)
|
|
{
|
|
while (n--)
|
|
{
|
|
bits = *src++;
|
|
*dst = FbDoDestInvarientMergeRop(bits);
|
|
dst++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (n--)
|
|
{
|
|
bits = *src++;
|
|
*dst = FbDoMergeRop (bits, *dst);
|
|
dst++;
|
|
}
|
|
}
|
|
if (endmask)
|
|
{
|
|
bits = *src;
|
|
*dst = FbDoMaskMergeRop(bits, *dst, endmask);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bits = 0;
|
|
if (srcX > dstX)
|
|
bits = *src++;
|
|
if (startmask)
|
|
{
|
|
bits1 = FbScrLeft(bits, leftShift);
|
|
bits = *src++;
|
|
bits1 |= FbScrRight(bits, rightShift);
|
|
*dst = FbDoMaskMergeRop (bits1, *dst, startmask);
|
|
dst++;
|
|
}
|
|
n = nmiddle;
|
|
if (destInvarient)
|
|
{
|
|
while (n--)
|
|
{
|
|
bits1 = FbScrLeft(bits, leftShift);
|
|
bits = *src++;
|
|
bits1 |= FbScrRight(bits, rightShift);
|
|
*dst = FbDoDestInvarientMergeRop(bits1);
|
|
dst++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (n--)
|
|
{
|
|
bits1 = FbScrLeft(bits, leftShift);
|
|
bits = *src++;
|
|
bits1 |= FbScrRight(bits, rightShift);
|
|
*dst = FbDoMergeRop(bits1, *dst);
|
|
dst++;
|
|
}
|
|
}
|
|
if (endmask)
|
|
{
|
|
bits1 = FbScrLeft(bits, leftShift);
|
|
if (FbScrLeft(endmask, rightShift))
|
|
{
|
|
bits = *src;
|
|
bits1 |= FbScrRight(bits, rightShift);
|
|
}
|
|
*dst = FbDoMaskMergeRop (bits1, *dst, endmask);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef FB_24BIT
|
|
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;
|
|
}
|
|
}
|
|
#if 0
|
|
fprintf (stderr, "\n");
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#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);
|
|
|
|
#ifdef FB_24BIT
|
|
if (bpp == 24 && !FbCheck24Pix (pm))
|
|
{
|
|
fbBltOdd24 (s, srcStrideEven, srcStrideOdd,
|
|
srcXEven, srcXOdd,
|
|
|
|
d, dstStrideEven, dstStrideOdd,
|
|
dstXEven, dstXOdd,
|
|
|
|
width, height, alu, pm);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
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);
|
|
}
|
|
}
|