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