xref: /csrg-svn/sys/sparc/rcons/raster_op.c (revision 63321)
155131Storek /*-
2*63321Sbostic  * Copyright (c) 1991, 1993
3*63321Sbostic  *	The Regents of the University of California.  All rights reserved.
455131Storek  *
555131Storek  * This code is derived from software contributed to the Computer Systems
655131Storek  * Engineering Group at Lawrence Berkeley Laboratory and to the University
755131Storek  * of California at Berkeley by Jef Poskanzer.
855131Storek  *
955131Storek  * %sccs.include.redist.c%
1055131Storek  *
11*63321Sbostic  *	@(#)raster_op.c	8.1 (Berkeley) 06/11/93
1255131Storek  *
1355131Storek  * from: $Header: raster_op.c,v 1.22 92/06/17 08:14:44 torek Exp $
1455131Storek  */
1555131Storek 
1655131Storek /*
1755131Storek  * Bitblit routine for raster library.
1855131Storek  *
1955131Storek  * This raster-op is machined to exacting tolerances by skilled native
2055131Storek  * craftsmen with pride in their work.
2155131Storek  *
2255131Storek  * The various cases are broken down like this:
2355131Storek  *
2455131Storek  *   src required
2555131Storek  *       1-bit to 1-bit
2655131Storek  *       1-bit to 8-bits
2755131Storek  *       8-bits to 8-bits
2855131Storek  *   no src required
2955131Storek  *       1-bit no-src
3055131Storek  *       8-bits no-src
3155131Storek  */
3255131Storek 
3355131Storek #include <sys/types.h>
3456539Sbostic #include <sparc/rcons/raster.h>
3555131Storek 
3655131Storek /* CONFIGURE: To save on executable size, you can configure out the seldom-used
3755131Storek ** logical operations.  With this variable set, the only operations implemented
3855131Storek ** are: RAS_SRC, RAS_CLEAR, RAS_SET, RAS_INVERT, RAS_XOR, RAS_INVERTSRC.
3955131Storek */
4055131Storek #ifdef KERNEL
4155131Storek #define PARTIAL_LOGICAL_OPS
4255131Storek #endif
4355131Storek 
4455131Storek /* CONFIGURE: bcopy() is supposed to be the ultimately fastest way to move
4555131Storek ** bytes, overlapping or not, ignoring the startup cost.  Unfortunately
4655131Storek ** this is not true on some systems.  For example, on a Sun 3 running
4755131Storek ** SunOS 3.5, bcopy() is about five times slower than a simple for loop
4855131Storek ** on overlapping copies.  And on a 4.1.1 SPARC, bcopy() is about 2/3rds
4955131Storek ** as fast on backwards overlaps.  So, only define this if your bcopy is ok.
5055131Storek */
5155131Storek #undef BCOPY_FASTER
5255131Storek 
5355131Storek /* End of configurable definitions. */
5455131Storek 
5555131Storek 
5655131Storek /* Definitions. */
5755131Storek 
5855131Storek /* Raster-op macros.  These encapsulate the switch statements and so make
5955131Storek ** the source code 16 times smaller.  The pre and pst args are code
6055131Storek ** fragments to put before and after the assignment in each case.  They
6155131Storek ** can be the beginning and end of a loop.  If the pst fragment includes a
6255131Storek ** masked assignment, for example to handle the left or right edge cases,
6355131Storek ** a good optimizing compiler will simplify the boolean expressions very
6455131Storek ** nicely - both cc and gcc on the SPARC will do this.
6555131Storek */
6655131Storek 
6755131Storek #ifndef PARTIAL_LOGICAL_OPS
6855131Storek 
6955131Storek #define ROP_DST(op,pre,d,pst) \
7055131Storek     switch ( op ) \
7155131Storek 	{ \
7255131Storek 	case RAS_CLEAR: \
7355131Storek 	pre \
7455131Storek 	(d) = 0; \
7555131Storek 	pst \
7655131Storek 	break; \
7755131Storek 	case RAS_INVERT: \
7855131Storek 	pre \
7955131Storek 	(d) = ~(d); \
8055131Storek 	pst \
8155131Storek 	break; \
8255131Storek 	case RAS_DST: \
8355131Storek 	/* noop */ \
8455131Storek 	break; \
8555131Storek 	case RAS_SET: \
8655131Storek 	pre \
8755131Storek 	(d) = ~0; \
8855131Storek 	pst \
8955131Storek 	break; \
9055131Storek 	default: \
9155131Storek 	return -1; \
9255131Storek 	}
9355131Storek 
9455131Storek #define ROP_DSTCOLOR(op,pre,d,c,pst) \
9555131Storek     switch ( op ) \
9655131Storek 	{ \
9755131Storek 	case RAS_CLEAR: \
9855131Storek 	pre \
9955131Storek 	(d) = 0; \
10055131Storek 	pst \
10155131Storek 	break; \
10255131Storek 	case RAS_INVERT: \
10355131Storek 	pre \
10455131Storek 	(d) = ~(d); \
10555131Storek 	pst \
10655131Storek 	break; \
10755131Storek 	case RAS_DST: \
10855131Storek 	/* noop */ \
10955131Storek 	break; \
11055131Storek 	case RAS_SET: \
11155131Storek 	pre \
11255131Storek 	(d) = (c); \
11355131Storek 	pst \
11455131Storek 	break; \
11555131Storek 	default: \
11655131Storek 	return -1; \
11755131Storek 	}
11855131Storek 
11955131Storek #define ROP_SRCDST(op,pre,s,d,pst) \
12055131Storek     switch ( op ) \
12155131Storek 	{ \
12255131Storek 	case RAS_NOTOR: \
12355131Storek 	pre \
12455131Storek 	(d) = ~( (s) | (d) ); \
12555131Storek 	pst \
12655131Storek 	break; \
12755131Storek 	case RAS_NOTSRC_AND_DST: \
12855131Storek 	pre \
12955131Storek 	(d) = ~(s) & (d); \
13055131Storek 	pst \
13155131Storek 	break; \
13255131Storek 	case RAS_INVERTSRC: \
13355131Storek 	pre \
13455131Storek 	(d) = ~(s); \
13555131Storek 	pst \
13655131Storek 	break; \
13755131Storek 	case RAS_SRC_AND_NOTDST: \
13855131Storek 	pre \
13955131Storek 	(d) = (s) & ~(d); \
14055131Storek 	pst \
14155131Storek 	break; \
14255131Storek 	case RAS_XOR: \
14355131Storek 	pre \
14455131Storek 	(d) = (s) ^ (d); \
14555131Storek 	pst \
14655131Storek 	break; \
14755131Storek 	case RAS_NOTAND: \
14855131Storek 	pre \
14955131Storek 	(d) = ~( (s) & (d) ); \
15055131Storek 	pst \
15155131Storek 	break; \
15255131Storek 	case RAS_AND: \
15355131Storek 	pre \
15455131Storek 	(d) = (s) & (d); \
15555131Storek 	pst \
15655131Storek 	break; \
15755131Storek 	case RAS_NOTXOR: \
15855131Storek 	pre \
15955131Storek 	(d) = ~( (s) ^ (d) ); \
16055131Storek 	pst \
16155131Storek 	break; \
16255131Storek 	case RAS_NOTSRC_OR_DST: \
16355131Storek 	pre \
16455131Storek 	(d) = ~(s) | (d); \
16555131Storek 	pst \
16655131Storek 	break; \
16755131Storek 	case RAS_SRC: \
16855131Storek 	pre \
16955131Storek 	(d) = (s); \
17055131Storek 	pst \
17155131Storek 	break; \
17255131Storek 	case RAS_SRC_OR_NOTDST: \
17355131Storek 	pre \
17455131Storek 	(d) = (s) | ~(d); \
17555131Storek 	pst \
17655131Storek 	break; \
17755131Storek 	case RAS_OR: \
17855131Storek 	pre \
17955131Storek 	(d) = (s) | (d); \
18055131Storek 	pst \
18155131Storek 	break; \
18255131Storek 	default: \
18355131Storek 	return -1; \
18455131Storek 	}
18555131Storek 
18655131Storek #define ROP_SRCDSTCOLOR(op,pre,s,d,c,pst) \
18755131Storek     switch ( op ) \
18855131Storek 	{ \
18955131Storek 	case RAS_NOTOR: \
19055131Storek 	pre \
19155131Storek 	if ( s ) \
19255131Storek 	    (d) = ~( (c) | (d) ); \
19355131Storek 	else \
19455131Storek 	    (d) = ~(d); \
19555131Storek 	pst \
19655131Storek 	break; \
19755131Storek 	case RAS_NOTSRC_AND_DST: \
19855131Storek 	pre \
19955131Storek 	if ( s ) \
20055131Storek 	    (d) = ~(c) & (d); \
20155131Storek 	pst \
20255131Storek 	break; \
20355131Storek 	case RAS_INVERTSRC: \
20455131Storek 	pre \
20555131Storek 	if ( s ) \
20655131Storek 	    (d) = ~(c); \
20755131Storek 	else \
20855131Storek 	    (d) = ~0; \
20955131Storek 	pst \
21055131Storek 	break; \
21155131Storek 	case RAS_SRC_AND_NOTDST: \
21255131Storek 	pre \
21355131Storek 	if ( s ) \
21455131Storek 	    (d) = (c) & ~(d); \
21555131Storek 	else \
21655131Storek 	    (d) = 0; \
21755131Storek 	pst \
21855131Storek 	break; \
21955131Storek 	case RAS_XOR: \
22055131Storek 	pre \
22155131Storek 	if ( s ) \
22255131Storek 	    (d) = (c) ^ (d); \
22355131Storek 	pst \
22455131Storek 	break; \
22555131Storek 	case RAS_NOTAND: \
22655131Storek 	pre \
22755131Storek 	if ( s ) \
22855131Storek 	    (d) = ~( (c) & (d) ); \
22955131Storek 	else \
23055131Storek 	    (d) = ~0; \
23155131Storek 	pst \
23255131Storek 	break; \
23355131Storek 	case RAS_AND: \
23455131Storek 	pre \
23555131Storek 	if ( s ) \
23655131Storek 	    (d) = (c) & (d); \
23755131Storek 	else \
23855131Storek 	    (d) = 0; \
23955131Storek 	pst \
24055131Storek 	break; \
24155131Storek 	case RAS_NOTXOR: \
24255131Storek 	pre \
24355131Storek 	if ( s ) \
24455131Storek 	    (d) = ~( (c) ^ (d) ); \
24555131Storek 	else \
24655131Storek 	    (d) = ~(d); \
24755131Storek 	pst \
24855131Storek 	break; \
24955131Storek 	case RAS_NOTSRC_OR_DST: \
25055131Storek 	pre \
25155131Storek 	if ( s ) \
25255131Storek 	    (d) = ~(c) | (d); \
25355131Storek 	else \
25455131Storek 	    (d) = ~0; \
25555131Storek 	pst \
25655131Storek 	break; \
25755131Storek 	case RAS_SRC: \
25855131Storek 	pre \
25955131Storek 	if ( s ) \
26055131Storek 	    (d) = (c); \
26155131Storek 	else \
26255131Storek 	    (d) = 0; \
26355131Storek 	pst \
26455131Storek 	break; \
26555131Storek 	case RAS_SRC_OR_NOTDST: \
26655131Storek 	pre \
26755131Storek 	if ( s ) \
26855131Storek 	    (d) = (c) | ~(d); \
26955131Storek 	else \
27055131Storek 	    (d) = ~(d); \
27155131Storek 	pst \
27255131Storek 	break; \
27355131Storek 	case RAS_OR: \
27455131Storek 	pre \
27555131Storek 	if ( s ) \
27655131Storek 	    (d) = (c) | (d); \
27755131Storek 	pst \
27855131Storek 	break; \
27955131Storek 	default: \
28055131Storek 	return -1; \
28155131Storek 	}
28255131Storek 
28355131Storek #else /*PARTIAL_LOGICAL_OPS*/
28455131Storek 
28555131Storek #define ROP_DST(op,pre,d,pst) \
28655131Storek     switch ( op ) \
28755131Storek 	{ \
28855131Storek 	case RAS_CLEAR: \
28955131Storek 	pre \
29055131Storek 	(d) = 0; \
29155131Storek 	pst \
29255131Storek 	break; \
29355131Storek 	case RAS_INVERT: \
29455131Storek 	pre \
29555131Storek 	(d) = ~(d); \
29655131Storek 	pst \
29755131Storek 	break; \
29855131Storek 	case RAS_SET: \
29955131Storek 	pre \
30055131Storek 	(d) = ~0; \
30155131Storek 	pst \
30255131Storek 	break; \
30355131Storek 	default: \
30455131Storek 	return -1; \
30555131Storek 	}
30655131Storek 
30755131Storek #define ROP_DSTCOLOR(op,pre,d,c,pst) \
30855131Storek     switch ( op ) \
30955131Storek 	{ \
31055131Storek 	case RAS_CLEAR: \
31155131Storek 	pre \
31255131Storek 	(d) = 0; \
31355131Storek 	pst \
31455131Storek 	break; \
31555131Storek 	case RAS_INVERT: \
31655131Storek 	pre \
31755131Storek 	(d) = ~(d); \
31855131Storek 	pst \
31955131Storek 	break; \
32055131Storek 	case RAS_SET: \
32155131Storek 	pre \
32255131Storek 	(d) = (c); \
32355131Storek 	pst \
32455131Storek 	break; \
32555131Storek 	default: \
32655131Storek 	return -1; \
32755131Storek 	}
32855131Storek 
32955131Storek #define ROP_SRCDST(op,pre,s,d,pst) \
33055131Storek     switch ( op ) \
33155131Storek 	{ \
33255131Storek 	case RAS_INVERTSRC: \
33355131Storek 	pre \
33455131Storek 	(d) = ~(s); \
33555131Storek 	pst \
33655131Storek 	break; \
33755131Storek 	case RAS_XOR: \
33855131Storek 	pre \
33955131Storek 	(d) = (s) ^ (d); \
34055131Storek 	pst \
34155131Storek 	break; \
34255131Storek 	case RAS_SRC: \
34355131Storek 	pre \
34455131Storek 	(d) = (s); \
34555131Storek 	pst \
34655131Storek 	break; \
34755131Storek 	default: \
34855131Storek 	return -1; \
34955131Storek 	}
35055131Storek 
35155131Storek #define ROP_SRCDSTCOLOR(op,pre,s,d,c,pst) \
35255131Storek     switch ( op ) \
35355131Storek 	{ \
35455131Storek 	case RAS_INVERTSRC: \
35555131Storek 	pre \
35655131Storek 	if ( s ) \
35755131Storek 	    (d) = ~(c); \
35855131Storek 	else \
35955131Storek 	    (d) = ~0; \
36055131Storek 	pst \
36155131Storek 	break; \
36255131Storek 	case RAS_XOR: \
36355131Storek 	pre \
36455131Storek 	if ( s ) \
36555131Storek 	    (d) = (c) ^ (d); \
36655131Storek 	pst \
36755131Storek 	break; \
36855131Storek 	case RAS_SRC: \
36955131Storek 	pre \
37055131Storek 	if ( s ) \
37155131Storek 	    (d) = (c); \
37255131Storek 	else \
37355131Storek 	    (d) = 0; \
37455131Storek 	pst \
37555131Storek 	break; \
37655131Storek 	default: \
37755131Storek 	return -1; \
37855131Storek 	}
37955131Storek 
38055131Storek #endif /*PARTIAL_LOGICAL_OPS*/
38155131Storek 
38255131Storek 
38355131Storek /* Variables. */
38455131Storek 
38555131Storek static int needsrc[16] = { 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0 };
38655131Storek /*                       CLEAR          INVERT          DST            SET */
38755131Storek 
38855131Storek #ifdef MSBIT_FIRST
38955131Storek 
39055131Storek u_long raster_bitmask[32] = {
39155131Storek     0x80000000, 0x40000000, 0x20000000, 0x10000000,
39255131Storek     0x08000000, 0x04000000, 0x02000000, 0x01000000,
39355131Storek     0x00800000, 0x00400000, 0x00200000, 0x00100000,
39455131Storek     0x00080000, 0x00040000, 0x00020000, 0x00010000,
39555131Storek     0x00008000, 0x00004000, 0x00002000, 0x00001000,
39655131Storek     0x00000800, 0x00000400, 0x00000200, 0x00000100,
39755131Storek     0x00000080, 0x00000040, 0x00000020, 0x00000010,
39855131Storek     0x00000008, 0x00000004, 0x00000002, 0x00000001 };
39955131Storek 
40055131Storek #ifdef MSBYTE_FIRST
40155131Storek static u_long leftmask[32] = {
40255131Storek     0x00000000, 0x80000000, 0xc0000000, 0xe0000000,
40355131Storek     0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
40455131Storek     0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
40555131Storek     0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
40655131Storek     0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000,
40755131Storek     0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
40855131Storek     0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0,
40955131Storek     0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe };
41055131Storek static u_long rightmask[32] = {
41155131Storek     0x00000000, 0x00000001, 0x00000003, 0x00000007,
41255131Storek     0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
41355131Storek     0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
41455131Storek     0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
41555131Storek     0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
41655131Storek     0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
41755131Storek     0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
41855131Storek     0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff };
41955131Storek #endif /*MSBYTE_FIRST*/
42055131Storek 
42155131Storek #else /*MSBIT_FIRST*/
42255131Storek 
42355131Storek u_long raster_bitmask[32] = {
42455131Storek     0x00000001, 0x00000002, 0x00000004, 0x00000008,
42555131Storek     0x00000010, 0x00000020, 0x00000040, 0x00000080,
42655131Storek     0x00000100, 0x00000200, 0x00000400, 0x00000800,
42755131Storek     0x00001000, 0x00002000, 0x00004000, 0x00008000,
42855131Storek     0x00010000, 0x00020000, 0x00040000, 0x00080000,
42955131Storek     0x00100000, 0x00200000, 0x00400000, 0x00800000,
43055131Storek     0x01000000, 0x02000000, 0x04000000, 0x08000000,
43155131Storek     0x10000000, 0x20000000, 0x40000000, 0x80000000 };
43255131Storek 
43355131Storek #ifndef MSBYTE_FIRST
43455131Storek static u_long leftmask[32] = {
43555131Storek     0x00000000, 0x00000001, 0x00000003, 0x00000007,
43655131Storek     0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
43755131Storek     0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
43855131Storek     0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
43955131Storek     0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
44055131Storek     0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
44155131Storek     0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
44255131Storek     0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff };
44355131Storek static u_long rightmask[32] = {
44455131Storek     0x00000000, 0x80000000, 0xc0000000, 0xe0000000,
44555131Storek     0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
44655131Storek     0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
44755131Storek     0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
44855131Storek     0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000,
44955131Storek     0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
45055131Storek     0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0,
45155131Storek     0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe };
45255131Storek #endif /*not MSBYTE_FIRST*/
45355131Storek 
45455131Storek #endif /*MSBIT_FIRST*/
45555131Storek 
45655131Storek /* (The odd combinations MSBIT+~MSBYTE and ~MSBIT+MSBYTE could be added.) */
45755131Storek 
45855131Storek #ifdef MSBYTE_FIRST
45955131Storek static u_long bytemask[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff };
46055131Storek #else /*MSBYTE_FIRST*/
46155131Storek static u_long bytemask[4] = { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 };
46255131Storek #endif /*MSBYTE_FIRST*/
46355131Storek 
46455131Storek 
46555131Storek /* Forward routines. */
46655131Storek 
46755131Storek static int raster_blit();
46855131Storek 
46955131Storek 
47055131Storek /* Raster operations.  */
47155131Storek 
47255131Storek /* Performs a bitblit.  Returns 0 on success, -1 on failure. */
47355131Storek int
raster_op(dst,dx,dy,w,h,rop,src,sx,sy)47455131Storek raster_op( dst, dx, dy, w, h, rop, src, sx, sy )
47555131Storek     struct raster* dst;
47655131Storek     int dx, dy, w, h, rop;
47755131Storek     struct raster* src;
47855131Storek     int sx, sy;
47955131Storek     {
48055131Storek     if ( dst == (struct raster*) 0 )
48155131Storek 	return -1;			/* no destination */
48255131Storek 
48355131Storek     if ( needsrc[RAS_GETOP( rop )] )
48455131Storek 	{
48555131Storek 	/* Two-operand blit. */
48655131Storek 	if ( src == (struct raster*) 0 )
48755131Storek 	    return -1;			/* no source */
48855131Storek 
48955131Storek 	/* Clip against source. */
49055131Storek 	if ( sx < 0 )
49155131Storek 	    {
49255131Storek 	    w += sx;
49355131Storek 	    sx = 0;
49455131Storek 	    }
49555131Storek 	if ( sy < 0 )
49655131Storek 	    {
49755131Storek 	    h += sy;
49855131Storek 	    sy = 0;
49955131Storek 	    }
50055131Storek 	if ( sx + w > src->width )
50155131Storek 	    w = src->width - sx;
50255131Storek 	if ( sy + h > src->height )
50355131Storek 	    h = src->height - sy;
50455131Storek 
50555131Storek 	/* Clip against dest. */
50655131Storek 	if ( dx < 0 )
50755131Storek 	    {
50855131Storek 	    w += dx;
50955131Storek 	    sx -= dx;
51055131Storek 	    dx = 0;
51155131Storek 	    }
51255131Storek 	if ( dy < 0 )
51355131Storek 	    {
51455131Storek 	    h += dy;
51555131Storek 	    sy -= dy;
51655131Storek 	    dy = 0;
51755131Storek 	    }
51855131Storek 	if ( dx + w > dst->width )
51955131Storek 	    w = dst->width - dx;
52055131Storek 	if ( dy + h > dst->height )
52155131Storek 	    h = dst->height - dy;
52255131Storek 
52355131Storek 	if ( w <= 0 || h <= 0 )
52455131Storek 	    return 0;			/* nothing to do */
52555131Storek 
52655131Storek 	return raster_op_noclip( dst, dx, dy, w, h, rop, src, sx, sy );
52755131Storek 	}
52855131Storek 
52955131Storek     /* No source necessary - one-operand blit. */
53055131Storek     if ( src != (struct raster*) 0 )
53155131Storek 	return -1;			/* unwanted source */
53255131Storek 
53355131Storek     /* Clip against dest. */
53455131Storek     if ( dx < 0 )
53555131Storek 	{
53655131Storek 	w += dx;
53755131Storek 	dx = 0;
53855131Storek 	}
53955131Storek     if ( dy < 0 )
54055131Storek 	{
54155131Storek 	h += dy;
54255131Storek 	dy = 0;
54355131Storek 	}
54455131Storek     if ( dx + w > dst->width )
54555131Storek 	w = dst->width - dx;
54655131Storek     if ( dy + h > dst->height )
54755131Storek 	h = dst->height - dy;
54855131Storek 
54955131Storek     if ( w <= 0 || h <= 0 )
55055131Storek 	return 0;			/* nothing to do */
55155131Storek 
55255131Storek     return raster_op_nosrc_noclip( dst, dx, dy, w, h, rop );
55355131Storek     }
55455131Storek 
55555131Storek /* Semi-public routine to do a bitblit without clipping.  Returns 0 on
55655131Storek ** success, -1 on failure.
55755131Storek */
55855131Storek int
raster_op_noclip(dst,dx,dy,w,h,rop,src,sx,sy)55955131Storek raster_op_noclip( dst, dx, dy, w, h, rop, src, sx, sy )
56055131Storek     struct raster* dst;
56155131Storek     int dx, dy, w, h, rop;
56255131Storek     struct raster* src;
56355131Storek     int sx, sy;
56455131Storek     {
56555131Storek     int op;
56655131Storek 
56755131Storek     op = RAS_GETOP( rop );
56855131Storek 
56955131Storek     if ( src->depth == 1 )
57055131Storek 	{
57155131Storek 	/* One-bit to ? blit. */
57255131Storek 	if ( dst->depth == 1 )
57355131Storek 	    {
57455131Storek 	    /* One to one blit. */
57555131Storek 	    u_long* srclin1;
57655131Storek 	    u_long* dstlin1;
57755131Storek 	    int srcleftignore, srcrightignore, srclongs;
57855131Storek 	    int dstleftignore, dstrightignore, dstlongs;
57955131Storek 
58055131Storek 	    srclin1 = RAS_ADDR( src, sx, sy );
58155131Storek 	    dstlin1 = RAS_ADDR( dst, dx, dy );
58255131Storek 
58355131Storek #ifdef BCOPY_FASTER
58455131Storek 	    /* Special-case full-width to full-width copies. */
58555131Storek 	    if ( op == RAS_SRC && src->width == w && dst->width == w &&
58655131Storek 		 src->linelongs == dst->linelongs && src->linelongs == w >> 5 )
58755131Storek 		{
58855131Storek 		bcopy(
58955131Storek 		    (char*) srclin1, (char*) dstlin1,
59055131Storek 		    h * src->linelongs * sizeof(u_long) );
59155131Storek 		return 0;
59255131Storek 		}
59355131Storek #endif /*BCOPY_FASTER*/
59455131Storek 
59555131Storek 	    srcleftignore = ( sx & 31 );
59655131Storek 	    srclongs = ( srcleftignore + w + 31 ) >> 5;
59755131Storek 	    srcrightignore = ( srclongs * 32 - w - srcleftignore ) & 31;
59855131Storek 	    dstleftignore = ( dx & 31 );
59955131Storek 	    dstlongs = ( dstleftignore + w + 31 ) >> 5;
60055131Storek 	    dstrightignore = ( dstlongs * 32 - w - dstleftignore ) & 31;
60155131Storek 
60255131Storek 	    return raster_blit(
60355131Storek 		src, srclin1, srcleftignore, srcrightignore, srclongs,
60455131Storek 		dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op );
60555131Storek 	    }
60655131Storek 
60755131Storek 	else
60855131Storek 	    {
60955131Storek 	    /* One to eight, using the color in the rop.  This could
61055131Storek 	    ** probably be sped up by handling each four-bit source nybble
61155131Storek 	    ** as a group, indexing into a 16-element runtime-constructed
61255131Storek 	    ** table of longwords.
61355131Storek 	    */
61455131Storek 	    u_long* srclin1;
61555131Storek 	    u_long* dstlin1;
61655131Storek 	    u_long* srclin2;
61755131Storek 	    u_long* srclin;
61855131Storek 	    u_long* dstlin;
61955131Storek 	    register u_long* srclong;
62055131Storek 	    register u_long* dstlong;
62155131Storek 	    register u_long color, dl;
62255131Storek 	    register int srcbit, dstbyte, i;
62355131Storek 
62455131Storek 	    color = RAS_GETCOLOR( rop );
62555131Storek 	    if ( color == 0 )
62655131Storek 		color = 255;
62755131Storek 
62855131Storek 	    /* Make 32 bits of color so we can do the ROP without shifting. */
62955131Storek 	    color |= ( color << 24 ) | ( color << 16 ) | ( color << 8 );
63055131Storek 
63155131Storek 	    /* Don't have to worry about overlapping blits here. */
63255131Storek 	    srclin1 = RAS_ADDR( src, sx, sy );
63355131Storek 	    srclin2 = srclin1 + h * src->linelongs;
63455131Storek 	    dstlin1 = RAS_ADDR( dst, dx, dy );
63555131Storek 	    srclin = srclin1;
63655131Storek 	    dstlin = dstlin1;
63755131Storek 	    while ( srclin != srclin2 )
63855131Storek 		{
63955131Storek 		srclong = srclin;
64055131Storek 		srcbit = sx & 31;
64155131Storek 		dstlong = dstlin;
64255131Storek 		dstbyte = dx & 3;
64355131Storek 		i = w;
64455131Storek 
64555131Storek 		/* WARNING: this code is KNOWN TO FAIL on Sun 3's / CG2's. */
64655131Storek 		ROP_SRCDSTCOLOR(
64755131Storek 		/*op*/  op,
64855131Storek 		/*pre*/ while ( i > 0 )
64955131Storek 			    {
65055131Storek 			    dl = *dstlong;,
65155131Storek 		/*s*/       *srclong & raster_bitmask[srcbit],
65255131Storek 		/*d*/       dl,
65355131Storek 		/*c*/       color,
65455131Storek 		/*pst*/     *dstlong = ( *dstlong & ~bytemask[dstbyte] ) |
65555131Storek 				       ( dl & bytemask[dstbyte] );
65655131Storek 			    if ( srcbit == 31 )
65755131Storek 				{
65855131Storek 				srcbit = 0;
65955131Storek 				++srclong;
66055131Storek 				}
66155131Storek 			    else
66255131Storek 				++srcbit;
66355131Storek 			    if ( dstbyte == 3 )
66455131Storek 				{
66555131Storek 				dstbyte = 0;
66655131Storek 				++dstlong;
66755131Storek 				}
66855131Storek 			    else
66955131Storek 				++dstbyte;
67055131Storek 			    --i;
67155131Storek 			    } )
67255131Storek 
67355131Storek 		srclin += src->linelongs;
67455131Storek 		dstlin += dst->linelongs;
67555131Storek 		}
67655131Storek 	    }
67755131Storek 	}
67855131Storek 
67955131Storek     else
68055131Storek 	{
68155131Storek 	/* Eight to eight blit. */
68255131Storek 	u_long* srclin1;
68355131Storek 	u_long* dstlin1;
68455131Storek 	int srcleftignore, srcrightignore, srclongs;
68555131Storek 	int dstleftignore, dstrightignore, dstlongs;
68655131Storek 
68755131Storek 	if ( dst->depth != 8 )
68855131Storek 	    return -1;		/* depth mismatch */
68955131Storek 
69055131Storek 	srclin1 = RAS_ADDR( src, sx, sy );
69155131Storek 	dstlin1 = RAS_ADDR( dst, dx, dy );
69255131Storek 
69355131Storek #ifdef BCOPY_FASTER
69455131Storek 	/* Special-case full-width to full-width copies. */
69555131Storek 	if ( op == RAS_SRC && src->width == w && dst->width == w &&
69655131Storek 	     src->linelongs == dst->linelongs && src->linelongs == w >> 2 )
69755131Storek 	    {
69855131Storek 	    bcopy( (char*) srclin1, (char*) dstlin1,
69955131Storek 		   h * src->linelongs * sizeof(u_long) );
70055131Storek 	    return 0;
70155131Storek 	    }
70255131Storek #endif /*BCOPY_FASTER*/
70355131Storek 
70455131Storek 	srcleftignore = ( sx & 3 ) * 8;
70555131Storek 	srclongs = ( srcleftignore + w * 8 + 31 ) >> 5;
70655131Storek 	srcrightignore = ( srclongs * 32 - w * 8 - srcleftignore ) & 31;
70755131Storek 	dstleftignore = ( dx & 3 ) * 8;
70855131Storek 	dstlongs = ( dstleftignore + w * 8 + 31 ) >> 5;
70955131Storek 	dstrightignore = ( dstlongs * 32 - w * 8 - dstleftignore ) & 31;
71055131Storek 
71155131Storek 	return raster_blit(
71255131Storek 	    src, srclin1, srcleftignore, srcrightignore, srclongs,
71355131Storek 	    dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op );
71455131Storek 	}
71555131Storek 
71655131Storek     return 0;
71755131Storek     }
71855131Storek 
71955131Storek /* Semi-public routine to do a no-src bitblit without clipping.  Returns 0
72055131Storek ** on success, -1 on failure.
72155131Storek */
72255131Storek int
raster_op_nosrc_noclip(dst,dx,dy,w,h,rop)72355131Storek raster_op_nosrc_noclip( dst, dx, dy, w, h, rop )
72455131Storek     struct raster* dst;
72555131Storek     int dx, dy, w, h, rop;
72655131Storek     {
72755131Storek     int op;
72855131Storek 
72955131Storek     op = RAS_GETOP( rop );
73055131Storek 
73155131Storek     if ( dst->depth == 1 )
73255131Storek 	{
73355131Storek 	/* One-bit no-src blit. */
73455131Storek 	u_long* dstlin1;
73555131Storek 	u_long* dstlin2;
73655131Storek 	u_long* dstlin;
73755131Storek 	int dstleftignore, dstrightignore, dstlongs;
73855131Storek 	u_long dl, lm, nlm, rm, nrm;
73955131Storek 	register u_long* dstlong2;
74055131Storek 	register u_long* dstlong;
74155131Storek 
74255131Storek 	dstlin1 = RAS_ADDR( dst, dx, dy );
74355131Storek 
74455131Storek #ifdef BCOPY_FASTER
74555131Storek 	/* Special-case full-width clears. */
74655131Storek 	if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 5 )
74755131Storek 	    {
74855131Storek 	    bzero( (char*) dstlin1, h * dst->linelongs * sizeof(u_long) );
74955131Storek 	    return 0;
75055131Storek 	    }
75155131Storek #endif /*BCOPY_FASTER*/
75255131Storek 
75355131Storek 	dstleftignore = ( dx & 31 );
75455131Storek 	dstlongs = ( dstleftignore + w + 31 ) >> 5;
75555131Storek 	dstrightignore = ( dstlongs * 32 - w - dstleftignore ) & 31;
75655131Storek 
75755131Storek 	dstlin2 = dstlin1 + h * dst->linelongs;
75855131Storek 	dstlin = dstlin1;
75955131Storek 
76055131Storek 	if ( dstlongs == 1 )
76155131Storek 	    {
76255131Storek 	    /* It fits into a single longword. */
76355131Storek 	    lm = leftmask[dstleftignore] | rightmask[dstrightignore];
76455131Storek 	    nlm = ~lm;
76555131Storek 	    while ( dstlin != dstlin2 )
76655131Storek 		{
76755131Storek 		ROP_DST(
76855131Storek 		/*op*/  op,
76955131Storek 		/*pre*/ dl = *dstlin;,
77055131Storek 		/*d*/   dl,
77155131Storek 		/*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
77255131Storek 
77355131Storek 		dstlin += dst->linelongs;
77455131Storek 		}
77555131Storek 	    }
77655131Storek 	else
77755131Storek 	    {
77855131Storek 	    lm = leftmask[dstleftignore];
77955131Storek 	    rm = rightmask[dstrightignore];
78055131Storek 	    nrm = ~rm;
78155131Storek 	    nlm = ~lm;
78255131Storek 
78355131Storek 	    while ( dstlin != dstlin2 )
78455131Storek 		{
78555131Storek 		dstlong = dstlin;
78655131Storek 		dstlong2 = dstlong + dstlongs;
78755131Storek 		if ( dstrightignore != 0 )
78855131Storek 		    --dstlong2;
78955131Storek 
79055131Storek 		/* Leading edge. */
79155131Storek 		if ( dstleftignore != 0 )
79255131Storek 		    {
79355131Storek 		    ROP_DST(
79455131Storek 		    /*op*/  op,
79555131Storek 		    /*pre*/ dl = *dstlong;,
79655131Storek 		    /*d*/   dl,
79755131Storek 		    /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
79855131Storek 		    ++dstlong;
79955131Storek 		    }
80055131Storek 
80155131Storek 		/* Main rop. */
80255131Storek 		ROP_DST(
80355131Storek 		/*op*/  op,
80455131Storek 		/*pre*/ while ( dstlong != dstlong2 )
80555131Storek 			    {,
80655131Storek 		/*d*/       *dstlong,
80755131Storek 		/*pst*/     ++dstlong;
80855131Storek 			    } )
80955131Storek 
81055131Storek 		/* Trailing edge. */
81155131Storek 		if ( dstrightignore != 0 )
81255131Storek 		    {
81355131Storek 		    ROP_DST(
81455131Storek 		    /*op*/  op,
81555131Storek 		    /*pre*/ dl = *dstlong;,
81655131Storek 		    /*d*/   dl,
81755131Storek 		    /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
81855131Storek 		    }
81955131Storek 
82055131Storek 		dstlin += dst->linelongs;
82155131Storek 		}
82255131Storek 	    }
82355131Storek 	}
82455131Storek 
82555131Storek     else
82655131Storek 	{
82755131Storek 	/* Eight-bit no-src blit. */
82855131Storek 	register u_long color;
82955131Storek 	u_long* dstlin1;
83055131Storek 	u_long* dstlin2;
83155131Storek 	u_long* dstlin;
83255131Storek 	int dstleftignore, dstrightignore, dstlongs;
83355131Storek 	u_long dl, lm, nlm, rm, nrm;
83455131Storek 	register u_long* dstlong2;
83555131Storek 	register u_long* dstlong;
83655131Storek 
83755131Storek 	dstlin1 = RAS_ADDR( dst, dx, dy );
83855131Storek 
83955131Storek #ifdef BCOPY_FASTER
84055131Storek 	/* Special-case full-width clears. */
84155131Storek 	if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 2 )
84255131Storek 	    {
84355131Storek 	    bzero( (char*) dstlin1, h * dst->linelongs * sizeof(u_long) );
84455131Storek 	    return 0;
84555131Storek 	    }
84655131Storek #endif /*BCOPY_FASTER*/
84755131Storek 
84855131Storek 	color = RAS_GETCOLOR( rop );
84955131Storek 	if ( color == 0 )
85055131Storek 	    color = 255;
85155131Storek 
85255131Storek 	/* Make 32 bits of color so we can do the ROP without shifting. */
85355131Storek 	color |= ( color << 24 ) | ( color << 16 ) | ( color << 8 );
85455131Storek 
85555131Storek 	dstleftignore = ( dx & 3 ) * 8;
85655131Storek 	dstlongs = ( dstleftignore + w * 8 + 31 ) >> 5;
85755131Storek 	dstrightignore = ( dstlongs * 32 - w * 8 - dstleftignore ) & 31;
85855131Storek 
85955131Storek 	dstlin2 = dstlin1 + h * dst->linelongs;
86055131Storek 	dstlin = dstlin1;
86155131Storek 
86255131Storek 	if ( dstlongs == 1 )
86355131Storek 	    {
86455131Storek 	    /* It fits into a single longword. */
86555131Storek 	    lm = leftmask[dstleftignore] | rightmask[dstrightignore];
86655131Storek 	    nlm = ~lm;
86755131Storek 	    while ( dstlin != dstlin2 )
86855131Storek 		{
86955131Storek 		ROP_DSTCOLOR(
87055131Storek 		/*op*/  op,
87155131Storek 		/*pre*/ dl = *dstlin;,
87255131Storek 		/*d*/   dl,
87355131Storek 		/*c*/	color,
87455131Storek 		/*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
87555131Storek 
87655131Storek 		dstlin += dst->linelongs;
87755131Storek 		}
87855131Storek 	    }
87955131Storek 	else
88055131Storek 	    {
88155131Storek 	    lm = leftmask[dstleftignore];
88255131Storek 	    rm = rightmask[dstrightignore];
88355131Storek 	    nrm = ~rm;
88455131Storek 	    nlm = ~lm;
88555131Storek 	    while ( dstlin != dstlin2 )
88655131Storek 		{
88755131Storek 		dstlong = dstlin;
88855131Storek 		dstlong2 = dstlong + dstlongs;
88955131Storek 		if ( dstrightignore != 0 )
89055131Storek 		    --dstlong2;
89155131Storek 
89255131Storek 		/* Leading edge. */
89355131Storek 		if ( dstleftignore != 0 )
89455131Storek 		    {
89555131Storek 		    ROP_DSTCOLOR(
89655131Storek 		    /*op*/  op,
89755131Storek 		    /*pre*/ dl = *dstlong;,
89855131Storek 		    /*d*/   dl,
89955131Storek 		    /*c*/   color,
90055131Storek 		    /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
90155131Storek 		    ++dstlong;
90255131Storek 		    }
90355131Storek 
90455131Storek 		/* Main rop. */
90555131Storek 		ROP_DSTCOLOR(
90655131Storek 		/*op*/  op,
90755131Storek 		/*pre*/ while ( dstlong != dstlong2 )
90855131Storek 			    {,
90955131Storek 		/*d*/       *dstlong,
91055131Storek 		/*c*/       color,
91155131Storek 		/*pst*/     ++dstlong;
91255131Storek 			    } )
91355131Storek 
91455131Storek 		/* Trailing edge. */
91555131Storek 		if ( dstrightignore != 0 )
91655131Storek 		    {
91755131Storek 		    ROP_DSTCOLOR(
91855131Storek 		    /*op*/  op,
91955131Storek 		    /*pre*/ dl = *dstlong;,
92055131Storek 		    /*d*/   dl,
92155131Storek 		    /*c*/   color,
92255131Storek 		    /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
92355131Storek 		    }
92455131Storek 
92555131Storek 		dstlin += dst->linelongs;
92655131Storek 		}
92755131Storek 	    }
92855131Storek 	}
92955131Storek 
93055131Storek     return 0;
93155131Storek     }
93255131Storek 
93355131Storek /* This is a general bitblit routine, handling overlapping source and
93455131Storek ** destination.  It's used for both the 1-to-1 and 8-to-8 cases.
93555131Storek */
93655131Storek static int
raster_blit(src,srclin1,srcleftignore,srcrightignore,srclongs,dst,dstlin1,dstleftignore,dstrightignore,dstlongs,h,op)93755131Storek raster_blit( src, srclin1, srcleftignore, srcrightignore, srclongs, dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op )
93855131Storek     struct raster* src;
93955131Storek     u_long* srclin1;
94055131Storek     int srcleftignore, srcrightignore, srclongs;
94155131Storek     struct raster* dst;
94255131Storek     u_long* dstlin1;
94355131Storek     int dstleftignore, dstrightignore, dstlongs;
94455131Storek     int h, op;
94555131Storek     {
94655131Storek     u_long* srclin2;
94755131Storek     u_long* dstlin2;
94855131Storek     int srclininc, dstlininc;
94955131Storek     u_long* srclin;
95055131Storek     u_long* dstlin;
95155131Storek     register int prevleftshift, currrightshift;
95255131Storek     int longinc;
95355131Storek     register u_long* srclong;
95455131Storek     register u_long* dstlong;
95555131Storek     register u_long* dstlong2;
95655131Storek     register u_long dl, lm, nlm, rm, nrm;
95755131Storek 
95855131Storek     prevleftshift = ( srcleftignore - dstleftignore ) & 31;
95955131Storek 
96055131Storek     srclin2 = srclin1 + h * src->linelongs;
96155131Storek     dstlin2 = dstlin1 + h * dst->linelongs;
96255131Storek     srclininc = src->linelongs;
96355131Storek     dstlininc = dst->linelongs;
96455131Storek     longinc = 1;
96555131Storek 
96655131Storek     /* Check for overlaps. */
96755131Storek     if ( ( dstlin1 >= srclin1 && dstlin1 < srclin1 + srclongs ) ||
96855131Storek 	 ( srclin1 >= dstlin1 && srclin1 < dstlin1 + dstlongs ) )
96955131Storek 	{
97055131Storek 	/* Horizontal overlap.  Should we reverse? */
97155131Storek 	if ( srclin1 < dstlin1 )
97255131Storek 	    {
97355131Storek 	    longinc = -1;
97455131Storek 	    srclin1 += srclongs - 1;
97555131Storek 	    srclin2 += srclongs - 1;
97655131Storek 	    dstlin1 += dstlongs - 1;
97755131Storek 	    }
97855131Storek 	}
97955131Storek     else if ( ( dstlin1 >= srclin1 && dstlin1 < srclin2 ) ||
98055131Storek 	      ( srclin1 >= dstlin1 && srclin1 < dstlin2 ) )
98155131Storek 	{
98255131Storek 	/* Vertical overlap.  Should we reverse? */
98355131Storek 	if ( srclin1 < dstlin1 )
98455131Storek 	    {
98555131Storek 	    srclin2 = srclin1 - srclininc;
98655131Storek 	    srclin1 += ( h - 1 ) * srclininc;
98755131Storek 	    dstlin1 += ( h - 1 ) * dstlininc;
98855131Storek 	    srclininc = -srclininc;
98955131Storek 	    dstlininc = -dstlininc;
99055131Storek 	    }
99155131Storek 	}
99255131Storek     srclin = srclin1;
99355131Storek     dstlin = dstlin1;
99455131Storek 
99555131Storek     if ( prevleftshift == 0 )
99655131Storek 	{
99755131Storek 	/* The bits line up, no shifting necessary. */
99855131Storek 	if ( dstlongs == 1 )
99955131Storek 	    {
100055131Storek 	    /* It all fits into a single longword. */
100155131Storek 	    lm = leftmask[dstleftignore] | rightmask[dstrightignore];
100255131Storek 	    nlm = ~lm;
100355131Storek 	    while ( srclin != srclin2 )
100455131Storek 		{
100555131Storek 		ROP_SRCDST(
100655131Storek 		/*op*/  op,
100755131Storek 		/*pre*/ dl = *dstlin;,
100855131Storek 		/*s*/   *srclin,
100955131Storek 		/*d*/   dl,
101055131Storek 		/*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
101155131Storek 
101255131Storek 		srclin += srclininc;
101355131Storek 		dstlin += dstlininc;
101455131Storek 		}
101555131Storek 	    }
101655131Storek 	else
101755131Storek 	    {
101855131Storek 	    /* Multiple longwords. */
101955131Storek 	    lm = leftmask[dstleftignore];
102055131Storek 	    rm = rightmask[dstrightignore];
102155131Storek 	    nrm = ~rm;
102255131Storek 	    nlm = ~lm;
102355131Storek 	    if ( longinc == 1 )
102455131Storek 		{
102555131Storek 		/* Left to right. */
102655131Storek 		while ( srclin != srclin2 )
102755131Storek 		    {
102855131Storek 		    srclong = srclin;
102955131Storek 		    dstlong = dstlin;
103055131Storek 		    dstlong2 = dstlong + dstlongs;
103155131Storek 		    if ( dstrightignore != 0 )
103255131Storek 			--dstlong2;
103355131Storek 
103455131Storek 		    /* Leading edge. */
103555131Storek 		    if ( dstleftignore != 0 )
103655131Storek 			{
103755131Storek 			ROP_SRCDST(
103855131Storek 			/*op*/  op,
103955131Storek 			/*pre*/ dl = *dstlong;,
104055131Storek 			/*s*/   *srclong,
104155131Storek 			/*d*/   dl,
104255131Storek 			/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
104355131Storek 			++srclong;
104455131Storek 			++dstlong;
104555131Storek 			}
104655131Storek 
104755131Storek 		    /* Main rop. */
104855131Storek 		    ROP_SRCDST(
104955131Storek 		    /*op*/  op,
105055131Storek 		    /*pre*/ while ( dstlong != dstlong2 )
105155131Storek 				{,
105255131Storek 		    /*s*/       *srclong,
105355131Storek 		    /*d*/       *dstlong,
105455131Storek 		    /*pst*/     ++srclong;
105555131Storek 				++dstlong;
105655131Storek 				} )
105755131Storek 
105855131Storek 		    /* Trailing edge. */
105955131Storek 		    if ( dstrightignore != 0 )
106055131Storek 			{
106155131Storek 			ROP_SRCDST(
106255131Storek 			/*op*/  op,
106355131Storek 			/*pre*/ dl = *dstlong;,
106455131Storek 			/*s*/   *srclong,
106555131Storek 			/*d*/   dl,
106655131Storek 			/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
106755131Storek 			}
106855131Storek 
106955131Storek 		    srclin += srclininc;
107055131Storek 		    dstlin += dstlininc;
107155131Storek 		    }
107255131Storek 		}
107355131Storek 	    else
107455131Storek 		{
107555131Storek 		/* Right to left. */
107655131Storek 		while ( srclin != srclin2 )
107755131Storek 		    {
107855131Storek 		    srclong = srclin;
107955131Storek 		    dstlong = dstlin;
108055131Storek 		    dstlong2 = dstlong - dstlongs;
108155131Storek 		    if ( dstleftignore != 0 )
108255131Storek 			++dstlong2;
108355131Storek 
108455131Storek 		    /* Leading edge. */
108555131Storek 		    if ( dstrightignore != 0 )
108655131Storek 			{
108755131Storek 			ROP_SRCDST(
108855131Storek 			/*op*/  op,
108955131Storek 			/*pre*/ dl = *dstlong;,
109055131Storek 			/*s*/   *srclong,
109155131Storek 			/*d*/   dl,
109255131Storek 			/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
109355131Storek 			--srclong;
109455131Storek 			--dstlong;
109555131Storek 			}
109655131Storek 
109755131Storek 		    /* Main rop. */
109855131Storek 		    ROP_SRCDST(
109955131Storek 		    /*op*/  op,
110055131Storek 		    /*pre*/ while ( dstlong != dstlong2 )
110155131Storek 				{,
110255131Storek 		    /*s*/       *srclong,
110355131Storek 		    /*d*/       *dstlong,
110455131Storek 		    /*pst*/     --srclong;
110555131Storek 				--dstlong;
110655131Storek 				} )
110755131Storek 
110855131Storek 		    /* Trailing edge. */
110955131Storek 		    if ( dstleftignore != 0 )
111055131Storek 			{
111155131Storek 			ROP_SRCDST(
111255131Storek 			/*op*/  op,
111355131Storek 			/*pre*/ dl = *dstlong;,
111455131Storek 			/*s*/   *srclong,
111555131Storek 			/*d*/   dl,
111655131Storek 			/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
111755131Storek 			}
111855131Storek 
111955131Storek 		    srclin += srclininc;
112055131Storek 		    dstlin += dstlininc;
112155131Storek 		    }
112255131Storek 		}
112355131Storek 	    }
112455131Storek 	}
112555131Storek 
112655131Storek     else
112755131Storek 	{
112855131Storek 	/* General case, with shifting and everything. */
112955131Storek 	register u_long sl, prevsl;
113055131Storek 
113155131Storek 	currrightshift = 32 - prevleftshift;
113255131Storek 	if ( srclongs == 1 && dstlongs == 1 )
113355131Storek 	    {
113455131Storek 	    /* It fits into a single longword, with a shift. */
113555131Storek 	    lm = leftmask[dstleftignore] | rightmask[dstrightignore];
113655131Storek 	    nlm = ~lm;
113755131Storek 	    if ( srcleftignore > dstleftignore )
113855131Storek 		{
113955131Storek 		while ( srclin != srclin2 )
114055131Storek 		    {
114155131Storek 		    ROP_SRCDST(
114255131Storek 		    /*op*/  op,
114355131Storek 		    /*pre*/ dl = *dstlin;,
114455131Storek 		    /*s*/   *srclin << prevleftshift,
114555131Storek 		    /*d*/   dl,
114655131Storek 		    /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
114755131Storek 
114855131Storek 		    srclin += srclininc;
114955131Storek 		    dstlin += dstlininc;
115055131Storek 		    }
115155131Storek 		}
115255131Storek 	    else
115355131Storek 		{
115455131Storek 		while ( srclin != srclin2 )
115555131Storek 		    {
115655131Storek 		    ROP_SRCDST(
115755131Storek 		    /*op*/  op,
115855131Storek 		    /*pre*/ dl = *dstlin;,
115955131Storek 		    /*s*/   *srclin >> currrightshift,
116055131Storek 		    /*d*/   dl,
116155131Storek 		    /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
116255131Storek 
116355131Storek 		    srclin += srclininc;
116455131Storek 		    dstlin += dstlininc;
116555131Storek 		    }
116655131Storek 		}
116755131Storek 	    }
116855131Storek 	else
116955131Storek 	    {
117055131Storek 	    /* Multiple longwords. */
117155131Storek 	    lm = leftmask[dstleftignore];
117255131Storek 	    rm = rightmask[dstrightignore];
117355131Storek 	    nrm = ~rm;
117455131Storek 	    nlm = ~lm;
117555131Storek 	    if ( longinc == 1 )
117655131Storek 		{
117755131Storek 		/* Left to right. */
117855131Storek 		while ( srclin != srclin2 )
117955131Storek 		    {
118055131Storek 		    srclong = srclin;
118155131Storek 		    dstlong = dstlin;
118255131Storek 		    dstlong2 = dstlong + dstlongs;
118355131Storek 		    if ( srcleftignore > dstleftignore )
118455131Storek 			prevsl = *srclong++ << prevleftshift;
118555131Storek 		    else
118655131Storek 			prevsl = 0;
118755131Storek 		    if ( dstrightignore != 0 )
118855131Storek 			--dstlong2;
118955131Storek 
119055131Storek 		    /* Leading edge. */
119155131Storek 		    if ( dstleftignore != 0 )
119255131Storek 			{
119355131Storek 			ROP_SRCDST(
119455131Storek 			/*op*/  op,
119555131Storek 			/*pre*/ sl = *srclong;
119655131Storek 				dl = *dstlong;,
119755131Storek 			/*s*/   prevsl | ( sl >> currrightshift ),
119855131Storek 			/*d*/   dl,
119955131Storek 			/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
120055131Storek 			prevsl = sl << prevleftshift;
120155131Storek 			++srclong;
120255131Storek 			++dstlong;
120355131Storek 			}
120455131Storek 
120555131Storek 		    /* Main rop. */
120655131Storek 		    ROP_SRCDST(
120755131Storek 		    /*op*/  op,
120855131Storek 		    /*pre*/ while ( dstlong != dstlong2 )
120955131Storek 				{
121055131Storek 				sl = *srclong;,
121155131Storek 		    /*s*/       prevsl | ( sl >> currrightshift ),
121255131Storek 		    /*d*/       *dstlong,
121355131Storek 		    /*pst*/     prevsl = sl << prevleftshift;
121455131Storek 				++srclong;
121555131Storek 				++dstlong;
121655131Storek 				} )
121755131Storek 
121855131Storek 		    /* Trailing edge. */
121955131Storek 		    if ( dstrightignore != 0 )
122055131Storek 			{
122155131Storek 			ROP_SRCDST(
122255131Storek 			/*op*/  op,
122355131Storek 			/*pre*/ dl = *dstlong;,
122455131Storek 			/*s*/   prevsl | ( *srclong >> currrightshift ),
122555131Storek 			/*d*/   dl,
122655131Storek 			/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
122755131Storek 			}
122855131Storek 
122955131Storek 		    srclin += srclininc;
123055131Storek 		    dstlin += dstlininc;
123155131Storek 		    }
123255131Storek 		}
123355131Storek 	    else
123455131Storek 		{
123555131Storek 		/* Right to left. */
123655131Storek 		while ( srclin != srclin2 )
123755131Storek 		    {
123855131Storek 		    srclong = srclin;
123955131Storek 		    dstlong = dstlin;
124055131Storek 		    dstlong2 = dstlong - dstlongs;
124155131Storek 		    if ( srcrightignore > dstrightignore )
124255131Storek 			prevsl = *srclong-- >> currrightshift;
124355131Storek 		    else
124455131Storek 			prevsl = 0;
124555131Storek 		    if ( dstleftignore != 0 )
124655131Storek 			++dstlong2;
124755131Storek 
124855131Storek 		    /* Leading edge. */
124955131Storek 		    if ( dstrightignore != 0 )
125055131Storek 			{
125155131Storek 			ROP_SRCDST(
125255131Storek 			/*op*/  op,
125355131Storek 			/*pre*/ sl = *srclong;
125455131Storek 				dl = *dstlong;,
125555131Storek 			/*s*/   prevsl | ( sl << prevleftshift ),
125655131Storek 			/*d*/   dl,
125755131Storek 			/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
125855131Storek 			prevsl = sl >> currrightshift;
125955131Storek 			--srclong;
126055131Storek 			--dstlong;
126155131Storek 			}
126255131Storek 
126355131Storek 		    /* Main rop. */
126455131Storek 		    ROP_SRCDST(
126555131Storek 		    /*op*/  op,
126655131Storek 		    /*pre*/ while ( dstlong != dstlong2 )
126755131Storek 				{
126855131Storek 				sl = *srclong;,
126955131Storek 		    /*s*/       prevsl | ( sl << prevleftshift ),
127055131Storek 		    /*d*/       *dstlong,
127155131Storek 		    /*pst*/     prevsl = sl >> currrightshift;
127255131Storek 				--srclong;
127355131Storek 				--dstlong;
127455131Storek 				} )
127555131Storek 
127655131Storek 		    /* Trailing edge. */
127755131Storek 		    if ( dstleftignore != 0 )
127855131Storek 			{
127955131Storek 			ROP_SRCDST(
128055131Storek 			/*op*/  op,
128155131Storek 			/*pre*/ dl = *dstlong;,
128255131Storek 			/*s*/   prevsl | ( *srclong << prevleftshift ),
128355131Storek 			/*d*/   dl,
128455131Storek 			/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
128555131Storek 			}
128655131Storek 
128755131Storek 		    srclin += srclininc;
128855131Storek 		    dstlin += dstlininc;
128955131Storek 		    }
129055131Storek 		}
129155131Storek 	    }
129255131Storek 	}
129355131Storek 
129455131Storek     return 0;
129555131Storek     }
1296