4.4BSD/usr/src/contrib/X11R5-hp300/mit/server/ddx/hpbsd/hyperion/hyperMBits.c

Compare this file to the similar file:
Show the results in this format:

/*
 */
#include "X.h"
#define  NEED_EVENTS
#include "Xproto.h"
#include "scrnintstr.h"
#include "cursorstr.h"
#include "pixmapstr.h"
#include "inputstr.h"
#include "regionstr.h"
#include <sys/types.h>

#include "hppriv.h"
#include "hyperion.h"

#include "../mfb/mfb.h"
#include "../mfb/maskbits.h"

#ifdef FASTGETBITS
#define getunalignedword(psrc, x, dst) { \
        register int _tmp; \
        FASTGETBITS(psrc, x, 32, _tmp); \
        dst = _tmp; \
}
#else
#define getunalignedword(psrc, x, dst) \
{ \
    dst = (SCRLEFT((unsigned) *(psrc), (x))) | \
          (SCRRIGHT((unsigned) *((psrc)+1), 32-(x))); \
}
#endif  /* FASTGETBITS */

#include "../mfb/fastblt.h"


void
hyperMoveBits(pScreen, planeMask, alu,
	      sourceX, sourceY, destX, destY, w, h)
     ScreenPtr	pScreen;
     u_char	planeMask;
     int	alu, sourceX, sourceY, destX, destY, w, h;
{
    unsigned int *pBase;	
				/* start of src and dst bitmaps */
    int width;	/* add to get to same position in next line */

    unsigned int *psrcLine, *pdstLine;	
				/* pointers to line with current src and dst */
    register unsigned int *psrc;/* pointer to current src longword */
    register unsigned int *pdst;/* pointer to current dst longword */

				/* following used for looping through a line */
    unsigned int startmask, endmask;	/* masks for writing ends of dst */
    int nlMiddle;		/* whole longwords in dst */
    register int nl;		/* temp copy of nlMiddle */
    register unsigned int tmpSrc;
				/* place to store full source word */
    register int xoffSrc;	/* offset (>= 0, < 32) from which to
			           fetch whole longwords fetched 
				   in src */
    int nstart;			/* number of ragged bits at start of dst */
    int nend;			/* number of ragged bits at end of dst */
    int srcStartOver;		/* pulling nstart bits from src
				   overflows into the next word? */

    if (h == 0 || w == 0)
	return;
    
    pBase = (unsigned int *) getPrivScreenPtr(pScreen)->bits;
    width = getPrivScreenPtr(pScreen)->memWidth >> 5;

    if (sourceY < destY) /* start at last scanline of rectangle */
    {
	psrcLine = pBase + ((sourceY+h-1) * width);
	pdstLine = pBase + ((destY+h-1) * width);
	width = -width;
    }
    else /* start at first scanline */
    {
	psrcLine = pBase + (sourceY * width);
	pdstLine = pBase + (destY * width);
    }

    /* special case copy */
    if (alu == GXcopy)
    {
	register unsigned int bits;
	register unsigned int bits1;
	int xoffSrc, xoffDst;
	int	leftShift, rightShift;

	if ((destX & 0x1f) + w <= 32)
	{
	    pdst = pdstLine + (destX >> 5);
	    psrc = psrcLine + (sourceX >> 5);
	    xoffSrc = sourceX & 0x1f;
	    xoffDst = destX & 0x1f;
	    while (h--)
	    {
		getandputbits(psrc, xoffSrc, xoffDst, w, pdst);
		psrc += width;
		pdst += width;
	    }
	}
	else
	{
	    maskbits(destX, w, startmask, endmask, nlMiddle);
	    if (sourceX >= destX)
	    {
		xoffSrc = sourceX & 0x1f;
		xoffDst = destX & 0x1f;
		pdstLine += (destX >> 5);
		psrcLine += (sourceX >> 5);
		if (xoffSrc == xoffDst)
		{
		    while (h--)
		    {
			psrc = psrcLine;
			pdst = pdstLine;
			pdstLine += width;
			psrcLine += width;
			if (startmask)
			{
			    *pdst = (*pdst & ~startmask) | (*psrc++ & startmask);
			    pdst++;
			}
			nl = nlMiddle;

			DuffL(nl, label1, *pdst++ = *psrc++;)
			if (endmask)
			    *pdst = (*pdst & ~endmask) | (*psrc++ & endmask);
		    }
		}
		else
		{
		    if (xoffSrc > xoffDst)
		    {
			leftShift = (xoffSrc - xoffDst);
			rightShift = 32 - leftShift;
		    }
		    else
		    {
			rightShift = (xoffDst - xoffSrc);
			leftShift = 32 - rightShift;
		    }
		    while (h--)
		    {
			psrc = psrcLine;
			pdst = pdstLine;
			pdstLine += width;
			psrcLine += width;
			bits = 0;
			if (xoffSrc > xoffDst)
			    bits = *psrc++;
			if (startmask)
			{
			    bits1 = SCRLEFT(bits,leftShift);
			    bits = *psrc++;
			    bits1 |= SCRRIGHT(bits,rightShift);
			    *pdst = (*pdst & ~startmask) |
				(bits1 & startmask);
			    pdst++;
			}
			nl = nlMiddle;

			DuffL (nl,label2,
			       bits1 = BitLeft(bits, leftShift);
			       bits = *psrc++;
			       *pdst++ = bits1 | BitRight(bits, rightShift);
			       )
			if (endmask)
			{
			    bits1 = SCRLEFT(bits, leftShift);
			    if (SCRLEFT(endmask, rightShift))
			    {
				bits = *psrc++;
				bits1 |= SCRRIGHT(bits, rightShift);
			    }
			    *pdst = (*pdst & ~endmask) |
				(bits1 & endmask);
			}
		    }
		}
	    }
	    else	/* walk source right to left */
	    {
		xoffSrc = (sourceX + w - 1) & 0x1f;
		xoffDst = (destX+w - 1) & 0x1f;
		pdstLine += ((destX+w-1) >> 5) + 1;
		psrcLine += ((sourceX+w - 1) >> 5) + 1;
		if (xoffSrc == xoffDst)
		{
		    while (h--)
		    {
			psrc = psrcLine;
			pdst = pdstLine;
			pdstLine += width;
			psrcLine += width;
			if (endmask)
			{
			    pdst--;
			    *pdst = (*pdst & ~endmask) | (*--psrc & endmask);
			}
			nl = nlMiddle;

			DuffL(nl,label3, *--pdst = *--psrc;)
			if (startmask)
			{
			    --pdst;
			    *pdst = (*pdst & ~startmask) | (*--psrc & startmask);
			}
		    }
		}
		else
		{
		    if (xoffDst > xoffSrc)
		    {
			rightShift = (xoffDst - xoffSrc);
			leftShift = 32 - rightShift;
		    }
		    else
		    {
			leftShift = (xoffSrc - xoffDst);
			rightShift = 32 - leftShift;
		    }
		    while (h--)
		    {
			psrc = psrcLine;
			pdst = pdstLine;
			pdstLine += width;
			psrcLine += width;
			bits = 0;
			if (xoffDst > xoffSrc)
			    bits = *--psrc;
			if (endmask)
			{
			    bits1 = SCRRIGHT(bits, rightShift);
			    bits = *--psrc;
			    bits1 |= SCRLEFT(bits, leftShift);
			    pdst--;
			    *pdst = (*pdst & ~endmask) |
				(bits1 & endmask);
			}
			nl = nlMiddle;

			DuffL (nl, label4,
			       bits1 = BitRight(bits, rightShift);
			       bits = *--psrc;
			       *--pdst = bits1 | BitLeft(bits, leftShift);
			       )

			if (startmask)
			{
			    bits1 = SCRRIGHT(bits, rightShift);
			    if (SCRRIGHT (startmask, leftShift))
			    {
				bits = *--psrc;
				bits1 |= SCRLEFT(bits, leftShift);
			    }
			    --pdst;
			    *pdst = (*pdst & ~startmask) |
				(bits1 & startmask);
			}
		    }
		}
	    }
	}
    }
    else /* do some rop */
    {
	/* x direction doesn't matter for < 1 longword */
	if (w <= 32)
	{
	    int srcBit, dstBit;	/* bit offset of src and dst */

	    pdstLine += (destX >> 5);
	    psrcLine += (sourceX >> 5);
	    psrc = psrcLine;
	    pdst = pdstLine;

	    srcBit = sourceX & 0x1f;
	    dstBit = destX & 0x1f;

	    while (h--)
	    {
		getandputrop(psrc, srcBit, dstBit, w, pdst, alu)
		pdst += width;
		psrc += width;
	    }
	}
	else
	{
	    maskbits(destX, w, startmask, endmask, nlMiddle)
	    if (startmask)
		nstart = 32 - (destX & 0x1f);
	    else
		nstart = 0;
	    if (endmask)
		nend = destX+w & 0x1f;
	    else
		nend = 0;

	    xoffSrc = ((sourceX & 0x1f) + nstart) & 0x1f;
	    srcStartOver = ((sourceX & 0x1f) + nstart) > 31;

	    if (sourceX >= destX) /* move left to right */
	    {
		pdstLine += (destX >> 5);
		psrcLine += (sourceX >> 5);

		while (h--)
		{
		    psrc = psrcLine;
		    pdst = pdstLine;

		    if (startmask)
		    {
			getandputrop(psrc, (sourceX & 0x1f), 
				     (destX & 0x1f), nstart, pdst, alu)
			pdst++;
			if (srcStartOver)
			    psrc++;
		    }

		    /* special case for aligned operations */
		    if (xoffSrc == 0)
		    {
			nl = nlMiddle;
			while (nl--)
			{
			    DoRop (*pdst, alu, *psrc++, *pdst);
			    pdst++;
			}
		    }
		    else
		    {
			nl = nlMiddle + 1;
			while (--nl)
			{
			    getunalignedword (psrc, xoffSrc, tmpSrc)
			    DoRop (*pdst, alu, tmpSrc, *pdst);
			    pdst++;
			    psrc++;
			}
		    }

		    if (endmask)
		    {
			getandputrop0(psrc, xoffSrc, nend, pdst, alu);
		    }

		    pdstLine += width;
		    psrcLine += width;
		}
	    }
	    else /* move right to left */
	    {
		pdstLine += (destX+w >> 5);
		psrcLine += (sourceX+w >> 5);
		/* if fetch of last partial bits from source crosses
		   a longword boundary, start at the previous longword
		   */
		if (xoffSrc + nend >= 32)
		    --psrcLine;

		while (h--)
		{
		    psrc = psrcLine;
		    pdst = pdstLine;

		    if (endmask)
		    {
			getandputrop0(psrc, xoffSrc, nend, pdst, alu);
		    }

		    nl = nlMiddle + 1;
		    while (--nl)
		    {
			--psrc;
			--pdst;
			getunalignedword(psrc, xoffSrc, tmpSrc)
			DoRop(*pdst, alu, tmpSrc, *pdst);
		    }

		    if (startmask)
		    {
			if (srcStartOver)
			    --psrc;
			--pdst;
			getandputrop(psrc, (sourceX & 0x1f), 
				     (destX & 0x1f), nstart, pdst, alu)
		    }

		    pdstLine += width;
		    psrcLine += width;
		}
	    } /* move right to left */
	}
    }
}