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