raster_op.c revision 1.5 1 /* $NetBSD: raster_op.c,v 1.5 1998/12/18 21:59:34 thorpej 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
450 #define LSOP <<
451 #define RSOP >>
452 #endif /*MSBYTE_FIRST*/
453
454 #else /*MSBIT_FIRST*/
455
456 u_int32_t raster_bitmask[32] = {
457 0x00000001, 0x00000002, 0x00000004, 0x00000008,
458 0x00000010, 0x00000020, 0x00000040, 0x00000080,
459 0x00000100, 0x00000200, 0x00000400, 0x00000800,
460 0x00001000, 0x00002000, 0x00004000, 0x00008000,
461 0x00010000, 0x00020000, 0x00040000, 0x00080000,
462 0x00100000, 0x00200000, 0x00400000, 0x00800000,
463 0x01000000, 0x02000000, 0x04000000, 0x08000000,
464 0x10000000, 0x20000000, 0x40000000, 0x80000000 };
465
466 #ifndef MSBYTE_FIRST
467 static u_int32_t leftmask[32] = {
468 0x00000000, 0x00000001, 0x00000003, 0x00000007,
469 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
470 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
471 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
472 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
473 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
474 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
475 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff };
476 static u_int32_t rightmask[32] = {
477 0x00000000, 0x80000000, 0xc0000000, 0xe0000000,
478 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
479 0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
480 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
481 0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000,
482 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
483 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0,
484 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe };
485 #define LSOP >>
486 #define RSOP <<
487 #endif /*not MSBYTE_FIRST*/
488
489 #endif /*MSBIT_FIRST*/
490
491 /* (The odd combinations MSBIT+~MSBYTE and ~MSBIT+MSBYTE could be added.) */
492
493 #ifdef MSBYTE_FIRST
494 static u_int32_t bytemask[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff };
495 #else /*MSBYTE_FIRST*/
496 static u_int32_t bytemask[4] = { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 };
497 #endif /*MSBYTE_FIRST*/
498
499
500 /* Forward routines. */
501
502 static int raster_blit __P((struct raster *, u_int32_t *, int, int, int,
503 struct raster *, u_int32_t *, int, int, int,
504 int, int));
505
506 /* Raster operations. */
507
508 /* Performs a bitblit. Returns 0 on success, -1 on failure. */
509 int
510 raster_op( dst, dx, dy, w, h, rop, src, sx, sy )
511 struct raster* dst;
512 int dx, dy, w, h, rop;
513 struct raster* src;
514 int sx, sy;
515 {
516 if ( dst == (struct raster*) 0 )
517 return -1; /* no destination */
518
519 if ( needsrc[RAS_GETOP( rop )] )
520 {
521 /* Two-operand blit. */
522 if ( src == (struct raster*) 0 )
523 return -1; /* no source */
524
525 /* Clip against source. */
526 if ( sx < 0 )
527 {
528 w += sx;
529 sx = 0;
530 }
531 if ( sy < 0 )
532 {
533 h += sy;
534 sy = 0;
535 }
536 if ( sx + w > src->width )
537 w = src->width - sx;
538 if ( sy + h > src->height )
539 h = src->height - sy;
540
541 /* Clip against dest. */
542 if ( dx < 0 )
543 {
544 w += dx;
545 sx -= dx;
546 dx = 0;
547 }
548 if ( dy < 0 )
549 {
550 h += dy;
551 sy -= dy;
552 dy = 0;
553 }
554 if ( dx + w > dst->width )
555 w = dst->width - dx;
556 if ( dy + h > dst->height )
557 h = dst->height - dy;
558
559 if ( w <= 0 || h <= 0 )
560 return 0; /* nothing to do */
561
562 return raster_op_noclip( dst, dx, dy, w, h, rop, src, sx, sy );
563 }
564
565 /* No source necessary - one-operand blit. */
566 if ( src != (struct raster*) 0 )
567 return -1; /* unwanted source */
568
569 /* Clip against dest. */
570 if ( dx < 0 )
571 {
572 w += dx;
573 dx = 0;
574 }
575 if ( dy < 0 )
576 {
577 h += dy;
578 dy = 0;
579 }
580 if ( dx + w > dst->width )
581 w = dst->width - dx;
582 if ( dy + h > dst->height )
583 h = dst->height - dy;
584
585 if ( w <= 0 || h <= 0 )
586 return 0; /* nothing to do */
587
588 return raster_op_nosrc_noclip( dst, dx, dy, w, h, rop );
589 }
590
591 /* Semi-public routine to do a bitblit without clipping. Returns 0 on
592 ** success, -1 on failure.
593 */
594 int
595 raster_op_noclip( dst, dx, dy, w, h, rop, src, sx, sy )
596 struct raster* dst;
597 int dx, dy, w, h, rop;
598 struct raster* src;
599 int sx, sy;
600 {
601 int op;
602
603 op = RAS_GETOP( rop );
604
605 if ( src->depth == 1 )
606 {
607 /* One-bit to ? blit. */
608 if ( dst->depth == 1 )
609 {
610 /* One to one blit. */
611 u_int32_t* srclin1;
612 u_int32_t* dstlin1;
613 int srcleftignore, srcrightignore, srclongs;
614 int dstleftignore, dstrightignore, dstlongs;
615
616 srclin1 = RAS_ADDR( src, sx, sy );
617 dstlin1 = RAS_ADDR( dst, dx, dy );
618
619 #ifdef BCOPY_FASTER
620 /* Special-case full-width to full-width copies. */
621 if ( op == RAS_SRC && src->width == w && dst->width == w &&
622 src->linelongs == dst->linelongs && src->linelongs == w >> 5 )
623 {
624 bcopy(
625 (char*) srclin1, (char*) dstlin1,
626 h * src->linelongs * sizeof(u_int32_t) );
627 return 0;
628 }
629 #endif /*BCOPY_FASTER*/
630
631 srcleftignore = ( sx & 31 );
632 srclongs = ( srcleftignore + w + 31 ) >> 5;
633 srcrightignore = ( srclongs * 32 - w - srcleftignore ) & 31;
634 dstleftignore = ( dx & 31 );
635 dstlongs = ( dstleftignore + w + 31 ) >> 5;
636 dstrightignore = ( dstlongs * 32 - w - dstleftignore ) & 31;
637
638 return raster_blit(
639 src, srclin1, srcleftignore, srcrightignore, srclongs,
640 dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op );
641 }
642
643 else
644 {
645 /* One to eight, using the color in the rop. This could
646 ** probably be sped up by handling each four-bit source nybble
647 ** as a group, indexing into a 16-element runtime-constructed
648 ** table of longwords.
649 */
650 u_int32_t* srclin1;
651 u_int32_t* dstlin1;
652 u_int32_t* srclin2;
653 u_int32_t* srclin;
654 u_int32_t* dstlin;
655 register u_int32_t* srclong;
656 register u_int32_t* dstlong;
657 register u_int32_t color, dl;
658 register int srcbit, dstbyte, i;
659
660 color = RAS_GETCOLOR( rop );
661 if ( color == 0 )
662 color = 255;
663
664 /* Make 32 bits of color so we can do the ROP without shifting. */
665 color |= ( color << 24 ) | ( color << 16 ) | ( color << 8 );
666
667 /* Don't have to worry about overlapping blits here. */
668 srclin1 = RAS_ADDR( src, sx, sy );
669 srclin2 = srclin1 + h * src->linelongs;
670 dstlin1 = RAS_ADDR( dst, dx, dy );
671 srclin = srclin1;
672 dstlin = dstlin1;
673 while ( srclin != srclin2 )
674 {
675 srclong = srclin;
676 srcbit = sx & 31;
677 dstlong = dstlin;
678 dstbyte = dx & 3;
679 i = w;
680
681 /* WARNING: this code is KNOWN TO FAIL on Sun 3's / CG2's. */
682 ROP_SRCDSTCOLOR(
683 /*op*/ op,
684 /*pre*/ while ( i > 0 )
685 {
686 dl = *dstlong;,
687 /*s*/ *srclong & raster_bitmask[srcbit],
688 /*d*/ dl,
689 /*c*/ color,
690 /*pst*/ *dstlong = ( *dstlong & ~bytemask[dstbyte] ) |
691 ( dl & bytemask[dstbyte] );
692 if ( srcbit == 31 )
693 {
694 srcbit = 0;
695 ++srclong;
696 }
697 else
698 ++srcbit;
699 if ( dstbyte == 3 )
700 {
701 dstbyte = 0;
702 ++dstlong;
703 }
704 else
705 ++dstbyte;
706 --i;
707 } )
708
709 srclin += src->linelongs;
710 dstlin += dst->linelongs;
711 }
712 }
713 }
714
715 else
716 {
717 /* Eight to eight blit. */
718 u_int32_t* srclin1;
719 u_int32_t* dstlin1;
720 int srcleftignore, srcrightignore, srclongs;
721 int dstleftignore, dstrightignore, dstlongs;
722
723 if ( dst->depth != 8 )
724 return -1; /* depth mismatch */
725
726 srclin1 = RAS_ADDR( src, sx, sy );
727 dstlin1 = RAS_ADDR( dst, dx, dy );
728
729 #ifdef BCOPY_FASTER
730 /* Special-case full-width to full-width copies. */
731 if ( op == RAS_SRC && src->width == w && dst->width == w &&
732 src->linelongs == dst->linelongs && src->linelongs == w >> 2 )
733 {
734 bcopy( (char*) srclin1, (char*) dstlin1,
735 h * src->linelongs * sizeof(u_int32_t) );
736 return 0;
737 }
738 #endif /*BCOPY_FASTER*/
739
740 srcleftignore = ( sx & 3 ) * 8;
741 srclongs = ( srcleftignore + w * 8 + 31 ) >> 5;
742 srcrightignore = ( srclongs * 32 - w * 8 - srcleftignore ) & 31;
743 dstleftignore = ( dx & 3 ) * 8;
744 dstlongs = ( dstleftignore + w * 8 + 31 ) >> 5;
745 dstrightignore = ( dstlongs * 32 - w * 8 - dstleftignore ) & 31;
746
747 return raster_blit(
748 src, srclin1, srcleftignore, srcrightignore, srclongs,
749 dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op );
750 }
751
752 return 0;
753 }
754
755 /* Semi-public routine to do a no-src bitblit without clipping. Returns 0
756 ** on success, -1 on failure.
757 */
758 int
759 raster_op_nosrc_noclip( dst, dx, dy, w, h, rop )
760 struct raster* dst;
761 int dx, dy, w, h, rop;
762 {
763 int op;
764
765 op = RAS_GETOP( rop );
766
767 if ( dst->depth == 1 )
768 {
769 /* One-bit no-src blit. */
770 u_int32_t* dstlin1;
771 u_int32_t* dstlin2;
772 u_int32_t* dstlin;
773 int dstleftignore, dstrightignore, dstlongs;
774 u_int32_t dl, lm, nlm, rm, nrm;
775 register u_int32_t* dstlong2;
776 register u_int32_t* dstlong;
777
778 dstlin1 = RAS_ADDR( dst, dx, dy );
779
780 #ifdef BCOPY_FASTER
781 /* Special-case full-width clears. */
782 if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 5 )
783 {
784 bzero( (char*) dstlin1, h * dst->linelongs * sizeof(u_int32_t) );
785 return 0;
786 }
787 #endif /*BCOPY_FASTER*/
788
789 dstleftignore = ( dx & 31 );
790 dstlongs = ( dstleftignore + w + 31 ) >> 5;
791 dstrightignore = ( dstlongs * 32 - w - dstleftignore ) & 31;
792
793 dstlin2 = dstlin1 + h * dst->linelongs;
794 dstlin = dstlin1;
795
796 if ( dstlongs == 1 )
797 {
798 /* It fits into a single longword. */
799 lm = leftmask[dstleftignore] | rightmask[dstrightignore];
800 nlm = ~lm;
801 while ( dstlin != dstlin2 )
802 {
803 ROP_DST(
804 /*op*/ op,
805 /*pre*/ dl = *dstlin;,
806 /*d*/ dl,
807 /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
808
809 dstlin += dst->linelongs;
810 }
811 }
812 else
813 {
814 lm = leftmask[dstleftignore];
815 rm = rightmask[dstrightignore];
816 nrm = ~rm;
817 nlm = ~lm;
818
819 while ( dstlin != dstlin2 )
820 {
821 dstlong = dstlin;
822 dstlong2 = dstlong + dstlongs;
823 if ( dstrightignore != 0 )
824 --dstlong2;
825
826 /* Leading edge. */
827 if ( dstleftignore != 0 )
828 {
829 ROP_DST(
830 /*op*/ op,
831 /*pre*/ dl = *dstlong;,
832 /*d*/ dl,
833 /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
834 ++dstlong;
835 }
836
837 /* Main rop. */
838 ROP_DST(
839 /*op*/ op,
840 /*pre*/ while ( dstlong != dstlong2 )
841 {,
842 /*d*/ *dstlong,
843 /*pst*/ ++dstlong;
844 } )
845
846 /* Trailing edge. */
847 if ( dstrightignore != 0 )
848 {
849 ROP_DST(
850 /*op*/ op,
851 /*pre*/ dl = *dstlong;,
852 /*d*/ dl,
853 /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
854 }
855
856 dstlin += dst->linelongs;
857 }
858 }
859 }
860
861 else
862 {
863 /* Eight-bit no-src blit. */
864 register u_int32_t color;
865 u_int32_t* dstlin1;
866 u_int32_t* dstlin2;
867 u_int32_t* dstlin;
868 int dstleftignore, dstrightignore, dstlongs;
869 u_int32_t dl, lm, nlm, rm, nrm;
870 register u_int32_t* dstlong2;
871 register u_int32_t* dstlong;
872
873 dstlin1 = RAS_ADDR( dst, dx, dy );
874
875 #ifdef BCOPY_FASTER
876 /* Special-case full-width clears. */
877 if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 2 )
878 {
879 bzero( (char*) dstlin1, h * dst->linelongs * sizeof(u_int32_t) );
880 return 0;
881 }
882 #endif /*BCOPY_FASTER*/
883
884 color = RAS_GETCOLOR( rop );
885 if ( color == 0 )
886 color = 255;
887
888 /* Make 32 bits of color so we can do the ROP without shifting. */
889 color |= ( color << 24 ) | ( color << 16 ) | ( color << 8 );
890
891 dstleftignore = ( dx & 3 ) * 8;
892 dstlongs = ( dstleftignore + w * 8 + 31 ) >> 5;
893 dstrightignore = ( dstlongs * 32 - w * 8 - dstleftignore ) & 31;
894
895 dstlin2 = dstlin1 + h * dst->linelongs;
896 dstlin = dstlin1;
897
898 if ( dstlongs == 1 )
899 {
900 /* It fits into a single longword. */
901 lm = leftmask[dstleftignore] | rightmask[dstrightignore];
902 nlm = ~lm;
903 while ( dstlin != dstlin2 )
904 {
905 ROP_DSTCOLOR(
906 /*op*/ op,
907 /*pre*/ dl = *dstlin;,
908 /*d*/ dl,
909 /*c*/ color,
910 /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
911
912 dstlin += dst->linelongs;
913 }
914 }
915 else
916 {
917 lm = leftmask[dstleftignore];
918 rm = rightmask[dstrightignore];
919 nrm = ~rm;
920 nlm = ~lm;
921 while ( dstlin != dstlin2 )
922 {
923 dstlong = dstlin;
924 dstlong2 = dstlong + dstlongs;
925 if ( dstrightignore != 0 )
926 --dstlong2;
927
928 /* Leading edge. */
929 if ( dstleftignore != 0 )
930 {
931 ROP_DSTCOLOR(
932 /*op*/ op,
933 /*pre*/ dl = *dstlong;,
934 /*d*/ dl,
935 /*c*/ color,
936 /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
937 ++dstlong;
938 }
939
940 /* Main rop. */
941 ROP_DSTCOLOR(
942 /*op*/ op,
943 /*pre*/ while ( dstlong != dstlong2 )
944 {,
945 /*d*/ *dstlong,
946 /*c*/ color,
947 /*pst*/ ++dstlong;
948 } )
949
950 /* Trailing edge. */
951 if ( dstrightignore != 0 )
952 {
953 ROP_DSTCOLOR(
954 /*op*/ op,
955 /*pre*/ dl = *dstlong;,
956 /*d*/ dl,
957 /*c*/ color,
958 /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
959 }
960
961 dstlin += dst->linelongs;
962 }
963 }
964 }
965
966 return 0;
967 }
968
969 /* This is a general bitblit routine, handling overlapping source and
970 ** destination. It's used for both the 1-to-1 and 8-to-8 cases.
971 */
972 static int
973 raster_blit( src, srclin1, srcleftignore, srcrightignore, srclongs, dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op )
974 struct raster* src;
975 u_int32_t* srclin1;
976 int srcleftignore, srcrightignore, srclongs;
977 struct raster* dst;
978 u_int32_t* dstlin1;
979 int dstleftignore, dstrightignore, dstlongs;
980 int h, op;
981 {
982 u_int32_t* srclin2;
983 u_int32_t* dstlin2;
984 int srclininc, dstlininc;
985 u_int32_t* srclin;
986 u_int32_t* dstlin;
987 register int prevleftshift, currrightshift;
988 int longinc;
989 register u_int32_t* srclong;
990 register u_int32_t* dstlong;
991 register u_int32_t* dstlong2;
992 register u_int32_t dl, lm, nlm, rm, nrm;
993
994 prevleftshift = ( srcleftignore - dstleftignore ) & 31;
995
996 srclin2 = srclin1 + h * src->linelongs;
997 dstlin2 = dstlin1 + h * dst->linelongs;
998 srclininc = src->linelongs;
999 dstlininc = dst->linelongs;
1000 longinc = 1;
1001
1002 /* Check for overlaps. */
1003 if ( ( dstlin1 >= srclin1 && dstlin1 < srclin1 + srclongs ) ||
1004 ( srclin1 >= dstlin1 && srclin1 < dstlin1 + dstlongs ) )
1005 {
1006 /* Horizontal overlap. Should we reverse? */
1007 if ( srclin1 < dstlin1 )
1008 {
1009 longinc = -1;
1010 srclin1 += srclongs - 1;
1011 srclin2 += srclongs - 1;
1012 dstlin1 += dstlongs - 1;
1013 }
1014 }
1015 else if ( ( dstlin1 >= srclin1 && dstlin1 < srclin2 ) ||
1016 ( srclin1 >= dstlin1 && srclin1 < dstlin2 ) )
1017 {
1018 /* Vertical overlap. Should we reverse? */
1019 if ( srclin1 < dstlin1 )
1020 {
1021 srclin2 = srclin1 - srclininc;
1022 srclin1 += ( h - 1 ) * srclininc;
1023 dstlin1 += ( h - 1 ) * dstlininc;
1024 srclininc = -srclininc;
1025 dstlininc = -dstlininc;
1026 }
1027 }
1028 srclin = srclin1;
1029 dstlin = dstlin1;
1030
1031 if ( prevleftshift == 0 )
1032 {
1033 /* The bits line up, no shifting necessary. */
1034 if ( dstlongs == 1 )
1035 {
1036 /* It all fits into a single longword. */
1037 lm = leftmask[dstleftignore] | rightmask[dstrightignore];
1038 nlm = ~lm;
1039 while ( srclin != srclin2 )
1040 {
1041 ROP_SRCDST(
1042 /*op*/ op,
1043 /*pre*/ dl = *dstlin;,
1044 /*s*/ *srclin,
1045 /*d*/ dl,
1046 /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
1047
1048 srclin += srclininc;
1049 dstlin += dstlininc;
1050 }
1051 }
1052 else
1053 {
1054 /* Multiple longwords. */
1055 lm = leftmask[dstleftignore];
1056 rm = rightmask[dstrightignore];
1057 nrm = ~rm;
1058 nlm = ~lm;
1059 if ( longinc == 1 )
1060 {
1061 /* Left to right. */
1062 while ( srclin != srclin2 )
1063 {
1064 srclong = srclin;
1065 dstlong = dstlin;
1066 dstlong2 = dstlong + dstlongs;
1067 if ( dstrightignore != 0 )
1068 --dstlong2;
1069
1070 /* Leading edge. */
1071 if ( dstleftignore != 0 )
1072 {
1073 ROP_SRCDST(
1074 /*op*/ op,
1075 /*pre*/ dl = *dstlong;,
1076 /*s*/ *srclong,
1077 /*d*/ dl,
1078 /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
1079 ++srclong;
1080 ++dstlong;
1081 }
1082
1083 /* Main rop. */
1084 ROP_SRCDST(
1085 /*op*/ op,
1086 /*pre*/ while ( dstlong != dstlong2 )
1087 {,
1088 /*s*/ *srclong,
1089 /*d*/ *dstlong,
1090 /*pst*/ ++srclong;
1091 ++dstlong;
1092 } )
1093
1094 /* Trailing edge. */
1095 if ( dstrightignore != 0 )
1096 {
1097 ROP_SRCDST(
1098 /*op*/ op,
1099 /*pre*/ dl = *dstlong;,
1100 /*s*/ *srclong,
1101 /*d*/ dl,
1102 /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
1103 }
1104
1105 srclin += srclininc;
1106 dstlin += dstlininc;
1107 }
1108 }
1109 else
1110 {
1111 /* Right to left. */
1112 while ( srclin != srclin2 )
1113 {
1114 srclong = srclin;
1115 dstlong = dstlin;
1116 dstlong2 = dstlong - dstlongs;
1117 if ( dstleftignore != 0 )
1118 ++dstlong2;
1119
1120 /* Leading edge. */
1121 if ( dstrightignore != 0 )
1122 {
1123 ROP_SRCDST(
1124 /*op*/ op,
1125 /*pre*/ dl = *dstlong;,
1126 /*s*/ *srclong,
1127 /*d*/ dl,
1128 /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
1129 --srclong;
1130 --dstlong;
1131 }
1132
1133 /* Main rop. */
1134 ROP_SRCDST(
1135 /*op*/ op,
1136 /*pre*/ while ( dstlong != dstlong2 )
1137 {,
1138 /*s*/ *srclong,
1139 /*d*/ *dstlong,
1140 /*pst*/ --srclong;
1141 --dstlong;
1142 } )
1143
1144 /* Trailing edge. */
1145 if ( dstleftignore != 0 )
1146 {
1147 ROP_SRCDST(
1148 /*op*/ op,
1149 /*pre*/ dl = *dstlong;,
1150 /*s*/ *srclong,
1151 /*d*/ dl,
1152 /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
1153 }
1154
1155 srclin += srclininc;
1156 dstlin += dstlininc;
1157 }
1158 }
1159 }
1160 }
1161
1162 else
1163 {
1164 /* General case, with shifting and everything. */
1165 register u_int32_t sl, prevsl;
1166
1167 currrightshift = 32 - prevleftshift;
1168 if ( srclongs == 1 && dstlongs == 1 )
1169 {
1170 /* It fits into a single longword, with a shift. */
1171 lm = leftmask[dstleftignore] | rightmask[dstrightignore];
1172 nlm = ~lm;
1173 if ( srcleftignore > dstleftignore )
1174 {
1175 while ( srclin != srclin2 )
1176 {
1177 ROP_SRCDST(
1178 /*op*/ op,
1179 /*pre*/ dl = *dstlin;,
1180 /*s*/ *srclin LSOP prevleftshift,
1181 /*d*/ dl,
1182 /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
1183
1184 srclin += srclininc;
1185 dstlin += dstlininc;
1186 }
1187 }
1188 else
1189 {
1190 while ( srclin != srclin2 )
1191 {
1192 ROP_SRCDST(
1193 /*op*/ op,
1194 /*pre*/ dl = *dstlin;,
1195 /*s*/ *srclin RSOP currrightshift,
1196 /*d*/ dl,
1197 /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
1198
1199 srclin += srclininc;
1200 dstlin += dstlininc;
1201 }
1202 }
1203 }
1204 else
1205 {
1206 /* Multiple longwords. */
1207 lm = leftmask[dstleftignore];
1208 rm = rightmask[dstrightignore];
1209 nrm = ~rm;
1210 nlm = ~lm;
1211 if ( longinc == 1 )
1212 {
1213 /* Left to right. */
1214 while ( srclin != srclin2 )
1215 {
1216 srclong = srclin;
1217 dstlong = dstlin;
1218 dstlong2 = dstlong + dstlongs;
1219 if ( srcleftignore > dstleftignore )
1220 prevsl = *srclong++ LSOP prevleftshift;
1221 else
1222 prevsl = 0;
1223 if ( dstrightignore != 0 )
1224 --dstlong2;
1225
1226 /* Leading edge. */
1227 if ( dstleftignore != 0 )
1228 {
1229 ROP_SRCDST(
1230 /*op*/ op,
1231 /*pre*/ sl = *srclong;
1232 dl = *dstlong;,
1233 /*s*/ prevsl | ( sl RSOP currrightshift ),
1234 /*d*/ dl,
1235 /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
1236 prevsl = sl LSOP prevleftshift;
1237 ++srclong;
1238 ++dstlong;
1239 }
1240
1241 /* Main rop. */
1242 ROP_SRCDST(
1243 /*op*/ op,
1244 /*pre*/ while ( dstlong != dstlong2 )
1245 {
1246 sl = *srclong;,
1247 /*s*/ prevsl | ( sl RSOP currrightshift ),
1248 /*d*/ *dstlong,
1249 /*pst*/ prevsl = sl LSOP prevleftshift;
1250 ++srclong;
1251 ++dstlong;
1252 } )
1253
1254 /* Trailing edge. */
1255 if ( dstrightignore != 0 )
1256 {
1257 ROP_SRCDST(
1258 /*op*/ op,
1259 /*pre*/ dl = *dstlong;,
1260 /*s*/ prevsl | ( *srclong RSOP currrightshift ),
1261 /*d*/ dl,
1262 /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
1263 }
1264
1265 srclin += srclininc;
1266 dstlin += dstlininc;
1267 }
1268 }
1269 else
1270 {
1271 /* Right to left. */
1272 while ( srclin != srclin2 )
1273 {
1274 srclong = srclin;
1275 dstlong = dstlin;
1276 dstlong2 = dstlong - dstlongs;
1277 if ( srcrightignore > dstrightignore )
1278 prevsl = *srclong-- RSOP currrightshift;
1279 else
1280 prevsl = 0;
1281 if ( dstleftignore != 0 )
1282 ++dstlong2;
1283
1284 /* Leading edge. */
1285 if ( dstrightignore != 0 )
1286 {
1287 ROP_SRCDST(
1288 /*op*/ op,
1289 /*pre*/ sl = *srclong;
1290 dl = *dstlong;,
1291 /*s*/ prevsl | ( sl LSOP prevleftshift ),
1292 /*d*/ dl,
1293 /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
1294 prevsl = sl RSOP currrightshift;
1295 --srclong;
1296 --dstlong;
1297 }
1298
1299 /* Main rop. */
1300 ROP_SRCDST(
1301 /*op*/ op,
1302 /*pre*/ while ( dstlong != dstlong2 )
1303 {
1304 sl = *srclong;,
1305 /*s*/ prevsl | ( sl LSOP prevleftshift ),
1306 /*d*/ *dstlong,
1307 /*pst*/ prevsl = sl RSOP currrightshift;
1308 --srclong;
1309 --dstlong;
1310 } )
1311
1312 /* Trailing edge. */
1313 if ( dstleftignore != 0 )
1314 {
1315 ROP_SRCDST(
1316 /*op*/ op,
1317 /*pre*/ dl = *dstlong;,
1318 /*s*/ prevsl | ( *srclong LSOP prevleftshift ),
1319 /*d*/ dl,
1320 /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
1321 }
1322
1323 srclin += srclininc;
1324 dstlin += dstlininc;
1325 }
1326 }
1327 }
1328 }
1329
1330 return 0;
1331 }
1332