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