xref: /netbsd-src/sys/dev/rcons/raster_op.c (revision 91d94812e8ac26fff5f8abfaa569f340058cbb88)
1*91d94812Smatt /*	$NetBSD: raster_op.c,v 1.19 2012/01/31 04:28:02 matt Exp $ */
2a8e925d3Spk 
3a8e925d3Spk /*-
4a8e925d3Spk  * Copyright (c) 1991, 1993
5a8e925d3Spk  *	The Regents of the University of California.  All rights reserved.
6a8e925d3Spk  *
7a8e925d3Spk  * This code is derived from software contributed to the Computer Systems
8a8e925d3Spk  * Engineering Group at Lawrence Berkeley Laboratory and to the University
9a8e925d3Spk  * of California at Berkeley by Jef Poskanzer.
10a8e925d3Spk  *
11a8e925d3Spk  * Redistribution and use in source and binary forms, with or without
12a8e925d3Spk  * modification, are permitted provided that the following conditions
13a8e925d3Spk  * are met:
14a8e925d3Spk  * 1. Redistributions of source code must retain the above copyright
15a8e925d3Spk  *    notice, this list of conditions and the following disclaimer.
16a8e925d3Spk  * 2. Redistributions in binary form must reproduce the above copyright
17a8e925d3Spk  *    notice, this list of conditions and the following disclaimer in the
18a8e925d3Spk  *    documentation and/or other materials provided with the distribution.
19aad01611Sagc  * 3. Neither the name of the University nor the names of its contributors
20a8e925d3Spk  *    may be used to endorse or promote products derived from this software
21a8e925d3Spk  *    without specific prior written permission.
22a8e925d3Spk  *
23a8e925d3Spk  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24a8e925d3Spk  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25a8e925d3Spk  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26a8e925d3Spk  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27a8e925d3Spk  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28a8e925d3Spk  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29a8e925d3Spk  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30a8e925d3Spk  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31a8e925d3Spk  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32a8e925d3Spk  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33a8e925d3Spk  * SUCH DAMAGE.
34a8e925d3Spk  *
35a8e925d3Spk  *	@(#)raster_op.c	8.1 (Berkeley) 6/11/93
36a8e925d3Spk  */
37a8e925d3Spk 
38a8e925d3Spk /*
39a8e925d3Spk  * Bitblit routine for raster library.
40a8e925d3Spk  *
41a8e925d3Spk  * This raster-op is machined to exacting tolerances by skilled native
42a8e925d3Spk  * craftsmen with pride in their work.
43a8e925d3Spk  *
44a8e925d3Spk  * The various cases are broken down like this:
45a8e925d3Spk  *
46a8e925d3Spk  *   src required
47a8e925d3Spk  *       1-bit to 1-bit
4823795512Sdrochner  *       1-bit to 2-bits
49d617933eSscottr  *       1-bit to 4-bits
50a8e925d3Spk  *       1-bit to 8-bits
519d326d48Sdbj  *       1-bit to 16-bits
5223795512Sdrochner  *       2-bits to 2-bits
53d617933eSscottr  *       2-bits to 4-bits (not implemented)
549d326d48Sdbj  *       2-bits to 8-bits (not implemented)
559d326d48Sdbj  *       2-bits to 16-bits (not implemented)
56d617933eSscottr  *       4-bits to 4-bits
57d617933eSscottr  *       4-bits to 8-bits (not implemented)
58d617933eSscottr  *       4-bits to 16-bits (not implemented)
59a8e925d3Spk  *       8-bits to 8-bits
609d326d48Sdbj  *       8-bits to 16-bits (not implemented)
619d326d48Sdbj  *       16-bits to 16-bits
62a8e925d3Spk  *   no src required
63a8e925d3Spk  *       1-bit no-src
6423795512Sdrochner  *       2-bits no-src
65a8e925d3Spk  *       8-bits no-src
669d326d48Sdbj  *       16-bits no-src
67a8e925d3Spk  */
68a8e925d3Spk 
697ba10b35Slukem #include <sys/cdefs.h>
70*91d94812Smatt __KERNEL_RCSID(0, "$NetBSD: raster_op.c,v 1.19 2012/01/31 04:28:02 matt Exp $");
717ba10b35Slukem 
72a8e925d3Spk #include <sys/types.h>
73540ab1b8Scgd #ifdef _KERNEL
749d326d48Sdbj #include "opt_rcons.h"
759a37177dSdeberg #include <dev/rcons/raster.h>
76540ab1b8Scgd #else
77540ab1b8Scgd #include "raster.h"
78540ab1b8Scgd #endif
79a8e925d3Spk 
80a8e925d3Spk /* CONFIGURE: To save on executable size, you can configure out the seldom-used
81a8e925d3Spk ** logical operations.  With this variable set, the only operations implemented
82a8e925d3Spk ** are: RAS_SRC, RAS_CLEAR, RAS_SET, RAS_INVERT, RAS_XOR, RAS_INVERTSRC.
83a8e925d3Spk */
84a8e925d3Spk #ifdef _KERNEL
85a8e925d3Spk #define PARTIAL_LOGICAL_OPS
86a8e925d3Spk #endif
87a8e925d3Spk 
88a8e925d3Spk /* CONFIGURE: bcopy() is supposed to be the ultimately fastest way to move
89a8e925d3Spk ** bytes, overlapping or not, ignoring the startup cost.  Unfortunately
90a8e925d3Spk ** this is not true on some systems.  For example, on a Sun 3 running
91a8e925d3Spk ** SunOS 3.5, bcopy() is about five times slower than a simple for loop
92a8e925d3Spk ** on overlapping copies.  And on a 4.1.1 SPARC, bcopy() is about 2/3rds
93a8e925d3Spk ** as fast on backwards overlaps.  So, only define this if your bcopy is ok.
94a8e925d3Spk */
95a8e925d3Spk #undef BCOPY_FASTER
96a8e925d3Spk 
97a8e925d3Spk /* End of configurable definitions. */
98a8e925d3Spk 
99a8e925d3Spk 
100a8e925d3Spk /* Definitions. */
101a8e925d3Spk 
102a8e925d3Spk /* Raster-op macros.  These encapsulate the switch statements and so make
103a8e925d3Spk ** the source code 16 times smaller.  The pre and pst args are code
104a8e925d3Spk ** fragments to put before and after the assignment in each case.  They
105a8e925d3Spk ** can be the beginning and end of a loop.  If the pst fragment includes a
106a8e925d3Spk ** masked assignment, for example to handle the left or right edge cases,
107a8e925d3Spk ** a good optimizing compiler will simplify the boolean expressions very
108a8e925d3Spk ** nicely - both cc and gcc on the SPARC will do this.
109a8e925d3Spk */
110a8e925d3Spk 
111a8e925d3Spk #ifndef PARTIAL_LOGICAL_OPS
112a8e925d3Spk 
113a8e925d3Spk #define ROP_DST(op,pre,d,pst) \
114a8e925d3Spk     switch ( op ) \
115a8e925d3Spk 	{ \
116a8e925d3Spk 	case RAS_CLEAR: \
117a8e925d3Spk 	pre \
118a8e925d3Spk 	(d) = 0; \
119a8e925d3Spk 	pst \
120a8e925d3Spk 	break; \
121a8e925d3Spk 	case RAS_INVERT: \
122a8e925d3Spk 	pre \
123a8e925d3Spk 	(d) = ~(d); \
124a8e925d3Spk 	pst \
125a8e925d3Spk 	break; \
126a8e925d3Spk 	case RAS_DST: \
127a8e925d3Spk 	/* noop */ \
128a8e925d3Spk 	break; \
129a8e925d3Spk 	case RAS_SET: \
130a8e925d3Spk 	pre \
131a8e925d3Spk 	(d) = ~0; \
132a8e925d3Spk 	pst \
133a8e925d3Spk 	break; \
134a8e925d3Spk 	default: \
135a8e925d3Spk 	return -1; \
136a8e925d3Spk 	}
137a8e925d3Spk 
138a8e925d3Spk #define ROP_DSTCOLOR(op,pre,d,c,pst) \
139a8e925d3Spk     switch ( op ) \
140a8e925d3Spk 	{ \
141a8e925d3Spk 	case RAS_CLEAR: \
142a8e925d3Spk 	pre \
143a8e925d3Spk 	(d) = 0; \
144a8e925d3Spk 	pst \
145a8e925d3Spk 	break; \
146a8e925d3Spk 	case RAS_INVERT: \
147a8e925d3Spk 	pre \
148a8e925d3Spk 	(d) = ~(d); \
149a8e925d3Spk 	pst \
150a8e925d3Spk 	break; \
151a8e925d3Spk 	case RAS_DST: \
152a8e925d3Spk 	/* noop */ \
153a8e925d3Spk 	break; \
154a8e925d3Spk 	case RAS_SET: \
155a8e925d3Spk 	pre \
156a8e925d3Spk 	(d) = (c); \
157a8e925d3Spk 	pst \
158a8e925d3Spk 	break; \
159a8e925d3Spk 	default: \
160a8e925d3Spk 	return -1; \
161a8e925d3Spk 	}
162a8e925d3Spk 
163a8e925d3Spk #define ROP_SRCDST(op,pre,s,d,pst) \
164a8e925d3Spk     switch ( op ) \
165a8e925d3Spk 	{ \
166a8e925d3Spk 	case RAS_NOTOR: \
167a8e925d3Spk 	pre \
168a8e925d3Spk 	(d) = ~( (s) | (d) ); \
169a8e925d3Spk 	pst \
170a8e925d3Spk 	break; \
171a8e925d3Spk 	case RAS_NOTSRC_AND_DST: \
172a8e925d3Spk 	pre \
173a8e925d3Spk 	(d) = ~(s) & (d); \
174a8e925d3Spk 	pst \
175a8e925d3Spk 	break; \
176a8e925d3Spk 	case RAS_INVERTSRC: \
177a8e925d3Spk 	pre \
178a8e925d3Spk 	(d) = ~(s); \
179a8e925d3Spk 	pst \
180a8e925d3Spk 	break; \
181a8e925d3Spk 	case RAS_SRC_AND_NOTDST: \
182a8e925d3Spk 	pre \
183a8e925d3Spk 	(d) = (s) & ~(d); \
184a8e925d3Spk 	pst \
185a8e925d3Spk 	break; \
186a8e925d3Spk 	case RAS_XOR: \
187a8e925d3Spk 	pre \
188a8e925d3Spk 	(d) = (s) ^ (d); \
189a8e925d3Spk 	pst \
190a8e925d3Spk 	break; \
191a8e925d3Spk 	case RAS_NOTAND: \
192a8e925d3Spk 	pre \
193a8e925d3Spk 	(d) = ~( (s) & (d) ); \
194a8e925d3Spk 	pst \
195a8e925d3Spk 	break; \
196a8e925d3Spk 	case RAS_AND: \
197a8e925d3Spk 	pre \
198a8e925d3Spk 	(d) = (s) & (d); \
199a8e925d3Spk 	pst \
200a8e925d3Spk 	break; \
201a8e925d3Spk 	case RAS_NOTXOR: \
202a8e925d3Spk 	pre \
203a8e925d3Spk 	(d) = ~( (s) ^ (d) ); \
204a8e925d3Spk 	pst \
205a8e925d3Spk 	break; \
206a8e925d3Spk 	case RAS_NOTSRC_OR_DST: \
207a8e925d3Spk 	pre \
208a8e925d3Spk 	(d) = ~(s) | (d); \
209a8e925d3Spk 	pst \
210a8e925d3Spk 	break; \
211a8e925d3Spk 	case RAS_SRC: \
212a8e925d3Spk 	pre \
213a8e925d3Spk 	(d) = (s); \
214a8e925d3Spk 	pst \
215a8e925d3Spk 	break; \
216a8e925d3Spk 	case RAS_SRC_OR_NOTDST: \
217a8e925d3Spk 	pre \
218a8e925d3Spk 	(d) = (s) | ~(d); \
219a8e925d3Spk 	pst \
220a8e925d3Spk 	break; \
221a8e925d3Spk 	case RAS_OR: \
222a8e925d3Spk 	pre \
223a8e925d3Spk 	(d) = (s) | (d); \
224a8e925d3Spk 	pst \
225a8e925d3Spk 	break; \
226a8e925d3Spk 	default: \
227a8e925d3Spk 	return -1; \
228a8e925d3Spk 	}
229a8e925d3Spk 
230a8e925d3Spk #define ROP_SRCDSTCOLOR(op,pre,s,d,c,pst) \
231a8e925d3Spk     switch ( op ) \
232a8e925d3Spk 	{ \
233a8e925d3Spk 	case RAS_NOTOR: \
234a8e925d3Spk 	pre \
235a8e925d3Spk 	if ( s ) \
236a8e925d3Spk 	    (d) = ~( (c) | (d) ); \
237a8e925d3Spk 	else \
238a8e925d3Spk 	    (d) = ~(d); \
239a8e925d3Spk 	pst \
240a8e925d3Spk 	break; \
241a8e925d3Spk 	case RAS_NOTSRC_AND_DST: \
242a8e925d3Spk 	pre \
243a8e925d3Spk 	if ( s ) \
244a8e925d3Spk 	    (d) = ~(c) & (d); \
245a8e925d3Spk 	pst \
246a8e925d3Spk 	break; \
247a8e925d3Spk 	case RAS_INVERTSRC: \
248a8e925d3Spk 	pre \
249a8e925d3Spk 	if ( s ) \
250a8e925d3Spk 	    (d) = ~(c); \
251a8e925d3Spk 	else \
252a8e925d3Spk 	    (d) = ~0; \
253a8e925d3Spk 	pst \
254a8e925d3Spk 	break; \
255a8e925d3Spk 	case RAS_SRC_AND_NOTDST: \
256a8e925d3Spk 	pre \
257a8e925d3Spk 	if ( s ) \
258a8e925d3Spk 	    (d) = (c) & ~(d); \
259a8e925d3Spk 	else \
260a8e925d3Spk 	    (d) = 0; \
261a8e925d3Spk 	pst \
262a8e925d3Spk 	break; \
263a8e925d3Spk 	case RAS_XOR: \
264a8e925d3Spk 	pre \
265a8e925d3Spk 	if ( s ) \
266a8e925d3Spk 	    (d) = (c) ^ (d); \
267a8e925d3Spk 	pst \
268a8e925d3Spk 	break; \
269a8e925d3Spk 	case RAS_NOTAND: \
270a8e925d3Spk 	pre \
271a8e925d3Spk 	if ( s ) \
272a8e925d3Spk 	    (d) = ~( (c) & (d) ); \
273a8e925d3Spk 	else \
274a8e925d3Spk 	    (d) = ~0; \
275a8e925d3Spk 	pst \
276a8e925d3Spk 	break; \
277a8e925d3Spk 	case RAS_AND: \
278a8e925d3Spk 	pre \
279a8e925d3Spk 	if ( s ) \
280a8e925d3Spk 	    (d) = (c) & (d); \
281a8e925d3Spk 	else \
282a8e925d3Spk 	    (d) = 0; \
283a8e925d3Spk 	pst \
284a8e925d3Spk 	break; \
285a8e925d3Spk 	case RAS_NOTXOR: \
286a8e925d3Spk 	pre \
287a8e925d3Spk 	if ( s ) \
288a8e925d3Spk 	    (d) = ~( (c) ^ (d) ); \
289a8e925d3Spk 	else \
290a8e925d3Spk 	    (d) = ~(d); \
291a8e925d3Spk 	pst \
292a8e925d3Spk 	break; \
293a8e925d3Spk 	case RAS_NOTSRC_OR_DST: \
294a8e925d3Spk 	pre \
295a8e925d3Spk 	if ( s ) \
296a8e925d3Spk 	    (d) = ~(c) | (d); \
297a8e925d3Spk 	else \
298a8e925d3Spk 	    (d) = ~0; \
299a8e925d3Spk 	pst \
300a8e925d3Spk 	break; \
301a8e925d3Spk 	case RAS_SRC: \
302a8e925d3Spk 	pre \
303a8e925d3Spk 	if ( s ) \
304a8e925d3Spk 	    (d) = (c); \
305a8e925d3Spk 	else \
306a8e925d3Spk 	    (d) = 0; \
307a8e925d3Spk 	pst \
308a8e925d3Spk 	break; \
309a8e925d3Spk 	case RAS_SRC_OR_NOTDST: \
310a8e925d3Spk 	pre \
311a8e925d3Spk 	if ( s ) \
312a8e925d3Spk 	    (d) = (c) | ~(d); \
313a8e925d3Spk 	else \
314a8e925d3Spk 	    (d) = ~(d); \
315a8e925d3Spk 	pst \
316a8e925d3Spk 	break; \
317a8e925d3Spk 	case RAS_OR: \
318a8e925d3Spk 	pre \
319a8e925d3Spk 	if ( s ) \
320a8e925d3Spk 	    (d) = (c) | (d); \
321a8e925d3Spk 	pst \
322a8e925d3Spk 	break; \
323a8e925d3Spk 	default: \
324a8e925d3Spk 	return -1; \
325a8e925d3Spk 	}
326a8e925d3Spk 
327a8e925d3Spk #else /*PARTIAL_LOGICAL_OPS*/
328a8e925d3Spk 
329a8e925d3Spk #define ROP_DST(op,pre,d,pst) \
330a8e925d3Spk     switch ( op ) \
331a8e925d3Spk 	{ \
332a8e925d3Spk 	case RAS_CLEAR: \
333a8e925d3Spk 	pre \
334a8e925d3Spk 	(d) = 0; \
335a8e925d3Spk 	pst \
336a8e925d3Spk 	break; \
337a8e925d3Spk 	case RAS_INVERT: \
338a8e925d3Spk 	pre \
339a8e925d3Spk 	(d) = ~(d); \
340a8e925d3Spk 	pst \
341a8e925d3Spk 	break; \
342a8e925d3Spk 	case RAS_SET: \
343a8e925d3Spk 	pre \
344a8e925d3Spk 	(d) = ~0; \
345a8e925d3Spk 	pst \
346a8e925d3Spk 	break; \
347a8e925d3Spk 	default: \
348a8e925d3Spk 	return -1; \
349a8e925d3Spk 	}
350a8e925d3Spk 
351a8e925d3Spk #define ROP_DSTCOLOR(op,pre,d,c,pst) \
352a8e925d3Spk     switch ( op ) \
353a8e925d3Spk 	{ \
354a8e925d3Spk 	case RAS_CLEAR: \
355a8e925d3Spk 	pre \
356a8e925d3Spk 	(d) = 0; \
357a8e925d3Spk 	pst \
358a8e925d3Spk 	break; \
359a8e925d3Spk 	case RAS_INVERT: \
360a8e925d3Spk 	pre \
361a8e925d3Spk 	(d) = ~(d); \
362a8e925d3Spk 	pst \
363a8e925d3Spk 	break; \
364a8e925d3Spk 	case RAS_SET: \
365a8e925d3Spk 	pre \
366a8e925d3Spk 	(d) = (c); \
367a8e925d3Spk 	pst \
368a8e925d3Spk 	break; \
369a8e925d3Spk 	default: \
370a8e925d3Spk 	return -1; \
371a8e925d3Spk 	}
372a8e925d3Spk 
373a8e925d3Spk #define ROP_SRCDST(op,pre,s,d,pst) \
374a8e925d3Spk     switch ( op ) \
375a8e925d3Spk 	{ \
376a8e925d3Spk 	case RAS_INVERTSRC: \
377a8e925d3Spk 	pre \
378a8e925d3Spk 	(d) = ~(s); \
379a8e925d3Spk 	pst \
380a8e925d3Spk 	break; \
381a8e925d3Spk 	case RAS_XOR: \
382a8e925d3Spk 	pre \
383a8e925d3Spk 	(d) = (s) ^ (d); \
384a8e925d3Spk 	pst \
385a8e925d3Spk 	break; \
386a8e925d3Spk 	case RAS_SRC: \
387a8e925d3Spk 	pre \
388a8e925d3Spk 	(d) = (s); \
389a8e925d3Spk 	pst \
390a8e925d3Spk 	break; \
391a8e925d3Spk 	default: \
392a8e925d3Spk 	return -1; \
393a8e925d3Spk 	}
394a8e925d3Spk 
395a8e925d3Spk #define ROP_SRCDSTCOLOR(op,pre,s,d,c,pst) \
396a8e925d3Spk     switch ( op ) \
397a8e925d3Spk 	{ \
398a8e925d3Spk 	case RAS_INVERTSRC: \
399a8e925d3Spk 	pre \
400a8e925d3Spk 	if ( s ) \
401a8e925d3Spk 	    (d) = ~(c); \
402a8e925d3Spk 	else \
403a8e925d3Spk 	    (d) = ~0; \
404a8e925d3Spk 	pst \
405a8e925d3Spk 	break; \
406a8e925d3Spk 	case RAS_XOR: \
407a8e925d3Spk 	pre \
408a8e925d3Spk 	if ( s ) \
409a8e925d3Spk 	    (d) = (c) ^ (d); \
410a8e925d3Spk 	pst \
411a8e925d3Spk 	break; \
412a8e925d3Spk 	case RAS_SRC: \
413a8e925d3Spk 	pre \
414a8e925d3Spk 	if ( s ) \
415a8e925d3Spk 	    (d) = (c); \
416a8e925d3Spk 	else \
417a8e925d3Spk 	    (d) = 0; \
418a8e925d3Spk 	pst \
419a8e925d3Spk 	break; \
420a8e925d3Spk 	default: \
421a8e925d3Spk 	return -1; \
422a8e925d3Spk 	}
423a8e925d3Spk 
424a8e925d3Spk #endif /*PARTIAL_LOGICAL_OPS*/
425a8e925d3Spk 
426a8e925d3Spk 
427a8e925d3Spk /* Variables. */
428a8e925d3Spk 
429a8e925d3Spk static int needsrc[16] = { 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0 };
430a8e925d3Spk /*                       CLEAR          INVERT          DST            SET */
431a8e925d3Spk 
432a8e925d3Spk #ifdef MSBIT_FIRST
433a8e925d3Spk 
434540ab1b8Scgd u_int32_t raster_bitmask[32] = {
435a8e925d3Spk     0x80000000, 0x40000000, 0x20000000, 0x10000000,
436a8e925d3Spk     0x08000000, 0x04000000, 0x02000000, 0x01000000,
437a8e925d3Spk     0x00800000, 0x00400000, 0x00200000, 0x00100000,
438a8e925d3Spk     0x00080000, 0x00040000, 0x00020000, 0x00010000,
439a8e925d3Spk     0x00008000, 0x00004000, 0x00002000, 0x00001000,
440a8e925d3Spk     0x00000800, 0x00000400, 0x00000200, 0x00000100,
441a8e925d3Spk     0x00000080, 0x00000040, 0x00000020, 0x00000010,
442a8e925d3Spk     0x00000008, 0x00000004, 0x00000002, 0x00000001 };
443a8e925d3Spk 
444a8e925d3Spk #ifdef MSBYTE_FIRST
445540ab1b8Scgd static u_int32_t leftmask[32] = {
446a8e925d3Spk     0x00000000, 0x80000000, 0xc0000000, 0xe0000000,
447a8e925d3Spk     0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
448a8e925d3Spk     0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
449a8e925d3Spk     0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
450a8e925d3Spk     0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000,
451a8e925d3Spk     0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
452a8e925d3Spk     0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0,
453a8e925d3Spk     0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe };
454540ab1b8Scgd static u_int32_t rightmask[32] = {
455a8e925d3Spk     0x00000000, 0x00000001, 0x00000003, 0x00000007,
456a8e925d3Spk     0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
457a8e925d3Spk     0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
458a8e925d3Spk     0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
459a8e925d3Spk     0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
460a8e925d3Spk     0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
461a8e925d3Spk     0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
462a8e925d3Spk     0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff };
4633b2862c8Spk 
4643b2862c8Spk #define LSOP <<
4653b2862c8Spk #define RSOP >>
466a8e925d3Spk #endif /*MSBYTE_FIRST*/
467a8e925d3Spk 
468a8e925d3Spk #else /*MSBIT_FIRST*/
469a8e925d3Spk 
470540ab1b8Scgd u_int32_t raster_bitmask[32] = {
471a8e925d3Spk     0x00000001, 0x00000002, 0x00000004, 0x00000008,
472a8e925d3Spk     0x00000010, 0x00000020, 0x00000040, 0x00000080,
473a8e925d3Spk     0x00000100, 0x00000200, 0x00000400, 0x00000800,
474a8e925d3Spk     0x00001000, 0x00002000, 0x00004000, 0x00008000,
475a8e925d3Spk     0x00010000, 0x00020000, 0x00040000, 0x00080000,
476a8e925d3Spk     0x00100000, 0x00200000, 0x00400000, 0x00800000,
477a8e925d3Spk     0x01000000, 0x02000000, 0x04000000, 0x08000000,
478a8e925d3Spk     0x10000000, 0x20000000, 0x40000000, 0x80000000 };
479a8e925d3Spk 
480a8e925d3Spk #ifndef MSBYTE_FIRST
481540ab1b8Scgd static u_int32_t leftmask[32] = {
482a8e925d3Spk     0x00000000, 0x00000001, 0x00000003, 0x00000007,
483a8e925d3Spk     0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
484a8e925d3Spk     0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
485a8e925d3Spk     0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
486a8e925d3Spk     0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
487a8e925d3Spk     0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
488a8e925d3Spk     0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
489a8e925d3Spk     0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff };
490540ab1b8Scgd static u_int32_t rightmask[32] = {
491a8e925d3Spk     0x00000000, 0x80000000, 0xc0000000, 0xe0000000,
492a8e925d3Spk     0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
493a8e925d3Spk     0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
494a8e925d3Spk     0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
495a8e925d3Spk     0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000,
496a8e925d3Spk     0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
497a8e925d3Spk     0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0,
498a8e925d3Spk     0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe };
4993b2862c8Spk #define LSOP >>
5003b2862c8Spk #define RSOP <<
501a8e925d3Spk #endif /*not MSBYTE_FIRST*/
502a8e925d3Spk 
503a8e925d3Spk #endif /*MSBIT_FIRST*/
504a8e925d3Spk 
505a8e925d3Spk /* (The odd combinations MSBIT+~MSBYTE and ~MSBIT+MSBYTE could be added.) */
506a8e925d3Spk 
507a8e925d3Spk #ifdef MSBYTE_FIRST
508540ab1b8Scgd static u_int32_t bytemask[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff };
50923795512Sdrochner #ifdef RCONS_2BPP
51023795512Sdrochner static u_int32_t twobitmask[16] = {
51123795512Sdrochner   0xc0000000, 0x30000000, 0x0c000000, 0x03000000,
51223795512Sdrochner   0x00c00000, 0x00300000, 0x000c0000, 0x00030000,
51323795512Sdrochner   0x0000c000, 0x00003000, 0x00000c00, 0x00000300,
51423795512Sdrochner   0x000000c0, 0x00000030, 0x0000000c, 0x00000003 };
51523795512Sdrochner #endif /* RCONS_2BPP */
516d617933eSscottr #ifdef RCONS_4BPP
517d617933eSscottr static u_int32_t fourbitmask[8] = {
518d617933eSscottr   0xf0000000, 0x0f000000,
519d617933eSscottr   0x00f00000, 0x000f0000,
520d617933eSscottr   0x0000f000, 0x00000f00,
521d617933eSscottr   0x000000f0, 0x0000000f };
522d617933eSscottr #endif /* RCONS_4BPP */
5239d326d48Sdbj #ifdef RCONS_16BPP
5249d326d48Sdbj static u_int32_t twobytemask[2] = { 0xffff0000, 0x0000ffff };
5259d326d48Sdbj #endif /* RCONS_16BPP */
526a8e925d3Spk #else /*MSBYTE_FIRST*/
527540ab1b8Scgd static u_int32_t bytemask[4] = { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 };
52823795512Sdrochner #ifdef RCONS_2BPP
52923795512Sdrochner static u_int32_t twobitmask[16] = {
53023795512Sdrochner   0x00000003, 0x0000000c, 0x00000030, 0x000000c0,
53123795512Sdrochner   0x00000300, 0x00000c00, 0x00003000, 0x0000c000,
53223795512Sdrochner   0x00030000, 0x000c0000, 0x00300000, 0x00c00000,
53323795512Sdrochner   0x03000000, 0x0c000000, 0x30000000, 0xc0000000 };
53423795512Sdrochner #endif /* RCONS_2BPP */
535d617933eSscottr #ifdef RCONS_4BPP
536d617933eSscottr static u_int32_t fourbitmask[16] = {
537d617933eSscottr   0x0000000f, 0x000000f0,
538d617933eSscottr   0x00000f00, 0x0000f000,
539d617933eSscottr   0x000f0000, 0x00f00000,
540d617933eSscottr   0x0f000000, 0xf0000000 };
541d617933eSscottr #endif /* RCONS_4BPP */
5429d326d48Sdbj #ifdef RCONS_16BPP
5439d326d48Sdbj static u_int32_t twobytemask[2] = { 0x0000ffff, 0xffff0000 };
5449d326d48Sdbj #endif /* RCONS_16BPP */
545a8e925d3Spk #endif /*MSBYTE_FIRST*/
546a8e925d3Spk 
547a8e925d3Spk 
548a8e925d3Spk /* Forward routines. */
549a8e925d3Spk 
55018db93c7Sperry static int raster_blit(struct raster *, u_int32_t *, int, int, int,
551357fb0e4Schristos 			struct raster *, u_int32_t *, int, int, int,
55218db93c7Sperry 			int, int);
553a8e925d3Spk 
554a8e925d3Spk /* Raster operations.  */
555a8e925d3Spk 
556a8e925d3Spk /* Performs a bitblit.  Returns 0 on success, -1 on failure. */
557a8e925d3Spk int
raster_op(struct raster * dst,int dx,int dy,int w,int h,int rop,struct raster * src,int sx,int sy)558*91d94812Smatt raster_op(struct raster* dst, int dx, int dy, int w, int h, int rop,
559*91d94812Smatt     struct raster* src, int sx, int sy)
560a8e925d3Spk     {
561a8e925d3Spk     if ( dst == (struct raster*) 0 )
562a8e925d3Spk 	return -1;			/* no destination */
563a8e925d3Spk 
564a8e925d3Spk     if ( needsrc[RAS_GETOP( rop )] )
565a8e925d3Spk 	{
566a8e925d3Spk 	/* Two-operand blit. */
567a8e925d3Spk 	if ( src == (struct raster*) 0 )
568a8e925d3Spk 	    return -1;			/* no source */
569a8e925d3Spk 
570a8e925d3Spk 	/* Clip against source. */
571a8e925d3Spk 	if ( sx < 0 )
572a8e925d3Spk 	    {
573a8e925d3Spk 	    w += sx;
574a8e925d3Spk 	    sx = 0;
575a8e925d3Spk 	    }
576a8e925d3Spk 	if ( sy < 0 )
577a8e925d3Spk 	    {
578a8e925d3Spk 	    h += sy;
579a8e925d3Spk 	    sy = 0;
580a8e925d3Spk 	    }
581a8e925d3Spk 	if ( sx + w > src->width )
582a8e925d3Spk 	    w = src->width - sx;
583a8e925d3Spk 	if ( sy + h > src->height )
584a8e925d3Spk 	    h = src->height - sy;
585a8e925d3Spk 
586a8e925d3Spk 	/* Clip against dest. */
587a8e925d3Spk 	if ( dx < 0 )
588a8e925d3Spk 	    {
589a8e925d3Spk 	    w += dx;
590a8e925d3Spk 	    sx -= dx;
591a8e925d3Spk 	    dx = 0;
592a8e925d3Spk 	    }
593a8e925d3Spk 	if ( dy < 0 )
594a8e925d3Spk 	    {
595a8e925d3Spk 	    h += dy;
596a8e925d3Spk 	    sy -= dy;
597a8e925d3Spk 	    dy = 0;
598a8e925d3Spk 	    }
599a8e925d3Spk 	if ( dx + w > dst->width )
600a8e925d3Spk 	    w = dst->width - dx;
601a8e925d3Spk 	if ( dy + h > dst->height )
602a8e925d3Spk 	    h = dst->height - dy;
603a8e925d3Spk 
604a8e925d3Spk 	if ( w <= 0 || h <= 0 )
605a8e925d3Spk 	    return 0;			/* nothing to do */
606a8e925d3Spk 
607a8e925d3Spk 	return raster_op_noclip( dst, dx, dy, w, h, rop, src, sx, sy );
608a8e925d3Spk 	}
609a8e925d3Spk 
610a8e925d3Spk     /* No source necessary - one-operand blit. */
611a8e925d3Spk     if ( src != (struct raster*) 0 )
612a8e925d3Spk 	return -1;			/* unwanted source */
613a8e925d3Spk 
614a8e925d3Spk     /* Clip against dest. */
615a8e925d3Spk     if ( dx < 0 )
616a8e925d3Spk 	{
617a8e925d3Spk 	w += dx;
618a8e925d3Spk 	dx = 0;
619a8e925d3Spk 	}
620a8e925d3Spk     if ( dy < 0 )
621a8e925d3Spk 	{
622a8e925d3Spk 	h += dy;
623a8e925d3Spk 	dy = 0;
624a8e925d3Spk 	}
625a8e925d3Spk     if ( dx + w > dst->width )
626a8e925d3Spk 	w = dst->width - dx;
627a8e925d3Spk     if ( dy + h > dst->height )
628a8e925d3Spk 	h = dst->height - dy;
629a8e925d3Spk 
630a8e925d3Spk     if ( w <= 0 || h <= 0 )
631a8e925d3Spk 	return 0;			/* nothing to do */
632a8e925d3Spk 
633a8e925d3Spk     return raster_op_nosrc_noclip( dst, dx, dy, w, h, rop );
634a8e925d3Spk     }
635a8e925d3Spk 
636a8e925d3Spk /* Semi-public routine to do a bitblit without clipping.  Returns 0 on
637a8e925d3Spk ** success, -1 on failure.
638a8e925d3Spk */
639a8e925d3Spk int
raster_op_noclip(struct raster * dst,int dx,int dy,int w,int h,int rop,struct raster * src,int sx,int sy)640*91d94812Smatt raster_op_noclip(struct raster* dst, int dx, int dy, int w, int h, int rop,
641*91d94812Smatt     struct raster* src, int sx, int sy)
642a8e925d3Spk     {
643a8e925d3Spk     int op;
644a8e925d3Spk 
645a8e925d3Spk     op = RAS_GETOP( rop );
646a8e925d3Spk 
647a8e925d3Spk     if ( src->depth == 1 )
648a8e925d3Spk 	{
649a8e925d3Spk 	/* One-bit to ? blit. */
650a8e925d3Spk 	if ( dst->depth == 1 )
651a8e925d3Spk 	    {
652a8e925d3Spk 	    /* One to one blit. */
653540ab1b8Scgd 	    u_int32_t* srclin1;
654540ab1b8Scgd 	    u_int32_t* dstlin1;
655a8e925d3Spk 	    int srcleftignore, srcrightignore, srclongs;
656a8e925d3Spk 	    int dstleftignore, dstrightignore, dstlongs;
657a8e925d3Spk 
658a8e925d3Spk 	    srclin1 = RAS_ADDR( src, sx, sy );
659a8e925d3Spk 	    dstlin1 = RAS_ADDR( dst, dx, dy );
660a8e925d3Spk 
661a8e925d3Spk #ifdef BCOPY_FASTER
662a8e925d3Spk 	    /* Special-case full-width to full-width copies. */
663a8e925d3Spk 	    if ( op == RAS_SRC && src->width == w && dst->width == w &&
664a8e925d3Spk 		 src->linelongs == dst->linelongs && src->linelongs == w >> 5 )
665a8e925d3Spk 		{
666a8e925d3Spk 		bcopy(
667a8e925d3Spk 		    (char*) srclin1, (char*) dstlin1,
668540ab1b8Scgd 		    h * src->linelongs * sizeof(u_int32_t) );
669a8e925d3Spk 		return 0;
670a8e925d3Spk 		}
671a8e925d3Spk #endif /*BCOPY_FASTER*/
672a8e925d3Spk 
673a8e925d3Spk 	    srcleftignore = ( sx & 31 );
674a8e925d3Spk 	    srclongs = ( srcleftignore + w + 31 ) >> 5;
675a8e925d3Spk 	    srcrightignore = ( srclongs * 32 - w - srcleftignore ) & 31;
676a8e925d3Spk 	    dstleftignore = ( dx & 31 );
677a8e925d3Spk 	    dstlongs = ( dstleftignore + w + 31 ) >> 5;
678a8e925d3Spk 	    dstrightignore = ( dstlongs * 32 - w - dstleftignore ) & 31;
679a8e925d3Spk 
680a8e925d3Spk 	    return raster_blit(
681a8e925d3Spk 		src, srclin1, srcleftignore, srcrightignore, srclongs,
682a8e925d3Spk 		dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op );
683a8e925d3Spk 	    }
684a8e925d3Spk 
68523795512Sdrochner #ifdef RCONS_2BPP
68623795512Sdrochner 	else if ( dst->depth == 2 )
68723795512Sdrochner           {
68823795512Sdrochner             /* One to two, using the color in the rop.  */
68923795512Sdrochner 	    u_int32_t* srclin1;
69023795512Sdrochner 	    u_int32_t* dstlin1;
69123795512Sdrochner 	    u_int32_t* srclin2;
69223795512Sdrochner 	    u_int32_t* srclin;
69323795512Sdrochner 	    u_int32_t* dstlin;
694169ac5b3Saugustss 	    u_int32_t* srclong;
695169ac5b3Saugustss 	    u_int32_t* dstlong;
696169ac5b3Saugustss 	    u_int32_t color, dl;
697169ac5b3Saugustss 	    int srcbit, dstbyte, i;
69823795512Sdrochner 
69923795512Sdrochner 	    color = RAS_GETCOLOR( rop );
70023795512Sdrochner 	    if ( color == 0 )
70123795512Sdrochner               color = 3;
70223795512Sdrochner 
70323795512Sdrochner 	    /* Make 32 bits of color so we can do the ROP without shifting. */
70423795512Sdrochner 	    color |= (( color << 30 ) | ( color << 28 ) | ( color << 26 )
70523795512Sdrochner                       | ( color << 24 ) | ( color << 22 ) | ( color << 20 )
70623795512Sdrochner                       | ( color << 18 ) | ( color << 16 ) | ( color << 14 )
70723795512Sdrochner                       | ( color << 12 ) | ( color << 10 ) | ( color << 8 )
70823795512Sdrochner                       | ( color << 6 ) | ( color << 4 ) | ( color << 2 ));
70923795512Sdrochner 
71023795512Sdrochner 	    /* Don't have to worry about overlapping blits here. */
71123795512Sdrochner 	    srclin1 = RAS_ADDR( src, sx, sy );
71223795512Sdrochner 	    srclin2 = srclin1 + h * src->linelongs;
71323795512Sdrochner 	    dstlin1 = RAS_ADDR( dst, dx, dy );
71423795512Sdrochner 	    srclin = srclin1;
71523795512Sdrochner 	    dstlin = dstlin1;
71623795512Sdrochner 
71723795512Sdrochner 	    while ( srclin != srclin2 )
71823795512Sdrochner 		{
71923795512Sdrochner 		srclong = srclin;
72023795512Sdrochner 		srcbit = sx & 31;
72123795512Sdrochner 		dstlong = dstlin;
72223795512Sdrochner 		dstbyte = dx & 15;
72323795512Sdrochner 		i = w;
72423795512Sdrochner 
72523795512Sdrochner 		/* WARNING: this code is KNOWN TO FAIL on Sun 3's / CG2's. */
72623795512Sdrochner 		ROP_SRCDSTCOLOR(
72723795512Sdrochner 		/*op*/  op,
72823795512Sdrochner 		/*pre*/ while ( i > 0 )
72923795512Sdrochner 			    {
73023795512Sdrochner 			    dl = *dstlong;,
73123795512Sdrochner 		/*s*/       *srclong & raster_bitmask[srcbit],
73223795512Sdrochner 		/*d*/       dl,
73323795512Sdrochner 		/*c*/       color,
73423795512Sdrochner 		/*pst*/     *dstlong = ( *dstlong & ~twobitmask[dstbyte] ) |
73523795512Sdrochner 				       ( dl & twobitmask[dstbyte] );
73623795512Sdrochner 			    if ( srcbit == 31 )
73723795512Sdrochner 				{
73823795512Sdrochner 				srcbit = 0;
73923795512Sdrochner 				++srclong;
74023795512Sdrochner 				}
74123795512Sdrochner 			    else
74223795512Sdrochner 				++srcbit;
74323795512Sdrochner 			    if ( dstbyte == 15 )
74423795512Sdrochner 				{
74523795512Sdrochner 				dstbyte = 0;
74623795512Sdrochner 				++dstlong;
74723795512Sdrochner 				}
74823795512Sdrochner 			    else
74923795512Sdrochner 				++dstbyte;
75023795512Sdrochner 			    --i;
75123795512Sdrochner 			    } )
75223795512Sdrochner 
75323795512Sdrochner 		srclin += src->linelongs;
75423795512Sdrochner 		dstlin += dst->linelongs;
75523795512Sdrochner 		}
75623795512Sdrochner           }
75723795512Sdrochner #endif /* RCONS_2BPP */
758d617933eSscottr #ifdef RCONS_4BPP
759d617933eSscottr 	else if ( dst->depth == 4 )
760d617933eSscottr           {
761d617933eSscottr             /* One to four, using the color in the rop.  */
762d617933eSscottr 	    u_int32_t* srclin1;
763d617933eSscottr 	    u_int32_t* dstlin1;
764d617933eSscottr 	    u_int32_t* srclin2;
765d617933eSscottr 	    u_int32_t* srclin;
766d617933eSscottr 	    u_int32_t* dstlin;
767169ac5b3Saugustss 	    u_int32_t* srclong;
768169ac5b3Saugustss 	    u_int32_t* dstlong;
769169ac5b3Saugustss 	    u_int32_t color, dl;
770169ac5b3Saugustss 	    int srcbit, dstbyte, i;
771d617933eSscottr 
772d617933eSscottr 	    color = RAS_GETCOLOR( rop );
773d617933eSscottr 	    if ( color == 0 )
774d617933eSscottr               color = 15;
775d617933eSscottr 
776d617933eSscottr 	    /* Make 32 bits of color so we can do the ROP without shifting. */
777d617933eSscottr 	    color |= (( color << 28 ) | ( color << 24 )
778d617933eSscottr                       | ( color << 20 ) | ( color << 16 )
779d617933eSscottr                       | ( color << 12 ) | ( color << 8 )
780d617933eSscottr                       | ( color << 4 ));
781d617933eSscottr 
782d617933eSscottr 	    /* Don't have to worry about overlapping blits here. */
783d617933eSscottr 	    srclin1 = RAS_ADDR( src, sx, sy );
784d617933eSscottr 	    srclin2 = srclin1 + h * src->linelongs;
785d617933eSscottr 	    dstlin1 = RAS_ADDR( dst, dx, dy );
786d617933eSscottr 	    srclin = srclin1;
787d617933eSscottr 	    dstlin = dstlin1;
788d617933eSscottr 
789d617933eSscottr 	    while ( srclin != srclin2 )
790d617933eSscottr 		{
791d617933eSscottr 		srclong = srclin;
792d617933eSscottr 		srcbit = sx & 31;
793d617933eSscottr 		dstlong = dstlin;
794d617933eSscottr 		dstbyte = dx & 7;
795d617933eSscottr 		i = w;
796d617933eSscottr 
797d617933eSscottr 		/* WARNING: this code is KNOWN TO FAIL on Sun 3's / CG2's. */
798d617933eSscottr 		ROP_SRCDSTCOLOR(
799d617933eSscottr 		/*op*/  op,
800d617933eSscottr 		/*pre*/ while ( i > 0 )
801d617933eSscottr 			    {
802d617933eSscottr 			    dl = *dstlong;,
803d617933eSscottr 		/*s*/       *srclong & raster_bitmask[srcbit],
804d617933eSscottr 		/*d*/       dl,
805d617933eSscottr 		/*c*/       color,
806d617933eSscottr 		/*pst*/     *dstlong = ( *dstlong & ~fourbitmask[dstbyte] ) |
807d617933eSscottr 				       ( dl & fourbitmask[dstbyte] );
808d617933eSscottr 			    if ( srcbit == 31 )
809d617933eSscottr 				{
810d617933eSscottr 				srcbit = 0;
811d617933eSscottr 				++srclong;
812d617933eSscottr 				}
813d617933eSscottr 			    else
814d617933eSscottr 				++srcbit;
815d617933eSscottr 			    if ( dstbyte == 7 )
816d617933eSscottr 				{
817d617933eSscottr 				dstbyte = 0;
818d617933eSscottr 				++dstlong;
819d617933eSscottr 				}
820d617933eSscottr 			    else
821d617933eSscottr 				++dstbyte;
822d617933eSscottr 			    --i;
823d617933eSscottr 			    } )
824d617933eSscottr 
825d617933eSscottr 		srclin += src->linelongs;
826d617933eSscottr 		dstlin += dst->linelongs;
827d617933eSscottr 		}
828d617933eSscottr           }
829d617933eSscottr #endif /* RCONS_4BPP */
8309d326d48Sdbj 	else if ( dst->depth == 8 )
831a8e925d3Spk 	    {
832a8e925d3Spk 	    /* One to eight, using the color in the rop.  This could
833a8e925d3Spk 	    ** probably be sped up by handling each four-bit source nybble
834a8e925d3Spk 	    ** as a group, indexing into a 16-element runtime-constructed
835a8e925d3Spk 	    ** table of longwords.
836a8e925d3Spk 	    */
837540ab1b8Scgd 	    u_int32_t* srclin1;
838540ab1b8Scgd 	    u_int32_t* dstlin1;
839540ab1b8Scgd 	    u_int32_t* srclin2;
840540ab1b8Scgd 	    u_int32_t* srclin;
841540ab1b8Scgd 	    u_int32_t* dstlin;
842169ac5b3Saugustss 	    u_int32_t* srclong;
843169ac5b3Saugustss 	    u_int32_t* dstlong;
844169ac5b3Saugustss 	    u_int32_t color, dl;
845169ac5b3Saugustss 	    int srcbit, dstbyte, i;
846a8e925d3Spk 
847a8e925d3Spk 	    color = RAS_GETCOLOR( rop );
848a8e925d3Spk 	    if ( color == 0 )
849a8e925d3Spk 		color = 255;
850a8e925d3Spk 
851a8e925d3Spk 	    /* Make 32 bits of color so we can do the ROP without shifting. */
852a8e925d3Spk 	    color |= ( color << 24 ) | ( color << 16 ) | ( color << 8 );
853a8e925d3Spk 
854a8e925d3Spk 	    /* Don't have to worry about overlapping blits here. */
855a8e925d3Spk 	    srclin1 = RAS_ADDR( src, sx, sy );
856a8e925d3Spk 	    srclin2 = srclin1 + h * src->linelongs;
857a8e925d3Spk 	    dstlin1 = RAS_ADDR( dst, dx, dy );
858a8e925d3Spk 	    srclin = srclin1;
859a8e925d3Spk 	    dstlin = dstlin1;
860a8e925d3Spk 	    while ( srclin != srclin2 )
861a8e925d3Spk 		{
862a8e925d3Spk 		srclong = srclin;
863a8e925d3Spk 		srcbit = sx & 31;
864a8e925d3Spk 		dstlong = dstlin;
865a8e925d3Spk 		dstbyte = dx & 3;
866a8e925d3Spk 		i = w;
867a8e925d3Spk 
868a8e925d3Spk 		/* WARNING: this code is KNOWN TO FAIL on Sun 3's / CG2's. */
869a8e925d3Spk 		ROP_SRCDSTCOLOR(
870a8e925d3Spk 		/*op*/  op,
871a8e925d3Spk 		/*pre*/ while ( i > 0 )
872a8e925d3Spk 			    {
873a8e925d3Spk 			    dl = *dstlong;,
874a8e925d3Spk 		/*s*/       *srclong & raster_bitmask[srcbit],
875a8e925d3Spk 		/*d*/       dl,
876a8e925d3Spk 		/*c*/       color,
877a8e925d3Spk 		/*pst*/     *dstlong = ( *dstlong & ~bytemask[dstbyte] ) |
878a8e925d3Spk 				       ( dl & bytemask[dstbyte] );
879a8e925d3Spk 			    if ( srcbit == 31 )
880a8e925d3Spk 				{
881a8e925d3Spk 				srcbit = 0;
882a8e925d3Spk 				++srclong;
883a8e925d3Spk 				}
884a8e925d3Spk 			    else
885a8e925d3Spk 				++srcbit;
886a8e925d3Spk 			    if ( dstbyte == 3 )
887a8e925d3Spk 				{
888a8e925d3Spk 				dstbyte = 0;
889a8e925d3Spk 				++dstlong;
890a8e925d3Spk 				}
891a8e925d3Spk 			    else
892a8e925d3Spk 				++dstbyte;
893a8e925d3Spk 			    --i;
894a8e925d3Spk 			    } )
895a8e925d3Spk 
896a8e925d3Spk 		srclin += src->linelongs;
897a8e925d3Spk 		dstlin += dst->linelongs;
898a8e925d3Spk 		}
899a8e925d3Spk 	    }
9009d326d48Sdbj #ifdef RCONS_16BPP
9019d326d48Sdbj 	else
9029d326d48Sdbj 	    {
9039d326d48Sdbj 	    /* One to sixteen, using the color in the rop.  This could
9049d326d48Sdbj 	    ** probably be sped up by handling each four-bit source nybble
9059d326d48Sdbj 	    ** as a group, indexing into a 16-element runtime-constructed
9069d326d48Sdbj 	    ** table of longwords.
9079d326d48Sdbj 	    */
9089d326d48Sdbj 	    u_int32_t* srclin1;
9099d326d48Sdbj 	    u_int32_t* dstlin1;
9109d326d48Sdbj 	    u_int32_t* srclin2;
9119d326d48Sdbj 	    u_int32_t* srclin;
9129d326d48Sdbj 	    u_int32_t* dstlin;
913169ac5b3Saugustss 	    u_int32_t* srclong;
914169ac5b3Saugustss 	    u_int32_t* dstlong;
915169ac5b3Saugustss 	    u_int32_t color, dl;
916169ac5b3Saugustss 	    int srcbit, dstbyte, i;
9179d326d48Sdbj 
9189d326d48Sdbj 	    color = RAS_GETCOLOR( rop );
9199d326d48Sdbj 	    if ( color == 0 )
9209a37177dSdeberg 		color = 0xffff;
9219d326d48Sdbj 
9229d326d48Sdbj 	    /* Make 32 bits of color so we can do the ROP without shifting. */
9239d326d48Sdbj 	    color |= ( color << 16 );
9249d326d48Sdbj 
9259d326d48Sdbj 	    /* Don't have to worry about overlapping blits here. */
9269d326d48Sdbj 	    srclin1 = RAS_ADDR( src, sx, sy );
9279d326d48Sdbj 	    srclin2 = srclin1 + h * src->linelongs;
9289d326d48Sdbj 	    dstlin1 = RAS_ADDR( dst, dx, dy );
9299d326d48Sdbj 	    srclin = srclin1;
9309d326d48Sdbj 	    dstlin = dstlin1;
9319d326d48Sdbj 	    while ( srclin != srclin2 )
9329d326d48Sdbj 		{
9339d326d48Sdbj 		srclong = srclin;
9349d326d48Sdbj 		srcbit = sx & 31;
9359d326d48Sdbj 		dstlong = dstlin;
9369d326d48Sdbj 		dstbyte = dx & 1;
9379d326d48Sdbj 		i = w;
9389d326d48Sdbj 
9399d326d48Sdbj 		/* WARNING: this code is KNOWN TO FAIL on Sun 3's / CG2's. */
9409d326d48Sdbj 		ROP_SRCDSTCOLOR(
9419d326d48Sdbj 		/*op*/  op,
9429d326d48Sdbj 		/*pre*/ while ( i > 0 )
9439d326d48Sdbj 			    {
9449d326d48Sdbj 			    dl = *dstlong;,
9459d326d48Sdbj 		/*s*/       *srclong & raster_bitmask[srcbit],
9469d326d48Sdbj 		/*d*/       dl,
9479d326d48Sdbj 		/*c*/       color,
9489d326d48Sdbj 		/*pst*/     *dstlong = ( *dstlong & ~twobytemask[dstbyte] ) |
9499d326d48Sdbj 				       ( dl & twobytemask[dstbyte] );
9509d326d48Sdbj 			    if ( srcbit == 31 )
9519d326d48Sdbj 				{
9529d326d48Sdbj 				srcbit = 0;
9539d326d48Sdbj 				++srclong;
9549d326d48Sdbj 				}
9559d326d48Sdbj 			    else
9569d326d48Sdbj 				++srcbit;
9579d326d48Sdbj 			    if ( dstbyte == 1 )
9589d326d48Sdbj 				{
9599d326d48Sdbj 				dstbyte = 0;
9609d326d48Sdbj 				++dstlong;
9619d326d48Sdbj 				}
9629d326d48Sdbj 			    else
9639d326d48Sdbj 				++dstbyte;
9649d326d48Sdbj 			    --i;
9659d326d48Sdbj 			    } )
9669d326d48Sdbj 
9679d326d48Sdbj 		srclin += src->linelongs;
9689d326d48Sdbj 		dstlin += dst->linelongs;
9699d326d48Sdbj 		}
9709d326d48Sdbj 	    }
9719d326d48Sdbj #endif /* RCONS_16BPP */
972a8e925d3Spk 	}
97323795512Sdrochner #ifdef RCONS_2BPP
97423795512Sdrochner     else if ( src->depth == 2 )
97523795512Sdrochner       {
97623795512Sdrochner         /* Two to two blit. */
97723795512Sdrochner 	    u_int32_t* srclin1;
97823795512Sdrochner 	    u_int32_t* dstlin1;
97923795512Sdrochner 	    int srcleftignore, srcrightignore, srclongs;
98023795512Sdrochner 	    int dstleftignore, dstrightignore, dstlongs;
98123795512Sdrochner 
98223795512Sdrochner 	    srclin1 = RAS_ADDR( src, sx, sy );
98323795512Sdrochner 	    dstlin1 = RAS_ADDR( dst, dx, dy );
98423795512Sdrochner 
98523795512Sdrochner 	    srcleftignore = ( sx & 15 ) * 2;
98623795512Sdrochner 	    srclongs = ( srcleftignore + w * 2 + 31 ) >> 5;
98723795512Sdrochner 	    srcrightignore = ( srclongs * 32 - w * 2 - srcleftignore ) & 31;
98823795512Sdrochner 	    dstleftignore = ( dx & 15 ) * 2;
98923795512Sdrochner 	    dstlongs = ( dstleftignore + w * 2 + 31 ) >> 5;
99023795512Sdrochner 	    dstrightignore = ( dstlongs * 32 - w * 2 - dstleftignore ) & 31;
99123795512Sdrochner 
99223795512Sdrochner 	    return raster_blit(
99323795512Sdrochner 		src, srclin1, srcleftignore, srcrightignore, srclongs,
99423795512Sdrochner 		dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op );
99523795512Sdrochner 	    }
99623795512Sdrochner #endif /* RCONS_2BPP */
997d617933eSscottr #ifdef RCONS_4BPP
998d617933eSscottr     else if ( src->depth == 4 )
999d617933eSscottr       {
1000d617933eSscottr         /* Four to four blit. */
1001d617933eSscottr 	    u_int32_t* srclin1;
1002d617933eSscottr 	    u_int32_t* dstlin1;
1003d617933eSscottr 	    int srcleftignore, srcrightignore, srclongs;
1004d617933eSscottr 	    int dstleftignore, dstrightignore, dstlongs;
1005d617933eSscottr 
1006d617933eSscottr 	    srclin1 = RAS_ADDR( src, sx, sy );
1007d617933eSscottr 	    dstlin1 = RAS_ADDR( dst, dx, dy );
1008d617933eSscottr 
1009d617933eSscottr 	    srcleftignore = ( sx & 7 ) * 4;
1010d617933eSscottr 	    srclongs = ( srcleftignore + w * 4 + 31 ) >> 5;
1011d617933eSscottr 	    srcrightignore = ( srclongs * 32 - w * 4 - srcleftignore ) & 31;
1012d617933eSscottr 	    dstleftignore = ( dx & 7 ) * 4;
1013d617933eSscottr 	    dstlongs = ( dstleftignore + w * 4 + 31 ) >> 5;
1014d617933eSscottr 	    dstrightignore = ( dstlongs * 32 - w * 4 - dstleftignore ) & 31;
1015d617933eSscottr 
1016d617933eSscottr 	    return raster_blit(
1017d617933eSscottr 		src, srclin1, srcleftignore, srcrightignore, srclongs,
1018d617933eSscottr 		dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op );
1019d617933eSscottr 	    }
1020d617933eSscottr #endif /* RCONS_4BPP */
1021a8e925d3Spk 
10229d326d48Sdbj     else if ( src->depth == 8 )
1023a8e925d3Spk 	{
1024a8e925d3Spk 	/* Eight to eight blit. */
1025540ab1b8Scgd 	u_int32_t* srclin1;
1026540ab1b8Scgd 	u_int32_t* dstlin1;
1027a8e925d3Spk 	int srcleftignore, srcrightignore, srclongs;
1028a8e925d3Spk 	int dstleftignore, dstrightignore, dstlongs;
1029a8e925d3Spk 
1030a8e925d3Spk 	if ( dst->depth != 8 )
1031a8e925d3Spk 	    return -1;		/* depth mismatch */
1032a8e925d3Spk 
1033a8e925d3Spk 	srclin1 = RAS_ADDR( src, sx, sy );
1034a8e925d3Spk 	dstlin1 = RAS_ADDR( dst, dx, dy );
1035a8e925d3Spk 
1036a8e925d3Spk #ifdef BCOPY_FASTER
1037a8e925d3Spk 	/* Special-case full-width to full-width copies. */
1038a8e925d3Spk 	if ( op == RAS_SRC && src->width == w && dst->width == w &&
1039a8e925d3Spk 	     src->linelongs == dst->linelongs && src->linelongs == w >> 2 )
1040a8e925d3Spk 	    {
1041d24f7d61Stsutsui 	    bcopy( (char*) srclin1, (char*) dstlin1,
1042540ab1b8Scgd 		   h * src->linelongs * sizeof(u_int32_t) );
1043a8e925d3Spk 	    return 0;
1044a8e925d3Spk 	    }
1045a8e925d3Spk #endif /*BCOPY_FASTER*/
1046a8e925d3Spk 
1047a8e925d3Spk 	srcleftignore = ( sx & 3 ) * 8;
1048a8e925d3Spk 	srclongs = ( srcleftignore + w * 8 + 31 ) >> 5;
1049a8e925d3Spk 	srcrightignore = ( srclongs * 32 - w * 8 - srcleftignore ) & 31;
1050a8e925d3Spk 	dstleftignore = ( dx & 3 ) * 8;
1051a8e925d3Spk 	dstlongs = ( dstleftignore + w * 8 + 31 ) >> 5;
1052a8e925d3Spk 	dstrightignore = ( dstlongs * 32 - w * 8 - dstleftignore ) & 31;
1053a8e925d3Spk 
1054a8e925d3Spk 	return raster_blit(
1055a8e925d3Spk 	    src, srclin1, srcleftignore, srcrightignore, srclongs,
1056a8e925d3Spk 	    dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op );
1057a8e925d3Spk 	}
10589d326d48Sdbj #ifdef RCONS_16BPP
10599d326d48Sdbj     else
10609d326d48Sdbj         {
10619d326d48Sdbj 	/* Sixteen to sixteen blit. */
10629d326d48Sdbj 	    u_int32_t* srclin1;
10639d326d48Sdbj 	    u_int32_t* dstlin1;
10649d326d48Sdbj 	    int srcleftignore, srcrightignore, srclongs;
10659d326d48Sdbj 	    int dstleftignore, dstrightignore, dstlongs;
1066a8e925d3Spk 
10679d326d48Sdbj 	    srclin1 = RAS_ADDR( src, sx, sy );
10689d326d48Sdbj 	    dstlin1 = RAS_ADDR( dst, dx, dy );
10699d326d48Sdbj 
10709d326d48Sdbj 	    srcleftignore = ( sx & 1 ) * 16;
10719d326d48Sdbj 	    srclongs = ( srcleftignore + w * 16 + 31 ) >> 5;
10729d326d48Sdbj 	    srcrightignore = ( srclongs * 32 - w * 16 - srcleftignore ) & 31;
10739d326d48Sdbj 	    dstleftignore = ( dx & 1 ) * 16;
10749d326d48Sdbj 	    dstlongs = ( dstleftignore + w * 16 + 31 ) >> 5;
10759d326d48Sdbj 	    dstrightignore = ( dstlongs * 32 - w * 16 - dstleftignore ) & 31;
10769d326d48Sdbj 
10779d326d48Sdbj 	    return raster_blit(
10789d326d48Sdbj 		src, srclin1, srcleftignore, srcrightignore, srclongs,
10799d326d48Sdbj 		dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op );
10809d326d48Sdbj 	}
10819d326d48Sdbj #endif /* RCONS_16BPP */
1082a8e925d3Spk     return 0;
1083a8e925d3Spk     }
1084a8e925d3Spk 
1085a8e925d3Spk /* Semi-public routine to do a no-src bitblit without clipping.  Returns 0
1086a8e925d3Spk ** on success, -1 on failure.
1087a8e925d3Spk */
1088a8e925d3Spk int
raster_op_nosrc_noclip(struct raster * dst,int dx,int dy,int w,int h,int rop)1089*91d94812Smatt raster_op_nosrc_noclip(struct raster* dst,
1090*91d94812Smatt     int dx, int dy, int w, int h, int rop)
1091a8e925d3Spk     {
1092a8e925d3Spk     int op;
1093a8e925d3Spk 
1094a8e925d3Spk     op = RAS_GETOP( rop );
1095a8e925d3Spk 
1096a8e925d3Spk     if ( dst->depth == 1 )
1097a8e925d3Spk 	{
1098a8e925d3Spk 	/* One-bit no-src blit. */
1099540ab1b8Scgd 	u_int32_t* dstlin1;
1100540ab1b8Scgd 	u_int32_t* dstlin2;
1101540ab1b8Scgd 	u_int32_t* dstlin;
1102a8e925d3Spk 	int dstleftignore, dstrightignore, dstlongs;
1103540ab1b8Scgd 	u_int32_t dl, lm, nlm, rm, nrm;
1104169ac5b3Saugustss 	u_int32_t* dstlong2;
1105169ac5b3Saugustss 	u_int32_t* dstlong;
1106a8e925d3Spk 
1107a8e925d3Spk 	dstlin1 = RAS_ADDR( dst, dx, dy );
1108a8e925d3Spk 
1109a8e925d3Spk #ifdef BCOPY_FASTER
1110a8e925d3Spk 	/* Special-case full-width clears. */
1111a8e925d3Spk 	if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 5 )
1112a8e925d3Spk 	    {
1113c363a9cbScegger 	    memset( (char*) dstlin1, 0, h * dst->linelongs * sizeof(u_int32_t) );
1114a8e925d3Spk 	    return 0;
1115a8e925d3Spk 	    }
1116a8e925d3Spk #endif /*BCOPY_FASTER*/
1117a8e925d3Spk 
1118a8e925d3Spk 	dstleftignore = ( dx & 31 );
1119a8e925d3Spk 	dstlongs = ( dstleftignore + w + 31 ) >> 5;
1120a8e925d3Spk 	dstrightignore = ( dstlongs * 32 - w - dstleftignore ) & 31;
1121a8e925d3Spk 
1122a8e925d3Spk 	dstlin2 = dstlin1 + h * dst->linelongs;
1123a8e925d3Spk 	dstlin = dstlin1;
1124a8e925d3Spk 
1125a8e925d3Spk 	if ( dstlongs == 1 )
1126a8e925d3Spk 	    {
1127a8e925d3Spk 	    /* It fits into a single longword. */
1128a8e925d3Spk 	    lm = leftmask[dstleftignore] | rightmask[dstrightignore];
1129a8e925d3Spk 	    nlm = ~lm;
1130a8e925d3Spk 	    while ( dstlin != dstlin2 )
1131a8e925d3Spk 		{
1132a8e925d3Spk 		ROP_DST(
1133a8e925d3Spk 		/*op*/  op,
1134a8e925d3Spk 		/*pre*/ dl = *dstlin;,
1135a8e925d3Spk 		/*d*/   dl,
1136a8e925d3Spk 		/*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
1137a8e925d3Spk 
1138a8e925d3Spk 		dstlin += dst->linelongs;
1139a8e925d3Spk 		}
1140a8e925d3Spk 	    }
1141a8e925d3Spk 	else
1142a8e925d3Spk 	    {
1143a8e925d3Spk 	    lm = leftmask[dstleftignore];
1144a8e925d3Spk 	    rm = rightmask[dstrightignore];
1145a8e925d3Spk 	    nrm = ~rm;
1146a8e925d3Spk 	    nlm = ~lm;
1147a8e925d3Spk 
1148a8e925d3Spk 	    while ( dstlin != dstlin2 )
1149a8e925d3Spk 		{
1150a8e925d3Spk 		dstlong = dstlin;
1151a8e925d3Spk 		dstlong2 = dstlong + dstlongs;
1152a8e925d3Spk 		if ( dstrightignore != 0 )
1153a8e925d3Spk 		    --dstlong2;
1154a8e925d3Spk 
1155a8e925d3Spk 		/* Leading edge. */
1156a8e925d3Spk 		if ( dstleftignore != 0 )
1157a8e925d3Spk 		    {
1158a8e925d3Spk 		    ROP_DST(
1159a8e925d3Spk 		    /*op*/  op,
1160a8e925d3Spk 		    /*pre*/ dl = *dstlong;,
1161a8e925d3Spk 		    /*d*/   dl,
1162a8e925d3Spk 		    /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
1163a8e925d3Spk 		    ++dstlong;
1164a8e925d3Spk 		    }
1165a8e925d3Spk 
1166a8e925d3Spk 		/* Main rop. */
1167a8e925d3Spk 		ROP_DST(
1168a8e925d3Spk 		/*op*/  op,
1169a8e925d3Spk 		/*pre*/ while ( dstlong != dstlong2 )
1170a8e925d3Spk 			    {,
1171a8e925d3Spk 		/*d*/       *dstlong,
1172a8e925d3Spk 		/*pst*/     ++dstlong;
1173a8e925d3Spk 			    } )
1174a8e925d3Spk 
1175a8e925d3Spk 		/* Trailing edge. */
1176a8e925d3Spk 		if ( dstrightignore != 0 )
1177a8e925d3Spk 		    {
1178a8e925d3Spk 		    ROP_DST(
1179a8e925d3Spk 		    /*op*/  op,
1180a8e925d3Spk 		    /*pre*/ dl = *dstlong;,
1181a8e925d3Spk 		    /*d*/   dl,
1182a8e925d3Spk 		    /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
1183a8e925d3Spk 		    }
1184a8e925d3Spk 
1185a8e925d3Spk 		dstlin += dst->linelongs;
1186a8e925d3Spk 		}
1187a8e925d3Spk 	    }
1188a8e925d3Spk 	}
1189a8e925d3Spk 
119023795512Sdrochner #ifdef RCONS_2BPP
119123795512Sdrochner     else if ( dst->depth == 2 )
119223795512Sdrochner 	{
119323795512Sdrochner 	/* Two-bit no-src blit. */
1194169ac5b3Saugustss 	u_int32_t color;
119523795512Sdrochner 	u_int32_t* dstlin1;
119623795512Sdrochner 	u_int32_t* dstlin2;
119723795512Sdrochner 	u_int32_t* dstlin;
119823795512Sdrochner 	int dstleftignore, dstrightignore, dstlongs;
119923795512Sdrochner 	u_int32_t dl, lm, nlm, rm, nrm;
1200169ac5b3Saugustss 	u_int32_t* dstlong2;
1201169ac5b3Saugustss 	u_int32_t* dstlong;
120223795512Sdrochner 
120323795512Sdrochner 	dstlin1 = RAS_ADDR( dst, dx, dy );
120423795512Sdrochner 
120523795512Sdrochner #ifdef BCOPY_FASTER
120623795512Sdrochner 	/* Special-case full-width clears. */
12079d326d48Sdbj 	if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 4 )
120823795512Sdrochner 	    {
1209c363a9cbScegger 	    memset( (char*) dstlin1, 0, h * dst->linelongs * sizeof(u_int32_t) );
121023795512Sdrochner 	    return 0;
121123795512Sdrochner 	    }
121223795512Sdrochner #endif /*BCOPY_FASTER*/
121323795512Sdrochner 
121423795512Sdrochner 	color = RAS_GETCOLOR( rop );
121523795512Sdrochner 	if ( color == 0 )
121623795512Sdrochner 	    color = 3;
121723795512Sdrochner 
121823795512Sdrochner         /* Make 32 bits of color so we can do the ROP without shifting. */
121923795512Sdrochner         color |= (( color << 30 ) | ( color << 28 ) | ( color << 26 )
122023795512Sdrochner                   | ( color << 24 ) | ( color << 22 ) | ( color << 20 )
122123795512Sdrochner                   | ( color << 18 ) | ( color << 16 ) | ( color << 14 )
122223795512Sdrochner                   | ( color << 12 ) | ( color << 10 ) | ( color << 8 )
122323795512Sdrochner                   | ( color << 6 ) | ( color << 4 ) | ( color << 2 ));
122423795512Sdrochner 
122523795512Sdrochner 	dstleftignore = ( dx & 15 ) * 2;
122623795512Sdrochner 	dstlongs = ( dstleftignore + w * 2 + 31 ) >> 5;
122723795512Sdrochner 	dstrightignore = ( dstlongs * 32 - w * 2 - dstleftignore ) & 31;
122823795512Sdrochner 
122923795512Sdrochner 	dstlin2 = dstlin1 + h * dst->linelongs;
123023795512Sdrochner 	dstlin = dstlin1;
123123795512Sdrochner 
123223795512Sdrochner 	if ( dstlongs == 1 )
123323795512Sdrochner 	    {
123423795512Sdrochner 	    /* It fits into a single longword. */
123523795512Sdrochner 	    lm = leftmask[dstleftignore] | rightmask[dstrightignore];
123623795512Sdrochner 	    nlm = ~lm;
123723795512Sdrochner 	    while ( dstlin != dstlin2 )
123823795512Sdrochner 		{
123923795512Sdrochner 		ROP_DST(
124023795512Sdrochner 		/*op*/  op,
124123795512Sdrochner 		/*pre*/ dl = *dstlin;,
124223795512Sdrochner 		/*d*/   dl,
124323795512Sdrochner 		/*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
124423795512Sdrochner 
124523795512Sdrochner 		dstlin += dst->linelongs;
124623795512Sdrochner 		}
124723795512Sdrochner 	    }
124823795512Sdrochner 	else
124923795512Sdrochner 	    {
125023795512Sdrochner 	    lm = leftmask[dstleftignore];
125123795512Sdrochner 	    rm = rightmask[dstrightignore];
125223795512Sdrochner 	    nrm = ~rm;
125323795512Sdrochner 	    nlm = ~lm;
125423795512Sdrochner 
125523795512Sdrochner 	    while ( dstlin != dstlin2 )
125623795512Sdrochner 		{
125723795512Sdrochner 		dstlong = dstlin;
125823795512Sdrochner 		dstlong2 = dstlong + dstlongs;
125923795512Sdrochner 		if ( dstrightignore != 0 )
126023795512Sdrochner 		    --dstlong2;
126123795512Sdrochner 
126223795512Sdrochner 		/* Leading edge. */
126323795512Sdrochner 		if ( dstleftignore != 0 )
126423795512Sdrochner 		    {
126523795512Sdrochner 		    ROP_DST(
126623795512Sdrochner 		    /*op*/  op,
126723795512Sdrochner 		    /*pre*/ dl = *dstlong;,
126823795512Sdrochner 		    /*d*/   dl,
126923795512Sdrochner 		    /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
127023795512Sdrochner 		    ++dstlong;
127123795512Sdrochner 		    }
127223795512Sdrochner 
127323795512Sdrochner 		/* Main rop. */
127423795512Sdrochner 		ROP_DST(
127523795512Sdrochner 		/*op*/  op,
127623795512Sdrochner 		/*pre*/ while ( dstlong != dstlong2 )
127723795512Sdrochner 			    {,
127823795512Sdrochner 		/*d*/       *dstlong,
127923795512Sdrochner 		/*pst*/     ++dstlong;
128023795512Sdrochner 			    } )
128123795512Sdrochner 
128223795512Sdrochner 		/* Trailing edge. */
128323795512Sdrochner 		if ( dstrightignore != 0 )
128423795512Sdrochner 		    {
128523795512Sdrochner 		    ROP_DST(
128623795512Sdrochner 		    /*op*/  op,
128723795512Sdrochner 		    /*pre*/ dl = *dstlong;,
128823795512Sdrochner 		    /*d*/   dl,
128923795512Sdrochner 		    /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
129023795512Sdrochner 		    }
129123795512Sdrochner 
129223795512Sdrochner 		dstlin += dst->linelongs;
129323795512Sdrochner 		}
129423795512Sdrochner 	    }
129523795512Sdrochner 	}
129623795512Sdrochner #endif /* RCONS_2BPP */
1297d617933eSscottr #ifdef RCONS_4BPP
1298d617933eSscottr     else if ( dst->depth == 4 )
1299d617933eSscottr 	{
1300d617933eSscottr 	/* Two-bit no-src blit. */
1301169ac5b3Saugustss 	u_int32_t color;
1302d617933eSscottr 	u_int32_t* dstlin1;
1303d617933eSscottr 	u_int32_t* dstlin2;
1304d617933eSscottr 	u_int32_t* dstlin;
1305d617933eSscottr 	int dstleftignore, dstrightignore, dstlongs;
1306d617933eSscottr 	u_int32_t dl, lm, nlm, rm, nrm;
1307169ac5b3Saugustss 	u_int32_t* dstlong2;
1308169ac5b3Saugustss 	u_int32_t* dstlong;
1309d617933eSscottr 
1310d617933eSscottr 	dstlin1 = RAS_ADDR( dst, dx, dy );
1311d617933eSscottr 
1312d617933eSscottr #ifdef BCOPY_FASTER
1313d617933eSscottr 	/* Special-case full-width clears. */
1314d617933eSscottr 	if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 3 )
1315d617933eSscottr 	    {
1316c363a9cbScegger 	    memset( (char*) dstlin1, 0, h * dst->linelongs * sizeof(u_int32_t) );
1317d617933eSscottr 	    return 0;
1318d617933eSscottr 	    }
1319d617933eSscottr #endif /*BCOPY_FASTER*/
1320d617933eSscottr 
1321d617933eSscottr 	color = RAS_GETCOLOR( rop );
1322d617933eSscottr 	if ( color == 0 )
1323d617933eSscottr 	    color = 15;
1324d617933eSscottr 
1325d617933eSscottr 	/* Make 32 bits of color so we can do the ROP without shifting. */
1326d617933eSscottr 	color |= (( color << 28 ) | ( color << 24 )
1327d617933eSscottr 		  | ( color << 20 ) | ( color << 16 )
1328d617933eSscottr 		  | ( color << 12 ) | ( color << 8 )
1329d617933eSscottr 		  | ( color << 4 ));
1330d617933eSscottr 
1331d617933eSscottr 	dstleftignore = ( dx & 7 ) * 4;
1332d617933eSscottr 	dstlongs = ( dstleftignore + w * 4 + 31 ) >> 5;
1333d617933eSscottr 	dstrightignore = ( dstlongs * 32 - w * 4 - dstleftignore ) & 31;
1334d617933eSscottr 
1335d617933eSscottr 	dstlin2 = dstlin1 + h * dst->linelongs;
1336d617933eSscottr 	dstlin = dstlin1;
1337d617933eSscottr 
1338d617933eSscottr 	if ( dstlongs == 1 )
1339d617933eSscottr 	    {
1340d617933eSscottr 	    /* It fits into a single longword. */
1341d617933eSscottr 	    lm = leftmask[dstleftignore] | rightmask[dstrightignore];
1342d617933eSscottr 	    nlm = ~lm;
1343d617933eSscottr 	    while ( dstlin != dstlin2 )
1344d617933eSscottr 		{
1345d617933eSscottr 		ROP_DST(
1346d617933eSscottr 		/*op*/  op,
1347d617933eSscottr 		/*pre*/ dl = *dstlin;,
1348d617933eSscottr 		/*d*/   dl,
1349d617933eSscottr 		/*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
1350d617933eSscottr 
1351d617933eSscottr 		dstlin += dst->linelongs;
1352d617933eSscottr 		}
1353d617933eSscottr 	    }
1354d617933eSscottr 	else
1355d617933eSscottr 	    {
1356d617933eSscottr 	    lm = leftmask[dstleftignore];
1357d617933eSscottr 	    rm = rightmask[dstrightignore];
1358d617933eSscottr 	    nrm = ~rm;
1359d617933eSscottr 	    nlm = ~lm;
1360d617933eSscottr 
1361d617933eSscottr 	    while ( dstlin != dstlin2 )
1362d617933eSscottr 		{
1363d617933eSscottr 		dstlong = dstlin;
1364d617933eSscottr 		dstlong2 = dstlong + dstlongs;
1365d617933eSscottr 		if ( dstrightignore != 0 )
1366d617933eSscottr 		    --dstlong2;
1367d617933eSscottr 
1368d617933eSscottr 		/* Leading edge. */
1369d617933eSscottr 		if ( dstleftignore != 0 )
1370d617933eSscottr 		    {
1371d617933eSscottr 		    ROP_DST(
1372d617933eSscottr 		    /*op*/  op,
1373d617933eSscottr 		    /*pre*/ dl = *dstlong;,
1374d617933eSscottr 		    /*d*/   dl,
1375d617933eSscottr 		    /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
1376d617933eSscottr 		    ++dstlong;
1377d617933eSscottr 		    }
1378d617933eSscottr 
1379d617933eSscottr 		/* Main rop. */
1380d617933eSscottr 		ROP_DST(
1381d617933eSscottr 		/*op*/  op,
1382d617933eSscottr 		/*pre*/ while ( dstlong != dstlong2 )
1383d617933eSscottr 			    {,
1384d617933eSscottr 		/*d*/       *dstlong,
1385d617933eSscottr 		/*pst*/     ++dstlong;
1386d617933eSscottr 			    } )
1387d617933eSscottr 
1388d617933eSscottr 		/* Trailing edge. */
1389d617933eSscottr 		if ( dstrightignore != 0 )
1390d617933eSscottr 		    {
1391d617933eSscottr 		    ROP_DST(
1392d617933eSscottr 		    /*op*/  op,
1393d617933eSscottr 		    /*pre*/ dl = *dstlong;,
1394d617933eSscottr 		    /*d*/   dl,
1395d617933eSscottr 		    /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
1396d617933eSscottr 		    }
1397d617933eSscottr 
1398d617933eSscottr 		dstlin += dst->linelongs;
1399d617933eSscottr 		}
1400d617933eSscottr 	    }
1401d617933eSscottr 	}
1402d617933eSscottr #endif /* RCONS_4BPP */
14039d326d48Sdbj     else if ( dst->depth == 8)
1404a8e925d3Spk 	{
1405a8e925d3Spk 	/* Eight-bit no-src blit. */
1406169ac5b3Saugustss 	u_int32_t color;
1407540ab1b8Scgd 	u_int32_t* dstlin1;
1408540ab1b8Scgd 	u_int32_t* dstlin2;
1409540ab1b8Scgd 	u_int32_t* dstlin;
1410a8e925d3Spk 	int dstleftignore, dstrightignore, dstlongs;
1411540ab1b8Scgd 	u_int32_t dl, lm, nlm, rm, nrm;
1412169ac5b3Saugustss 	u_int32_t* dstlong2;
1413169ac5b3Saugustss 	u_int32_t* dstlong;
1414a8e925d3Spk 
1415a8e925d3Spk 	dstlin1 = RAS_ADDR( dst, dx, dy );
1416a8e925d3Spk 
1417a8e925d3Spk #ifdef BCOPY_FASTER
1418a8e925d3Spk 	/* Special-case full-width clears. */
1419a8e925d3Spk 	if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 2 )
1420a8e925d3Spk 	    {
1421c363a9cbScegger 	    memset( (char*) dstlin1, 0, h * dst->linelongs * sizeof(u_int32_t) );
1422a8e925d3Spk 	    return 0;
1423a8e925d3Spk 	    }
1424a8e925d3Spk #endif /*BCOPY_FASTER*/
1425a8e925d3Spk 
1426a8e925d3Spk 	color = RAS_GETCOLOR( rop );
1427a8e925d3Spk 	if ( color == 0 )
1428a8e925d3Spk 	    color = 255;
1429a8e925d3Spk 
1430a8e925d3Spk 	/* Make 32 bits of color so we can do the ROP without shifting. */
1431a8e925d3Spk 	color |= ( color << 24 ) | ( color << 16 ) | ( color << 8 );
1432a8e925d3Spk 
1433a8e925d3Spk 	dstleftignore = ( dx & 3 ) * 8;
1434a8e925d3Spk 	dstlongs = ( dstleftignore + w * 8 + 31 ) >> 5;
1435a8e925d3Spk 	dstrightignore = ( dstlongs * 32 - w * 8 - dstleftignore ) & 31;
1436a8e925d3Spk 
1437a8e925d3Spk 	dstlin2 = dstlin1 + h * dst->linelongs;
1438a8e925d3Spk 	dstlin = dstlin1;
1439a8e925d3Spk 
1440a8e925d3Spk 	if ( dstlongs == 1 )
1441a8e925d3Spk 	    {
1442a8e925d3Spk 	    /* It fits into a single longword. */
1443a8e925d3Spk 	    lm = leftmask[dstleftignore] | rightmask[dstrightignore];
1444a8e925d3Spk 	    nlm = ~lm;
1445a8e925d3Spk 	    while ( dstlin != dstlin2 )
1446a8e925d3Spk 		{
1447a8e925d3Spk 		ROP_DSTCOLOR(
1448a8e925d3Spk 		/*op*/  op,
1449a8e925d3Spk 		/*pre*/ dl = *dstlin;,
1450a8e925d3Spk 		/*d*/   dl,
1451a8e925d3Spk 		/*c*/	color,
1452a8e925d3Spk 		/*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
1453a8e925d3Spk 
1454a8e925d3Spk 		dstlin += dst->linelongs;
1455a8e925d3Spk 		}
1456a8e925d3Spk 	    }
1457a8e925d3Spk 	else
1458a8e925d3Spk 	    {
1459a8e925d3Spk 	    lm = leftmask[dstleftignore];
1460a8e925d3Spk 	    rm = rightmask[dstrightignore];
1461a8e925d3Spk 	    nrm = ~rm;
1462a8e925d3Spk 	    nlm = ~lm;
1463a8e925d3Spk 	    while ( dstlin != dstlin2 )
1464a8e925d3Spk 		{
1465a8e925d3Spk 		dstlong = dstlin;
1466a8e925d3Spk 		dstlong2 = dstlong + dstlongs;
1467a8e925d3Spk 		if ( dstrightignore != 0 )
1468a8e925d3Spk 		    --dstlong2;
1469a8e925d3Spk 
1470a8e925d3Spk 		/* Leading edge. */
1471a8e925d3Spk 		if ( dstleftignore != 0 )
1472a8e925d3Spk 		    {
1473a8e925d3Spk 		    ROP_DSTCOLOR(
1474a8e925d3Spk 		    /*op*/  op,
1475a8e925d3Spk 		    /*pre*/ dl = *dstlong;,
1476a8e925d3Spk 		    /*d*/   dl,
1477a8e925d3Spk 		    /*c*/   color,
1478a8e925d3Spk 		    /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
1479a8e925d3Spk 		    ++dstlong;
1480a8e925d3Spk 		    }
1481a8e925d3Spk 
1482a8e925d3Spk 		/* Main rop. */
1483a8e925d3Spk 		ROP_DSTCOLOR(
1484a8e925d3Spk 		/*op*/  op,
1485a8e925d3Spk 		/*pre*/ while ( dstlong != dstlong2 )
1486a8e925d3Spk 			    {,
1487a8e925d3Spk 		/*d*/       *dstlong,
1488a8e925d3Spk 		/*c*/       color,
1489a8e925d3Spk 		/*pst*/     ++dstlong;
1490a8e925d3Spk 			    } )
1491a8e925d3Spk 
1492a8e925d3Spk 		/* Trailing edge. */
1493a8e925d3Spk 		if ( dstrightignore != 0 )
1494a8e925d3Spk 		    {
1495a8e925d3Spk 		    ROP_DSTCOLOR(
1496a8e925d3Spk 		    /*op*/  op,
1497a8e925d3Spk 		    /*pre*/ dl = *dstlong;,
1498a8e925d3Spk 		    /*d*/   dl,
1499a8e925d3Spk 		    /*c*/   color,
1500a8e925d3Spk 		    /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
1501a8e925d3Spk 		    }
1502a8e925d3Spk 
1503a8e925d3Spk 		dstlin += dst->linelongs;
1504a8e925d3Spk 		}
1505a8e925d3Spk 	    }
1506a8e925d3Spk 	}
15079d326d48Sdbj #ifdef RCONS_16BPP
15089d326d48Sdbj     else
15099d326d48Sdbj 	{
15109d326d48Sdbj 	/* Sixteen-bit no-src blit. */
1511169ac5b3Saugustss 	u_int32_t color;
15129d326d48Sdbj 	u_int32_t* dstlin1;
15139d326d48Sdbj 	u_int32_t* dstlin2;
15149d326d48Sdbj 	u_int32_t* dstlin;
15159d326d48Sdbj 	int dstleftignore, dstrightignore, dstlongs;
15169d326d48Sdbj 	u_int32_t dl, lm, nlm, rm, nrm;
1517169ac5b3Saugustss 	u_int32_t* dstlong2;
1518169ac5b3Saugustss 	u_int32_t* dstlong;
15199d326d48Sdbj 
15209d326d48Sdbj 	dstlin1 = RAS_ADDR( dst, dx, dy );
15219d326d48Sdbj 
15229d326d48Sdbj #ifdef BCOPY_FASTER
15239d326d48Sdbj 	/* Special-case full-width clears. */
15249d326d48Sdbj 	if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 1 )
15259d326d48Sdbj 	    {
1526c363a9cbScegger 	    memset( (char*) dstlin1, 0, h * dst->linelongs * sizeof(u_int32_t) );
15279d326d48Sdbj 	    return 0;
15289d326d48Sdbj 	    }
15299d326d48Sdbj #endif /*BCOPY_FASTER*/
15309d326d48Sdbj 
15319d326d48Sdbj 	color = RAS_GETCOLOR( rop );
15329d326d48Sdbj 	if ( color == 0 )
15339a37177dSdeberg 		color = 0xffff; /* XXX */
15349d326d48Sdbj 
15359d326d48Sdbj 	/* Make 32 bits of color so we can do the ROP without shifting. */
15369d326d48Sdbj 	color |= ( color << 16 );
15379d326d48Sdbj 
15389d326d48Sdbj 	dstleftignore = ( dx & 1 ) * 16;
15399d326d48Sdbj 	dstlongs = ( dstleftignore + w * 16 + 31 ) >> 5;
15409d326d48Sdbj 	dstrightignore = ( dstlongs * 32 - w * 8 - dstleftignore ) & 31;
15419d326d48Sdbj 
15429d326d48Sdbj 	dstlin2 = dstlin1 + h * dst->linelongs;
15439d326d48Sdbj 	dstlin = dstlin1;
15449d326d48Sdbj 
15459d326d48Sdbj 	if ( dstlongs == 1 )
15469d326d48Sdbj 	    {
15479d326d48Sdbj 	    /* It fits into a single longword. */
15489d326d48Sdbj 	    lm = leftmask[dstleftignore] | rightmask[dstrightignore];
15499d326d48Sdbj 	    nlm = ~lm;
15509d326d48Sdbj 	    while ( dstlin != dstlin2 )
15519d326d48Sdbj 		{
15529d326d48Sdbj 		ROP_DSTCOLOR(
15539d326d48Sdbj 		/*op*/  op,
15549d326d48Sdbj 		/*pre*/ dl = *dstlin;,
15559d326d48Sdbj 		/*d*/   dl,
15569d326d48Sdbj 		/*c*/	color,
15579d326d48Sdbj 		/*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
15589d326d48Sdbj 
15599d326d48Sdbj 		dstlin += dst->linelongs;
15609d326d48Sdbj 		}
15619d326d48Sdbj 	    }
15629d326d48Sdbj 	else
15639d326d48Sdbj 	    {
15649d326d48Sdbj 	    lm = leftmask[dstleftignore];
15659d326d48Sdbj 	    rm = rightmask[dstrightignore];
15669d326d48Sdbj 	    nrm = ~rm;
15679d326d48Sdbj 	    nlm = ~lm;
15689d326d48Sdbj 	    while ( dstlin != dstlin2 )
15699d326d48Sdbj 		{
15709d326d48Sdbj 		dstlong = dstlin;
15719d326d48Sdbj 		dstlong2 = dstlong + dstlongs;
15729d326d48Sdbj 		if ( dstrightignore != 0 )
15739d326d48Sdbj 		    --dstlong2;
15749d326d48Sdbj 
15759d326d48Sdbj 		/* Leading edge. */
15769d326d48Sdbj 		if ( dstleftignore != 0 )
15779d326d48Sdbj 		    {
15789d326d48Sdbj 		    ROP_DSTCOLOR(
15799d326d48Sdbj 		    /*op*/  op,
15809d326d48Sdbj 		    /*pre*/ dl = *dstlong;,
15819d326d48Sdbj 		    /*d*/   dl,
15829d326d48Sdbj 		    /*c*/   color,
15839d326d48Sdbj 		    /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
15849d326d48Sdbj 		    ++dstlong;
15859d326d48Sdbj 		    }
15869d326d48Sdbj 
15879d326d48Sdbj 		/* Main rop. */
15889d326d48Sdbj 		ROP_DSTCOLOR(
15899d326d48Sdbj 		/*op*/  op,
15909d326d48Sdbj 		/*pre*/ while ( dstlong != dstlong2 )
15919d326d48Sdbj 			    {,
15929d326d48Sdbj 		/*d*/       *dstlong,
15939d326d48Sdbj 		/*c*/       color,
15949d326d48Sdbj 		/*pst*/     ++dstlong;
15959d326d48Sdbj 			    } )
15969d326d48Sdbj 
15979d326d48Sdbj 		/* Trailing edge. */
15989d326d48Sdbj 		if ( dstrightignore != 0 )
15999d326d48Sdbj 		    {
16009d326d48Sdbj 		    ROP_DSTCOLOR(
16019d326d48Sdbj 		    /*op*/  op,
16029d326d48Sdbj 		    /*pre*/ dl = *dstlong;,
16039d326d48Sdbj 		    /*d*/   dl,
16049d326d48Sdbj 		    /*c*/   color,
16059d326d48Sdbj 		    /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
16069d326d48Sdbj 		    }
16079d326d48Sdbj 
16089d326d48Sdbj 		dstlin += dst->linelongs;
16099d326d48Sdbj 		}
16109d326d48Sdbj 	    }
16119d326d48Sdbj 	}
16129d326d48Sdbj #endif /* RCONS_16BPP */
1613a8e925d3Spk 
1614a8e925d3Spk     return 0;
1615a8e925d3Spk     }
1616a8e925d3Spk 
1617a8e925d3Spk /* This is a general bitblit routine, handling overlapping source and
1618a8e925d3Spk ** destination.  It's used for both the 1-to-1 and 8-to-8 cases.
1619a8e925d3Spk */
1620a8e925d3Spk static int
raster_blit(struct raster * src,uint32_t * srclin1,int srcleftignore,int srcrightignore,int srclongs,struct raster * dst,uint32_t * dstlin1,int dstleftignore,int dstrightignore,int dstlongs,int h,int op)1621*91d94812Smatt raster_blit(
1622*91d94812Smatt     struct raster* src, uint32_t* srclin1,
1623*91d94812Smatt     int srcleftignore, int srcrightignore, int srclongs,
1624*91d94812Smatt     struct raster* dst,
1625*91d94812Smatt     uint32_t* dstlin1,
1626*91d94812Smatt     int dstleftignore, int dstrightignore, int dstlongs,
1627*91d94812Smatt     int h, int op)
1628a8e925d3Spk     {
1629540ab1b8Scgd     u_int32_t* srclin2;
1630540ab1b8Scgd     u_int32_t* dstlin2;
1631a8e925d3Spk     int srclininc, dstlininc;
1632540ab1b8Scgd     u_int32_t* srclin;
1633540ab1b8Scgd     u_int32_t* dstlin;
1634169ac5b3Saugustss     int prevleftshift, currrightshift;
1635a8e925d3Spk     int longinc;
1636169ac5b3Saugustss     u_int32_t* srclong;
1637169ac5b3Saugustss     u_int32_t* dstlong;
1638169ac5b3Saugustss     u_int32_t* dstlong2;
1639169ac5b3Saugustss     u_int32_t dl, lm, nlm, rm, nrm;
1640a8e925d3Spk 
1641a8e925d3Spk     prevleftshift = ( srcleftignore - dstleftignore ) & 31;
1642a8e925d3Spk 
1643a8e925d3Spk     srclin2 = srclin1 + h * src->linelongs;
1644a8e925d3Spk     dstlin2 = dstlin1 + h * dst->linelongs;
1645a8e925d3Spk     srclininc = src->linelongs;
1646a8e925d3Spk     dstlininc = dst->linelongs;
1647a8e925d3Spk     longinc = 1;
1648a8e925d3Spk 
1649a8e925d3Spk     /* Check for overlaps. */
1650a8e925d3Spk     if ( ( dstlin1 >= srclin1 && dstlin1 < srclin1 + srclongs ) ||
1651a8e925d3Spk 	 ( srclin1 >= dstlin1 && srclin1 < dstlin1 + dstlongs ) )
1652a8e925d3Spk 	{
1653a8e925d3Spk 	/* Horizontal overlap.  Should we reverse? */
1654a8e925d3Spk 	if ( srclin1 < dstlin1 )
1655a8e925d3Spk 	    {
1656a8e925d3Spk 	    longinc = -1;
1657a8e925d3Spk 	    srclin1 += srclongs - 1;
1658a8e925d3Spk 	    srclin2 += srclongs - 1;
1659a8e925d3Spk 	    dstlin1 += dstlongs - 1;
1660a8e925d3Spk 	    }
1661a8e925d3Spk 	}
1662a8e925d3Spk     else if ( ( dstlin1 >= srclin1 && dstlin1 < srclin2 ) ||
1663a8e925d3Spk 	      ( srclin1 >= dstlin1 && srclin1 < dstlin2 ) )
1664a8e925d3Spk 	{
1665a8e925d3Spk 	/* Vertical overlap.  Should we reverse? */
1666a8e925d3Spk 	if ( srclin1 < dstlin1 )
1667a8e925d3Spk 	    {
1668a8e925d3Spk 	    srclin2 = srclin1 - srclininc;
1669a8e925d3Spk 	    srclin1 += ( h - 1 ) * srclininc;
1670a8e925d3Spk 	    dstlin1 += ( h - 1 ) * dstlininc;
1671a8e925d3Spk 	    srclininc = -srclininc;
1672a8e925d3Spk 	    dstlininc = -dstlininc;
1673a8e925d3Spk 	    }
1674a8e925d3Spk 	}
1675a8e925d3Spk     srclin = srclin1;
1676a8e925d3Spk     dstlin = dstlin1;
1677a8e925d3Spk 
1678a8e925d3Spk     if ( prevleftshift == 0 )
1679a8e925d3Spk 	{
1680a8e925d3Spk 	/* The bits line up, no shifting necessary. */
1681a8e925d3Spk 	if ( dstlongs == 1 )
1682a8e925d3Spk 	    {
1683a8e925d3Spk 	    /* It all fits into a single longword. */
1684a8e925d3Spk 	    lm = leftmask[dstleftignore] | rightmask[dstrightignore];
1685a8e925d3Spk 	    nlm = ~lm;
1686a8e925d3Spk 	    while ( srclin != srclin2 )
1687a8e925d3Spk 		{
1688a8e925d3Spk 		ROP_SRCDST(
1689a8e925d3Spk 		/*op*/  op,
1690a8e925d3Spk 		/*pre*/ dl = *dstlin;,
1691a8e925d3Spk 		/*s*/   *srclin,
1692a8e925d3Spk 		/*d*/   dl,
1693a8e925d3Spk 		/*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
1694a8e925d3Spk 
1695a8e925d3Spk 		srclin += srclininc;
1696a8e925d3Spk 		dstlin += dstlininc;
1697a8e925d3Spk 		}
1698a8e925d3Spk 	    }
1699a8e925d3Spk 	else
1700a8e925d3Spk 	    {
1701a8e925d3Spk 	    /* Multiple longwords. */
1702a8e925d3Spk 	    lm = leftmask[dstleftignore];
1703a8e925d3Spk 	    rm = rightmask[dstrightignore];
1704a8e925d3Spk 	    nrm = ~rm;
1705a8e925d3Spk 	    nlm = ~lm;
1706a8e925d3Spk 	    if ( longinc == 1 )
1707a8e925d3Spk 		{
1708a8e925d3Spk 		/* Left to right. */
1709a8e925d3Spk 		while ( srclin != srclin2 )
1710a8e925d3Spk 		    {
1711a8e925d3Spk 		    srclong = srclin;
1712a8e925d3Spk 		    dstlong = dstlin;
1713a8e925d3Spk 		    dstlong2 = dstlong + dstlongs;
1714a8e925d3Spk 		    if ( dstrightignore != 0 )
1715a8e925d3Spk 			--dstlong2;
1716a8e925d3Spk 
1717a8e925d3Spk 		    /* Leading edge. */
1718a8e925d3Spk 		    if ( dstleftignore != 0 )
1719a8e925d3Spk 			{
1720a8e925d3Spk 			ROP_SRCDST(
1721a8e925d3Spk 			/*op*/  op,
1722a8e925d3Spk 			/*pre*/ dl = *dstlong;,
1723a8e925d3Spk 			/*s*/   *srclong,
1724a8e925d3Spk 			/*d*/   dl,
1725a8e925d3Spk 			/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
1726a8e925d3Spk 			++srclong;
1727a8e925d3Spk 			++dstlong;
1728a8e925d3Spk 			}
1729a8e925d3Spk 
1730a8e925d3Spk 		    /* Main rop. */
1731a8e925d3Spk 		    ROP_SRCDST(
1732a8e925d3Spk 		    /*op*/  op,
1733a8e925d3Spk 		    /*pre*/ while ( dstlong != dstlong2 )
1734a8e925d3Spk 				{,
1735a8e925d3Spk 		    /*s*/       *srclong,
1736a8e925d3Spk 		    /*d*/       *dstlong,
1737a8e925d3Spk 		    /*pst*/     ++srclong;
1738a8e925d3Spk 				++dstlong;
1739a8e925d3Spk 				} )
1740a8e925d3Spk 
1741a8e925d3Spk 		    /* Trailing edge. */
1742a8e925d3Spk 		    if ( dstrightignore != 0 )
1743a8e925d3Spk 			{
1744a8e925d3Spk 			ROP_SRCDST(
1745a8e925d3Spk 			/*op*/  op,
1746a8e925d3Spk 			/*pre*/ dl = *dstlong;,
1747a8e925d3Spk 			/*s*/   *srclong,
1748a8e925d3Spk 			/*d*/   dl,
1749a8e925d3Spk 			/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
1750a8e925d3Spk 			}
1751a8e925d3Spk 
1752a8e925d3Spk 		    srclin += srclininc;
1753a8e925d3Spk 		    dstlin += dstlininc;
1754a8e925d3Spk 		    }
1755a8e925d3Spk 		}
1756a8e925d3Spk 	    else
1757a8e925d3Spk 		{
1758a8e925d3Spk 		/* Right to left. */
1759a8e925d3Spk 		while ( srclin != srclin2 )
1760a8e925d3Spk 		    {
1761a8e925d3Spk 		    srclong = srclin;
1762a8e925d3Spk 		    dstlong = dstlin;
1763a8e925d3Spk 		    dstlong2 = dstlong - dstlongs;
1764a8e925d3Spk 		    if ( dstleftignore != 0 )
1765a8e925d3Spk 			++dstlong2;
1766a8e925d3Spk 
1767a8e925d3Spk 		    /* Leading edge. */
1768a8e925d3Spk 		    if ( dstrightignore != 0 )
1769a8e925d3Spk 			{
1770a8e925d3Spk 			ROP_SRCDST(
1771a8e925d3Spk 			/*op*/  op,
1772a8e925d3Spk 			/*pre*/ dl = *dstlong;,
1773a8e925d3Spk 			/*s*/   *srclong,
1774a8e925d3Spk 			/*d*/   dl,
1775a8e925d3Spk 			/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
1776a8e925d3Spk 			--srclong;
1777a8e925d3Spk 			--dstlong;
1778a8e925d3Spk 			}
1779a8e925d3Spk 
1780a8e925d3Spk 		    /* Main rop. */
1781a8e925d3Spk 		    ROP_SRCDST(
1782a8e925d3Spk 		    /*op*/  op,
1783a8e925d3Spk 		    /*pre*/ while ( dstlong != dstlong2 )
1784a8e925d3Spk 				{,
1785a8e925d3Spk 		    /*s*/       *srclong,
1786a8e925d3Spk 		    /*d*/       *dstlong,
1787a8e925d3Spk 		    /*pst*/     --srclong;
1788a8e925d3Spk 				--dstlong;
1789a8e925d3Spk 				} )
1790a8e925d3Spk 
1791a8e925d3Spk 		    /* Trailing edge. */
1792a8e925d3Spk 		    if ( dstleftignore != 0 )
1793a8e925d3Spk 			{
1794a8e925d3Spk 			ROP_SRCDST(
1795a8e925d3Spk 			/*op*/  op,
1796a8e925d3Spk 			/*pre*/ dl = *dstlong;,
1797a8e925d3Spk 			/*s*/   *srclong,
1798a8e925d3Spk 			/*d*/   dl,
1799a8e925d3Spk 			/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
1800a8e925d3Spk 			}
1801a8e925d3Spk 
1802a8e925d3Spk 		    srclin += srclininc;
1803a8e925d3Spk 		    dstlin += dstlininc;
1804a8e925d3Spk 		    }
1805a8e925d3Spk 		}
1806a8e925d3Spk 	    }
1807a8e925d3Spk 	}
1808a8e925d3Spk 
1809a8e925d3Spk     else
1810a8e925d3Spk 	{
1811a8e925d3Spk 	/* General case, with shifting and everything. */
1812169ac5b3Saugustss 	u_int32_t sl, prevsl;
1813a8e925d3Spk 
1814a8e925d3Spk 	currrightshift = 32 - prevleftshift;
1815a8e925d3Spk 	if ( srclongs == 1 && dstlongs == 1 )
1816a8e925d3Spk 	    {
1817a8e925d3Spk 	    /* It fits into a single longword, with a shift. */
1818a8e925d3Spk 	    lm = leftmask[dstleftignore] | rightmask[dstrightignore];
1819a8e925d3Spk 	    nlm = ~lm;
1820a8e925d3Spk 	    if ( srcleftignore > dstleftignore )
1821a8e925d3Spk 		{
1822a8e925d3Spk 		while ( srclin != srclin2 )
1823a8e925d3Spk 		    {
1824a8e925d3Spk 		    ROP_SRCDST(
1825a8e925d3Spk 		    /*op*/  op,
1826a8e925d3Spk 		    /*pre*/ dl = *dstlin;,
18273b2862c8Spk 		    /*s*/   *srclin LSOP prevleftshift,
1828a8e925d3Spk 		    /*d*/   dl,
1829a8e925d3Spk 		    /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
1830a8e925d3Spk 
1831a8e925d3Spk 		    srclin += srclininc;
1832a8e925d3Spk 		    dstlin += dstlininc;
1833a8e925d3Spk 		    }
1834a8e925d3Spk 		}
1835a8e925d3Spk 	    else
1836a8e925d3Spk 		{
1837a8e925d3Spk 		while ( srclin != srclin2 )
1838a8e925d3Spk 		    {
1839a8e925d3Spk 		    ROP_SRCDST(
1840a8e925d3Spk 		    /*op*/  op,
1841a8e925d3Spk 		    /*pre*/ dl = *dstlin;,
18423b2862c8Spk 		    /*s*/   *srclin RSOP currrightshift,
1843a8e925d3Spk 		    /*d*/   dl,
1844a8e925d3Spk 		    /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
1845a8e925d3Spk 
1846a8e925d3Spk 		    srclin += srclininc;
1847a8e925d3Spk 		    dstlin += dstlininc;
1848a8e925d3Spk 		    }
1849a8e925d3Spk 		}
1850a8e925d3Spk 	    }
1851a8e925d3Spk 	else
1852a8e925d3Spk 	    {
1853a8e925d3Spk 	    /* Multiple longwords. */
1854a8e925d3Spk 	    lm = leftmask[dstleftignore];
1855a8e925d3Spk 	    rm = rightmask[dstrightignore];
1856a8e925d3Spk 	    nrm = ~rm;
1857a8e925d3Spk 	    nlm = ~lm;
1858a8e925d3Spk 	    if ( longinc == 1 )
1859a8e925d3Spk 		{
1860a8e925d3Spk 		/* Left to right. */
1861a8e925d3Spk 		while ( srclin != srclin2 )
1862a8e925d3Spk 		    {
1863a8e925d3Spk 		    srclong = srclin;
1864a8e925d3Spk 		    dstlong = dstlin;
1865a8e925d3Spk 		    dstlong2 = dstlong + dstlongs;
1866a8e925d3Spk 		    if ( srcleftignore > dstleftignore )
18673b2862c8Spk 			prevsl = *srclong++ LSOP prevleftshift;
1868a8e925d3Spk 		    else
1869a8e925d3Spk 			prevsl = 0;
1870a8e925d3Spk 		    if ( dstrightignore != 0 )
1871a8e925d3Spk 			--dstlong2;
1872a8e925d3Spk 
1873a8e925d3Spk 		    /* Leading edge. */
1874a8e925d3Spk 		    if ( dstleftignore != 0 )
1875a8e925d3Spk 			{
1876a8e925d3Spk 			ROP_SRCDST(
1877a8e925d3Spk 			/*op*/  op,
1878a8e925d3Spk 			/*pre*/ sl = *srclong;
1879a8e925d3Spk 				dl = *dstlong;,
18803b2862c8Spk 			/*s*/   prevsl | ( sl RSOP currrightshift ),
1881a8e925d3Spk 			/*d*/   dl,
1882a8e925d3Spk 			/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
1883f64a09cfSthorpej 			prevsl = sl LSOP prevleftshift;
1884a8e925d3Spk 			++srclong;
1885a8e925d3Spk 			++dstlong;
1886a8e925d3Spk 			}
1887a8e925d3Spk 
1888a8e925d3Spk 		    /* Main rop. */
1889a8e925d3Spk 		    ROP_SRCDST(
1890a8e925d3Spk 		    /*op*/  op,
1891a8e925d3Spk 		    /*pre*/ while ( dstlong != dstlong2 )
1892a8e925d3Spk 				{
1893a8e925d3Spk 				sl = *srclong;,
18943b2862c8Spk 		    /*s*/       prevsl | ( sl RSOP currrightshift ),
1895a8e925d3Spk 		    /*d*/       *dstlong,
18963b2862c8Spk 		    /*pst*/     prevsl = sl LSOP prevleftshift;
1897a8e925d3Spk 				++srclong;
1898a8e925d3Spk 				++dstlong;
1899a8e925d3Spk 				} )
1900a8e925d3Spk 
1901a8e925d3Spk 		    /* Trailing edge. */
1902a8e925d3Spk 		    if ( dstrightignore != 0 )
1903a8e925d3Spk 			{
1904a8e925d3Spk 			ROP_SRCDST(
1905a8e925d3Spk 			/*op*/  op,
1906a8e925d3Spk 			/*pre*/ dl = *dstlong;,
19073b2862c8Spk 			/*s*/   prevsl | ( *srclong RSOP currrightshift ),
1908a8e925d3Spk 			/*d*/   dl,
1909a8e925d3Spk 			/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
1910a8e925d3Spk 			}
1911a8e925d3Spk 
1912a8e925d3Spk 		    srclin += srclininc;
1913a8e925d3Spk 		    dstlin += dstlininc;
1914a8e925d3Spk 		    }
1915a8e925d3Spk 		}
1916a8e925d3Spk 	    else
1917a8e925d3Spk 		{
1918a8e925d3Spk 		/* Right to left. */
1919a8e925d3Spk 		while ( srclin != srclin2 )
1920a8e925d3Spk 		    {
1921a8e925d3Spk 		    srclong = srclin;
1922a8e925d3Spk 		    dstlong = dstlin;
1923a8e925d3Spk 		    dstlong2 = dstlong - dstlongs;
1924a8e925d3Spk 		    if ( srcrightignore > dstrightignore )
19253b2862c8Spk 			prevsl = *srclong-- RSOP currrightshift;
1926a8e925d3Spk 		    else
1927a8e925d3Spk 			prevsl = 0;
1928a8e925d3Spk 		    if ( dstleftignore != 0 )
1929a8e925d3Spk 			++dstlong2;
1930a8e925d3Spk 
1931a8e925d3Spk 		    /* Leading edge. */
1932a8e925d3Spk 		    if ( dstrightignore != 0 )
1933a8e925d3Spk 			{
1934a8e925d3Spk 			ROP_SRCDST(
1935a8e925d3Spk 			/*op*/  op,
1936a8e925d3Spk 			/*pre*/ sl = *srclong;
1937a8e925d3Spk 				dl = *dstlong;,
19383b2862c8Spk 			/*s*/   prevsl | ( sl LSOP prevleftshift ),
1939a8e925d3Spk 			/*d*/   dl,
1940a8e925d3Spk 			/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
19413b2862c8Spk 			prevsl = sl RSOP currrightshift;
1942a8e925d3Spk 			--srclong;
1943a8e925d3Spk 			--dstlong;
1944a8e925d3Spk 			}
1945a8e925d3Spk 
1946a8e925d3Spk 		    /* Main rop. */
1947a8e925d3Spk 		    ROP_SRCDST(
1948a8e925d3Spk 		    /*op*/  op,
1949a8e925d3Spk 		    /*pre*/ while ( dstlong != dstlong2 )
1950a8e925d3Spk 				{
1951a8e925d3Spk 				sl = *srclong;,
19523b2862c8Spk 		    /*s*/       prevsl | ( sl LSOP prevleftshift ),
1953a8e925d3Spk 		    /*d*/       *dstlong,
19543b2862c8Spk 		    /*pst*/     prevsl = sl RSOP currrightshift;
1955a8e925d3Spk 				--srclong;
1956a8e925d3Spk 				--dstlong;
1957a8e925d3Spk 				} )
1958a8e925d3Spk 
1959a8e925d3Spk 		    /* Trailing edge. */
1960a8e925d3Spk 		    if ( dstleftignore != 0 )
1961a8e925d3Spk 			{
1962a8e925d3Spk 			ROP_SRCDST(
1963a8e925d3Spk 			/*op*/  op,
1964a8e925d3Spk 			/*pre*/ dl = *dstlong;,
19653b2862c8Spk 			/*s*/   prevsl | ( *srclong LSOP prevleftshift ),
1966a8e925d3Spk 			/*d*/   dl,
1967a8e925d3Spk 			/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
1968a8e925d3Spk 			}
1969a8e925d3Spk 
1970a8e925d3Spk 		    srclin += srclininc;
1971a8e925d3Spk 		    dstlin += dstlininc;
1972a8e925d3Spk 		    }
1973a8e925d3Spk 		}
1974a8e925d3Spk 	    }
1975a8e925d3Spk 	}
1976a8e925d3Spk 
1977a8e925d3Spk     return 0;
1978a8e925d3Spk     }
1979