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