fbblt.c revision 4642e01f
11.24Sriastrad/*
21.1Smacallan * Copyright © 1998 Keith Packard
31.1Smacallan *
41.1Smacallan * Permission to use, copy, modify, distribute, and sell this software and its
51.1Smacallan * documentation for any purpose is hereby granted without fee, provided that
61.1Smacallan * the above copyright notice appear in all copies and that both that
71.1Smacallan * copyright notice and this permission notice appear in supporting
81.1Smacallan * documentation, and that the name of Keith Packard not be used in
91.1Smacallan * advertising or publicity pertaining to distribution of the software without
101.1Smacallan * specific, written prior permission.  Keith Packard makes no
111.1Smacallan * representations about the suitability of this software for any purpose.  It
121.1Smacallan * is provided "as is" without express or implied warranty.
131.1Smacallan *
141.1Smacallan * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
151.1Smacallan * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
161.1Smacallan * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
171.1Smacallan * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
181.1Smacallan * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
191.1Smacallan * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
201.1Smacallan * PERFORMANCE OF THIS SOFTWARE.
211.1Smacallan */
221.1Smacallan
231.1Smacallan#ifdef HAVE_DIX_CONFIG_H
241.1Smacallan#include <dix-config.h>
251.1Smacallan#endif
261.1Smacallan
271.1Smacallan#include <string.h>
281.7Sriastrad#include "fb.h"
291.1Smacallan
301.1Smacallan#define InitializeShifts(sx,dx,ls,rs) { \
311.4Smacallan    if (sx != dx) { \
321.1Smacallan	if (sx > dx) { \
331.1Smacallan	    ls = sx - dx; \
341.1Smacallan	    rs = FB_UNIT - ls; \
351.24Sriastrad	} else { \
361.1Smacallan	    rs = dx - sx; \
371.1Smacallan	    ls = FB_UNIT - rs; \
381.1Smacallan	} \
391.1Smacallan    } \
401.1Smacallan}
411.1Smacallan
421.1Smacallanvoid
431.1SmacallanfbBlt (FbBits   *srcLine,
441.1Smacallan       FbStride	srcStride,
451.1Smacallan       int	srcX,
461.1Smacallan
471.1Smacallan       FbBits   *dstLine,
481.1Smacallan       FbStride dstStride,
491.1Smacallan       int	dstX,
501.1Smacallan
511.1Smacallan       int	width,
521.1Smacallan       int	height,
531.1Smacallan
541.1Smacallan       int	alu,
551.1Smacallan       FbBits	pm,
561.1Smacallan       int	bpp,
571.1Smacallan
581.1Smacallan       Bool	reverse,
591.1Smacallan       Bool	upsidedown)
601.1Smacallan{
611.1Smacallan    FbBits  *src, *dst;
621.1Smacallan    int	    leftShift, rightShift;
631.1Smacallan    FbBits  startmask, endmask;
641.1Smacallan    FbBits  bits, bits1;
651.1Smacallan    int	    n, nmiddle;
661.1Smacallan    Bool    destInvarient;
671.1Smacallan    int	    startbyte, endbyte;
681.1Smacallan    FbDeclareMergeRop ();
691.1Smacallan
701.1Smacallan#ifdef FB_24BIT
711.1Smacallan    if (bpp == 24 && !FbCheck24Pix (pm))
721.1Smacallan    {
731.1Smacallan	fbBlt24 (srcLine, srcStride, srcX, dstLine, dstStride, dstX,
741.1Smacallan		 width, height, alu, pm, reverse, upsidedown);
751.1Smacallan	return;
761.1Smacallan    }
771.1Smacallan#endif
781.1Smacallan
791.1Smacallan    if (alu == GXcopy && pm == FB_ALLONES && !reverse &&
801.1Smacallan            !(srcX & 7) && !(dstX & 7) && !(width & 7)) {
811.1Smacallan        int i;
821.1Smacallan        CARD8 *src = (CARD8 *) srcLine;
831.1Smacallan        CARD8 *dst = (CARD8 *) dstLine;
841.1Smacallan
851.1Smacallan        srcStride *= sizeof(FbBits);
861.1Smacallan        dstStride *= sizeof(FbBits);
871.1Smacallan        width >>= 3;
881.1Smacallan        src += (srcX >> 3);
891.1Smacallan        dst += (dstX >> 3);
901.1Smacallan
911.1Smacallan        if (!upsidedown)
921.1Smacallan            for (i = 0; i < height; i++)
931.1Smacallan                MEMCPY_WRAPPED(dst + i * dstStride, src + i * srcStride, width);
941.1Smacallan        else
951.1Smacallan            for (i = height - 1; i >= 0; i--)
961.1Smacallan                MEMCPY_WRAPPED(dst + i * dstStride, src + i * srcStride, width);
971.1Smacallan
981.6Smacallan        return;
991.6Smacallan    }
1001.6Smacallan
1011.1Smacallan    FbInitializeMergeRop(alu, pm);
1021.1Smacallan    destInvarient = FbDestInvarientMergeRop();
1031.1Smacallan    if (upsidedown)
1041.1Smacallan    {
1051.1Smacallan	srcLine += (height - 1) * (srcStride);
1061.1Smacallan	dstLine += (height - 1) * (dstStride);
1071.1Smacallan	srcStride = -srcStride;
1081.1Smacallan	dstStride = -dstStride;
1091.1Smacallan    }
1101.1Smacallan    FbMaskBitsBytes (dstX, width, destInvarient, startmask, startbyte,
1111.1Smacallan		     nmiddle, endmask, endbyte);
1121.5Smacallan    if (reverse)
1131.5Smacallan    {
1141.1Smacallan	srcLine += ((srcX + width - 1) >> FB_SHIFT) + 1;
1151.1Smacallan	dstLine += ((dstX + width - 1) >> FB_SHIFT) + 1;
1161.1Smacallan	srcX = (srcX + width - 1) & FB_MASK;
1171.1Smacallan	dstX = (dstX + width - 1) & FB_MASK;
1181.1Smacallan    }
1191.1Smacallan    else
1201.7Sriastrad    {
1211.7Sriastrad	srcLine += srcX >> FB_SHIFT;
1221.7Sriastrad	dstLine += dstX >> FB_SHIFT;
1231.7Sriastrad	srcX &= FB_MASK;
1241.1Smacallan	dstX &= FB_MASK;
1251.1Smacallan    }
1261.1Smacallan    if (srcX == dstX)
1271.1Smacallan    {
1281.1Smacallan	while (height--)
1291.1Smacallan	{
1301.2Smacallan	    src = srcLine;
1311.2Smacallan	    srcLine += srcStride;
1321.2Smacallan	    dst = dstLine;
1331.2Smacallan	    dstLine += dstStride;
1341.2Smacallan	    if (reverse)
1351.2Smacallan	    {
1361.2Smacallan		if (endmask)
1371.2Smacallan		{
1381.2Smacallan		    bits = READ(--src);
1391.2Smacallan		    --dst;
1401.2Smacallan		    FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask);
1411.2Smacallan		}
1421.2Smacallan		n = nmiddle;
1431.7Sriastrad		if (destInvarient)
1441.7Sriastrad		{
1451.2Smacallan		    while (n--)
1461.2Smacallan			WRITE(--dst, FbDoDestInvarientMergeRop(READ(--src)));
1471.2Smacallan		}
1481.1Smacallan		else
1491.1Smacallan		{
1501.1Smacallan		    while (n--)
1511.1Smacallan		    {
1521.1Smacallan			bits = READ(--src);
1531.1Smacallan			--dst;
1541.1Smacallan			WRITE(dst, FbDoMergeRop (bits, READ(dst)));
1551.1Smacallan		    }
1561.1Smacallan		}
1571.1Smacallan		if (startmask)
1581.1Smacallan		{
1591.1Smacallan		    bits = READ(--src);
1601.1Smacallan		    --dst;
1611.1Smacallan		    FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask);
1621.1Smacallan		}
1631.1Smacallan	    }
1641.1Smacallan	    else
1651.1Smacallan	    {
1661.1Smacallan		if (startmask)
1671.1Smacallan		{
1681.1Smacallan		    bits = READ(src++);
1691.1Smacallan		    FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask);
1701.1Smacallan		    dst++;
1711.1Smacallan		}
1721.1Smacallan		n = nmiddle;
1731.1Smacallan		if (destInvarient)
1741.1Smacallan		{
1751.1Smacallan#if 0
1761.1Smacallan		    /*
1771.1Smacallan		     * This provides some speedup on screen->screen blts
1781.1Smacallan		     * over the PCI bus, usually about 10%.  But fb
1791.1Smacallan		     * isn't usually used for this operation...
1801.1Smacallan		     */
1811.1Smacallan		    if (_ca2 + 1 == 0 && _cx2 == 0)
1821.1Smacallan		    {
1831.1Smacallan			FbBits	t1, t2, t3, t4;
1841.1Smacallan			while (n >= 4)
1851.1Smacallan			{
1861.1Smacallan			    t1 = *src++;
1871.1Smacallan			    t2 = *src++;
1881.1Smacallan			    t3 = *src++;
1891.1Smacallan			    t4 = *src++;
1901.1Smacallan			    *dst++ = t1;
1911.1Smacallan			    *dst++ = t2;
1921.1Smacallan			    *dst++ = t3;
1931.1Smacallan			    *dst++ = t4;
1941.1Smacallan			    n -= 4;
1951.2Smacallan			}
1961.2Smacallan		    }
1971.2Smacallan#endif
1981.2Smacallan		    while (n--)
1991.2Smacallan			WRITE(dst++, FbDoDestInvarientMergeRop(READ(src++)));
2001.2Smacallan		}
2011.2Smacallan		else
2021.2Smacallan		{
2031.2Smacallan		    while (n--)
2041.2Smacallan		    {
2051.5Smacallan			bits = READ(src++);
2061.1Smacallan			WRITE(dst, FbDoMergeRop (bits, READ(dst)));
2071.1Smacallan			dst++;
2081.1Smacallan		    }
2091.6Smacallan		}
2101.6Smacallan		if (endmask)
2111.6Smacallan		{
2121.6Smacallan		    bits = READ(src);
2131.1Smacallan		    FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask);
2141.5Smacallan		}
2151.11Sriastrad	    }
2161.10Smacallan	}
2171.5Smacallan    }
2181.6Smacallan    else
2191.11Sriastrad    {
2201.10Smacallan	if (srcX > dstX)
2211.6Smacallan	{
2221.6Smacallan	    leftShift = srcX - dstX;
2231.5Smacallan	    rightShift = FB_UNIT - leftShift;
2241.5Smacallan	}
2251.5Smacallan	else
2261.5Smacallan	{
2271.5Smacallan	    rightShift = dstX - srcX;
2281.5Smacallan	    leftShift = FB_UNIT - rightShift;
2291.5Smacallan	}
2301.5Smacallan	while (height--)
2311.5Smacallan	{
2321.5Smacallan	    src = srcLine;
2331.5Smacallan	    srcLine += srcStride;
2341.11Sriastrad	    dst = dstLine;
2351.10Smacallan	    dstLine += dstStride;
2361.5Smacallan
2371.1Smacallan	    bits1 = 0;
2381.5Smacallan	    if (reverse)
2391.1Smacallan	    {
2401.1Smacallan		if (srcX < dstX)
2411.1Smacallan		    bits1 = READ(--src);
2421.1Smacallan		if (endmask)
2431.1Smacallan		{
2441.1Smacallan		    bits = FbScrRight(bits1, rightShift);
2451.1Smacallan		    if (FbScrRight(endmask, leftShift))
2461.1Smacallan		    {
2471.1Smacallan			bits1 = READ(--src);
2481.1Smacallan			bits |= FbScrLeft(bits1, leftShift);
2491.1Smacallan		    }
2501.1Smacallan		    --dst;
2511.1Smacallan		    FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask);
2521.1Smacallan		}
2531.1Smacallan		n = nmiddle;
2541.1Smacallan		if (destInvarient)
2551.1Smacallan		{
2561.1Smacallan		    while (n--)
2571.1Smacallan		    {
2581.1Smacallan			bits = FbScrRight(bits1, rightShift);
2591.1Smacallan			bits1 = READ(--src);
2601.1Smacallan			bits |= FbScrLeft(bits1, leftShift);
2611.1Smacallan			--dst;
2621.1Smacallan			WRITE(dst, FbDoDestInvarientMergeRop(bits));
2631.1Smacallan		    }
2641.1Smacallan		}
2651.1Smacallan		else
2661.1Smacallan		{
2671.1Smacallan		    while (n--)
2681.1Smacallan		    {
2691.1Smacallan			bits = FbScrRight(bits1, rightShift);
2701.1Smacallan			bits1 = READ(--src);
2711.1Smacallan			bits |= FbScrLeft(bits1, leftShift);
2721.1Smacallan			--dst;
2731.1Smacallan			WRITE(dst, FbDoMergeRop(bits, READ(dst)));
2741.1Smacallan		    }
2751.1Smacallan		}
2761.1Smacallan		if (startmask)
2771.1Smacallan		{
2781.1Smacallan		    bits = FbScrRight(bits1, rightShift);
2791.1Smacallan		    if (FbScrRight(startmask, leftShift))
2801.1Smacallan		    {
2811.1Smacallan			bits1 = READ(--src);
2821.1Smacallan			bits |= FbScrLeft(bits1, leftShift);
2831.1Smacallan		    }
2841.1Smacallan		    --dst;
2851.1Smacallan		    FbDoLeftMaskByteMergeRop (dst, bits, startbyte, startmask);
2861.1Smacallan		}
2871.1Smacallan	    }
2881.1Smacallan	    else
2891.1Smacallan	    {
2901.1Smacallan		if (srcX > dstX)
2911.1Smacallan		    bits1 = READ(src++);
2921.1Smacallan		if (startmask)
2931.1Smacallan		{
2941.1Smacallan		    bits = FbScrLeft(bits1, leftShift);
2951.1Smacallan		    if (FbScrLeft(startmask, rightShift))
2961.1Smacallan		    {
2971.1Smacallan			bits1 = READ(src++);
2981.1Smacallan			bits |= FbScrRight(bits1, rightShift);
2991.1Smacallan		    }
3001.1Smacallan		    FbDoLeftMaskByteMergeRop (dst, bits, startbyte, startmask);
3011.1Smacallan		    dst++;
3021.1Smacallan		}
3031.1Smacallan		n = nmiddle;
3041.1Smacallan		if (destInvarient)
3051.1Smacallan		{
3061.1Smacallan		    while (n--)
3071.1Smacallan		    {
3081.1Smacallan			bits = FbScrLeft(bits1, leftShift);
3091.1Smacallan			bits1 = READ(src++);
3101.1Smacallan			bits |= FbScrRight(bits1, rightShift);
3111.1Smacallan			WRITE(dst, FbDoDestInvarientMergeRop(bits));
3121.1Smacallan			dst++;
3131.1Smacallan		    }
3141.1Smacallan		}
3151.1Smacallan		else
3161.1Smacallan		{
3171.1Smacallan		    while (n--)
3181.1Smacallan		    {
3191.1Smacallan			bits = FbScrLeft(bits1, leftShift);
3201.1Smacallan			bits1 = READ(src++);
3211.1Smacallan			bits |= FbScrRight(bits1, rightShift);
3221.1Smacallan			WRITE(dst, FbDoMergeRop(bits, READ(dst)));
3231.1Smacallan			dst++;
3241.1Smacallan		    }
3251.1Smacallan		}
3261.1Smacallan		if (endmask)
3271.1Smacallan		{
3281.1Smacallan		    bits = FbScrLeft(bits1, leftShift);
3291.1Smacallan		    if (FbScrLeft(endmask, rightShift))
3301.1Smacallan		    {
3311.1Smacallan			bits1 = READ(src);
3321.1Smacallan			bits |= FbScrRight(bits1, rightShift);
3331.1Smacallan		    }
3341.1Smacallan		    FbDoRightMaskByteMergeRop (dst, bits, endbyte, endmask);
3351.1Smacallan		}
3361.1Smacallan	    }
3371.1Smacallan	}
3381.1Smacallan    }
3391.1Smacallan}
3401.1Smacallan
3411.7Sriastrad#ifdef FB_24BIT
3421.1Smacallan
3431.1Smacallan#undef DEBUG_BLT24
3441.1Smacallan#ifdef DEBUG_BLT24
3451.1Smacallan
3461.1Smacallanstatic unsigned long
3471.1SmacallangetPixel (char *src, int x)
3481.1Smacallan{
3491.1Smacallan    unsigned long   l;
3501.1Smacallan
3511.1Smacallan    l = 0;
3521.7Sriastrad    memcpy (&l, src + x * 3, 3);
3531.7Sriastrad    return l;
3541.1Smacallan}
3551.1Smacallan#endif
3561.1Smacallan
3571.1Smacallanstatic void
3581.1SmacallanfbBlt24Line (FbBits	    *src,
3591.1Smacallan	     int	    srcX,
3601.1Smacallan
3611.1Smacallan	     FbBits	    *dst,
3621.1Smacallan	     int	    dstX,
3631.1Smacallan
3641.1Smacallan	     int	    width,
3651.1Smacallan
3661.1Smacallan	     int	    alu,
3671.1Smacallan	     FbBits	    pm,
3681.7Sriastrad
3691.7Sriastrad	     Bool	    reverse)
3701.7Sriastrad{
3711.1Smacallan#ifdef DEBUG_BLT24
3721.1Smacallan    char    *origDst = (char *) dst;
3731.1Smacallan    FbBits  *origLine = dst + ((dstX >> FB_SHIFT) - 1);
3741.1Smacallan    int	    origNlw = ((width + FB_MASK) >> FB_SHIFT) + 3;
3751.1Smacallan    int	    origX = dstX / 24;
3761.1Smacallan#endif
3771.1Smacallan
3781.1Smacallan    int	    leftShift, rightShift;
3791.1Smacallan    FbBits  startmask, endmask;
3801.1Smacallan    int	    n;
3811.1Smacallan
3821.1Smacallan    FbBits  bits, bits1;
3831.1Smacallan    FbBits  mask;
3841.1Smacallan
3851.1Smacallan    int	    rot;
3861.1Smacallan    FbDeclareMergeRop ();
3871.1Smacallan
3881.1Smacallan    FbInitializeMergeRop (alu, FB_ALLONES);
3891.1Smacallan    FbMaskBits(dstX, width, startmask, n, endmask);
3901.1Smacallan#ifdef DEBUG_BLT24
3911.1Smacallan    ErrorF ("dstX %d width %d reverse %d\n", dstX, width, reverse);
3921.1Smacallan#endif
3931.1Smacallan    if (reverse)
3941.1Smacallan    {
3951.5Smacallan	src += ((srcX + width - 1) >> FB_SHIFT) + 1;
3961.5Smacallan	dst += ((dstX + width - 1) >> FB_SHIFT) + 1;
3971.5Smacallan	rot = FbFirst24Rot (((dstX + width - 8) & FB_MASK));
3981.1Smacallan	rot = FbPrev24Rot(rot);
3991.1Smacallan#ifdef DEBUG_BLT24
4001.1Smacallan	ErrorF ("dstX + width - 8: %d rot: %d\n", (dstX + width - 8) & FB_MASK, rot);
4011.1Smacallan#endif
4021.1Smacallan	srcX = (srcX + width - 1) & FB_MASK;
4031.1Smacallan	dstX = (dstX + width - 1) & FB_MASK;
4041.1Smacallan    }
4051.1Smacallan    else
4061.1Smacallan    {
4071.1Smacallan	src += srcX >> FB_SHIFT;
4081.1Smacallan	dst += dstX >> FB_SHIFT;
4091.1Smacallan	srcX &= FB_MASK;
4101.1Smacallan	dstX &= FB_MASK;
4111.1Smacallan	rot = FbFirst24Rot (dstX);
4121.1Smacallan#ifdef DEBUG_BLT24
4131.1Smacallan	ErrorF ("dstX: %d rot: %d\n", dstX, rot);
4141.1Smacallan#endif
4151.1Smacallan    }
4161.1Smacallan    mask = FbRot24(pm,rot);
4171.1Smacallan#ifdef DEBUG_BLT24
4181.1Smacallan    ErrorF ("pm 0x%x mask 0x%x\n", pm, mask);
4191.1Smacallan#endif
4201.19Smacallan    if (srcX == dstX)
4211.19Smacallan    {
4221.19Smacallan	if (reverse)
4231.19Smacallan	{
4241.19Smacallan	    if (endmask)
4251.19Smacallan	    {
4261.19Smacallan		bits = READ(--src);
4271.1Smacallan		--dst;
4281.19Smacallan		WRITE(dst, FbDoMaskMergeRop (bits, READ(dst), mask & endmask));
4291.19Smacallan		mask = FbPrev24Pix (mask);
4301.19Smacallan	    }
4311.19Smacallan	    while (n--)
4321.19Smacallan	    {
4331.19Smacallan		bits = READ(--src);
4341.1Smacallan		--dst;
4351.1Smacallan		WRITE(dst, FbDoMaskMergeRop (bits, READ(dst), mask));
4361.1Smacallan		mask = FbPrev24Pix (mask);
4371.1Smacallan	    }
4381.1Smacallan	    if (startmask)
4391.1Smacallan	    {
4401.1Smacallan		bits = READ(--src);
4411.1Smacallan		--dst;
4421.1Smacallan		WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask & startmask));
4431.1Smacallan	    }
4441.1Smacallan	}
4451.1Smacallan	else
4461.1Smacallan	{
4471.1Smacallan	    if (startmask)
4481.1Smacallan	    {
4491.1Smacallan		bits = READ(src++);
4501.1Smacallan		WRITE(dst, FbDoMaskMergeRop (bits, READ(dst), mask & startmask));
4511.5Smacallan		dst++;
4521.1Smacallan		mask = FbNext24Pix(mask);
4531.1Smacallan	    }
4541.1Smacallan	    while (n--)
4551.1Smacallan	    {
4561.1Smacallan		bits = READ(src++);
4571.1Smacallan		WRITE(dst, FbDoMaskMergeRop (bits, READ(dst), mask));
4581.1Smacallan		dst++;
4591.1Smacallan		mask = FbNext24Pix(mask);
4601.1Smacallan	    }
4611.1Smacallan	    if (endmask)
4621.1Smacallan	    {
4631.14Smacallan		bits = READ(src);
4641.14Smacallan		WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask & endmask));
4651.14Smacallan	    }
4661.1Smacallan	}
4671.14Smacallan    }
4681.1Smacallan    else
4691.7Sriastrad    {
4701.1Smacallan	if (srcX > dstX)
4711.1Smacallan	{
4721.1Smacallan	    leftShift = srcX - dstX;
4731.1Smacallan	    rightShift = FB_UNIT - leftShift;
4741.1Smacallan	}
4751.1Smacallan	else
4761.2Smacallan	{
4771.1Smacallan	    rightShift = dstX - srcX;
4781.1Smacallan	    leftShift = FB_UNIT - rightShift;
4791.1Smacallan	}
4801.1Smacallan
4811.1Smacallan	bits1 = 0;
4821.2Smacallan	if (reverse)
4831.2Smacallan	{
4841.2Smacallan	    if (srcX < dstX)
4851.2Smacallan		bits1 = READ(--src);
4861.2Smacallan	    if (endmask)
4871.2Smacallan	    {
4881.2Smacallan		bits = FbScrRight(bits1, rightShift);
4891.1Smacallan		if (FbScrRight(endmask, leftShift))
4901.1Smacallan		{
4911.1Smacallan		    bits1 = READ(--src);
4921.1Smacallan		    bits |= FbScrLeft(bits1, leftShift);
4931.7Sriastrad		}
4941.1Smacallan		--dst;
4951.1Smacallan		WRITE(dst, FbDoMaskMergeRop (bits, READ(dst), mask & endmask));
4961.1Smacallan		mask = FbPrev24Pix(mask);
4971.1Smacallan	    }
4981.1Smacallan	    while (n--)
4991.1Smacallan	    {
5001.1Smacallan		bits = FbScrRight(bits1, rightShift);
5011.1Smacallan		bits1 = READ(--src);
5021.1Smacallan		bits |= FbScrLeft(bits1, leftShift);
5031.1Smacallan		--dst;
5041.1Smacallan		WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask));
5051.12Smacallan		mask = FbPrev24Pix(mask);
5061.12Smacallan	    }
5071.12Smacallan	    if (startmask)
5081.12Smacallan	    {
5091.1Smacallan		bits = FbScrRight(bits1, rightShift);
5101.1Smacallan		if (FbScrRight(startmask, leftShift))
5111.1Smacallan		{
5121.1Smacallan		    bits1 = READ(--src);
5131.1Smacallan		    bits |= FbScrLeft(bits1, leftShift);
5141.7Sriastrad		}
5151.7Sriastrad		--dst;
5161.1Smacallan		WRITE(dst, FbDoMaskMergeRop (bits, READ(dst), mask & startmask));
5171.1Smacallan	    }
5181.1Smacallan	}
5191.1Smacallan	else
5201.1Smacallan	{
5211.1Smacallan	    if (srcX > dstX)
5221.1Smacallan		bits1 = READ(src++);
5231.1Smacallan	    if (startmask)
5241.1Smacallan	    {
5251.1Smacallan		bits = FbScrLeft(bits1, leftShift);
5261.1Smacallan		bits1 = READ(src++);
5271.1Smacallan		bits |= FbScrRight(bits1, rightShift);
5281.5Smacallan		WRITE(dst, FbDoMaskMergeRop (bits, READ(dst), mask & startmask));
5291.1Smacallan		dst++;
5301.1Smacallan		mask = FbNext24Pix(mask);
5311.1Smacallan	    }
5321.1Smacallan	    while (n--)
5331.1Smacallan	    {
5341.1Smacallan		bits = FbScrLeft(bits1, leftShift);
5351.7Sriastrad		bits1 = READ(src++);
5361.1Smacallan		bits |= FbScrRight(bits1, rightShift);
5371.1Smacallan		WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask));
5381.1Smacallan		dst++;
5391.1Smacallan		mask = FbNext24Pix(mask);
5401.1Smacallan	    }
5411.1Smacallan	    if (endmask)
5421.1Smacallan	    {
5431.5Smacallan		bits = FbScrLeft(bits1, leftShift);
5441.5Smacallan		if (FbScrLeft(endmask, rightShift))
5451.5Smacallan		{
5461.5Smacallan		    bits1 = READ(src);
5471.5Smacallan		    bits |= FbScrRight(bits1, rightShift);
5481.1Smacallan		}
5491.1Smacallan		WRITE(dst, FbDoMaskMergeRop (bits, READ(dst), mask & endmask));
5501.1Smacallan	    }
5511.1Smacallan	}
5521.1Smacallan    }
5531.7Sriastrad#ifdef DEBUG_BLT24
5541.7Sriastrad    {
5551.7Sriastrad	int firstx, lastx, x;
5561.7Sriastrad
5571.7Sriastrad	firstx = origX;
5581.7Sriastrad	if (firstx)
5591.7Sriastrad	    firstx--;
5601.7Sriastrad	lastx = origX + width/24 + 1;
5611.7Sriastrad	for (x = firstx; x <= lastx; x++)
5621.7Sriastrad	    ErrorF ("%06x ", getPixel (origDst, x));
5631.7Sriastrad	ErrorF ("\n");
5641.7Sriastrad	while (origNlw--)
5651.7Sriastrad	    ErrorF ("%08x ", *origLine++);
5661.7Sriastrad	ErrorF ("\n");
5671.7Sriastrad    }
5681.7Sriastrad#endif
5691.7Sriastrad}
5701.5Smacallan
5711.1Smacallanvoid
5721.7SriastradfbBlt24 (FbBits	    *srcLine,
5731.7Sriastrad	 FbStride   srcStride,
5741.1Smacallan	 int	    srcX,
5751.7Sriastrad
5761.7Sriastrad	 FbBits	    *dstLine,
5771.1Smacallan	 FbStride   dstStride,
5781.7Sriastrad	 int	    dstX,
5791.7Sriastrad
5801.7Sriastrad	 int	    width,
5811.1Smacallan	 int	    height,
5821.1Smacallan
5831.7Sriastrad	 int	    alu,
5841.7Sriastrad	 FbBits	    pm,
5851.1Smacallan
5861.7Sriastrad	 Bool	    reverse,
5871.7Sriastrad	 Bool	    upsidedown)
5881.1Smacallan{
5891.1Smacallan    if (upsidedown)
5901.7Sriastrad    {
5911.7Sriastrad	srcLine += (height-1) * srcStride;
5921.1Smacallan	dstLine += (height-1) * dstStride;
5931.7Sriastrad	srcStride = -srcStride;
5941.7Sriastrad	dstStride = -dstStride;
5951.7Sriastrad    }
5961.1Smacallan    while (height--)
5971.1Smacallan    {
5981.7Sriastrad	fbBlt24Line (srcLine, srcX, dstLine, dstX, width, alu, pm, reverse);
5991.7Sriastrad	srcLine += srcStride;
6001.1Smacallan	dstLine += dstStride;
6011.7Sriastrad    }
6021.7Sriastrad#ifdef DEBUG_BLT24
6031.1Smacallan    ErrorF ("\n");
6041.1Smacallan#endif
6051.1Smacallan}
6061.1Smacallan#endif /* FB_24BIT */
6071.1Smacallan
6081.13Smacallan#if FB_SHIFT == FB_STIP_SHIFT + 1
6091.1Smacallan
6101.13Smacallan/*
6111.1Smacallan * Could be generalized to FB_SHIFT > FB_STIP_SHIFT + 1 by
6121.1Smacallan * creating an ring of values stepped through for each line
6131.1Smacallan */
6141.1Smacallan
6151.1Smacallanvoid
6161.1SmacallanfbBltOdd (FbBits    *srcLine,
6171.1Smacallan	  FbStride  srcStrideEven,
6181.1Smacallan	  FbStride  srcStrideOdd,
6191.1Smacallan	  int	    srcXEven,
6201.1Smacallan	  int	    srcXOdd,
6211.1Smacallan
6221.1Smacallan	  FbBits    *dstLine,
6231.1Smacallan	  FbStride  dstStrideEven,
6241.1Smacallan	  FbStride  dstStrideOdd,
6251.1Smacallan	  int	    dstXEven,
6261.8Smacallan	  int	    dstXOdd,
6271.8Smacallan
6281.1Smacallan	  int	    width,
6291.7Sriastrad	  int	    height,
6301.7Sriastrad
6311.7Sriastrad	  int	    alu,
6321.18Smacallan	  FbBits    pm,
6331.1Smacallan	  int	    bpp)
6341.1Smacallan{
6351.1Smacallan    FbBits  *src;
6361.1Smacallan    int	    leftShiftEven, rightShiftEven;
6371.1Smacallan    FbBits  startmaskEven, endmaskEven;
6381.1Smacallan    int	    nmiddleEven;
6391.1Smacallan
6401.1Smacallan    FbBits  *dst;
6411.1Smacallan    int	    leftShiftOdd, rightShiftOdd;
6421.1Smacallan    FbBits  startmaskOdd, endmaskOdd;
6431.1Smacallan    int	    nmiddleOdd;
6441.1Smacallan
6451.1Smacallan    int	    leftShift, rightShift;
6461.1Smacallan    FbBits  startmask, endmask;
6471.1Smacallan    int	    nmiddle;
6481.1Smacallan
6491.1Smacallan    int	    srcX, dstX;
6501.1Smacallan
6511.1Smacallan    FbBits  bits, bits1;
6521.1Smacallan    int	    n;
6531.1Smacallan
6541.1Smacallan    Bool    destInvarient;
6551.1Smacallan    Bool    even;
6561.1Smacallan    FbDeclareMergeRop ();
6571.1Smacallan
6581.1Smacallan    FbInitializeMergeRop (alu, pm);
6591.1Smacallan    destInvarient = FbDestInvarientMergeRop();
6601.1Smacallan
6611.1Smacallan    srcLine += srcXEven >> FB_SHIFT;
6621.1Smacallan    dstLine += dstXEven >> FB_SHIFT;
6631.1Smacallan    srcXEven &= FB_MASK;
6641.1Smacallan    dstXEven &= FB_MASK;
6651.1Smacallan    srcXOdd &= FB_MASK;
6661.1Smacallan    dstXOdd &= FB_MASK;
6671.1Smacallan
6681.1Smacallan    FbMaskBits(dstXEven, width, startmaskEven, nmiddleEven, endmaskEven);
6691.1Smacallan    FbMaskBits(dstXOdd, width, startmaskOdd, nmiddleOdd, endmaskOdd);
6701.1Smacallan
6711.1Smacallan    even = TRUE;
6721.1Smacallan    InitializeShifts(srcXEven, dstXEven, leftShiftEven, rightShiftEven);
6731.1Smacallan    InitializeShifts(srcXOdd, dstXOdd, leftShiftOdd, rightShiftOdd);
6741.1Smacallan    while (height--)
6751.1Smacallan    {
6761.1Smacallan	src = srcLine;
6771.1Smacallan	dst = dstLine;
6781.1Smacallan	if (even)
6791.1Smacallan	{
6801.1Smacallan	    srcX = srcXEven;
6811.1Smacallan	    dstX = dstXEven;
6821.1Smacallan	    startmask = startmaskEven;
6831.1Smacallan	    endmask = endmaskEven;
6841.1Smacallan	    nmiddle = nmiddleEven;
6851.1Smacallan	    leftShift = leftShiftEven;
6861.1Smacallan	    rightShift = rightShiftEven;
6871.1Smacallan	    srcLine += srcStrideEven;
6881.1Smacallan	    dstLine += dstStrideEven;
6891.1Smacallan	    even = FALSE;
6901.1Smacallan	}
6911.1Smacallan	else
6921.1Smacallan	{
6931.1Smacallan	    srcX = srcXOdd;
6941.1Smacallan	    dstX = dstXOdd;
6951.1Smacallan	    startmask = startmaskOdd;
6961.1Smacallan	    endmask = endmaskOdd;
6971.1Smacallan	    nmiddle = nmiddleOdd;
6981.1Smacallan	    leftShift = leftShiftOdd;
6991.1Smacallan	    rightShift = rightShiftOdd;
7001.1Smacallan	    srcLine += srcStrideOdd;
7011.1Smacallan	    dstLine += dstStrideOdd;
7021.1Smacallan	    even = TRUE;
7031.1Smacallan	}
7041.1Smacallan	if (srcX == dstX)
7051.1Smacallan	{
7061.1Smacallan	    if (startmask)
7071.1Smacallan	    {
7081.1Smacallan		bits = READ(src++);
7091.1Smacallan		WRITE(dst, FbDoMaskMergeRop (bits, READ(dst), startmask));
7101.1Smacallan		dst++;
7111.1Smacallan	    }
7121.1Smacallan	    n = nmiddle;
7131.1Smacallan	    if (destInvarient)
7141.1Smacallan	    {
7151.1Smacallan		while (n--)
7161.1Smacallan		{
7171.1Smacallan		    bits = READ(src++);
7181.1Smacallan		    WRITE(dst, FbDoDestInvarientMergeRop(bits));
7191.1Smacallan		    dst++;
7201.1Smacallan		}
7211.1Smacallan	    }
7221.1Smacallan	    else
7231.1Smacallan	    {
7241.1Smacallan		while (n--)
7251.1Smacallan		{
7261.1Smacallan		    bits = READ(src++);
7271.1Smacallan		    WRITE(dst, FbDoMergeRop (bits, READ(dst)));
7281.1Smacallan		    dst++;
7291.1Smacallan		}
7301.1Smacallan	    }
7311.1Smacallan	    if (endmask)
7321.1Smacallan	    {
7331.1Smacallan		bits = READ(src);
7341.1Smacallan		WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), endmask));
7351.1Smacallan	    }
7361.1Smacallan	}
7371.1Smacallan	else
7381.1Smacallan	{
7391.1Smacallan	    bits = 0;
7401.1Smacallan	    if (srcX > dstX)
7411.1Smacallan		bits = READ(src++);
7421.1Smacallan	    if (startmask)
7431.1Smacallan	    {
7441.1Smacallan		bits1 = FbScrLeft(bits, leftShift);
7451.1Smacallan		bits = READ(src++);
7461.1Smacallan		bits1 |= FbScrRight(bits, rightShift);
7471.1Smacallan		WRITE(dst, FbDoMaskMergeRop (bits1, READ(dst), startmask));
7481.1Smacallan		dst++;
7491.1Smacallan	    }
7501.1Smacallan	    n = nmiddle;
7511.1Smacallan	    if (destInvarient)
7521.23Smacallan	    {
7531.1Smacallan		while (n--)
7541.5Smacallan		{
7551.5Smacallan		    bits1 = FbScrLeft(bits, leftShift);
7561.5Smacallan		    bits = READ(src++);
7571.7Sriastrad		    bits1 |= FbScrRight(bits, rightShift);
7581.5Smacallan		    WRITE(dst, FbDoDestInvarientMergeRop(bits1));
7591.7Sriastrad		    dst++;
7601.7Sriastrad		}
7611.7Sriastrad	    }
7621.7Sriastrad	    else
7631.5Smacallan	    {
7641.7Sriastrad		while (n--)
7651.7Sriastrad		{
7661.5Smacallan		    bits1 = FbScrLeft(bits, leftShift);
7671.5Smacallan		    bits = READ(src++);
7681.5Smacallan		    bits1 |= FbScrRight(bits, rightShift);
7691.5Smacallan		    WRITE(dst, FbDoMergeRop(bits1, READ(dst)));
7701.7Sriastrad		    dst++;
7711.7Sriastrad		}
7721.7Sriastrad	    }
7731.7Sriastrad	    if (endmask)
7741.1Smacallan	    {
7751.5Smacallan		bits1 = FbScrLeft(bits, leftShift);
7761.5Smacallan		if (FbScrLeft(endmask, rightShift))
7771.5Smacallan		{
7781.5Smacallan		    bits = READ(src);
7791.7Sriastrad		    bits1 |= FbScrRight(bits, rightShift);
7801.1Smacallan		}
7811.1Smacallan		WRITE(dst, FbDoMaskMergeRop (bits1, READ(dst), endmask));
7821.23Smacallan	    }
7831.23Smacallan	}
7841.23Smacallan    }
7851.23Smacallan}
7861.24Sriastrad
7871.24Sriastrad#ifdef FB_24BIT
7881.23Smacallanvoid
7891.23SmacallanfbBltOdd24 (FbBits	*srcLine,
7901.23Smacallan	    FbStride	srcStrideEven,
7911.23Smacallan	    FbStride	srcStrideOdd,
7921.24Sriastrad	    int		srcXEven,
7931.23Smacallan	    int		srcXOdd,
7941.23Smacallan
7951.1Smacallan	    FbBits	*dstLine,
7961.5Smacallan	    FbStride	dstStrideEven,
7971.5Smacallan	    FbStride	dstStrideOdd,
7981.5Smacallan	    int		dstXEven,
7991.5Smacallan	    int		dstXOdd,
8001.23Smacallan
8011.1Smacallan	    int		width,
8021.1Smacallan	    int		height,
8031.1Smacallan
8041.1Smacallan	    int		alu,
8051.1Smacallan	    FbBits	pm)
8061.1Smacallan{
8071.1Smacallan    Bool    even = TRUE;
8081.7Sriastrad
8091.1Smacallan    while (height--)
8101.1Smacallan    {
8111.5Smacallan	if (even)
8121.1Smacallan	{
8131.1Smacallan	    fbBlt24Line (srcLine, srcXEven, dstLine, dstXEven,
8141.1Smacallan			 width, alu, pm, FALSE);
8151.7Sriastrad	    srcLine += srcStrideEven;
8161.5Smacallan	    dstLine += dstStrideEven;
8171.5Smacallan	    even = FALSE;
8181.5Smacallan	}
8191.5Smacallan	else
8201.7Sriastrad	{
8211.7Sriastrad	    fbBlt24Line (srcLine, srcXOdd, dstLine, dstXOdd,
8221.7Sriastrad			 width, alu, pm, FALSE);
8231.5Smacallan	    srcLine += srcStrideOdd;
8241.11Sriastrad	    dstLine += dstStrideOdd;
8251.10Smacallan	    even = TRUE;
8261.24Sriastrad	}
8271.23Smacallan    }
8281.23Smacallan}
8291.23Smacallan#endif
8301.23Smacallan
8311.23Smacallan#endif
8321.23Smacallan
8331.23Smacallan#if FB_STIP_SHIFT != FB_SHIFT
8341.23Smacallanvoid
8351.5SmacallanfbSetBltOdd (FbStip	*stip,
8361.5Smacallan	     FbStride	stipStride,
8371.23Smacallan	     int	srcX,
8381.5Smacallan	     FbBits	**bits,
8391.5Smacallan	     FbStride	*strideEven,
8401.5Smacallan	     FbStride	*strideOdd,
8411.5Smacallan	     int	*srcXEven,
8421.5Smacallan	     int	*srcXOdd)
8431.5Smacallan{
8441.5Smacallan    int	    srcAdjust;
8451.5Smacallan    int	    strideAdjust;
8461.7Sriastrad
8471.5Smacallan    /*
8481.7Sriastrad     * bytes needed to align source
8491.7Sriastrad     */
8501.7Sriastrad    srcAdjust = (((int) stip) & (FB_MASK >> 3));
8511.5Smacallan    /*
8521.5Smacallan     * FbStip units needed to align stride
8531.19Smacallan     */
8541.7Sriastrad    strideAdjust = stipStride & (FB_MASK >> FB_STIP_SHIFT);
8551.5Smacallan
8561.5Smacallan    *bits = (FbBits *) ((char *) stip - srcAdjust);
8571.5Smacallan    if (srcAdjust)
8581.5Smacallan    {
8591.5Smacallan	*strideEven = FbStipStrideToBitsStride (stipStride + 1);
8601.5Smacallan	*strideOdd = FbStipStrideToBitsStride (stipStride);
8611.5Smacallan
8621.5Smacallan	*srcXEven = srcX + (srcAdjust << 3);
8631.5Smacallan	*srcXOdd = srcX + (srcAdjust << 3) - (strideAdjust << FB_STIP_SHIFT);
8641.5Smacallan    }
8651.5Smacallan    else
8661.5Smacallan    {
8671.5Smacallan	*strideEven = FbStipStrideToBitsStride (stipStride);
8681.5Smacallan	*strideOdd = FbStipStrideToBitsStride (stipStride + 1);
8691.5Smacallan
8701.5Smacallan	*srcXEven = srcX;
8711.7Sriastrad	*srcXOdd = srcX + (strideAdjust << FB_STIP_SHIFT);
8721.7Sriastrad    }
8731.5Smacallan}
8741.5Smacallan#endif
8751.7Sriastrad
8761.7Sriastradvoid
8771.5SmacallanfbBltStip (FbStip   *src,
8781.5Smacallan	   FbStride srcStride,	    /* in FbStip units, not FbBits units */
8791.1Smacallan	   int	    srcX,
8801.1Smacallan
8811.1Smacallan	   FbStip   *dst,
8821.1Smacallan	   FbStride dstStride,	    /* in FbStip units, not FbBits units */
8831.1Smacallan	   int	    dstX,
8841.1Smacallan
8851.1Smacallan	   int	    width,
8861.7Sriastrad	   int	    height,
8871.1Smacallan
8881.1Smacallan	   int	    alu,
8891.1Smacallan	   FbBits   pm,
8901.1Smacallan	   int	    bpp)
8911.1Smacallan{
8921.1Smacallan#if FB_STIP_SHIFT != FB_SHIFT
8931.1Smacallan    if (FB_STIP_ODDSTRIDE(srcStride) || FB_STIP_ODDPTR(src) ||
8941.1Smacallan	FB_STIP_ODDSTRIDE(dstStride) || FB_STIP_ODDPTR(dst))
8951.1Smacallan    {
8961.1Smacallan	FbStride    srcStrideEven, srcStrideOdd;
8971.1Smacallan	FbStride    dstStrideEven, dstStrideOdd;
8981.1Smacallan	int	    srcXEven, srcXOdd;
8991.1Smacallan	int	    dstXEven, dstXOdd;
9001.1Smacallan	FbBits	    *s, *d;
9011.1Smacallan	int	    sx, dx;
9021.1Smacallan
9031.5Smacallan	src += srcX >> FB_STIP_SHIFT;
9041.1Smacallan	srcX &= FB_STIP_MASK;
9051.1Smacallan	dst += dstX >> FB_STIP_SHIFT;
9061.1Smacallan	dstX &= FB_STIP_MASK;
9071.1Smacallan
9081.1Smacallan	fbSetBltOdd (src, srcStride, srcX,
9091.1Smacallan		     &s,
9101.1Smacallan		     &srcStrideEven, &srcStrideOdd,
9111.1Smacallan		     &srcXEven, &srcXOdd);
9121.1Smacallan
9131.1Smacallan	fbSetBltOdd (dst, dstStride, dstX,
9141.3Smacallan		     &d,
9151.7Sriastrad		     &dstStrideEven, &dstStrideOdd,
9161.1Smacallan		     &dstXEven, &dstXOdd);
9171.3Smacallan
9181.1Smacallan#ifdef FB_24BIT
9191.1Smacallan	if (bpp == 24 && !FbCheck24Pix (pm))
9201.1Smacallan	{
9211.1Smacallan	    fbBltOdd24  (s, srcStrideEven, srcStrideOdd,
9221.1Smacallan			 srcXEven, srcXOdd,
9231.1Smacallan
9241.7Sriastrad			 d, dstStrideEven, dstStrideOdd,
9251.1Smacallan			 dstXEven, dstXOdd,
9261.1Smacallan
9271.7Sriastrad			 width, height, alu, pm);
9281.1Smacallan	}
9291.1Smacallan	else
9301.1Smacallan#endif
9311.1Smacallan	{
9321.7Sriastrad	    fbBltOdd (s, srcStrideEven, srcStrideOdd,
9331.1Smacallan		      srcXEven, srcXOdd,
9341.3Smacallan
9351.1Smacallan		      d, dstStrideEven, dstStrideOdd,
9361.3Smacallan		      dstXEven, dstXOdd,
9371.1Smacallan
9381.1Smacallan		      width, height, alu, pm, bpp);
9391.2Smacallan	}
9401.21Smacallan    }
9411.21Smacallan    else
9421.2Smacallan#endif
9431.2Smacallan    {
9441.14Smacallan	fbBlt ((FbBits *) src, FbStipStrideToBitsStride (srcStride),
9451.2Smacallan	       srcX,
9461.2Smacallan	       (FbBits *) dst, FbStipStrideToBitsStride (dstStride),
9471.2Smacallan	       dstX,
9481.7Sriastrad	       width, height,
9491.20Smacallan	       alu, pm, bpp, FALSE, FALSE);
9501.21Smacallan    }
9511.2Smacallan}
9521.2Smacallan