1/* 2 * Copyright © 1998 Keith Packard 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that 7 * copyright notice and this permission notice appear in supporting 8 * documentation, and that the name of Keith Packard not be used in 9 * advertising or publicity pertaining to distribution of the software without 10 * specific, written prior permission. Keith Packard makes no 11 * representations about the suitability of this software for any purpose. It 12 * is provided "as is" without express or implied warranty. 13 * 14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 * PERFORMANCE OF THIS SOFTWARE. 21 */ 22 23#ifdef HAVE_DIX_CONFIG_H 24#include <dix-config.h> 25#endif 26 27#include "fb.h" 28 29/* 30 * Example: srcX = 13 dstX = 8 (FB unit 32 dstBpp 8) 31 * 32 * **** **** **** **** **** **** **** **** 33 * ^ 34 * ******** ******** ******** ******** 35 * ^ 36 * leftShift = 12 37 * rightShift = 20 38 * 39 * Example: srcX = 0 dstX = 8 (FB unit 32 dstBpp 8) 40 * 41 * **** **** **** **** **** **** **** **** 42 * ^ 43 * ******** ******** ******** ******** 44 * ^ 45 * 46 * leftShift = 24 47 * rightShift = 8 48 */ 49 50#define LoadBits {\ 51 if (leftShift) { \ 52 bitsRight = (src < srcEnd ? READ(src++) : 0); \ 53 bits = (FbStipLeft (bitsLeft, leftShift) | \ 54 FbStipRight(bitsRight, rightShift)); \ 55 bitsLeft = bitsRight; \ 56 } else \ 57 bits = (src < srcEnd ? READ(src++) : 0); \ 58} 59 60#ifndef FBNOPIXADDR 61 62#define LaneCases1(n,a) case n: FbLaneCase(n,a); break 63#define LaneCases2(n,a) LaneCases1(n,a); LaneCases1(n+1,a) 64#define LaneCases4(n,a) LaneCases2(n,a); LaneCases2(n+2,a) 65#define LaneCases8(n,a) LaneCases4(n,a); LaneCases4(n+4,a) 66#define LaneCases16(n,a) LaneCases8(n,a); LaneCases8(n+8,a) 67#define LaneCases32(n,a) LaneCases16(n,a); LaneCases16(n+16,a) 68#define LaneCases64(n,a) LaneCases32(n,a); LaneCases32(n+32,a) 69#define LaneCases128(n,a) LaneCases64(n,a); LaneCases64(n+64,a) 70#define LaneCases256(n,a) LaneCases128(n,a); LaneCases128(n+128,a) 71 72#if FB_SHIFT == 6 73#define LaneCases(a) LaneCases256(0,a) 74#endif 75 76#if FB_SHIFT == 5 77#define LaneCases(a) LaneCases16(0,a) 78#endif 79 80#if FB_SHIFT == 6 81CARD8 fb8Lane[256] = { 820, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 8322, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 8441, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 8560, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 8679, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 8798, 99, 100, 101, 102,103,104,105,106,107,108,109,110,111,112,113,114,115, 88116, 117, 118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133, 89134, 135, 136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151, 90152, 153, 154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169, 91170, 171, 172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187, 92188, 189, 190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205, 93206, 207, 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, 94224, 225, 226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241, 95242, 243, 244,245,246,247,248,249,250,251,252,253,254,255, 96}; 97 98CARD8 fb16Lane[256] = { 99 0x00, 0x03, 0x0c, 0x0f, 100 0x30, 0x33, 0x3c, 0x3f, 101 0xc0, 0xc3, 0xcc, 0xcf, 102 0xf0, 0xf3, 0xfc, 0xff, 103}; 104 105CARD8 fb32Lane[16] = { 106 0x00, 0x0f, 0xf0, 0xff, 107}; 108#endif 109 110#if FB_SHIFT == 5 111CARD8 fb8Lane[16] = { 112 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 113}; 114 115CARD8 fb16Lane[16] = { 116 0, 3, 12, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117}; 118 119CARD8 fb32Lane[16] = { 120 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121}; 122#endif 123 124CARD8 *fbLaneTable[33] = { 125 0, 0, 0, 0, 0, 0, 0, 0, 126 fb8Lane, 0, 0, 0, 0, 0, 0, 0, 127 fb16Lane, 0, 0, 0, 0, 0, 0, 0, 128 0, 0, 0, 0, 0, 0, 0, 0, 129 fb32Lane 130}; 131#endif 132 133void 134fbBltOne (FbStip *src, 135 FbStride srcStride, /* FbStip units per scanline */ 136 int srcX, /* bit position of source */ 137 FbBits *dst, 138 FbStride dstStride, /* FbBits units per scanline */ 139 int dstX, /* bit position of dest */ 140 int dstBpp, /* bits per destination unit */ 141 142 int width, /* width in bits of destination */ 143 int height, /* height in scanlines */ 144 145 FbBits fgand, /* rrop values */ 146 FbBits fgxor, 147 FbBits bgand, 148 FbBits bgxor) 149{ 150 const FbBits *fbBits; 151 FbBits *srcEnd; 152 int pixelsPerDst; /* dst pixels per FbBits */ 153 int unitsPerSrc; /* src patterns per FbStip */ 154 int leftShift, rightShift; /* align source with dest */ 155 FbBits startmask, endmask; /* dest scanline masks */ 156 FbStip bits=0, bitsLeft, bitsRight;/* source bits */ 157 FbStip left; 158 FbBits mask; 159 int nDst; /* dest longwords (w.o. end) */ 160 int w; 161 int n, nmiddle; 162 int dstS; /* stipple-relative dst X coordinate */ 163 Bool copy; /* accelerate dest-invariant */ 164 Bool transparent; /* accelerate 0 nop */ 165 int srcinc; /* source units consumed */ 166 Bool endNeedsLoad = FALSE; /* need load for endmask */ 167#ifndef FBNOPIXADDR 168 CARD8 *fbLane; 169#endif 170 int startbyte, endbyte; 171 172#ifdef FB_24BIT 173 if (dstBpp == 24) 174 { 175 fbBltOne24 (src, srcStride, srcX, 176 dst, dstStride, dstX, dstBpp, 177 width, height, 178 fgand, fgxor, bgand, bgxor); 179 return; 180 } 181#endif 182 183 /* 184 * Do not read past the end of the buffer! 185 */ 186 srcEnd = src + height * srcStride; 187 188 /* 189 * Number of destination units in FbBits == number of stipple pixels 190 * used each time 191 */ 192 pixelsPerDst = FB_UNIT / dstBpp; 193 194 /* 195 * Number of source stipple patterns in FbStip 196 */ 197 unitsPerSrc = FB_STIP_UNIT / pixelsPerDst; 198 199 copy = FALSE; 200 transparent = FALSE; 201 if (bgand == 0 && fgand == 0) 202 copy = TRUE; 203 else if (bgand == FB_ALLONES && bgxor == 0) 204 transparent = TRUE; 205 206 /* 207 * Adjust source and dest to nearest FbBits boundary 208 */ 209 src += srcX >> FB_STIP_SHIFT; 210 dst += dstX >> FB_SHIFT; 211 srcX &= FB_STIP_MASK; 212 dstX &= FB_MASK; 213 214 FbMaskBitsBytes(dstX, width, copy, 215 startmask, startbyte, nmiddle, endmask, endbyte); 216 217 /* 218 * Compute effective dest alignment requirement for 219 * source -- must align source to dest unit boundary 220 */ 221 dstS = dstX / dstBpp; 222 /* 223 * Compute shift constants for effective alignement 224 */ 225 if (srcX >= dstS) 226 { 227 leftShift = srcX - dstS; 228 rightShift = FB_STIP_UNIT - leftShift; 229 } 230 else 231 { 232 rightShift = dstS - srcX; 233 leftShift = FB_STIP_UNIT - rightShift; 234 } 235 /* 236 * Get pointer to stipple mask array for this depth 237 */ 238 fbBits = 0; /* unused */ 239 if (pixelsPerDst <= 8) 240 fbBits = fbStippleTable[pixelsPerDst]; 241#ifndef FBNOPIXADDR 242 fbLane = 0; 243 if (transparent && fgand == 0 && dstBpp >= 8) 244 fbLane = fbLaneTable[dstBpp]; 245#endif 246 247 /* 248 * Compute total number of destination words written, but 249 * don't count endmask 250 */ 251 nDst = nmiddle; 252 if (startmask) 253 nDst++; 254 255 dstStride -= nDst; 256 257 /* 258 * Compute total number of source words consumed 259 */ 260 261 srcinc = (nDst + unitsPerSrc - 1) / unitsPerSrc; 262 263 if (srcX > dstS) 264 srcinc++; 265 if (endmask) 266 { 267 endNeedsLoad = nDst % unitsPerSrc == 0; 268 if (endNeedsLoad) 269 srcinc++; 270 } 271 272 srcStride -= srcinc; 273 274 /* 275 * Copy rectangle 276 */ 277 while (height--) 278 { 279 w = nDst; /* total units across scanline */ 280 n = unitsPerSrc; /* units avail in single stipple */ 281 if (n > w) 282 n = w; 283 284 bitsLeft = 0; 285 if (srcX > dstS) 286 bitsLeft = READ(src++); 287 if (n) 288 { 289 /* 290 * Load first set of stipple bits 291 */ 292 LoadBits; 293 294 /* 295 * Consume stipple bits for startmask 296 */ 297 if (startmask) 298 { 299#if FB_UNIT > 32 300 if (pixelsPerDst == 16) 301 mask = FbStipple16Bits(FbLeftStipBits(bits,16)); 302 else 303#endif 304 mask = fbBits[FbLeftStipBits(bits,pixelsPerDst)]; 305#ifndef FBNOPIXADDR 306 if (fbLane) 307 { 308 fbTransparentSpan (dst, mask & startmask, fgxor, 1); 309 } 310 else 311#endif 312 { 313 if (mask || !transparent) 314 FbDoLeftMaskByteStippleRRop (dst, mask, 315 fgand, fgxor, bgand, bgxor, 316 startbyte, startmask); 317 } 318 bits = FbStipLeft (bits, pixelsPerDst); 319 dst++; 320 n--; 321 w--; 322 } 323 /* 324 * Consume stipple bits across scanline 325 */ 326 for (;;) 327 { 328 w -= n; 329 if (copy) 330 { 331 while (n--) 332 { 333#if FB_UNIT > 32 334 if (pixelsPerDst == 16) 335 mask = FbStipple16Bits(FbLeftStipBits(bits,16)); 336 else 337#endif 338 mask = fbBits[FbLeftStipBits(bits,pixelsPerDst)]; 339 WRITE(dst, FbOpaqueStipple (mask, fgxor, bgxor)); 340 dst++; 341 bits = FbStipLeft(bits, pixelsPerDst); 342 } 343 } 344 else 345 { 346#ifndef FBNOPIXADDR 347 if (fbLane) 348 { 349 while (bits && n) 350 { 351 switch (fbLane[FbLeftStipBits(bits,pixelsPerDst)]) { 352 LaneCases((CARD8 *) dst); 353 } 354 bits = FbStipLeft(bits,pixelsPerDst); 355 dst++; 356 n--; 357 } 358 dst += n; 359 } 360 else 361#endif 362 { 363 while (n--) 364 { 365 left = FbLeftStipBits(bits,pixelsPerDst); 366 if (left || !transparent) 367 { 368 mask = fbBits[left]; 369 WRITE(dst, FbStippleRRop (READ(dst), mask, 370 fgand, fgxor, bgand, bgxor)); 371 } 372 dst++; 373 bits = FbStipLeft(bits, pixelsPerDst); 374 } 375 } 376 } 377 if (!w) 378 break; 379 /* 380 * Load another set and reset number of available units 381 */ 382 LoadBits; 383 n = unitsPerSrc; 384 if (n > w) 385 n = w; 386 } 387 } 388 /* 389 * Consume stipple bits for endmask 390 */ 391 if (endmask) 392 { 393 if (endNeedsLoad) 394 { 395 LoadBits; 396 } 397#if FB_UNIT > 32 398 if (pixelsPerDst == 16) 399 mask = FbStipple16Bits(FbLeftStipBits(bits,16)); 400 else 401#endif 402 mask = fbBits[FbLeftStipBits(bits,pixelsPerDst)]; 403#ifndef FBNOPIXADDR 404 if (fbLane) 405 { 406 fbTransparentSpan (dst, mask & endmask, fgxor, 1); 407 } 408 else 409#endif 410 { 411 if (mask || !transparent) 412 FbDoRightMaskByteStippleRRop (dst, mask, 413 fgand, fgxor, bgand, bgxor, 414 endbyte, endmask); 415 } 416 } 417 dst += dstStride; 418 src += srcStride; 419 } 420} 421 422#ifdef FB_24BIT 423 424/* 425 * Crufty macros to initialize the mask array, most of this 426 * is to avoid compile-time warnings about shift overflow 427 */ 428 429#if BITMAP_BIT_ORDER == MSBFirst 430#define Mask24Pos(x,r) ((x)*24-(r)) 431#else 432#define Mask24Pos(x,r) ((x)*24-((r) ? 24 - (r) : 0)) 433#endif 434 435#define Mask24Neg(x,r) (Mask24Pos(x,r) < 0 ? -Mask24Pos(x,r) : 0) 436#define Mask24Check(x,r) (Mask24Pos(x,r) < 0 ? 0 : \ 437 Mask24Pos(x,r) >= FB_UNIT ? 0 : Mask24Pos(x,r)) 438 439#define Mask24(x,r) (Mask24Pos(x,r) < FB_UNIT ? \ 440 (Mask24Pos(x,r) < 0 ? \ 441 0xffffffU >> Mask24Neg (x,r) : \ 442 0xffffffU << Mask24Check(x,r)) : 0) 443 444#define SelMask24(b,n,r) ((((b) >> n) & 1) * Mask24(n,r)) 445 446/* 447 * Untested for MSBFirst or FB_UNIT == 32 448 */ 449 450#if FB_UNIT == 64 451#define C4_24(b,r) \ 452 (SelMask24(b,0,r) | \ 453 SelMask24(b,1,r) | \ 454 SelMask24(b,2,r) | \ 455 SelMask24(b,3,r)) 456 457#define FbStip24New(rot) (2 + (rot != 0)) 458#define FbStip24Len 4 459 460const FbBits fbStipple24Bits[3][1 << FbStip24Len] = { 461 /* rotate 0 */ 462 { 463 C4_24( 0, 0), C4_24( 1, 0), C4_24( 2, 0), C4_24( 3, 0), 464 C4_24( 4, 0), C4_24( 5, 0), C4_24( 6, 0), C4_24( 7, 0), 465 C4_24( 8, 0), C4_24( 9, 0), C4_24(10, 0), C4_24(11, 0), 466 C4_24(12, 0), C4_24(13, 0), C4_24(14, 0), C4_24(15, 0), 467 }, 468 /* rotate 8 */ 469 { 470 C4_24( 0, 8), C4_24( 1, 8), C4_24( 2, 8), C4_24( 3, 8), 471 C4_24( 4, 8), C4_24( 5, 8), C4_24( 6, 8), C4_24( 7, 8), 472 C4_24( 8, 8), C4_24( 9, 8), C4_24(10, 8), C4_24(11, 8), 473 C4_24(12, 8), C4_24(13, 8), C4_24(14, 8), C4_24(15, 8), 474 }, 475 /* rotate 16 */ 476 { 477 C4_24( 0,16), C4_24( 1,16), C4_24( 2,16), C4_24( 3,16), 478 C4_24( 4,16), C4_24( 5,16), C4_24( 6,16), C4_24( 7,16), 479 C4_24( 8,16), C4_24( 9,16), C4_24(10,16), C4_24(11,16), 480 C4_24(12,16), C4_24(13,16), C4_24(14,16), C4_24(15,16), 481 } 482}; 483 484#endif 485 486#if FB_UNIT == 32 487#define C2_24(b,r) \ 488 (SelMask24(b,0,r) | \ 489 SelMask24(b,1,r)) 490 491#define FbStip24Len 2 492#if BITMAP_BIT_ORDER == MSBFirst 493#define FbStip24New(rot) (1 + (rot == 0)) 494#else 495#define FbStip24New(rot) (1 + (rot == 8)) 496#endif 497 498const FbBits fbStipple24Bits[3][1 << FbStip24Len] = { 499 /* rotate 0 */ 500 { 501 C2_24( 0, 0), C2_24 ( 1, 0), C2_24 ( 2, 0), C2_24 ( 3, 0), 502 }, 503 /* rotate 8 */ 504 { 505 C2_24( 0, 8), C2_24 ( 1, 8), C2_24 ( 2, 8), C2_24 ( 3, 8), 506 }, 507 /* rotate 16 */ 508 { 509 C2_24( 0,16), C2_24 ( 1,16), C2_24 ( 2,16), C2_24 ( 3,16), 510 } 511}; 512#endif 513 514#if BITMAP_BIT_ORDER == LSBFirst 515 516#define FbMergeStip24Bits(left, right, new) \ 517 (FbStipLeft (left, new) | FbStipRight ((right), (FbStip24Len - (new)))) 518 519#define FbMergePartStip24Bits(left, right, llen, rlen) \ 520 (left | FbStipRight(right, llen)) 521 522#else 523 524#define FbMergeStip24Bits(left, right, new) \ 525 ((FbStipLeft (left, new) & ((1 << FbStip24Len) - 1)) | right) 526 527#define FbMergePartStip24Bits(left, right, llen, rlen) \ 528 (FbStipLeft(left, rlen) | right) 529 530#endif 531 532#define fbFirstStipBits(len,stip) {\ 533 int __len = (len); \ 534 if (len <= remain) { \ 535 stip = FbLeftStipBits(bits, len); \ 536 } else { \ 537 stip = FbLeftStipBits(bits, remain); \ 538 bits = (src < srcEnd ? READ(src++) : 0); \ 539 __len = (len) - remain; \ 540 stip = FbMergePartStip24Bits(stip, FbLeftStipBits(bits, __len), \ 541 remain, __len); \ 542 remain = FB_STIP_UNIT; \ 543 } \ 544 bits = FbStipLeft (bits, __len); \ 545 remain -= __len; \ 546} 547 548#define fbInitStipBits(offset,len,stip) {\ 549 bits = FbStipLeft (READ(src++),offset); \ 550 remain = FB_STIP_UNIT - offset; \ 551 fbFirstStipBits(len,stip); \ 552 stip = FbMergeStip24Bits (0, stip, len); \ 553} 554 555#define fbNextStipBits(rot,stip) {\ 556 int __new = FbStip24New(rot); \ 557 FbStip __right; \ 558 fbFirstStipBits(__new, __right); \ 559 stip = FbMergeStip24Bits (stip, __right, __new); \ 560 rot = FbNext24Rot (rot); \ 561} 562 563/* 564 * Use deep mask tables that incorporate rotation, pull 565 * a variable number of bits out of the stipple and 566 * reuse the right bits as needed for the next write 567 * 568 * Yes, this is probably too much code, but most 24-bpp screens 569 * have no acceleration so this code is used for stipples, copyplane 570 * and text 571 */ 572void 573fbBltOne24 (FbStip *srcLine, 574 FbStride srcStride, /* FbStip units per scanline */ 575 int srcX, /* bit position of source */ 576 FbBits *dst, 577 FbStride dstStride, /* FbBits units per scanline */ 578 int dstX, /* bit position of dest */ 579 int dstBpp, /* bits per destination unit */ 580 581 int width, /* width in bits of destination */ 582 int height, /* height in scanlines */ 583 584 FbBits fgand, /* rrop values */ 585 FbBits fgxor, 586 FbBits bgand, 587 FbBits bgxor) 588{ 589 FbStip *src, *srcEnd; 590 FbBits leftMask, rightMask, mask; 591 int nlMiddle, nl; 592 FbStip stip, bits; 593 int remain; 594 int dstS; 595 int firstlen; 596 int rot0, rot; 597 int nDst; 598 599 /* 600 * Do not read past the end of the buffer! 601 */ 602 srcEnd = srcLine + height * srcStride; 603 604 srcLine += srcX >> FB_STIP_SHIFT; 605 dst += dstX >> FB_SHIFT; 606 srcX &= FB_STIP_MASK; 607 dstX &= FB_MASK; 608 rot0 = FbFirst24Rot (dstX); 609 610 FbMaskBits (dstX, width, leftMask, nlMiddle, rightMask); 611 612 dstS = (dstX + 23) / 24; 613 firstlen = FbStip24Len - dstS; 614 615 nDst = nlMiddle; 616 if (leftMask) 617 nDst++; 618 dstStride -= nDst; 619 620 /* opaque copy */ 621 if (bgand == 0 && fgand == 0) 622 { 623 while (height--) 624 { 625 rot = rot0; 626 src = srcLine; 627 srcLine += srcStride; 628 fbInitStipBits (srcX,firstlen, stip); 629 if (leftMask) 630 { 631 mask = fbStipple24Bits[rot >> 3][stip]; 632 WRITE(dst, (READ(dst) & ~leftMask) | 633 (FbOpaqueStipple (mask, 634 FbRot24(fgxor, rot), 635 FbRot24(bgxor, rot)) 636 & leftMask)); 637 dst++; 638 fbNextStipBits(rot,stip); 639 } 640 nl = nlMiddle; 641 while (nl--) 642 { 643 mask = fbStipple24Bits[rot>>3][stip]; 644 WRITE(dst, FbOpaqueStipple (mask, 645 FbRot24(fgxor, rot), 646 FbRot24(bgxor, rot))); 647 dst++; 648 fbNextStipBits(rot,stip); 649 } 650 if (rightMask) 651 { 652 mask = fbStipple24Bits[rot >> 3][stip]; 653 WRITE(dst, (READ(dst) & ~rightMask) | 654 (FbOpaqueStipple (mask, 655 FbRot24(fgxor, rot), 656 FbRot24(bgxor, rot)) 657 & rightMask)); 658 } 659 dst += dstStride; 660 src += srcStride; 661 } 662 } 663 /* transparent copy */ 664 else if (bgand == FB_ALLONES && bgxor == 0 && fgand == 0) 665 { 666 while (height--) 667 { 668 rot = rot0; 669 src = srcLine; 670 srcLine += srcStride; 671 fbInitStipBits (srcX, firstlen, stip); 672 if (leftMask) 673 { 674 if (stip) 675 { 676 mask = fbStipple24Bits[rot >> 3][stip] & leftMask; 677 WRITE(dst, (READ(dst) & ~mask) | (FbRot24(fgxor, rot) & mask)); 678 } 679 dst++; 680 fbNextStipBits (rot, stip); 681 } 682 nl = nlMiddle; 683 while (nl--) 684 { 685 if (stip) 686 { 687 mask = fbStipple24Bits[rot>>3][stip]; 688 WRITE(dst, (READ(dst) & ~mask) | (FbRot24(fgxor,rot) & mask)); 689 } 690 dst++; 691 fbNextStipBits (rot, stip); 692 } 693 if (rightMask) 694 { 695 if (stip) 696 { 697 mask = fbStipple24Bits[rot >> 3][stip] & rightMask; 698 WRITE(dst, (READ(dst) & ~mask) | (FbRot24(fgxor, rot) & mask)); 699 } 700 } 701 dst += dstStride; 702 } 703 } 704 else 705 { 706 while (height--) 707 { 708 rot = rot0; 709 src = srcLine; 710 srcLine += srcStride; 711 fbInitStipBits (srcX, firstlen, stip); 712 if (leftMask) 713 { 714 mask = fbStipple24Bits[rot >> 3][stip]; 715 WRITE(dst, FbStippleRRopMask (READ(dst), mask, 716 FbRot24(fgand, rot), 717 FbRot24(fgxor, rot), 718 FbRot24(bgand, rot), 719 FbRot24(bgxor, rot), 720 leftMask)); 721 dst++; 722 fbNextStipBits(rot,stip); 723 } 724 nl = nlMiddle; 725 while (nl--) 726 { 727 mask = fbStipple24Bits[rot >> 3][stip]; 728 WRITE(dst, FbStippleRRop (READ(dst), mask, 729 FbRot24(fgand, rot), 730 FbRot24(fgxor, rot), 731 FbRot24(bgand, rot), 732 FbRot24(bgxor, rot))); 733 dst++; 734 fbNextStipBits(rot,stip); 735 } 736 if (rightMask) 737 { 738 mask = fbStipple24Bits[rot >> 3][stip]; 739 WRITE(dst, FbStippleRRopMask (READ(dst), mask, 740 FbRot24(fgand, rot), 741 FbRot24(fgxor, rot), 742 FbRot24(bgand, rot), 743 FbRot24(bgxor, rot), 744 rightMask)); 745 } 746 dst += dstStride; 747 } 748 } 749} 750#endif 751 752/* 753 * Not very efficient, but simple -- copy a single plane 754 * from an N bit image to a 1 bit image 755 */ 756 757void 758fbBltPlane (FbBits *src, 759 FbStride srcStride, 760 int srcX, 761 int srcBpp, 762 763 FbStip *dst, 764 FbStride dstStride, 765 int dstX, 766 767 int width, 768 int height, 769 770 FbStip fgand, 771 FbStip fgxor, 772 FbStip bgand, 773 FbStip bgxor, 774 Pixel planeMask) 775{ 776 FbBits *s; 777 FbBits pm; 778 FbBits srcMask; 779 FbBits srcMaskFirst; 780 FbBits srcMask0 = 0; 781 FbBits srcBits; 782 783 FbStip dstBits; 784 FbStip *d; 785 FbStip dstMask; 786 FbStip dstMaskFirst; 787 FbStip dstUnion; 788 int w; 789 int wt; 790 int rot0; 791 792 if (!width) 793 return; 794 795 src += srcX >> FB_SHIFT; 796 srcX &= FB_MASK; 797 798 dst += dstX >> FB_STIP_SHIFT; 799 dstX &= FB_STIP_MASK; 800 801 w = width / srcBpp; 802 803 pm = fbReplicatePixel (planeMask, srcBpp); 804#ifdef FB_24BIT 805 if (srcBpp == 24) 806 { 807 int w = 24; 808 809 rot0 = FbFirst24Rot (srcX); 810 if (srcX + w > FB_UNIT) 811 w = FB_UNIT - srcX; 812 srcMaskFirst = FbRot24(pm,rot0) & FbBitsMask(srcX,w); 813 } 814 else 815#endif 816 { 817 rot0 = 0; 818 srcMaskFirst = pm & FbBitsMask(srcX, srcBpp); 819 srcMask0 = pm & FbBitsMask(0, srcBpp); 820 } 821 822 dstMaskFirst = FbStipMask(dstX,1); 823 while (height--) 824 { 825 d = dst; 826 dst += dstStride; 827 s = src; 828 src += srcStride; 829 830 srcMask = srcMaskFirst; 831#ifdef FB_24BIT 832 if (srcBpp == 24) 833 srcMask0 = FbRot24(pm,rot0) & FbBitsMask(0, srcBpp); 834#endif 835 srcBits = READ(s++); 836 837 dstMask = dstMaskFirst; 838 dstUnion = 0; 839 dstBits = 0; 840 841 wt = w; 842 843 while (wt--) 844 { 845 if (!srcMask) 846 { 847 srcBits = READ(s++); 848#ifdef FB_24BIT 849 if (srcBpp == 24) 850 srcMask0 = FbNext24Pix(srcMask0) & FbBitsMask(0,24); 851#endif 852 srcMask = srcMask0; 853 } 854 if (!dstMask) 855 { 856 WRITE(d, FbStippleRRopMask(READ(d), dstBits, 857 fgand, fgxor, bgand, bgxor, 858 dstUnion)); 859 d++; 860 dstMask = FbStipMask(0,1); 861 dstUnion = 0; 862 dstBits = 0; 863 } 864 if (srcBits & srcMask) 865 dstBits |= dstMask; 866 dstUnion |= dstMask; 867 if (srcBpp == FB_UNIT) 868 srcMask = 0; 869 else 870 srcMask = FbScrRight(srcMask,srcBpp); 871 dstMask = FbStipRight(dstMask,1); 872 } 873 if (dstUnion) 874 WRITE(d, FbStippleRRopMask(READ(d),dstBits, 875 fgand, fgxor, bgand, bgxor, 876 dstUnion)); 877 } 878} 879 880