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