fbbltone.c revision 35c4bbdf
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 * Stipple masks are independent of bit/byte order as long 31 * as bitorder == byteorder. FB doesn't handle the case 32 * where these differ 33 */ 34#define BitsMask(x,w) ((FB_ALLONES << ((x) & FB_MASK)) & \ 35 (FB_ALLONES >> ((FB_UNIT - ((x) + (w))) & FB_MASK))) 36 37#define Mask(x,w) BitsMask((x)*(w),(w)) 38 39#define SelMask(b,n,w) ((((b) >> n) & 1) * Mask(n,w)) 40 41#define C1(b,w) \ 42 (SelMask(b,0,w)) 43 44#define C2(b,w) \ 45 (SelMask(b,0,w) | \ 46 SelMask(b,1,w)) 47 48#define C4(b,w) \ 49 (SelMask(b,0,w) | \ 50 SelMask(b,1,w) | \ 51 SelMask(b,2,w) | \ 52 SelMask(b,3,w)) 53 54#define C8(b,w) \ 55 (SelMask(b,0,w) | \ 56 SelMask(b,1,w) | \ 57 SelMask(b,2,w) | \ 58 SelMask(b,3,w) | \ 59 SelMask(b,4,w) | \ 60 SelMask(b,5,w) | \ 61 SelMask(b,6,w) | \ 62 SelMask(b,7,w)) 63 64static const FbBits fbStipple8Bits[256] = { 65 C8(0, 4), C8(1, 4), C8(2, 4), C8(3, 4), C8(4, 4), C8(5, 4), 66 C8(6, 4), C8(7, 4), C8(8, 4), C8(9, 4), C8(10, 4), C8(11, 4), 67 C8(12, 4), C8(13, 4), C8(14, 4), C8(15, 4), C8(16, 4), C8(17, 4), 68 C8(18, 4), C8(19, 4), C8(20, 4), C8(21, 4), C8(22, 4), C8(23, 4), 69 C8(24, 4), C8(25, 4), C8(26, 4), C8(27, 4), C8(28, 4), C8(29, 4), 70 C8(30, 4), C8(31, 4), C8(32, 4), C8(33, 4), C8(34, 4), C8(35, 4), 71 C8(36, 4), C8(37, 4), C8(38, 4), C8(39, 4), C8(40, 4), C8(41, 4), 72 C8(42, 4), C8(43, 4), C8(44, 4), C8(45, 4), C8(46, 4), C8(47, 4), 73 C8(48, 4), C8(49, 4), C8(50, 4), C8(51, 4), C8(52, 4), C8(53, 4), 74 C8(54, 4), C8(55, 4), C8(56, 4), C8(57, 4), C8(58, 4), C8(59, 4), 75 C8(60, 4), C8(61, 4), C8(62, 4), C8(63, 4), C8(64, 4), C8(65, 4), 76 C8(66, 4), C8(67, 4), C8(68, 4), C8(69, 4), C8(70, 4), C8(71, 4), 77 C8(72, 4), C8(73, 4), C8(74, 4), C8(75, 4), C8(76, 4), C8(77, 4), 78 C8(78, 4), C8(79, 4), C8(80, 4), C8(81, 4), C8(82, 4), C8(83, 4), 79 C8(84, 4), C8(85, 4), C8(86, 4), C8(87, 4), C8(88, 4), C8(89, 4), 80 C8(90, 4), C8(91, 4), C8(92, 4), C8(93, 4), C8(94, 4), C8(95, 4), 81 C8(96, 4), C8(97, 4), C8(98, 4), C8(99, 4), C8(100, 4), C8(101, 4), 82 C8(102, 4), C8(103, 4), C8(104, 4), C8(105, 4), C8(106, 4), C8(107, 4), 83 C8(108, 4), C8(109, 4), C8(110, 4), C8(111, 4), C8(112, 4), C8(113, 4), 84 C8(114, 4), C8(115, 4), C8(116, 4), C8(117, 4), C8(118, 4), C8(119, 4), 85 C8(120, 4), C8(121, 4), C8(122, 4), C8(123, 4), C8(124, 4), C8(125, 4), 86 C8(126, 4), C8(127, 4), C8(128, 4), C8(129, 4), C8(130, 4), C8(131, 4), 87 C8(132, 4), C8(133, 4), C8(134, 4), C8(135, 4), C8(136, 4), C8(137, 4), 88 C8(138, 4), C8(139, 4), C8(140, 4), C8(141, 4), C8(142, 4), C8(143, 4), 89 C8(144, 4), C8(145, 4), C8(146, 4), C8(147, 4), C8(148, 4), C8(149, 4), 90 C8(150, 4), C8(151, 4), C8(152, 4), C8(153, 4), C8(154, 4), C8(155, 4), 91 C8(156, 4), C8(157, 4), C8(158, 4), C8(159, 4), C8(160, 4), C8(161, 4), 92 C8(162, 4), C8(163, 4), C8(164, 4), C8(165, 4), C8(166, 4), C8(167, 4), 93 C8(168, 4), C8(169, 4), C8(170, 4), C8(171, 4), C8(172, 4), C8(173, 4), 94 C8(174, 4), C8(175, 4), C8(176, 4), C8(177, 4), C8(178, 4), C8(179, 4), 95 C8(180, 4), C8(181, 4), C8(182, 4), C8(183, 4), C8(184, 4), C8(185, 4), 96 C8(186, 4), C8(187, 4), C8(188, 4), C8(189, 4), C8(190, 4), C8(191, 4), 97 C8(192, 4), C8(193, 4), C8(194, 4), C8(195, 4), C8(196, 4), C8(197, 4), 98 C8(198, 4), C8(199, 4), C8(200, 4), C8(201, 4), C8(202, 4), C8(203, 4), 99 C8(204, 4), C8(205, 4), C8(206, 4), C8(207, 4), C8(208, 4), C8(209, 4), 100 C8(210, 4), C8(211, 4), C8(212, 4), C8(213, 4), C8(214, 4), C8(215, 4), 101 C8(216, 4), C8(217, 4), C8(218, 4), C8(219, 4), C8(220, 4), C8(221, 4), 102 C8(222, 4), C8(223, 4), C8(224, 4), C8(225, 4), C8(226, 4), C8(227, 4), 103 C8(228, 4), C8(229, 4), C8(230, 4), C8(231, 4), C8(232, 4), C8(233, 4), 104 C8(234, 4), C8(235, 4), C8(236, 4), C8(237, 4), C8(238, 4), C8(239, 4), 105 C8(240, 4), C8(241, 4), C8(242, 4), C8(243, 4), C8(244, 4), C8(245, 4), 106 C8(246, 4), C8(247, 4), C8(248, 4), C8(249, 4), C8(250, 4), C8(251, 4), 107 C8(252, 4), C8(253, 4), C8(254, 4), C8(255, 4), 108}; 109 110static const FbBits fbStipple4Bits[16] = { 111 C4(0, 8), C4(1, 8), C4(2, 8), C4(3, 8), C4(4, 8), C4(5, 8), 112 C4(6, 8), C4(7, 8), C4(8, 8), C4(9, 8), C4(10, 8), C4(11, 8), 113 C4(12, 8), C4(13, 8), C4(14, 8), C4(15, 8), 114}; 115 116static const FbBits fbStipple2Bits[4] = { 117 C2(0, 16), C2(1, 16), C2(2, 16), C2(3, 16), 118}; 119 120static const FbBits fbStipple1Bits[2] = { 121 C1(0, 32), C1(1, 32), 122}; 123 124#ifdef __clang__ 125/* shift overflow is intentional */ 126#pragma clang diagnostic ignored "-Wshift-overflow" 127#endif 128 129/* 130 * Example: srcX = 13 dstX = 8 (FB unit 32 dstBpp 8) 131 * 132 * **** **** **** **** **** **** **** **** 133 * ^ 134 * ******** ******** ******** ******** 135 * ^ 136 * leftShift = 12 137 * rightShift = 20 138 * 139 * Example: srcX = 0 dstX = 8 (FB unit 32 dstBpp 8) 140 * 141 * **** **** **** **** **** **** **** **** 142 * ^ 143 * ******** ******** ******** ******** 144 * ^ 145 * 146 * leftShift = 24 147 * rightShift = 8 148 */ 149 150#define LoadBits {\ 151 if (leftShift) { \ 152 bitsRight = (src < srcEnd ? READ(src++) : 0); \ 153 bits = (FbStipLeft (bitsLeft, leftShift) | \ 154 FbStipRight(bitsRight, rightShift)); \ 155 bitsLeft = bitsRight; \ 156 } else \ 157 bits = (src < srcEnd ? READ(src++) : 0); \ 158} 159 160void 161fbBltOne(FbStip * src, FbStride srcStride, /* FbStip units per scanline */ 162 int srcX, /* bit position of source */ 163 FbBits * dst, FbStride dstStride, /* FbBits units per scanline */ 164 int dstX, /* bit position of dest */ 165 int dstBpp, /* bits per destination unit */ 166 int width, /* width in bits of destination */ 167 int height, /* height in scanlines */ 168 FbBits fgand, /* rrop values */ 169 FbBits fgxor, FbBits bgand, FbBits bgxor) 170{ 171 const FbBits *fbBits; 172 FbBits *srcEnd; 173 int pixelsPerDst; /* dst pixels per FbBits */ 174 int unitsPerSrc; /* src patterns per FbStip */ 175 int leftShift, rightShift; /* align source with dest */ 176 FbBits startmask, endmask; /* dest scanline masks */ 177 FbStip bits = 0, bitsLeft, bitsRight; /* source bits */ 178 FbStip left; 179 FbBits mask; 180 int nDst; /* dest longwords (w.o. end) */ 181 int w; 182 int n, nmiddle; 183 int dstS; /* stipple-relative dst X coordinate */ 184 Bool copy; /* accelerate dest-invariant */ 185 Bool transparent; /* accelerate 0 nop */ 186 int srcinc; /* source units consumed */ 187 Bool endNeedsLoad = FALSE; /* need load for endmask */ 188 int startbyte, endbyte; 189 190 if (dstBpp == 24) { 191 fbBltOne24(src, srcStride, srcX, 192 dst, dstStride, dstX, dstBpp, 193 width, height, fgand, fgxor, bgand, bgxor); 194 return; 195 } 196 197 /* 198 * Do not read past the end of the buffer! 199 */ 200 srcEnd = src + height * srcStride; 201 202 /* 203 * Number of destination units in FbBits == number of stipple pixels 204 * used each time 205 */ 206 pixelsPerDst = FB_UNIT / dstBpp; 207 208 /* 209 * Number of source stipple patterns in FbStip 210 */ 211 unitsPerSrc = FB_STIP_UNIT / pixelsPerDst; 212 213 copy = FALSE; 214 transparent = FALSE; 215 if (bgand == 0 && fgand == 0) 216 copy = TRUE; 217 else if (bgand == FB_ALLONES && bgxor == 0) 218 transparent = TRUE; 219 220 /* 221 * Adjust source and dest to nearest FbBits boundary 222 */ 223 src += srcX >> FB_STIP_SHIFT; 224 dst += dstX >> FB_SHIFT; 225 srcX &= FB_STIP_MASK; 226 dstX &= FB_MASK; 227 228 FbMaskBitsBytes(dstX, width, copy, 229 startmask, startbyte, nmiddle, endmask, endbyte); 230 231 /* 232 * Compute effective dest alignment requirement for 233 * source -- must align source to dest unit boundary 234 */ 235 dstS = dstX / dstBpp; 236 /* 237 * Compute shift constants for effective alignement 238 */ 239 if (srcX >= dstS) { 240 leftShift = srcX - dstS; 241 rightShift = FB_STIP_UNIT - leftShift; 242 } 243 else { 244 rightShift = dstS - srcX; 245 leftShift = FB_STIP_UNIT - rightShift; 246 } 247 /* 248 * Get pointer to stipple mask array for this depth 249 */ 250 fbBits = 0; /* unused */ 251 switch (pixelsPerDst) { 252 case 8: 253 fbBits = fbStipple8Bits; 254 break; 255 case 4: 256 fbBits = fbStipple4Bits; 257 break; 258 case 2: 259 fbBits = fbStipple2Bits; 260 break; 261 case 1: 262 fbBits = fbStipple1Bits; 263 break; 264 default: 265 return; 266 } 267 268 /* 269 * Compute total number of destination words written, but 270 * don't count endmask 271 */ 272 nDst = nmiddle; 273 if (startmask) 274 nDst++; 275 276 dstStride -= nDst; 277 278 /* 279 * Compute total number of source words consumed 280 */ 281 282 srcinc = (nDst + unitsPerSrc - 1) / unitsPerSrc; 283 284 if (srcX > dstS) 285 srcinc++; 286 if (endmask) { 287 endNeedsLoad = nDst % unitsPerSrc == 0; 288 if (endNeedsLoad) 289 srcinc++; 290 } 291 292 srcStride -= srcinc; 293 294 /* 295 * Copy rectangle 296 */ 297 while (height--) { 298 w = nDst; /* total units across scanline */ 299 n = unitsPerSrc; /* units avail in single stipple */ 300 if (n > w) 301 n = w; 302 303 bitsLeft = 0; 304 if (srcX > dstS) 305 bitsLeft = READ(src++); 306 if (n) { 307 /* 308 * Load first set of stipple bits 309 */ 310 LoadBits; 311 312 /* 313 * Consume stipple bits for startmask 314 */ 315 if (startmask) { 316 mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)]; 317 if (mask || !transparent) 318 FbDoLeftMaskByteStippleRRop(dst, mask, 319 fgand, fgxor, bgand, bgxor, 320 startbyte, startmask); 321 bits = FbStipLeft(bits, pixelsPerDst); 322 dst++; 323 n--; 324 w--; 325 } 326 /* 327 * Consume stipple bits across scanline 328 */ 329 for (;;) { 330 w -= n; 331 if (copy) { 332 while (n--) { 333 mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)]; 334 WRITE(dst, FbOpaqueStipple(mask, fgxor, bgxor)); 335 dst++; 336 bits = FbStipLeft(bits, pixelsPerDst); 337 } 338 } 339 else { 340 while (n--) { 341 left = FbLeftStipBits(bits, pixelsPerDst); 342 if (left || !transparent) { 343 mask = fbBits[left]; 344 WRITE(dst, FbStippleRRop(READ(dst), mask, fgand, 345 fgxor, bgand, bgxor)); 346 } 347 dst++; 348 bits = FbStipLeft(bits, pixelsPerDst); 349 } 350 } 351 if (!w) 352 break; 353 /* 354 * Load another set and reset number of available units 355 */ 356 LoadBits; 357 n = unitsPerSrc; 358 if (n > w) 359 n = w; 360 } 361 } 362 /* 363 * Consume stipple bits for endmask 364 */ 365 if (endmask) { 366 if (endNeedsLoad) { 367 LoadBits; 368 } 369 mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)]; 370 if (mask || !transparent) 371 FbDoRightMaskByteStippleRRop(dst, mask, fgand, fgxor, 372 bgand, bgxor, endbyte, endmask); 373 } 374 dst += dstStride; 375 src += srcStride; 376 } 377} 378 379/* 380 * Crufty macros to initialize the mask array, most of this 381 * is to avoid compile-time warnings about shift overflow 382 */ 383 384#if BITMAP_BIT_ORDER == MSBFirst 385#define Mask24Pos(x,r) ((x)*24-(r)) 386#else 387#define Mask24Pos(x,r) ((x)*24-((r) ? 24 - (r) : 0)) 388#endif 389 390#define Mask24Neg(x,r) (Mask24Pos(x,r) < 0 ? -Mask24Pos(x,r) : 0) 391#define Mask24Check(x,r) (Mask24Pos(x,r) < 0 ? 0 : \ 392 Mask24Pos(x,r) >= FB_UNIT ? 0 : Mask24Pos(x,r)) 393 394#define Mask24(x,r) (Mask24Pos(x,r) < FB_UNIT ? \ 395 (Mask24Pos(x,r) < 0 ? \ 396 0xffffffU >> Mask24Neg (x,r) : \ 397 0xffffffU << Mask24Check(x,r)) : 0) 398 399#define SelMask24(b,n,r) ((((b) >> n) & 1) * Mask24(n,r)) 400 401#define C2_24(b,r) \ 402 (SelMask24(b,0,r) | \ 403 SelMask24(b,1,r)) 404 405#define FbStip24Len 2 406#if BITMAP_BIT_ORDER == MSBFirst 407#define FbStip24New(rot) (1 + (rot == 0)) 408#else 409#define FbStip24New(rot) (1 + (rot == 8)) 410#endif 411 412const FbBits fbStipple24Bits[3][1 << FbStip24Len] = { 413 /* rotate 0 */ 414 { 415 C2_24(0, 0), C2_24(1, 0), C2_24(2, 0), C2_24(3, 0), 416 }, 417 /* rotate 8 */ 418 { 419 C2_24(0, 8), C2_24(1, 8), C2_24(2, 8), C2_24(3, 8), 420 }, 421 /* rotate 16 */ 422 { 423 C2_24(0, 16), C2_24(1, 16), C2_24(2, 16), C2_24(3, 16), 424 } 425}; 426 427#if BITMAP_BIT_ORDER == LSBFirst 428 429#define FbMergeStip24Bits(left, right, new) \ 430 (FbStipLeft (left, new) | FbStipRight ((right), (FbStip24Len - (new)))) 431 432#define FbMergePartStip24Bits(left, right, llen, rlen) \ 433 (left | FbStipRight(right, llen)) 434 435#else 436 437#define FbMergeStip24Bits(left, right, new) \ 438 ((FbStipLeft (left, new) & ((1 << FbStip24Len) - 1)) | right) 439 440#define FbMergePartStip24Bits(left, right, llen, rlen) \ 441 (FbStipLeft(left, rlen) | right) 442 443#endif 444 445#define fbFirstStipBits(len,stip) {\ 446 int __len = (len); \ 447 if (len <= remain) { \ 448 stip = FbLeftStipBits(bits, len); \ 449 } else { \ 450 stip = FbLeftStipBits(bits, remain); \ 451 bits = (src < srcEnd ? READ(src++) : 0); \ 452 __len = (len) - remain; \ 453 stip = FbMergePartStip24Bits(stip, FbLeftStipBits(bits, __len), \ 454 remain, __len); \ 455 remain = FB_STIP_UNIT; \ 456 } \ 457 bits = FbStipLeft (bits, __len); \ 458 remain -= __len; \ 459} 460 461#define fbInitStipBits(offset,len,stip) {\ 462 bits = FbStipLeft (READ(src++),offset); \ 463 remain = FB_STIP_UNIT - offset; \ 464 fbFirstStipBits(len,stip); \ 465 stip = FbMergeStip24Bits (0, stip, len); \ 466} 467 468#define fbNextStipBits(rot,stip) {\ 469 int __new = FbStip24New(rot); \ 470 FbStip __right; \ 471 fbFirstStipBits(__new, __right); \ 472 stip = FbMergeStip24Bits (stip, __right, __new); \ 473 rot = FbNext24Rot (rot); \ 474} 475 476/* 477 * Use deep mask tables that incorporate rotation, pull 478 * a variable number of bits out of the stipple and 479 * reuse the right bits as needed for the next write 480 * 481 * Yes, this is probably too much code, but most 24-bpp screens 482 * have no acceleration so this code is used for stipples, copyplane 483 * and text 484 */ 485void 486fbBltOne24(FbStip * srcLine, FbStride srcStride, /* FbStip units per scanline */ 487 int srcX, /* bit position of source */ 488 FbBits * dst, FbStride dstStride, /* FbBits units per scanline */ 489 int dstX, /* bit position of dest */ 490 int dstBpp, /* bits per destination unit */ 491 int width, /* width in bits of destination */ 492 int height, /* height in scanlines */ 493 FbBits fgand, /* rrop values */ 494 FbBits fgxor, FbBits bgand, FbBits bgxor) 495{ 496 FbStip *src, *srcEnd; 497 FbBits leftMask, rightMask, mask; 498 int nlMiddle, nl; 499 FbStip stip, bits; 500 int remain; 501 int dstS; 502 int firstlen; 503 int rot0, rot; 504 int nDst; 505 506 /* 507 * Do not read past the end of the buffer! 508 */ 509 srcEnd = srcLine + height * srcStride; 510 511 srcLine += srcX >> FB_STIP_SHIFT; 512 dst += dstX >> FB_SHIFT; 513 srcX &= FB_STIP_MASK; 514 dstX &= FB_MASK; 515 rot0 = FbFirst24Rot(dstX); 516 517 FbMaskBits(dstX, width, leftMask, nlMiddle, rightMask); 518 519 dstS = (dstX + 23) / 24; 520 firstlen = FbStip24Len - dstS; 521 522 nDst = nlMiddle; 523 if (leftMask) 524 nDst++; 525 dstStride -= nDst; 526 527 /* opaque copy */ 528 if (bgand == 0 && fgand == 0) { 529 while (height--) { 530 rot = rot0; 531 src = srcLine; 532 srcLine += srcStride; 533 fbInitStipBits(srcX, firstlen, stip); 534 if (leftMask) { 535 mask = fbStipple24Bits[rot >> 3][stip]; 536 WRITE(dst, (READ(dst) & ~leftMask) | 537 (FbOpaqueStipple(mask, 538 FbRot24(fgxor, rot), FbRot24(bgxor, rot)) 539 & leftMask)); 540 dst++; 541 fbNextStipBits(rot, stip); 542 } 543 nl = nlMiddle; 544 while (nl--) { 545 mask = fbStipple24Bits[rot >> 3][stip]; 546 WRITE(dst, FbOpaqueStipple(mask, 547 FbRot24(fgxor, rot), 548 FbRot24(bgxor, rot))); 549 dst++; 550 fbNextStipBits(rot, stip); 551 } 552 if (rightMask) { 553 mask = fbStipple24Bits[rot >> 3][stip]; 554 WRITE(dst, (READ(dst) & ~rightMask) | 555 (FbOpaqueStipple(mask, 556 FbRot24(fgxor, rot), FbRot24(bgxor, rot)) 557 & rightMask)); 558 } 559 dst += dstStride; 560 src += srcStride; 561 } 562 } 563 /* transparent copy */ 564 else if (bgand == FB_ALLONES && bgxor == 0 && fgand == 0) { 565 while (height--) { 566 rot = rot0; 567 src = srcLine; 568 srcLine += srcStride; 569 fbInitStipBits(srcX, firstlen, stip); 570 if (leftMask) { 571 if (stip) { 572 mask = fbStipple24Bits[rot >> 3][stip] & leftMask; 573 WRITE(dst, 574 (READ(dst) & ~mask) | (FbRot24(fgxor, rot) & mask)); 575 } 576 dst++; 577 fbNextStipBits(rot, stip); 578 } 579 nl = nlMiddle; 580 while (nl--) { 581 if (stip) { 582 mask = fbStipple24Bits[rot >> 3][stip]; 583 WRITE(dst, 584 (READ(dst) & ~mask) | (FbRot24(fgxor, rot) & mask)); 585 } 586 dst++; 587 fbNextStipBits(rot, stip); 588 } 589 if (rightMask) { 590 if (stip) { 591 mask = fbStipple24Bits[rot >> 3][stip] & rightMask; 592 WRITE(dst, 593 (READ(dst) & ~mask) | (FbRot24(fgxor, rot) & mask)); 594 } 595 } 596 dst += dstStride; 597 } 598 } 599 else { 600 while (height--) { 601 rot = rot0; 602 src = srcLine; 603 srcLine += srcStride; 604 fbInitStipBits(srcX, firstlen, stip); 605 if (leftMask) { 606 mask = fbStipple24Bits[rot >> 3][stip]; 607 WRITE(dst, FbStippleRRopMask(READ(dst), mask, 608 FbRot24(fgand, rot), 609 FbRot24(fgxor, rot), 610 FbRot24(bgand, rot), 611 FbRot24(bgxor, rot), leftMask)); 612 dst++; 613 fbNextStipBits(rot, stip); 614 } 615 nl = nlMiddle; 616 while (nl--) { 617 mask = fbStipple24Bits[rot >> 3][stip]; 618 WRITE(dst, FbStippleRRop(READ(dst), mask, 619 FbRot24(fgand, rot), 620 FbRot24(fgxor, rot), 621 FbRot24(bgand, rot), 622 FbRot24(bgxor, rot))); 623 dst++; 624 fbNextStipBits(rot, stip); 625 } 626 if (rightMask) { 627 mask = fbStipple24Bits[rot >> 3][stip]; 628 WRITE(dst, FbStippleRRopMask(READ(dst), mask, 629 FbRot24(fgand, rot), 630 FbRot24(fgxor, rot), 631 FbRot24(bgand, rot), 632 FbRot24(bgxor, rot), rightMask)); 633 } 634 dst += dstStride; 635 } 636 } 637} 638 639/* 640 * Not very efficient, but simple -- copy a single plane 641 * from an N bit image to a 1 bit image 642 */ 643 644void 645fbBltPlane(FbBits * src, 646 FbStride srcStride, 647 int srcX, 648 int srcBpp, 649 FbStip * dst, 650 FbStride dstStride, 651 int dstX, 652 int width, 653 int height, 654 FbStip fgand, 655 FbStip fgxor, FbStip bgand, FbStip bgxor, Pixel planeMask) 656{ 657 FbBits *s; 658 FbBits pm; 659 FbBits srcMask; 660 FbBits srcMaskFirst; 661 FbBits srcMask0 = 0; 662 FbBits srcBits; 663 664 FbStip dstBits; 665 FbStip *d; 666 FbStip dstMask; 667 FbStip dstMaskFirst; 668 FbStip dstUnion; 669 int w; 670 int wt; 671 int rot0; 672 673 if (!width) 674 return; 675 676 src += srcX >> FB_SHIFT; 677 srcX &= FB_MASK; 678 679 dst += dstX >> FB_STIP_SHIFT; 680 dstX &= FB_STIP_MASK; 681 682 w = width / srcBpp; 683 684 pm = fbReplicatePixel(planeMask, srcBpp); 685 if (srcBpp == 24) { 686 int tmpw = 24; 687 688 rot0 = FbFirst24Rot(srcX); 689 if (srcX + tmpw > FB_UNIT) 690 tmpw = FB_UNIT - srcX; 691 srcMaskFirst = FbRot24(pm, rot0) & FbBitsMask(srcX, tmpw); 692 } 693 else { 694 rot0 = 0; 695 srcMaskFirst = pm & FbBitsMask(srcX, srcBpp); 696 srcMask0 = pm & FbBitsMask(0, srcBpp); 697 } 698 699 dstMaskFirst = FbStipMask(dstX, 1); 700 while (height--) { 701 d = dst; 702 dst += dstStride; 703 s = src; 704 src += srcStride; 705 706 srcMask = srcMaskFirst; 707 if (srcBpp == 24) 708 srcMask0 = FbRot24(pm, rot0) & FbBitsMask(0, srcBpp); 709 srcBits = READ(s++); 710 711 dstMask = dstMaskFirst; 712 dstUnion = 0; 713 dstBits = 0; 714 715 wt = w; 716 717 while (wt--) { 718 if (!srcMask) { 719 srcBits = READ(s++); 720 if (srcBpp == 24) 721 srcMask0 = FbNext24Pix(srcMask0) & FbBitsMask(0, 24); 722 srcMask = srcMask0; 723 } 724 if (!dstMask) { 725 WRITE(d, FbStippleRRopMask(READ(d), dstBits, 726 fgand, fgxor, bgand, bgxor, 727 dstUnion)); 728 d++; 729 dstMask = FbStipMask(0, 1); 730 dstUnion = 0; 731 dstBits = 0; 732 } 733 if (srcBits & srcMask) 734 dstBits |= dstMask; 735 dstUnion |= dstMask; 736 if (srcBpp == FB_UNIT) 737 srcMask = 0; 738 else 739 srcMask = FbScrRight(srcMask, srcBpp); 740 dstMask = FbStipRight(dstMask, 1); 741 } 742 if (dstUnion) 743 WRITE(d, FbStippleRRopMask(READ(d), dstBits, 744 fgand, fgxor, bgand, bgxor, dstUnion)); 745 } 746} 747