fbbltone.c revision 9ace9065
105b261ecSmrg/*
205b261ecSmrg * Copyright © 1998 Keith Packard
305b261ecSmrg *
405b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its
505b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that
605b261ecSmrg * the above copyright notice appear in all copies and that both that
705b261ecSmrg * copyright notice and this permission notice appear in supporting
805b261ecSmrg * documentation, and that the name of Keith Packard not be used in
905b261ecSmrg * advertising or publicity pertaining to distribution of the software without
1005b261ecSmrg * specific, written prior permission.  Keith Packard makes no
1105b261ecSmrg * representations about the suitability of this software for any purpose.  It
1205b261ecSmrg * is provided "as is" without express or implied warranty.
1305b261ecSmrg *
1405b261ecSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1505b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1605b261ecSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1705b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1805b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1905b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2005b261ecSmrg * PERFORMANCE OF THIS SOFTWARE.
2105b261ecSmrg */
2205b261ecSmrg
2305b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
2405b261ecSmrg#include <dix-config.h>
2505b261ecSmrg#endif
2605b261ecSmrg
2705b261ecSmrg#include "fb.h"
2805b261ecSmrg
2905b261ecSmrg/*
3005b261ecSmrg *  Example: srcX = 13 dstX = 8	(FB unit 32 dstBpp 8)
3105b261ecSmrg *
3205b261ecSmrg *	**** **** **** **** **** **** **** ****
3305b261ecSmrg *			^
3405b261ecSmrg *	********  ********  ********  ********
3505b261ecSmrg *		  ^
3605b261ecSmrg *  leftShift = 12
3705b261ecSmrg *  rightShift = 20
3805b261ecSmrg *
3905b261ecSmrg *  Example: srcX = 0 dstX = 8 (FB unit 32 dstBpp 8)
4005b261ecSmrg *
4105b261ecSmrg *	**** **** **** **** **** **** **** ****
4205b261ecSmrg *	^
4305b261ecSmrg *	********  ********  ********  ********
4405b261ecSmrg *		  ^
4505b261ecSmrg *
4605b261ecSmrg *  leftShift = 24
4705b261ecSmrg *  rightShift = 8
4805b261ecSmrg */
4905b261ecSmrg
5005b261ecSmrg#define LoadBits {\
5105b261ecSmrg    if (leftShift) { \
5205b261ecSmrg	bitsRight = (src < srcEnd ? READ(src++) : 0); \
5305b261ecSmrg	bits = (FbStipLeft (bitsLeft, leftShift) | \
5405b261ecSmrg		FbStipRight(bitsRight, rightShift)); \
5505b261ecSmrg	bitsLeft = bitsRight; \
5605b261ecSmrg    } else \
5705b261ecSmrg	bits = (src < srcEnd ? READ(src++) : 0); \
5805b261ecSmrg}
5905b261ecSmrg
6005b261ecSmrg#ifndef FBNOPIXADDR
6105b261ecSmrg
626747b715Smrg#define LaneCases1(n,a)	    case n: FbLaneCase(n,a); break
6305b261ecSmrg#define LaneCases2(n,a)	    LaneCases1(n,a); LaneCases1(n+1,a)
6405b261ecSmrg#define LaneCases4(n,a)	    LaneCases2(n,a); LaneCases2(n+2,a)
6505b261ecSmrg#define LaneCases8(n,a)	    LaneCases4(n,a); LaneCases4(n+4,a)
6605b261ecSmrg#define LaneCases16(n,a)    LaneCases8(n,a); LaneCases8(n+8,a)
6705b261ecSmrg#define LaneCases32(n,a)    LaneCases16(n,a); LaneCases16(n+16,a)
6805b261ecSmrg#define LaneCases64(n,a)    LaneCases32(n,a); LaneCases32(n+32,a)
6905b261ecSmrg#define LaneCases128(n,a)   LaneCases64(n,a); LaneCases64(n+64,a)
7005b261ecSmrg#define LaneCases256(n,a)   LaneCases128(n,a); LaneCases128(n+128,a)
7105b261ecSmrg
7205b261ecSmrg#if FB_SHIFT == 6
7305b261ecSmrg#define LaneCases(a)	    LaneCases256(0,a)
7405b261ecSmrg#endif
7505b261ecSmrg
7605b261ecSmrg#if FB_SHIFT == 5
7705b261ecSmrg#define LaneCases(a)	    LaneCases16(0,a)
7805b261ecSmrg#endif
7905b261ecSmrg
8005b261ecSmrg#if FB_SHIFT == 6
8105b261ecSmrgCARD8	fb8Lane[256] = {
8205b261ecSmrg0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
8305b261ecSmrg22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
8405b261ecSmrg41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
8505b261ecSmrg60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
8605b261ecSmrg79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
8705b261ecSmrg98, 99, 100, 101, 102,103,104,105,106,107,108,109,110,111,112,113,114,115,
8805b261ecSmrg116, 117, 118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,
8905b261ecSmrg134, 135, 136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,
9005b261ecSmrg152, 153, 154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,
9105b261ecSmrg170, 171, 172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,
9205b261ecSmrg188, 189, 190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,
9305b261ecSmrg206, 207, 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
9405b261ecSmrg224, 225, 226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,
9505b261ecSmrg242, 243, 244,245,246,247,248,249,250,251,252,253,254,255,
9605b261ecSmrg};
9705b261ecSmrg
9805b261ecSmrgCARD8	fb16Lane[256] = {
9905b261ecSmrg    0x00, 0x03, 0x0c, 0x0f,
10005b261ecSmrg    0x30, 0x33, 0x3c, 0x3f,
10105b261ecSmrg    0xc0, 0xc3, 0xcc, 0xcf,
10205b261ecSmrg    0xf0, 0xf3, 0xfc, 0xff,
10305b261ecSmrg};
10405b261ecSmrg
10505b261ecSmrgCARD8	fb32Lane[16] = {
10605b261ecSmrg    0x00, 0x0f, 0xf0, 0xff,
10705b261ecSmrg};
10805b261ecSmrg#endif
10905b261ecSmrg
11005b261ecSmrg#if FB_SHIFT == 5
11105b261ecSmrgCARD8	fb8Lane[16] = {
11205b261ecSmrg    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
11305b261ecSmrg};
11405b261ecSmrg
11505b261ecSmrgCARD8	fb16Lane[16] = {
11605b261ecSmrg    0, 3, 12, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
11705b261ecSmrg};
11805b261ecSmrg
11905b261ecSmrgCARD8	fb32Lane[16] = {
12005b261ecSmrg    0, 15,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12105b261ecSmrg};
12205b261ecSmrg#endif
12305b261ecSmrg
12405b261ecSmrgCARD8	*fbLaneTable[33] = {
12505b261ecSmrg    0, 0, 0, 0, 0, 0, 0, 0,
12605b261ecSmrg    fb8Lane,  0, 0, 0, 0, 0, 0, 0,
12705b261ecSmrg    fb16Lane, 0, 0, 0, 0, 0, 0, 0,
12805b261ecSmrg    0, 0, 0, 0, 0, 0, 0, 0,
12905b261ecSmrg    fb32Lane
13005b261ecSmrg};
13105b261ecSmrg#endif
13205b261ecSmrg
13305b261ecSmrgvoid
13405b261ecSmrgfbBltOne (FbStip    *src,
13505b261ecSmrg	  FbStride  srcStride,	    /* FbStip units per scanline */
13605b261ecSmrg	  int	    srcX,	    /* bit position of source */
13705b261ecSmrg	  FbBits    *dst,
13805b261ecSmrg	  FbStride  dstStride,	    /* FbBits units per scanline */
13905b261ecSmrg	  int	    dstX,	    /* bit position of dest */
14005b261ecSmrg	  int	    dstBpp,	    /* bits per destination unit */
14105b261ecSmrg
14205b261ecSmrg	  int	    width,	    /* width in bits of destination */
14305b261ecSmrg	  int	    height,	    /* height in scanlines */
14405b261ecSmrg
14505b261ecSmrg	  FbBits    fgand,	    /* rrop values */
14605b261ecSmrg	  FbBits    fgxor,
14705b261ecSmrg	  FbBits    bgand,
14805b261ecSmrg	  FbBits    bgxor)
14905b261ecSmrg{
15005b261ecSmrg    const FbBits    *fbBits;
15105b261ecSmrg    FbBits	    *srcEnd;
15205b261ecSmrg    int		    pixelsPerDst;		/* dst pixels per FbBits */
15305b261ecSmrg    int		    unitsPerSrc;		/* src patterns per FbStip */
15405b261ecSmrg    int		    leftShift, rightShift;	/* align source with dest */
15505b261ecSmrg    FbBits	    startmask, endmask;		/* dest scanline masks */
15605b261ecSmrg    FbStip	    bits=0, bitsLeft, bitsRight;/* source bits */
15705b261ecSmrg    FbStip	    left;
15805b261ecSmrg    FbBits	    mask;
15905b261ecSmrg    int		    nDst;			/* dest longwords (w.o. end) */
16005b261ecSmrg    int		    w;
16105b261ecSmrg    int		    n, nmiddle;
16205b261ecSmrg    int		    dstS;			/* stipple-relative dst X coordinate */
16305b261ecSmrg    Bool	    copy;			/* accelerate dest-invariant */
16405b261ecSmrg    Bool	    transparent;		/* accelerate 0 nop */
16505b261ecSmrg    int		    srcinc;			/* source units consumed */
16605b261ecSmrg    Bool	    endNeedsLoad = FALSE;	/* need load for endmask */
16705b261ecSmrg#ifndef FBNOPIXADDR
16805b261ecSmrg    CARD8	    *fbLane;
16905b261ecSmrg#endif
17005b261ecSmrg    int		    startbyte, endbyte;
17105b261ecSmrg
17205b261ecSmrg#ifdef FB_24BIT
17305b261ecSmrg    if (dstBpp == 24)
17405b261ecSmrg    {
17505b261ecSmrg	fbBltOne24 (src, srcStride, srcX,
17605b261ecSmrg		    dst, dstStride, dstX, dstBpp,
17705b261ecSmrg		    width, height,
17805b261ecSmrg		    fgand, fgxor, bgand, bgxor);
17905b261ecSmrg	return;
18005b261ecSmrg    }
18105b261ecSmrg#endif
18205b261ecSmrg
18305b261ecSmrg    /*
18405b261ecSmrg     * Do not read past the end of the buffer!
18505b261ecSmrg     */
18605b261ecSmrg    srcEnd = src + height * srcStride;
18705b261ecSmrg
18805b261ecSmrg    /*
18905b261ecSmrg     * Number of destination units in FbBits == number of stipple pixels
19005b261ecSmrg     * used each time
19105b261ecSmrg     */
19205b261ecSmrg    pixelsPerDst = FB_UNIT / dstBpp;
19305b261ecSmrg
19405b261ecSmrg    /*
19505b261ecSmrg     * Number of source stipple patterns in FbStip
19605b261ecSmrg     */
19705b261ecSmrg    unitsPerSrc = FB_STIP_UNIT / pixelsPerDst;
19805b261ecSmrg
19905b261ecSmrg    copy = FALSE;
20005b261ecSmrg    transparent = FALSE;
20105b261ecSmrg    if (bgand == 0 && fgand == 0)
20205b261ecSmrg	copy = TRUE;
20305b261ecSmrg    else if (bgand == FB_ALLONES && bgxor == 0)
20405b261ecSmrg	transparent = TRUE;
20505b261ecSmrg
20605b261ecSmrg    /*
20705b261ecSmrg     * Adjust source and dest to nearest FbBits boundary
20805b261ecSmrg     */
20905b261ecSmrg    src += srcX >> FB_STIP_SHIFT;
21005b261ecSmrg    dst += dstX >> FB_SHIFT;
21105b261ecSmrg    srcX &= FB_STIP_MASK;
21205b261ecSmrg    dstX &= FB_MASK;
21305b261ecSmrg
21405b261ecSmrg    FbMaskBitsBytes(dstX, width, copy,
21505b261ecSmrg		    startmask, startbyte, nmiddle, endmask, endbyte);
21605b261ecSmrg
21705b261ecSmrg    /*
21805b261ecSmrg     * Compute effective dest alignment requirement for
21905b261ecSmrg     * source -- must align source to dest unit boundary
22005b261ecSmrg     */
22105b261ecSmrg    dstS = dstX / dstBpp;
22205b261ecSmrg    /*
22305b261ecSmrg     * Compute shift constants for effective alignement
22405b261ecSmrg     */
22505b261ecSmrg    if (srcX >= dstS)
22605b261ecSmrg    {
22705b261ecSmrg	leftShift = srcX - dstS;
22805b261ecSmrg	rightShift = FB_STIP_UNIT - leftShift;
22905b261ecSmrg    }
23005b261ecSmrg    else
23105b261ecSmrg    {
23205b261ecSmrg	rightShift = dstS - srcX;
23305b261ecSmrg	leftShift = FB_STIP_UNIT - rightShift;
23405b261ecSmrg    }
23505b261ecSmrg    /*
23605b261ecSmrg     * Get pointer to stipple mask array for this depth
23705b261ecSmrg     */
23805b261ecSmrg    fbBits = 0;	/* unused */
23905b261ecSmrg    if (pixelsPerDst <= 8)
24005b261ecSmrg	fbBits = fbStippleTable[pixelsPerDst];
24105b261ecSmrg#ifndef FBNOPIXADDR
24205b261ecSmrg    fbLane = 0;
24305b261ecSmrg    if (transparent && fgand == 0 && dstBpp >= 8)
24405b261ecSmrg	fbLane = fbLaneTable[dstBpp];
24505b261ecSmrg#endif
24605b261ecSmrg
24705b261ecSmrg    /*
24805b261ecSmrg     * Compute total number of destination words written, but
24905b261ecSmrg     * don't count endmask
25005b261ecSmrg     */
25105b261ecSmrg    nDst = nmiddle;
25205b261ecSmrg    if (startmask)
25305b261ecSmrg	nDst++;
25405b261ecSmrg
25505b261ecSmrg    dstStride -= nDst;
25605b261ecSmrg
25705b261ecSmrg    /*
25805b261ecSmrg     * Compute total number of source words consumed
25905b261ecSmrg     */
26005b261ecSmrg
26105b261ecSmrg    srcinc = (nDst + unitsPerSrc - 1) / unitsPerSrc;
26205b261ecSmrg
26305b261ecSmrg    if (srcX > dstS)
26405b261ecSmrg	srcinc++;
26505b261ecSmrg    if (endmask)
26605b261ecSmrg    {
26705b261ecSmrg	endNeedsLoad = nDst % unitsPerSrc == 0;
26805b261ecSmrg	if (endNeedsLoad)
26905b261ecSmrg	    srcinc++;
27005b261ecSmrg    }
27105b261ecSmrg
27205b261ecSmrg    srcStride -= srcinc;
27305b261ecSmrg
27405b261ecSmrg    /*
27505b261ecSmrg     * Copy rectangle
27605b261ecSmrg     */
27705b261ecSmrg    while (height--)
27805b261ecSmrg    {
27905b261ecSmrg	w = nDst;	    /* total units across scanline */
28005b261ecSmrg	n = unitsPerSrc;    /* units avail in single stipple */
28105b261ecSmrg	if (n > w)
28205b261ecSmrg	    n = w;
28305b261ecSmrg
28405b261ecSmrg	bitsLeft = 0;
28505b261ecSmrg	if (srcX > dstS)
28605b261ecSmrg	    bitsLeft = READ(src++);
28705b261ecSmrg	if (n)
28805b261ecSmrg	{
28905b261ecSmrg	    /*
29005b261ecSmrg	     * Load first set of stipple bits
29105b261ecSmrg	     */
29205b261ecSmrg	    LoadBits;
29305b261ecSmrg
29405b261ecSmrg	    /*
29505b261ecSmrg	     * Consume stipple bits for startmask
29605b261ecSmrg	     */
29705b261ecSmrg	    if (startmask)
29805b261ecSmrg	    {
29905b261ecSmrg#if FB_UNIT > 32
30005b261ecSmrg		if (pixelsPerDst == 16)
30105b261ecSmrg		    mask = FbStipple16Bits(FbLeftStipBits(bits,16));
30205b261ecSmrg		else
30305b261ecSmrg#endif
30405b261ecSmrg		    mask = fbBits[FbLeftStipBits(bits,pixelsPerDst)];
30505b261ecSmrg#ifndef FBNOPIXADDR
30605b261ecSmrg		if (fbLane)
30705b261ecSmrg		{
30805b261ecSmrg		    fbTransparentSpan (dst, mask & startmask, fgxor, 1);
30905b261ecSmrg		}
31005b261ecSmrg		else
31105b261ecSmrg#endif
31205b261ecSmrg		{
31305b261ecSmrg		    if (mask || !transparent)
31405b261ecSmrg			FbDoLeftMaskByteStippleRRop (dst, mask,
31505b261ecSmrg						     fgand, fgxor, bgand, bgxor,
31605b261ecSmrg						     startbyte, startmask);
31705b261ecSmrg		}
31805b261ecSmrg		bits = FbStipLeft (bits, pixelsPerDst);
31905b261ecSmrg		dst++;
32005b261ecSmrg		n--;
32105b261ecSmrg		w--;
32205b261ecSmrg	    }
32305b261ecSmrg	    /*
32405b261ecSmrg	     * Consume stipple bits across scanline
32505b261ecSmrg	     */
32605b261ecSmrg	    for (;;)
32705b261ecSmrg	    {
32805b261ecSmrg		w -= n;
32905b261ecSmrg		if (copy)
33005b261ecSmrg		{
33105b261ecSmrg		    while (n--)
33205b261ecSmrg		    {
33305b261ecSmrg#if FB_UNIT > 32
33405b261ecSmrg			if (pixelsPerDst == 16)
33505b261ecSmrg			    mask = FbStipple16Bits(FbLeftStipBits(bits,16));
33605b261ecSmrg			else
33705b261ecSmrg#endif
33805b261ecSmrg			    mask = fbBits[FbLeftStipBits(bits,pixelsPerDst)];
33905b261ecSmrg			WRITE(dst, FbOpaqueStipple (mask, fgxor, bgxor));
34005b261ecSmrg			dst++;
34105b261ecSmrg			bits = FbStipLeft(bits, pixelsPerDst);
34205b261ecSmrg		    }
34305b261ecSmrg		}
34405b261ecSmrg		else
34505b261ecSmrg		{
34605b261ecSmrg#ifndef FBNOPIXADDR
34705b261ecSmrg		    if (fbLane)
34805b261ecSmrg		    {
34905b261ecSmrg			while (bits && n)
35005b261ecSmrg			{
35105b261ecSmrg			    switch (fbLane[FbLeftStipBits(bits,pixelsPerDst)]) {
35205b261ecSmrg				LaneCases((CARD8 *) dst);
35305b261ecSmrg			    }
35405b261ecSmrg			    bits = FbStipLeft(bits,pixelsPerDst);
35505b261ecSmrg			    dst++;
35605b261ecSmrg			    n--;
35705b261ecSmrg			}
35805b261ecSmrg			dst += n;
35905b261ecSmrg		    }
36005b261ecSmrg		    else
36105b261ecSmrg#endif
36205b261ecSmrg		    {
36305b261ecSmrg			while (n--)
36405b261ecSmrg			{
36505b261ecSmrg			    left = FbLeftStipBits(bits,pixelsPerDst);
36605b261ecSmrg			    if (left || !transparent)
36705b261ecSmrg			    {
36805b261ecSmrg				mask = fbBits[left];
36905b261ecSmrg				WRITE(dst, FbStippleRRop (READ(dst), mask,
37005b261ecSmrg						          fgand, fgxor, bgand, bgxor));
37105b261ecSmrg			    }
37205b261ecSmrg			    dst++;
37305b261ecSmrg			    bits = FbStipLeft(bits, pixelsPerDst);
37405b261ecSmrg			}
37505b261ecSmrg		    }
37605b261ecSmrg		}
37705b261ecSmrg		if (!w)
37805b261ecSmrg		    break;
37905b261ecSmrg		/*
38005b261ecSmrg		 * Load another set and reset number of available units
38105b261ecSmrg		 */
38205b261ecSmrg		LoadBits;
38305b261ecSmrg		n = unitsPerSrc;
38405b261ecSmrg		if (n > w)
38505b261ecSmrg		    n = w;
38605b261ecSmrg	    }
38705b261ecSmrg	}
38805b261ecSmrg	/*
38905b261ecSmrg	 * Consume stipple bits for endmask
39005b261ecSmrg	 */
39105b261ecSmrg	if (endmask)
39205b261ecSmrg	{
39305b261ecSmrg	    if (endNeedsLoad)
39405b261ecSmrg	    {
39505b261ecSmrg		LoadBits;
39605b261ecSmrg	    }
39705b261ecSmrg#if FB_UNIT > 32
39805b261ecSmrg	    if (pixelsPerDst == 16)
39905b261ecSmrg		mask = FbStipple16Bits(FbLeftStipBits(bits,16));
40005b261ecSmrg	    else
40105b261ecSmrg#endif
40205b261ecSmrg		mask = fbBits[FbLeftStipBits(bits,pixelsPerDst)];
40305b261ecSmrg#ifndef FBNOPIXADDR
40405b261ecSmrg	    if (fbLane)
40505b261ecSmrg	    {
40605b261ecSmrg		fbTransparentSpan (dst, mask & endmask, fgxor, 1);
40705b261ecSmrg	    }
40805b261ecSmrg	    else
40905b261ecSmrg#endif
41005b261ecSmrg	    {
41105b261ecSmrg		if (mask || !transparent)
41205b261ecSmrg		    FbDoRightMaskByteStippleRRop (dst, mask,
41305b261ecSmrg						  fgand, fgxor, bgand, bgxor,
41405b261ecSmrg						  endbyte, endmask);
41505b261ecSmrg	    }
41605b261ecSmrg	}
41705b261ecSmrg	dst += dstStride;
41805b261ecSmrg	src += srcStride;
41905b261ecSmrg    }
42005b261ecSmrg}
42105b261ecSmrg
42205b261ecSmrg#ifdef FB_24BIT
42305b261ecSmrg
42405b261ecSmrg/*
42505b261ecSmrg * Crufty macros to initialize the mask array, most of this
42605b261ecSmrg * is to avoid compile-time warnings about shift overflow
42705b261ecSmrg */
42805b261ecSmrg
42905b261ecSmrg#if BITMAP_BIT_ORDER == MSBFirst
43005b261ecSmrg#define Mask24Pos(x,r) ((x)*24-(r))
43105b261ecSmrg#else
43205b261ecSmrg#define Mask24Pos(x,r) ((x)*24-((r) ? 24 - (r) : 0))
43305b261ecSmrg#endif
43405b261ecSmrg
43505b261ecSmrg#define Mask24Neg(x,r)	(Mask24Pos(x,r) < 0 ? -Mask24Pos(x,r) : 0)
43605b261ecSmrg#define Mask24Check(x,r)    (Mask24Pos(x,r) < 0 ? 0 : \
43705b261ecSmrg			     Mask24Pos(x,r) >= FB_UNIT ? 0 : Mask24Pos(x,r))
43805b261ecSmrg
43905b261ecSmrg#define Mask24(x,r) (Mask24Pos(x,r) < FB_UNIT ? \
44005b261ecSmrg		     (Mask24Pos(x,r) < 0 ? \
4419ace9065Smrg		      0xffffffU >> Mask24Neg (x,r) : \
4429ace9065Smrg		      0xffffffU << Mask24Check(x,r)) : 0)
44305b261ecSmrg
44405b261ecSmrg#define SelMask24(b,n,r)	((((b) >> n) & 1) * Mask24(n,r))
44505b261ecSmrg
44605b261ecSmrg/*
44705b261ecSmrg * Untested for MSBFirst or FB_UNIT == 32
44805b261ecSmrg */
44905b261ecSmrg
45005b261ecSmrg#if FB_UNIT == 64
45105b261ecSmrg#define C4_24(b,r) \
45205b261ecSmrg    (SelMask24(b,0,r) | \
45305b261ecSmrg     SelMask24(b,1,r) | \
45405b261ecSmrg     SelMask24(b,2,r) | \
45505b261ecSmrg     SelMask24(b,3,r))
45605b261ecSmrg
45705b261ecSmrg#define FbStip24New(rot)    (2 + (rot != 0))
45805b261ecSmrg#define FbStip24Len	    4
45905b261ecSmrg
46005b261ecSmrgconst FbBits	fbStipple24Bits[3][1 << FbStip24Len] = {
46105b261ecSmrg    /* rotate 0 */
46205b261ecSmrg    {
46305b261ecSmrg	C4_24( 0, 0), C4_24( 1, 0), C4_24( 2, 0), C4_24( 3, 0),
46405b261ecSmrg	C4_24( 4, 0), C4_24( 5, 0), C4_24( 6, 0), C4_24( 7, 0),
46505b261ecSmrg	C4_24( 8, 0), C4_24( 9, 0), C4_24(10, 0), C4_24(11, 0),
46605b261ecSmrg	C4_24(12, 0), C4_24(13, 0), C4_24(14, 0), C4_24(15, 0),
46705b261ecSmrg    },
46805b261ecSmrg    /* rotate 8 */
46905b261ecSmrg    {
47005b261ecSmrg	C4_24( 0, 8), C4_24( 1, 8), C4_24( 2, 8), C4_24( 3, 8),
47105b261ecSmrg	C4_24( 4, 8), C4_24( 5, 8), C4_24( 6, 8), C4_24( 7, 8),
47205b261ecSmrg	C4_24( 8, 8), C4_24( 9, 8), C4_24(10, 8), C4_24(11, 8),
47305b261ecSmrg	C4_24(12, 8), C4_24(13, 8), C4_24(14, 8), C4_24(15, 8),
47405b261ecSmrg    },
47505b261ecSmrg    /* rotate 16 */
47605b261ecSmrg    {
47705b261ecSmrg	C4_24( 0,16), C4_24( 1,16), C4_24( 2,16), C4_24( 3,16),
47805b261ecSmrg	C4_24( 4,16), C4_24( 5,16), C4_24( 6,16), C4_24( 7,16),
47905b261ecSmrg	C4_24( 8,16), C4_24( 9,16), C4_24(10,16), C4_24(11,16),
48005b261ecSmrg	C4_24(12,16), C4_24(13,16), C4_24(14,16), C4_24(15,16),
48105b261ecSmrg    }
48205b261ecSmrg};
48305b261ecSmrg
48405b261ecSmrg#endif
48505b261ecSmrg
48605b261ecSmrg#if FB_UNIT == 32
48705b261ecSmrg#define C2_24(b,r)  \
48805b261ecSmrg    (SelMask24(b,0,r) | \
48905b261ecSmrg     SelMask24(b,1,r))
49005b261ecSmrg
49105b261ecSmrg#define FbStip24Len	    2
49205b261ecSmrg#if BITMAP_BIT_ORDER == MSBFirst
49305b261ecSmrg#define FbStip24New(rot)    (1 + (rot == 0))
49405b261ecSmrg#else
49505b261ecSmrg#define FbStip24New(rot)    (1 + (rot == 8))
49605b261ecSmrg#endif
49705b261ecSmrg
49805b261ecSmrgconst FbBits	fbStipple24Bits[3][1 << FbStip24Len] = {
49905b261ecSmrg    /* rotate 0 */
50005b261ecSmrg    {
50105b261ecSmrg	C2_24( 0, 0), C2_24 ( 1, 0), C2_24 ( 2, 0), C2_24 ( 3, 0),
50205b261ecSmrg    },
50305b261ecSmrg    /* rotate 8 */
50405b261ecSmrg    {
50505b261ecSmrg	C2_24( 0, 8), C2_24 ( 1, 8), C2_24 ( 2, 8), C2_24 ( 3, 8),
50605b261ecSmrg    },
50705b261ecSmrg    /* rotate 16 */
50805b261ecSmrg    {
50905b261ecSmrg	C2_24( 0,16), C2_24 ( 1,16), C2_24 ( 2,16), C2_24 ( 3,16),
51005b261ecSmrg    }
51105b261ecSmrg};
51205b261ecSmrg#endif
51305b261ecSmrg
51405b261ecSmrg#if BITMAP_BIT_ORDER == LSBFirst
51505b261ecSmrg
51605b261ecSmrg#define FbMergeStip24Bits(left, right, new) \
51705b261ecSmrg	(FbStipLeft (left, new) | FbStipRight ((right), (FbStip24Len - (new))))
51805b261ecSmrg
51905b261ecSmrg#define FbMergePartStip24Bits(left, right, llen, rlen) \
52005b261ecSmrg	(left | FbStipRight(right, llen))
52105b261ecSmrg
52205b261ecSmrg#else
52305b261ecSmrg
52405b261ecSmrg#define FbMergeStip24Bits(left, right, new) \
52505b261ecSmrg	((FbStipLeft (left, new) & ((1 << FbStip24Len) - 1)) | right)
52605b261ecSmrg
52705b261ecSmrg#define FbMergePartStip24Bits(left, right, llen, rlen) \
52805b261ecSmrg	(FbStipLeft(left, rlen) | right)
52905b261ecSmrg
53005b261ecSmrg#endif
53105b261ecSmrg
53205b261ecSmrg#define fbFirstStipBits(len,stip) {\
53305b261ecSmrg    int	__len = (len); \
53405b261ecSmrg    if (len <= remain) { \
53505b261ecSmrg	stip = FbLeftStipBits(bits, len); \
53605b261ecSmrg    } else { \
53705b261ecSmrg	stip = FbLeftStipBits(bits, remain); \
53805b261ecSmrg	bits = (src < srcEnd ? READ(src++) : 0); \
53905b261ecSmrg	__len = (len) - remain; \
54005b261ecSmrg	stip = FbMergePartStip24Bits(stip, FbLeftStipBits(bits, __len), \
54105b261ecSmrg				     remain, __len); \
54205b261ecSmrg	remain = FB_STIP_UNIT; \
54305b261ecSmrg    } \
54405b261ecSmrg    bits = FbStipLeft (bits, __len); \
54505b261ecSmrg    remain -= __len; \
54605b261ecSmrg}
54705b261ecSmrg
54805b261ecSmrg#define fbInitStipBits(offset,len,stip) {\
54905b261ecSmrg    bits = FbStipLeft (READ(src++),offset); \
55005b261ecSmrg    remain = FB_STIP_UNIT - offset; \
55105b261ecSmrg    fbFirstStipBits(len,stip); \
55205b261ecSmrg    stip = FbMergeStip24Bits (0, stip, len); \
55305b261ecSmrg}
55405b261ecSmrg
55505b261ecSmrg#define fbNextStipBits(rot,stip) {\
55605b261ecSmrg    int	    __new = FbStip24New(rot); \
55705b261ecSmrg    FbStip  __right; \
55805b261ecSmrg    fbFirstStipBits(__new, __right); \
55905b261ecSmrg    stip = FbMergeStip24Bits (stip, __right, __new); \
56005b261ecSmrg    rot = FbNext24Rot (rot); \
56105b261ecSmrg}
56205b261ecSmrg
56305b261ecSmrg/*
56405b261ecSmrg * Use deep mask tables that incorporate rotation, pull
56505b261ecSmrg * a variable number of bits out of the stipple and
56605b261ecSmrg * reuse the right bits as needed for the next write
56705b261ecSmrg *
56805b261ecSmrg * Yes, this is probably too much code, but most 24-bpp screens
56905b261ecSmrg * have no acceleration so this code is used for stipples, copyplane
57005b261ecSmrg * and text
57105b261ecSmrg */
57205b261ecSmrgvoid
57305b261ecSmrgfbBltOne24 (FbStip	*srcLine,
57405b261ecSmrg	    FbStride	srcStride,  /* FbStip units per scanline */
57505b261ecSmrg	    int		srcX,	    /* bit position of source */
57605b261ecSmrg	    FbBits	*dst,
57705b261ecSmrg	    FbStride	dstStride,  /* FbBits units per scanline */
57805b261ecSmrg	    int		dstX,	    /* bit position of dest */
57905b261ecSmrg	    int		dstBpp,	    /* bits per destination unit */
58005b261ecSmrg
58105b261ecSmrg	    int		width,	    /* width in bits of destination */
58205b261ecSmrg	    int		height,	    /* height in scanlines */
58305b261ecSmrg
58405b261ecSmrg	    FbBits	fgand,	    /* rrop values */
58505b261ecSmrg	    FbBits	fgxor,
58605b261ecSmrg	    FbBits	bgand,
58705b261ecSmrg	    FbBits	bgxor)
58805b261ecSmrg{
58905b261ecSmrg    FbStip	*src, *srcEnd;
59005b261ecSmrg    FbBits	leftMask, rightMask, mask;
59105b261ecSmrg    int		nlMiddle, nl;
59205b261ecSmrg    FbStip	stip, bits;
59305b261ecSmrg    int		remain;
59405b261ecSmrg    int		dstS;
59505b261ecSmrg    int		firstlen;
59605b261ecSmrg    int		rot0, rot;
59705b261ecSmrg    int		nDst;
59805b261ecSmrg
59905b261ecSmrg    /*
60005b261ecSmrg     * Do not read past the end of the buffer!
60105b261ecSmrg     */
60205b261ecSmrg    srcEnd = srcLine + height * srcStride;
60305b261ecSmrg
60405b261ecSmrg    srcLine += srcX >> FB_STIP_SHIFT;
60505b261ecSmrg    dst += dstX >> FB_SHIFT;
60605b261ecSmrg    srcX &= FB_STIP_MASK;
60705b261ecSmrg    dstX &= FB_MASK;
60805b261ecSmrg    rot0 = FbFirst24Rot (dstX);
60905b261ecSmrg
61005b261ecSmrg    FbMaskBits (dstX, width, leftMask, nlMiddle, rightMask);
61105b261ecSmrg
61205b261ecSmrg    dstS = (dstX + 23) / 24;
61305b261ecSmrg    firstlen = FbStip24Len - dstS;
61405b261ecSmrg
61505b261ecSmrg    nDst = nlMiddle;
61605b261ecSmrg    if (leftMask)
61705b261ecSmrg	nDst++;
61805b261ecSmrg    dstStride -= nDst;
61905b261ecSmrg
62005b261ecSmrg    /* opaque copy */
62105b261ecSmrg    if (bgand == 0 && fgand == 0)
62205b261ecSmrg    {
62305b261ecSmrg	while (height--)
62405b261ecSmrg	{
62505b261ecSmrg	    rot = rot0;
62605b261ecSmrg	    src = srcLine;
62705b261ecSmrg	    srcLine += srcStride;
62805b261ecSmrg	    fbInitStipBits (srcX,firstlen, stip);
62905b261ecSmrg	    if (leftMask)
63005b261ecSmrg	    {
63105b261ecSmrg		mask = fbStipple24Bits[rot >> 3][stip];
63205b261ecSmrg		WRITE(dst, (READ(dst) & ~leftMask) |
63305b261ecSmrg			    (FbOpaqueStipple (mask,
63405b261ecSmrg					      FbRot24(fgxor, rot),
63505b261ecSmrg					      FbRot24(bgxor, rot))
63605b261ecSmrg			     & leftMask));
63705b261ecSmrg		dst++;
63805b261ecSmrg		fbNextStipBits(rot,stip);
63905b261ecSmrg	    }
64005b261ecSmrg	    nl = nlMiddle;
64105b261ecSmrg	    while (nl--)
64205b261ecSmrg	    {
64305b261ecSmrg		mask = fbStipple24Bits[rot>>3][stip];
64405b261ecSmrg		WRITE(dst, FbOpaqueStipple (mask,
64505b261ecSmrg					    FbRot24(fgxor, rot),
64605b261ecSmrg					    FbRot24(bgxor, rot)));
64705b261ecSmrg		dst++;
64805b261ecSmrg		fbNextStipBits(rot,stip);
64905b261ecSmrg	    }
65005b261ecSmrg	    if (rightMask)
65105b261ecSmrg	    {
65205b261ecSmrg		mask = fbStipple24Bits[rot >> 3][stip];
65305b261ecSmrg		WRITE(dst, (READ(dst) & ~rightMask) |
65405b261ecSmrg			    (FbOpaqueStipple (mask,
65505b261ecSmrg					      FbRot24(fgxor, rot),
65605b261ecSmrg					      FbRot24(bgxor, rot))
65705b261ecSmrg			     & rightMask));
65805b261ecSmrg	    }
65905b261ecSmrg	    dst += dstStride;
66005b261ecSmrg	    src += srcStride;
66105b261ecSmrg	}
66205b261ecSmrg    }
66305b261ecSmrg    /* transparent copy */
66405b261ecSmrg    else if (bgand == FB_ALLONES && bgxor == 0 && fgand == 0)
66505b261ecSmrg    {
66605b261ecSmrg	while (height--)
66705b261ecSmrg	{
66805b261ecSmrg	    rot = rot0;
66905b261ecSmrg	    src = srcLine;
67005b261ecSmrg	    srcLine += srcStride;
67105b261ecSmrg	    fbInitStipBits (srcX, firstlen, stip);
67205b261ecSmrg	    if (leftMask)
67305b261ecSmrg	    {
67405b261ecSmrg		if (stip)
67505b261ecSmrg		{
67605b261ecSmrg		    mask = fbStipple24Bits[rot >> 3][stip] & leftMask;
67705b261ecSmrg		    WRITE(dst, (READ(dst) & ~mask) | (FbRot24(fgxor, rot) & mask));
67805b261ecSmrg		}
67905b261ecSmrg		dst++;
68005b261ecSmrg		fbNextStipBits (rot, stip);
68105b261ecSmrg	    }
68205b261ecSmrg	    nl = nlMiddle;
68305b261ecSmrg	    while (nl--)
68405b261ecSmrg	    {
68505b261ecSmrg		if (stip)
68605b261ecSmrg		{
68705b261ecSmrg		    mask = fbStipple24Bits[rot>>3][stip];
68805b261ecSmrg		    WRITE(dst, (READ(dst) & ~mask) | (FbRot24(fgxor,rot) & mask));
68905b261ecSmrg		}
69005b261ecSmrg		dst++;
69105b261ecSmrg		fbNextStipBits (rot, stip);
69205b261ecSmrg	    }
69305b261ecSmrg	    if (rightMask)
69405b261ecSmrg	    {
69505b261ecSmrg		if (stip)
69605b261ecSmrg		{
69705b261ecSmrg		    mask = fbStipple24Bits[rot >> 3][stip] & rightMask;
69805b261ecSmrg		    WRITE(dst, (READ(dst) & ~mask) | (FbRot24(fgxor, rot) & mask));
69905b261ecSmrg		}
70005b261ecSmrg	    }
70105b261ecSmrg	    dst += dstStride;
70205b261ecSmrg	}
70305b261ecSmrg    }
70405b261ecSmrg    else
70505b261ecSmrg    {
70605b261ecSmrg	while (height--)
70705b261ecSmrg	{
70805b261ecSmrg	    rot = rot0;
70905b261ecSmrg	    src = srcLine;
71005b261ecSmrg	    srcLine += srcStride;
71105b261ecSmrg	    fbInitStipBits (srcX, firstlen, stip);
71205b261ecSmrg	    if (leftMask)
71305b261ecSmrg	    {
71405b261ecSmrg		mask = fbStipple24Bits[rot >> 3][stip];
71505b261ecSmrg		WRITE(dst, FbStippleRRopMask (READ(dst), mask,
71605b261ecSmrg					      FbRot24(fgand, rot),
71705b261ecSmrg					      FbRot24(fgxor, rot),
71805b261ecSmrg					      FbRot24(bgand, rot),
71905b261ecSmrg					      FbRot24(bgxor, rot),
72005b261ecSmrg					      leftMask));
72105b261ecSmrg		dst++;
72205b261ecSmrg		fbNextStipBits(rot,stip);
72305b261ecSmrg	    }
72405b261ecSmrg	    nl = nlMiddle;
72505b261ecSmrg	    while (nl--)
72605b261ecSmrg	    {
72705b261ecSmrg		mask = fbStipple24Bits[rot >> 3][stip];
72805b261ecSmrg		WRITE(dst, FbStippleRRop (READ(dst), mask,
72905b261ecSmrg					  FbRot24(fgand, rot),
73005b261ecSmrg					  FbRot24(fgxor, rot),
73105b261ecSmrg					  FbRot24(bgand, rot),
73205b261ecSmrg					  FbRot24(bgxor, rot)));
73305b261ecSmrg		dst++;
73405b261ecSmrg		fbNextStipBits(rot,stip);
73505b261ecSmrg	    }
73605b261ecSmrg	    if (rightMask)
73705b261ecSmrg	    {
73805b261ecSmrg		mask = fbStipple24Bits[rot >> 3][stip];
73905b261ecSmrg		WRITE(dst, FbStippleRRopMask (READ(dst), mask,
74005b261ecSmrg					      FbRot24(fgand, rot),
74105b261ecSmrg					      FbRot24(fgxor, rot),
74205b261ecSmrg					      FbRot24(bgand, rot),
74305b261ecSmrg					      FbRot24(bgxor, rot),
74405b261ecSmrg					      rightMask));
74505b261ecSmrg	    }
74605b261ecSmrg	    dst += dstStride;
74705b261ecSmrg	}
74805b261ecSmrg    }
74905b261ecSmrg}
75005b261ecSmrg#endif
75105b261ecSmrg
75205b261ecSmrg/*
75305b261ecSmrg * Not very efficient, but simple -- copy a single plane
75405b261ecSmrg * from an N bit image to a 1 bit image
75505b261ecSmrg */
75605b261ecSmrg
75705b261ecSmrgvoid
75805b261ecSmrgfbBltPlane (FbBits	    *src,
75905b261ecSmrg	    FbStride	    srcStride,
76005b261ecSmrg	    int		    srcX,
76105b261ecSmrg	    int		    srcBpp,
76205b261ecSmrg
76305b261ecSmrg	    FbStip	    *dst,
76405b261ecSmrg	    FbStride	    dstStride,
76505b261ecSmrg	    int		    dstX,
76605b261ecSmrg
76705b261ecSmrg	    int		    width,
76805b261ecSmrg	    int		    height,
76905b261ecSmrg
77005b261ecSmrg	    FbStip	    fgand,
77105b261ecSmrg	    FbStip	    fgxor,
77205b261ecSmrg	    FbStip	    bgand,
77305b261ecSmrg	    FbStip	    bgxor,
77405b261ecSmrg	    Pixel	    planeMask)
77505b261ecSmrg{
77605b261ecSmrg    FbBits	*s;
77705b261ecSmrg    FbBits	pm;
77805b261ecSmrg    FbBits	srcMask;
77905b261ecSmrg    FbBits	srcMaskFirst;
78005b261ecSmrg    FbBits	srcMask0 = 0;
78105b261ecSmrg    FbBits	srcBits;
78205b261ecSmrg
78305b261ecSmrg    FbStip	dstBits;
78405b261ecSmrg    FbStip	*d;
78505b261ecSmrg    FbStip	dstMask;
78605b261ecSmrg    FbStip	dstMaskFirst;
78705b261ecSmrg    FbStip	dstUnion;
78805b261ecSmrg    int		w;
78905b261ecSmrg    int		wt;
79005b261ecSmrg    int		rot0;
79105b261ecSmrg
79205b261ecSmrg    if (!width)
79305b261ecSmrg	return;
79405b261ecSmrg
79505b261ecSmrg    src += srcX >> FB_SHIFT;
79605b261ecSmrg    srcX &= FB_MASK;
79705b261ecSmrg
79805b261ecSmrg    dst += dstX >> FB_STIP_SHIFT;
79905b261ecSmrg    dstX &= FB_STIP_MASK;
80005b261ecSmrg
80105b261ecSmrg    w = width / srcBpp;
80205b261ecSmrg
80305b261ecSmrg    pm = fbReplicatePixel (planeMask, srcBpp);
80405b261ecSmrg#ifdef FB_24BIT
80505b261ecSmrg    if (srcBpp == 24)
80605b261ecSmrg    {
80705b261ecSmrg	int w = 24;
80805b261ecSmrg
80905b261ecSmrg	rot0 = FbFirst24Rot (srcX);
81005b261ecSmrg	if (srcX + w > FB_UNIT)
81105b261ecSmrg	    w = FB_UNIT - srcX;
81205b261ecSmrg	srcMaskFirst = FbRot24(pm,rot0) & FbBitsMask(srcX,w);
81305b261ecSmrg    }
81405b261ecSmrg    else
81505b261ecSmrg#endif
81605b261ecSmrg    {
81705b261ecSmrg	rot0 = 0;
81805b261ecSmrg	srcMaskFirst = pm & FbBitsMask(srcX, srcBpp);
81905b261ecSmrg	srcMask0 = pm & FbBitsMask(0, srcBpp);
82005b261ecSmrg    }
82105b261ecSmrg
82205b261ecSmrg    dstMaskFirst = FbStipMask(dstX,1);
82305b261ecSmrg    while (height--)
82405b261ecSmrg    {
82505b261ecSmrg	d = dst;
82605b261ecSmrg	dst += dstStride;
82705b261ecSmrg	s = src;
82805b261ecSmrg	src += srcStride;
82905b261ecSmrg
83005b261ecSmrg	srcMask = srcMaskFirst;
83105b261ecSmrg#ifdef FB_24BIT
83205b261ecSmrg	if (srcBpp == 24)
83305b261ecSmrg	    srcMask0 = FbRot24(pm,rot0) & FbBitsMask(0, srcBpp);
83405b261ecSmrg#endif
83505b261ecSmrg    	srcBits = READ(s++);
83605b261ecSmrg
83705b261ecSmrg	dstMask = dstMaskFirst;
83805b261ecSmrg	dstUnion = 0;
83905b261ecSmrg	dstBits = 0;
84005b261ecSmrg
84105b261ecSmrg	wt = w;
84205b261ecSmrg
84305b261ecSmrg	while (wt--)
84405b261ecSmrg	{
84505b261ecSmrg	    if (!srcMask)
84605b261ecSmrg	    {
84705b261ecSmrg		srcBits = READ(s++);
84805b261ecSmrg#ifdef FB_24BIT
84905b261ecSmrg		if (srcBpp == 24)
85005b261ecSmrg		    srcMask0 = FbNext24Pix(srcMask0) & FbBitsMask(0,24);
85105b261ecSmrg#endif
85205b261ecSmrg		srcMask = srcMask0;
85305b261ecSmrg	    }
85405b261ecSmrg	    if (!dstMask)
85505b261ecSmrg	    {
85605b261ecSmrg		WRITE(d, FbStippleRRopMask(READ(d), dstBits,
85705b261ecSmrg					   fgand, fgxor, bgand, bgxor,
85805b261ecSmrg					   dstUnion));
85905b261ecSmrg		d++;
86005b261ecSmrg		dstMask = FbStipMask(0,1);
86105b261ecSmrg		dstUnion = 0;
86205b261ecSmrg		dstBits = 0;
86305b261ecSmrg	    }
86405b261ecSmrg	    if (srcBits & srcMask)
86505b261ecSmrg		dstBits |= dstMask;
86605b261ecSmrg	    dstUnion |= dstMask;
86705b261ecSmrg	    if (srcBpp == FB_UNIT)
86805b261ecSmrg		srcMask = 0;
86905b261ecSmrg	    else
87005b261ecSmrg		srcMask = FbScrRight(srcMask,srcBpp);
87105b261ecSmrg	    dstMask = FbStipRight(dstMask,1);
87205b261ecSmrg	}
87305b261ecSmrg	if (dstUnion)
87405b261ecSmrg	    WRITE(d, FbStippleRRopMask(READ(d),dstBits,
87505b261ecSmrg				       fgand, fgxor, bgand, bgxor,
87605b261ecSmrg				       dstUnion));
87705b261ecSmrg    }
87805b261ecSmrg}
87905b261ecSmrg
880