952 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			952 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 * Copyright © 1998 Keith Packard
 | 
						|
 *
 | 
						|
 * Permission to use, copy, modify, distribute, and sell this software and its
 | 
						|
 * documentation for any purpose is hereby granted without fee, provided that
 | 
						|
 * the above copyright notice appear in all copies and that both that
 | 
						|
 * copyright notice and this permission notice appear in supporting
 | 
						|
 * documentation, and that the name of Keith Packard not be used in
 | 
						|
 * advertising or publicity pertaining to distribution of the software without
 | 
						|
 * specific, written prior permission.  Keith Packard makes no
 | 
						|
 * representations about the suitability of this software for any purpose.  It
 | 
						|
 * is provided "as is" without express or implied warranty.
 | 
						|
 *
 | 
						|
 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 | 
						|
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 | 
						|
 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 | 
						|
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 | 
						|
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 | 
						|
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 | 
						|
 * PERFORMANCE OF THIS SOFTWARE.
 | 
						|
 */
 | 
						|
 | 
						|
#ifdef HAVE_DIX_CONFIG_H
 | 
						|
#include <dix-config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <string.h>
 | 
						|
#include "fb.h"
 | 
						|
 | 
						|
#define InitializeShifts(sx,dx,ls,rs) { \
 | 
						|
    if (sx != dx) { \
 | 
						|
	if (sx > dx) { \
 | 
						|
	    ls = sx - dx; \
 | 
						|
	    rs = FB_UNIT - ls; \
 | 
						|
	} else { \
 | 
						|
	    rs = dx - sx; \
 | 
						|
	    ls = FB_UNIT - rs; \
 | 
						|
	} \
 | 
						|
    } \
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
fbBlt (FbBits   *srcLine,
 | 
						|
       FbStride	srcStride,
 | 
						|
       int	srcX,
 | 
						|
       
 | 
						|
       FbBits   *dstLine,
 | 
						|
       FbStride dstStride,
 | 
						|
       int	dstX,
 | 
						|
       
 | 
						|
       int	width, 
 | 
						|
       int	height,
 | 
						|
       
 | 
						|
       int	alu,
 | 
						|
       FbBits	pm,
 | 
						|
       int	bpp,
 | 
						|
       
 | 
						|
       Bool	reverse,
 | 
						|
       Bool	upsidedown)
 | 
						|
{
 | 
						|
    FbBits  *src, *dst;
 | 
						|
    int	    leftShift, rightShift;
 | 
						|
    FbBits  startmask, endmask;
 | 
						|
    FbBits  bits, bits1;
 | 
						|
    int	    n, nmiddle;
 | 
						|
    Bool    destInvarient;
 | 
						|
    int	    startbyte, endbyte;
 | 
						|
    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_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);
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#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 = 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
 | 
						|
}
 | 
						|
#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 = 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));
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#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;
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
#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);
 | 
						|
    }
 | 
						|
}
 |