xref: /original-bsd/sys/sparc/rcons/raster_op.c (revision 860e07fc)
1 /*-
2  * Copyright (c) 1991 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to the Computer Systems
6  * Engineering Group at Lawrence Berkeley Laboratory and to the University
7  * of California at Berkeley by Jef Poskanzer.
8  *
9  * %sccs.include.redist.c%
10  *
11  *	@(#)raster_op.c	7.1 (Berkeley) 07/13/92
12  *
13  * from: $Header: raster_op.c,v 1.22 92/06/17 08:14:44 torek Exp $
14  */
15 
16 /*
17  * Bitblit routine for raster library.
18  *
19  * This raster-op is machined to exacting tolerances by skilled native
20  * craftsmen with pride in their work.
21  *
22  * The various cases are broken down like this:
23  *
24  *   src required
25  *       1-bit to 1-bit
26  *       1-bit to 8-bits
27  *       8-bits to 8-bits
28  *   no src required
29  *       1-bit no-src
30  *       8-bits no-src
31  */
32 
33 #ifdef KERNEL
34 #include "sys/types.h"
35 #else
36 #include <sys/types.h>
37 #endif
38 #include "raster.h"
39 
40 /* CONFIGURE: To save on executable size, you can configure out the seldom-used
41 ** logical operations.  With this variable set, the only operations implemented
42 ** are: RAS_SRC, RAS_CLEAR, RAS_SET, RAS_INVERT, RAS_XOR, RAS_INVERTSRC.
43 */
44 #ifdef KERNEL
45 #define PARTIAL_LOGICAL_OPS
46 #endif
47 
48 /* CONFIGURE: bcopy() is supposed to be the ultimately fastest way to move
49 ** bytes, overlapping or not, ignoring the startup cost.  Unfortunately
50 ** this is not true on some systems.  For example, on a Sun 3 running
51 ** SunOS 3.5, bcopy() is about five times slower than a simple for loop
52 ** on overlapping copies.  And on a 4.1.1 SPARC, bcopy() is about 2/3rds
53 ** as fast on backwards overlaps.  So, only define this if your bcopy is ok.
54 */
55 #undef BCOPY_FASTER
56 
57 /* End of configurable definitions. */
58 
59 
60 /* Definitions. */
61 
62 /* Raster-op macros.  These encapsulate the switch statements and so make
63 ** the source code 16 times smaller.  The pre and pst args are code
64 ** fragments to put before and after the assignment in each case.  They
65 ** can be the beginning and end of a loop.  If the pst fragment includes a
66 ** masked assignment, for example to handle the left or right edge cases,
67 ** a good optimizing compiler will simplify the boolean expressions very
68 ** nicely - both cc and gcc on the SPARC will do this.
69 */
70 
71 #ifndef PARTIAL_LOGICAL_OPS
72 
73 #define ROP_DST(op,pre,d,pst) \
74     switch ( op ) \
75 	{ \
76 	case RAS_CLEAR: \
77 	pre \
78 	(d) = 0; \
79 	pst \
80 	break; \
81 	case RAS_INVERT: \
82 	pre \
83 	(d) = ~(d); \
84 	pst \
85 	break; \
86 	case RAS_DST: \
87 	/* noop */ \
88 	break; \
89 	case RAS_SET: \
90 	pre \
91 	(d) = ~0; \
92 	pst \
93 	break; \
94 	default: \
95 	return -1; \
96 	}
97 
98 #define ROP_DSTCOLOR(op,pre,d,c,pst) \
99     switch ( op ) \
100 	{ \
101 	case RAS_CLEAR: \
102 	pre \
103 	(d) = 0; \
104 	pst \
105 	break; \
106 	case RAS_INVERT: \
107 	pre \
108 	(d) = ~(d); \
109 	pst \
110 	break; \
111 	case RAS_DST: \
112 	/* noop */ \
113 	break; \
114 	case RAS_SET: \
115 	pre \
116 	(d) = (c); \
117 	pst \
118 	break; \
119 	default: \
120 	return -1; \
121 	}
122 
123 #define ROP_SRCDST(op,pre,s,d,pst) \
124     switch ( op ) \
125 	{ \
126 	case RAS_NOTOR: \
127 	pre \
128 	(d) = ~( (s) | (d) ); \
129 	pst \
130 	break; \
131 	case RAS_NOTSRC_AND_DST: \
132 	pre \
133 	(d) = ~(s) & (d); \
134 	pst \
135 	break; \
136 	case RAS_INVERTSRC: \
137 	pre \
138 	(d) = ~(s); \
139 	pst \
140 	break; \
141 	case RAS_SRC_AND_NOTDST: \
142 	pre \
143 	(d) = (s) & ~(d); \
144 	pst \
145 	break; \
146 	case RAS_XOR: \
147 	pre \
148 	(d) = (s) ^ (d); \
149 	pst \
150 	break; \
151 	case RAS_NOTAND: \
152 	pre \
153 	(d) = ~( (s) & (d) ); \
154 	pst \
155 	break; \
156 	case RAS_AND: \
157 	pre \
158 	(d) = (s) & (d); \
159 	pst \
160 	break; \
161 	case RAS_NOTXOR: \
162 	pre \
163 	(d) = ~( (s) ^ (d) ); \
164 	pst \
165 	break; \
166 	case RAS_NOTSRC_OR_DST: \
167 	pre \
168 	(d) = ~(s) | (d); \
169 	pst \
170 	break; \
171 	case RAS_SRC: \
172 	pre \
173 	(d) = (s); \
174 	pst \
175 	break; \
176 	case RAS_SRC_OR_NOTDST: \
177 	pre \
178 	(d) = (s) | ~(d); \
179 	pst \
180 	break; \
181 	case RAS_OR: \
182 	pre \
183 	(d) = (s) | (d); \
184 	pst \
185 	break; \
186 	default: \
187 	return -1; \
188 	}
189 
190 #define ROP_SRCDSTCOLOR(op,pre,s,d,c,pst) \
191     switch ( op ) \
192 	{ \
193 	case RAS_NOTOR: \
194 	pre \
195 	if ( s ) \
196 	    (d) = ~( (c) | (d) ); \
197 	else \
198 	    (d) = ~(d); \
199 	pst \
200 	break; \
201 	case RAS_NOTSRC_AND_DST: \
202 	pre \
203 	if ( s ) \
204 	    (d) = ~(c) & (d); \
205 	pst \
206 	break; \
207 	case RAS_INVERTSRC: \
208 	pre \
209 	if ( s ) \
210 	    (d) = ~(c); \
211 	else \
212 	    (d) = ~0; \
213 	pst \
214 	break; \
215 	case RAS_SRC_AND_NOTDST: \
216 	pre \
217 	if ( s ) \
218 	    (d) = (c) & ~(d); \
219 	else \
220 	    (d) = 0; \
221 	pst \
222 	break; \
223 	case RAS_XOR: \
224 	pre \
225 	if ( s ) \
226 	    (d) = (c) ^ (d); \
227 	pst \
228 	break; \
229 	case RAS_NOTAND: \
230 	pre \
231 	if ( s ) \
232 	    (d) = ~( (c) & (d) ); \
233 	else \
234 	    (d) = ~0; \
235 	pst \
236 	break; \
237 	case RAS_AND: \
238 	pre \
239 	if ( s ) \
240 	    (d) = (c) & (d); \
241 	else \
242 	    (d) = 0; \
243 	pst \
244 	break; \
245 	case RAS_NOTXOR: \
246 	pre \
247 	if ( s ) \
248 	    (d) = ~( (c) ^ (d) ); \
249 	else \
250 	    (d) = ~(d); \
251 	pst \
252 	break; \
253 	case RAS_NOTSRC_OR_DST: \
254 	pre \
255 	if ( s ) \
256 	    (d) = ~(c) | (d); \
257 	else \
258 	    (d) = ~0; \
259 	pst \
260 	break; \
261 	case RAS_SRC: \
262 	pre \
263 	if ( s ) \
264 	    (d) = (c); \
265 	else \
266 	    (d) = 0; \
267 	pst \
268 	break; \
269 	case RAS_SRC_OR_NOTDST: \
270 	pre \
271 	if ( s ) \
272 	    (d) = (c) | ~(d); \
273 	else \
274 	    (d) = ~(d); \
275 	pst \
276 	break; \
277 	case RAS_OR: \
278 	pre \
279 	if ( s ) \
280 	    (d) = (c) | (d); \
281 	pst \
282 	break; \
283 	default: \
284 	return -1; \
285 	}
286 
287 #else /*PARTIAL_LOGICAL_OPS*/
288 
289 #define ROP_DST(op,pre,d,pst) \
290     switch ( op ) \
291 	{ \
292 	case RAS_CLEAR: \
293 	pre \
294 	(d) = 0; \
295 	pst \
296 	break; \
297 	case RAS_INVERT: \
298 	pre \
299 	(d) = ~(d); \
300 	pst \
301 	break; \
302 	case RAS_SET: \
303 	pre \
304 	(d) = ~0; \
305 	pst \
306 	break; \
307 	default: \
308 	return -1; \
309 	}
310 
311 #define ROP_DSTCOLOR(op,pre,d,c,pst) \
312     switch ( op ) \
313 	{ \
314 	case RAS_CLEAR: \
315 	pre \
316 	(d) = 0; \
317 	pst \
318 	break; \
319 	case RAS_INVERT: \
320 	pre \
321 	(d) = ~(d); \
322 	pst \
323 	break; \
324 	case RAS_SET: \
325 	pre \
326 	(d) = (c); \
327 	pst \
328 	break; \
329 	default: \
330 	return -1; \
331 	}
332 
333 #define ROP_SRCDST(op,pre,s,d,pst) \
334     switch ( op ) \
335 	{ \
336 	case RAS_INVERTSRC: \
337 	pre \
338 	(d) = ~(s); \
339 	pst \
340 	break; \
341 	case RAS_XOR: \
342 	pre \
343 	(d) = (s) ^ (d); \
344 	pst \
345 	break; \
346 	case RAS_SRC: \
347 	pre \
348 	(d) = (s); \
349 	pst \
350 	break; \
351 	default: \
352 	return -1; \
353 	}
354 
355 #define ROP_SRCDSTCOLOR(op,pre,s,d,c,pst) \
356     switch ( op ) \
357 	{ \
358 	case RAS_INVERTSRC: \
359 	pre \
360 	if ( s ) \
361 	    (d) = ~(c); \
362 	else \
363 	    (d) = ~0; \
364 	pst \
365 	break; \
366 	case RAS_XOR: \
367 	pre \
368 	if ( s ) \
369 	    (d) = (c) ^ (d); \
370 	pst \
371 	break; \
372 	case RAS_SRC: \
373 	pre \
374 	if ( s ) \
375 	    (d) = (c); \
376 	else \
377 	    (d) = 0; \
378 	pst \
379 	break; \
380 	default: \
381 	return -1; \
382 	}
383 
384 #endif /*PARTIAL_LOGICAL_OPS*/
385 
386 
387 /* Variables. */
388 
389 static int needsrc[16] = { 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0 };
390 /*                       CLEAR          INVERT          DST            SET */
391 
392 #ifdef MSBIT_FIRST
393 
394 u_long raster_bitmask[32] = {
395     0x80000000, 0x40000000, 0x20000000, 0x10000000,
396     0x08000000, 0x04000000, 0x02000000, 0x01000000,
397     0x00800000, 0x00400000, 0x00200000, 0x00100000,
398     0x00080000, 0x00040000, 0x00020000, 0x00010000,
399     0x00008000, 0x00004000, 0x00002000, 0x00001000,
400     0x00000800, 0x00000400, 0x00000200, 0x00000100,
401     0x00000080, 0x00000040, 0x00000020, 0x00000010,
402     0x00000008, 0x00000004, 0x00000002, 0x00000001 };
403 
404 #ifdef MSBYTE_FIRST
405 static u_long leftmask[32] = {
406     0x00000000, 0x80000000, 0xc0000000, 0xe0000000,
407     0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
408     0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
409     0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
410     0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000,
411     0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
412     0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0,
413     0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe };
414 static u_long rightmask[32] = {
415     0x00000000, 0x00000001, 0x00000003, 0x00000007,
416     0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
417     0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
418     0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
419     0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
420     0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
421     0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
422     0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff };
423 #endif /*MSBYTE_FIRST*/
424 
425 #else /*MSBIT_FIRST*/
426 
427 u_long raster_bitmask[32] = {
428     0x00000001, 0x00000002, 0x00000004, 0x00000008,
429     0x00000010, 0x00000020, 0x00000040, 0x00000080,
430     0x00000100, 0x00000200, 0x00000400, 0x00000800,
431     0x00001000, 0x00002000, 0x00004000, 0x00008000,
432     0x00010000, 0x00020000, 0x00040000, 0x00080000,
433     0x00100000, 0x00200000, 0x00400000, 0x00800000,
434     0x01000000, 0x02000000, 0x04000000, 0x08000000,
435     0x10000000, 0x20000000, 0x40000000, 0x80000000 };
436 
437 #ifndef MSBYTE_FIRST
438 static u_long leftmask[32] = {
439     0x00000000, 0x00000001, 0x00000003, 0x00000007,
440     0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
441     0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
442     0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
443     0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
444     0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
445     0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
446     0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff };
447 static u_long rightmask[32] = {
448     0x00000000, 0x80000000, 0xc0000000, 0xe0000000,
449     0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
450     0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
451     0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
452     0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000,
453     0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
454     0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0,
455     0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe };
456 #endif /*not MSBYTE_FIRST*/
457 
458 #endif /*MSBIT_FIRST*/
459 
460 /* (The odd combinations MSBIT+~MSBYTE and ~MSBIT+MSBYTE could be added.) */
461 
462 #ifdef MSBYTE_FIRST
463 static u_long bytemask[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff };
464 #else /*MSBYTE_FIRST*/
465 static u_long bytemask[4] = { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 };
466 #endif /*MSBYTE_FIRST*/
467 
468 
469 /* Forward routines. */
470 
471 static int raster_blit();
472 
473 
474 /* Raster operations.  */
475 
476 /* Performs a bitblit.  Returns 0 on success, -1 on failure. */
477 int
478 raster_op( dst, dx, dy, w, h, rop, src, sx, sy )
479     struct raster* dst;
480     int dx, dy, w, h, rop;
481     struct raster* src;
482     int sx, sy;
483     {
484     if ( dst == (struct raster*) 0 )
485 	return -1;			/* no destination */
486 
487     if ( needsrc[RAS_GETOP( rop )] )
488 	{
489 	/* Two-operand blit. */
490 	if ( src == (struct raster*) 0 )
491 	    return -1;			/* no source */
492 
493 	/* Clip against source. */
494 	if ( sx < 0 )
495 	    {
496 	    w += sx;
497 	    sx = 0;
498 	    }
499 	if ( sy < 0 )
500 	    {
501 	    h += sy;
502 	    sy = 0;
503 	    }
504 	if ( sx + w > src->width )
505 	    w = src->width - sx;
506 	if ( sy + h > src->height )
507 	    h = src->height - sy;
508 
509 	/* Clip against dest. */
510 	if ( dx < 0 )
511 	    {
512 	    w += dx;
513 	    sx -= dx;
514 	    dx = 0;
515 	    }
516 	if ( dy < 0 )
517 	    {
518 	    h += dy;
519 	    sy -= dy;
520 	    dy = 0;
521 	    }
522 	if ( dx + w > dst->width )
523 	    w = dst->width - dx;
524 	if ( dy + h > dst->height )
525 	    h = dst->height - dy;
526 
527 	if ( w <= 0 || h <= 0 )
528 	    return 0;			/* nothing to do */
529 
530 	return raster_op_noclip( dst, dx, dy, w, h, rop, src, sx, sy );
531 	}
532 
533     /* No source necessary - one-operand blit. */
534     if ( src != (struct raster*) 0 )
535 	return -1;			/* unwanted source */
536 
537     /* Clip against dest. */
538     if ( dx < 0 )
539 	{
540 	w += dx;
541 	dx = 0;
542 	}
543     if ( dy < 0 )
544 	{
545 	h += dy;
546 	dy = 0;
547 	}
548     if ( dx + w > dst->width )
549 	w = dst->width - dx;
550     if ( dy + h > dst->height )
551 	h = dst->height - dy;
552 
553     if ( w <= 0 || h <= 0 )
554 	return 0;			/* nothing to do */
555 
556     return raster_op_nosrc_noclip( dst, dx, dy, w, h, rop );
557     }
558 
559 /* Semi-public routine to do a bitblit without clipping.  Returns 0 on
560 ** success, -1 on failure.
561 */
562 int
563 raster_op_noclip( dst, dx, dy, w, h, rop, src, sx, sy )
564     struct raster* dst;
565     int dx, dy, w, h, rop;
566     struct raster* src;
567     int sx, sy;
568     {
569     int op;
570 
571     op = RAS_GETOP( rop );
572 
573     if ( src->depth == 1 )
574 	{
575 	/* One-bit to ? blit. */
576 	if ( dst->depth == 1 )
577 	    {
578 	    /* One to one blit. */
579 	    u_long* srclin1;
580 	    u_long* dstlin1;
581 	    int srcleftignore, srcrightignore, srclongs;
582 	    int dstleftignore, dstrightignore, dstlongs;
583 
584 	    srclin1 = RAS_ADDR( src, sx, sy );
585 	    dstlin1 = RAS_ADDR( dst, dx, dy );
586 
587 #ifdef BCOPY_FASTER
588 	    /* Special-case full-width to full-width copies. */
589 	    if ( op == RAS_SRC && src->width == w && dst->width == w &&
590 		 src->linelongs == dst->linelongs && src->linelongs == w >> 5 )
591 		{
592 		bcopy(
593 		    (char*) srclin1, (char*) dstlin1,
594 		    h * src->linelongs * sizeof(u_long) );
595 		return 0;
596 		}
597 #endif /*BCOPY_FASTER*/
598 
599 	    srcleftignore = ( sx & 31 );
600 	    srclongs = ( srcleftignore + w + 31 ) >> 5;
601 	    srcrightignore = ( srclongs * 32 - w - srcleftignore ) & 31;
602 	    dstleftignore = ( dx & 31 );
603 	    dstlongs = ( dstleftignore + w + 31 ) >> 5;
604 	    dstrightignore = ( dstlongs * 32 - w - dstleftignore ) & 31;
605 
606 	    return raster_blit(
607 		src, srclin1, srcleftignore, srcrightignore, srclongs,
608 		dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op );
609 	    }
610 
611 	else
612 	    {
613 	    /* One to eight, using the color in the rop.  This could
614 	    ** probably be sped up by handling each four-bit source nybble
615 	    ** as a group, indexing into a 16-element runtime-constructed
616 	    ** table of longwords.
617 	    */
618 	    u_long* srclin1;
619 	    u_long* dstlin1;
620 	    u_long* srclin2;
621 	    u_long* srclin;
622 	    u_long* dstlin;
623 	    register u_long* srclong;
624 	    register u_long* dstlong;
625 	    register u_long color, dl;
626 	    register int srcbit, dstbyte, i;
627 
628 	    color = RAS_GETCOLOR( rop );
629 	    if ( color == 0 )
630 		color = 255;
631 
632 	    /* Make 32 bits of color so we can do the ROP without shifting. */
633 	    color |= ( color << 24 ) | ( color << 16 ) | ( color << 8 );
634 
635 	    /* Don't have to worry about overlapping blits here. */
636 	    srclin1 = RAS_ADDR( src, sx, sy );
637 	    srclin2 = srclin1 + h * src->linelongs;
638 	    dstlin1 = RAS_ADDR( dst, dx, dy );
639 	    srclin = srclin1;
640 	    dstlin = dstlin1;
641 	    while ( srclin != srclin2 )
642 		{
643 		srclong = srclin;
644 		srcbit = sx & 31;
645 		dstlong = dstlin;
646 		dstbyte = dx & 3;
647 		i = w;
648 
649 		/* WARNING: this code is KNOWN TO FAIL on Sun 3's / CG2's. */
650 		ROP_SRCDSTCOLOR(
651 		/*op*/  op,
652 		/*pre*/ while ( i > 0 )
653 			    {
654 			    dl = *dstlong;,
655 		/*s*/       *srclong & raster_bitmask[srcbit],
656 		/*d*/       dl,
657 		/*c*/       color,
658 		/*pst*/     *dstlong = ( *dstlong & ~bytemask[dstbyte] ) |
659 				       ( dl & bytemask[dstbyte] );
660 			    if ( srcbit == 31 )
661 				{
662 				srcbit = 0;
663 				++srclong;
664 				}
665 			    else
666 				++srcbit;
667 			    if ( dstbyte == 3 )
668 				{
669 				dstbyte = 0;
670 				++dstlong;
671 				}
672 			    else
673 				++dstbyte;
674 			    --i;
675 			    } )
676 
677 		srclin += src->linelongs;
678 		dstlin += dst->linelongs;
679 		}
680 	    }
681 	}
682 
683     else
684 	{
685 	/* Eight to eight blit. */
686 	u_long* srclin1;
687 	u_long* dstlin1;
688 	int srcleftignore, srcrightignore, srclongs;
689 	int dstleftignore, dstrightignore, dstlongs;
690 
691 	if ( dst->depth != 8 )
692 	    return -1;		/* depth mismatch */
693 
694 	srclin1 = RAS_ADDR( src, sx, sy );
695 	dstlin1 = RAS_ADDR( dst, dx, dy );
696 
697 #ifdef BCOPY_FASTER
698 	/* Special-case full-width to full-width copies. */
699 	if ( op == RAS_SRC && src->width == w && dst->width == w &&
700 	     src->linelongs == dst->linelongs && src->linelongs == w >> 2 )
701 	    {
702 	    bcopy( (char*) srclin1, (char*) dstlin1,
703 		   h * src->linelongs * sizeof(u_long) );
704 	    return 0;
705 	    }
706 #endif /*BCOPY_FASTER*/
707 
708 	srcleftignore = ( sx & 3 ) * 8;
709 	srclongs = ( srcleftignore + w * 8 + 31 ) >> 5;
710 	srcrightignore = ( srclongs * 32 - w * 8 - srcleftignore ) & 31;
711 	dstleftignore = ( dx & 3 ) * 8;
712 	dstlongs = ( dstleftignore + w * 8 + 31 ) >> 5;
713 	dstrightignore = ( dstlongs * 32 - w * 8 - dstleftignore ) & 31;
714 
715 	return raster_blit(
716 	    src, srclin1, srcleftignore, srcrightignore, srclongs,
717 	    dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op );
718 	}
719 
720     return 0;
721     }
722 
723 /* Semi-public routine to do a no-src bitblit without clipping.  Returns 0
724 ** on success, -1 on failure.
725 */
726 int
727 raster_op_nosrc_noclip( dst, dx, dy, w, h, rop )
728     struct raster* dst;
729     int dx, dy, w, h, rop;
730     {
731     int op;
732 
733     op = RAS_GETOP( rop );
734 
735     if ( dst->depth == 1 )
736 	{
737 	/* One-bit no-src blit. */
738 	u_long* dstlin1;
739 	u_long* dstlin2;
740 	u_long* dstlin;
741 	int dstleftignore, dstrightignore, dstlongs;
742 	u_long dl, lm, nlm, rm, nrm;
743 	register u_long* dstlong2;
744 	register u_long* dstlong;
745 
746 	dstlin1 = RAS_ADDR( dst, dx, dy );
747 
748 #ifdef BCOPY_FASTER
749 	/* Special-case full-width clears. */
750 	if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 5 )
751 	    {
752 	    bzero( (char*) dstlin1, h * dst->linelongs * sizeof(u_long) );
753 	    return 0;
754 	    }
755 #endif /*BCOPY_FASTER*/
756 
757 	dstleftignore = ( dx & 31 );
758 	dstlongs = ( dstleftignore + w + 31 ) >> 5;
759 	dstrightignore = ( dstlongs * 32 - w - dstleftignore ) & 31;
760 
761 	dstlin2 = dstlin1 + h * dst->linelongs;
762 	dstlin = dstlin1;
763 
764 	if ( dstlongs == 1 )
765 	    {
766 	    /* It fits into a single longword. */
767 	    lm = leftmask[dstleftignore] | rightmask[dstrightignore];
768 	    nlm = ~lm;
769 	    while ( dstlin != dstlin2 )
770 		{
771 		ROP_DST(
772 		/*op*/  op,
773 		/*pre*/ dl = *dstlin;,
774 		/*d*/   dl,
775 		/*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
776 
777 		dstlin += dst->linelongs;
778 		}
779 	    }
780 	else
781 	    {
782 	    lm = leftmask[dstleftignore];
783 	    rm = rightmask[dstrightignore];
784 	    nrm = ~rm;
785 	    nlm = ~lm;
786 
787 	    while ( dstlin != dstlin2 )
788 		{
789 		dstlong = dstlin;
790 		dstlong2 = dstlong + dstlongs;
791 		if ( dstrightignore != 0 )
792 		    --dstlong2;
793 
794 		/* Leading edge. */
795 		if ( dstleftignore != 0 )
796 		    {
797 		    ROP_DST(
798 		    /*op*/  op,
799 		    /*pre*/ dl = *dstlong;,
800 		    /*d*/   dl,
801 		    /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
802 		    ++dstlong;
803 		    }
804 
805 		/* Main rop. */
806 		ROP_DST(
807 		/*op*/  op,
808 		/*pre*/ while ( dstlong != dstlong2 )
809 			    {,
810 		/*d*/       *dstlong,
811 		/*pst*/     ++dstlong;
812 			    } )
813 
814 		/* Trailing edge. */
815 		if ( dstrightignore != 0 )
816 		    {
817 		    ROP_DST(
818 		    /*op*/  op,
819 		    /*pre*/ dl = *dstlong;,
820 		    /*d*/   dl,
821 		    /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
822 		    }
823 
824 		dstlin += dst->linelongs;
825 		}
826 	    }
827 	}
828 
829     else
830 	{
831 	/* Eight-bit no-src blit. */
832 	register u_long color;
833 	u_long* dstlin1;
834 	u_long* dstlin2;
835 	u_long* dstlin;
836 	int dstleftignore, dstrightignore, dstlongs;
837 	u_long dl, lm, nlm, rm, nrm;
838 	register u_long* dstlong2;
839 	register u_long* dstlong;
840 
841 	dstlin1 = RAS_ADDR( dst, dx, dy );
842 
843 #ifdef BCOPY_FASTER
844 	/* Special-case full-width clears. */
845 	if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 2 )
846 	    {
847 	    bzero( (char*) dstlin1, h * dst->linelongs * sizeof(u_long) );
848 	    return 0;
849 	    }
850 #endif /*BCOPY_FASTER*/
851 
852 	color = RAS_GETCOLOR( rop );
853 	if ( color == 0 )
854 	    color = 255;
855 
856 	/* Make 32 bits of color so we can do the ROP without shifting. */
857 	color |= ( color << 24 ) | ( color << 16 ) | ( color << 8 );
858 
859 	dstleftignore = ( dx & 3 ) * 8;
860 	dstlongs = ( dstleftignore + w * 8 + 31 ) >> 5;
861 	dstrightignore = ( dstlongs * 32 - w * 8 - dstleftignore ) & 31;
862 
863 	dstlin2 = dstlin1 + h * dst->linelongs;
864 	dstlin = dstlin1;
865 
866 	if ( dstlongs == 1 )
867 	    {
868 	    /* It fits into a single longword. */
869 	    lm = leftmask[dstleftignore] | rightmask[dstrightignore];
870 	    nlm = ~lm;
871 	    while ( dstlin != dstlin2 )
872 		{
873 		ROP_DSTCOLOR(
874 		/*op*/  op,
875 		/*pre*/ dl = *dstlin;,
876 		/*d*/   dl,
877 		/*c*/	color,
878 		/*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
879 
880 		dstlin += dst->linelongs;
881 		}
882 	    }
883 	else
884 	    {
885 	    lm = leftmask[dstleftignore];
886 	    rm = rightmask[dstrightignore];
887 	    nrm = ~rm;
888 	    nlm = ~lm;
889 	    while ( dstlin != dstlin2 )
890 		{
891 		dstlong = dstlin;
892 		dstlong2 = dstlong + dstlongs;
893 		if ( dstrightignore != 0 )
894 		    --dstlong2;
895 
896 		/* Leading edge. */
897 		if ( dstleftignore != 0 )
898 		    {
899 		    ROP_DSTCOLOR(
900 		    /*op*/  op,
901 		    /*pre*/ dl = *dstlong;,
902 		    /*d*/   dl,
903 		    /*c*/   color,
904 		    /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
905 		    ++dstlong;
906 		    }
907 
908 		/* Main rop. */
909 		ROP_DSTCOLOR(
910 		/*op*/  op,
911 		/*pre*/ while ( dstlong != dstlong2 )
912 			    {,
913 		/*d*/       *dstlong,
914 		/*c*/       color,
915 		/*pst*/     ++dstlong;
916 			    } )
917 
918 		/* Trailing edge. */
919 		if ( dstrightignore != 0 )
920 		    {
921 		    ROP_DSTCOLOR(
922 		    /*op*/  op,
923 		    /*pre*/ dl = *dstlong;,
924 		    /*d*/   dl,
925 		    /*c*/   color,
926 		    /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
927 		    }
928 
929 		dstlin += dst->linelongs;
930 		}
931 	    }
932 	}
933 
934     return 0;
935     }
936 
937 /* This is a general bitblit routine, handling overlapping source and
938 ** destination.  It's used for both the 1-to-1 and 8-to-8 cases.
939 */
940 static int
941 raster_blit( src, srclin1, srcleftignore, srcrightignore, srclongs, dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op )
942     struct raster* src;
943     u_long* srclin1;
944     int srcleftignore, srcrightignore, srclongs;
945     struct raster* dst;
946     u_long* dstlin1;
947     int dstleftignore, dstrightignore, dstlongs;
948     int h, op;
949     {
950     u_long* srclin2;
951     u_long* dstlin2;
952     int srclininc, dstlininc;
953     u_long* srclin;
954     u_long* dstlin;
955     register int prevleftshift, currrightshift;
956     int longinc;
957     register u_long* srclong;
958     register u_long* dstlong;
959     register u_long* dstlong2;
960     register u_long dl, lm, nlm, rm, nrm;
961 
962     prevleftshift = ( srcleftignore - dstleftignore ) & 31;
963 
964     srclin2 = srclin1 + h * src->linelongs;
965     dstlin2 = dstlin1 + h * dst->linelongs;
966     srclininc = src->linelongs;
967     dstlininc = dst->linelongs;
968     longinc = 1;
969 
970     /* Check for overlaps. */
971     if ( ( dstlin1 >= srclin1 && dstlin1 < srclin1 + srclongs ) ||
972 	 ( srclin1 >= dstlin1 && srclin1 < dstlin1 + dstlongs ) )
973 	{
974 	/* Horizontal overlap.  Should we reverse? */
975 	if ( srclin1 < dstlin1 )
976 	    {
977 	    longinc = -1;
978 	    srclin1 += srclongs - 1;
979 	    srclin2 += srclongs - 1;
980 	    dstlin1 += dstlongs - 1;
981 	    }
982 	}
983     else if ( ( dstlin1 >= srclin1 && dstlin1 < srclin2 ) ||
984 	      ( srclin1 >= dstlin1 && srclin1 < dstlin2 ) )
985 	{
986 	/* Vertical overlap.  Should we reverse? */
987 	if ( srclin1 < dstlin1 )
988 	    {
989 	    srclin2 = srclin1 - srclininc;
990 	    srclin1 += ( h - 1 ) * srclininc;
991 	    dstlin1 += ( h - 1 ) * dstlininc;
992 	    srclininc = -srclininc;
993 	    dstlininc = -dstlininc;
994 	    }
995 	}
996     srclin = srclin1;
997     dstlin = dstlin1;
998 
999     if ( prevleftshift == 0 )
1000 	{
1001 	/* The bits line up, no shifting necessary. */
1002 	if ( dstlongs == 1 )
1003 	    {
1004 	    /* It all fits into a single longword. */
1005 	    lm = leftmask[dstleftignore] | rightmask[dstrightignore];
1006 	    nlm = ~lm;
1007 	    while ( srclin != srclin2 )
1008 		{
1009 		ROP_SRCDST(
1010 		/*op*/  op,
1011 		/*pre*/ dl = *dstlin;,
1012 		/*s*/   *srclin,
1013 		/*d*/   dl,
1014 		/*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
1015 
1016 		srclin += srclininc;
1017 		dstlin += dstlininc;
1018 		}
1019 	    }
1020 	else
1021 	    {
1022 	    /* Multiple longwords. */
1023 	    lm = leftmask[dstleftignore];
1024 	    rm = rightmask[dstrightignore];
1025 	    nrm = ~rm;
1026 	    nlm = ~lm;
1027 	    if ( longinc == 1 )
1028 		{
1029 		/* Left to right. */
1030 		while ( srclin != srclin2 )
1031 		    {
1032 		    srclong = srclin;
1033 		    dstlong = dstlin;
1034 		    dstlong2 = dstlong + dstlongs;
1035 		    if ( dstrightignore != 0 )
1036 			--dstlong2;
1037 
1038 		    /* Leading edge. */
1039 		    if ( dstleftignore != 0 )
1040 			{
1041 			ROP_SRCDST(
1042 			/*op*/  op,
1043 			/*pre*/ dl = *dstlong;,
1044 			/*s*/   *srclong,
1045 			/*d*/   dl,
1046 			/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
1047 			++srclong;
1048 			++dstlong;
1049 			}
1050 
1051 		    /* Main rop. */
1052 		    ROP_SRCDST(
1053 		    /*op*/  op,
1054 		    /*pre*/ while ( dstlong != dstlong2 )
1055 				{,
1056 		    /*s*/       *srclong,
1057 		    /*d*/       *dstlong,
1058 		    /*pst*/     ++srclong;
1059 				++dstlong;
1060 				} )
1061 
1062 		    /* Trailing edge. */
1063 		    if ( dstrightignore != 0 )
1064 			{
1065 			ROP_SRCDST(
1066 			/*op*/  op,
1067 			/*pre*/ dl = *dstlong;,
1068 			/*s*/   *srclong,
1069 			/*d*/   dl,
1070 			/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
1071 			}
1072 
1073 		    srclin += srclininc;
1074 		    dstlin += dstlininc;
1075 		    }
1076 		}
1077 	    else
1078 		{
1079 		/* Right to left. */
1080 		while ( srclin != srclin2 )
1081 		    {
1082 		    srclong = srclin;
1083 		    dstlong = dstlin;
1084 		    dstlong2 = dstlong - dstlongs;
1085 		    if ( dstleftignore != 0 )
1086 			++dstlong2;
1087 
1088 		    /* Leading edge. */
1089 		    if ( dstrightignore != 0 )
1090 			{
1091 			ROP_SRCDST(
1092 			/*op*/  op,
1093 			/*pre*/ dl = *dstlong;,
1094 			/*s*/   *srclong,
1095 			/*d*/   dl,
1096 			/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
1097 			--srclong;
1098 			--dstlong;
1099 			}
1100 
1101 		    /* Main rop. */
1102 		    ROP_SRCDST(
1103 		    /*op*/  op,
1104 		    /*pre*/ while ( dstlong != dstlong2 )
1105 				{,
1106 		    /*s*/       *srclong,
1107 		    /*d*/       *dstlong,
1108 		    /*pst*/     --srclong;
1109 				--dstlong;
1110 				} )
1111 
1112 		    /* Trailing edge. */
1113 		    if ( dstleftignore != 0 )
1114 			{
1115 			ROP_SRCDST(
1116 			/*op*/  op,
1117 			/*pre*/ dl = *dstlong;,
1118 			/*s*/   *srclong,
1119 			/*d*/   dl,
1120 			/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
1121 			}
1122 
1123 		    srclin += srclininc;
1124 		    dstlin += dstlininc;
1125 		    }
1126 		}
1127 	    }
1128 	}
1129 
1130     else
1131 	{
1132 	/* General case, with shifting and everything. */
1133 	register u_long sl, prevsl;
1134 
1135 	currrightshift = 32 - prevleftshift;
1136 	if ( srclongs == 1 && dstlongs == 1 )
1137 	    {
1138 	    /* It fits into a single longword, with a shift. */
1139 	    lm = leftmask[dstleftignore] | rightmask[dstrightignore];
1140 	    nlm = ~lm;
1141 	    if ( srcleftignore > dstleftignore )
1142 		{
1143 		while ( srclin != srclin2 )
1144 		    {
1145 		    ROP_SRCDST(
1146 		    /*op*/  op,
1147 		    /*pre*/ dl = *dstlin;,
1148 		    /*s*/   *srclin << prevleftshift,
1149 		    /*d*/   dl,
1150 		    /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
1151 
1152 		    srclin += srclininc;
1153 		    dstlin += dstlininc;
1154 		    }
1155 		}
1156 	    else
1157 		{
1158 		while ( srclin != srclin2 )
1159 		    {
1160 		    ROP_SRCDST(
1161 		    /*op*/  op,
1162 		    /*pre*/ dl = *dstlin;,
1163 		    /*s*/   *srclin >> currrightshift,
1164 		    /*d*/   dl,
1165 		    /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
1166 
1167 		    srclin += srclininc;
1168 		    dstlin += dstlininc;
1169 		    }
1170 		}
1171 	    }
1172 	else
1173 	    {
1174 	    /* Multiple longwords. */
1175 	    lm = leftmask[dstleftignore];
1176 	    rm = rightmask[dstrightignore];
1177 	    nrm = ~rm;
1178 	    nlm = ~lm;
1179 	    if ( longinc == 1 )
1180 		{
1181 		/* Left to right. */
1182 		while ( srclin != srclin2 )
1183 		    {
1184 		    srclong = srclin;
1185 		    dstlong = dstlin;
1186 		    dstlong2 = dstlong + dstlongs;
1187 		    if ( srcleftignore > dstleftignore )
1188 			prevsl = *srclong++ << prevleftshift;
1189 		    else
1190 			prevsl = 0;
1191 		    if ( dstrightignore != 0 )
1192 			--dstlong2;
1193 
1194 		    /* Leading edge. */
1195 		    if ( dstleftignore != 0 )
1196 			{
1197 			ROP_SRCDST(
1198 			/*op*/  op,
1199 			/*pre*/ sl = *srclong;
1200 				dl = *dstlong;,
1201 			/*s*/   prevsl | ( sl >> currrightshift ),
1202 			/*d*/   dl,
1203 			/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
1204 			prevsl = sl << prevleftshift;
1205 			++srclong;
1206 			++dstlong;
1207 			}
1208 
1209 		    /* Main rop. */
1210 		    ROP_SRCDST(
1211 		    /*op*/  op,
1212 		    /*pre*/ while ( dstlong != dstlong2 )
1213 				{
1214 				sl = *srclong;,
1215 		    /*s*/       prevsl | ( sl >> currrightshift ),
1216 		    /*d*/       *dstlong,
1217 		    /*pst*/     prevsl = sl << prevleftshift;
1218 				++srclong;
1219 				++dstlong;
1220 				} )
1221 
1222 		    /* Trailing edge. */
1223 		    if ( dstrightignore != 0 )
1224 			{
1225 			ROP_SRCDST(
1226 			/*op*/  op,
1227 			/*pre*/ dl = *dstlong;,
1228 			/*s*/   prevsl | ( *srclong >> currrightshift ),
1229 			/*d*/   dl,
1230 			/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
1231 			}
1232 
1233 		    srclin += srclininc;
1234 		    dstlin += dstlininc;
1235 		    }
1236 		}
1237 	    else
1238 		{
1239 		/* Right to left. */
1240 		while ( srclin != srclin2 )
1241 		    {
1242 		    srclong = srclin;
1243 		    dstlong = dstlin;
1244 		    dstlong2 = dstlong - dstlongs;
1245 		    if ( srcrightignore > dstrightignore )
1246 			prevsl = *srclong-- >> currrightshift;
1247 		    else
1248 			prevsl = 0;
1249 		    if ( dstleftignore != 0 )
1250 			++dstlong2;
1251 
1252 		    /* Leading edge. */
1253 		    if ( dstrightignore != 0 )
1254 			{
1255 			ROP_SRCDST(
1256 			/*op*/  op,
1257 			/*pre*/ sl = *srclong;
1258 				dl = *dstlong;,
1259 			/*s*/   prevsl | ( sl << prevleftshift ),
1260 			/*d*/   dl,
1261 			/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
1262 			prevsl = sl >> currrightshift;
1263 			--srclong;
1264 			--dstlong;
1265 			}
1266 
1267 		    /* Main rop. */
1268 		    ROP_SRCDST(
1269 		    /*op*/  op,
1270 		    /*pre*/ while ( dstlong != dstlong2 )
1271 				{
1272 				sl = *srclong;,
1273 		    /*s*/       prevsl | ( sl << prevleftshift ),
1274 		    /*d*/       *dstlong,
1275 		    /*pst*/     prevsl = sl >> currrightshift;
1276 				--srclong;
1277 				--dstlong;
1278 				} )
1279 
1280 		    /* Trailing edge. */
1281 		    if ( dstleftignore != 0 )
1282 			{
1283 			ROP_SRCDST(
1284 			/*op*/  op,
1285 			/*pre*/ dl = *dstlong;,
1286 			/*s*/   prevsl | ( *srclong << prevleftshift ),
1287 			/*d*/   dl,
1288 			/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
1289 			}
1290 
1291 		    srclin += srclininc;
1292 		    dstlin += dstlininc;
1293 		    }
1294 		}
1295 	    }
1296 	}
1297 
1298     return 0;
1299     }
1300