|
|
1.1 ! root 1: /******************************Module*Header*******************************\ ! 2: * Module Name: bitblt.c ! 3: * ! 4: * Banked Frame Buffer bitblit ! 5: * ! 6: * Copyright (c) 1992 Microsoft Corporation ! 7: * ! 8: \**************************************************************************/ ! 9: ! 10: #include "driver.h" ! 11: ! 12: /************************************************************************\ ! 13: * bIntersectRect ! 14: * ! 15: * Calculates the intersection between *prcSrc1 and *prcSrc2, ! 16: * returning the resulting rect in *prcDst. Returns TRUE if ! 17: * *prcSrc1 intersects *prcSrc2, FALSE otherwise. If there is no ! 18: * intersection, an empty rect is returned in *prcDst. ! 19: \************************************************************************/ ! 20: ! 21: static const RECTL rclEmpty = { 0, 0, 0, 0 }; ! 22: ! 23: BOOL bIntersectRect( ! 24: PRECTL prcDst, ! 25: PRECTL prcSrc1, ! 26: PRECTL prcSrc2) ! 27: ! 28: { ! 29: prcDst->left = max(prcSrc1->left, prcSrc2->left); ! 30: prcDst->right = min(prcSrc1->right, prcSrc2->right); ! 31: ! 32: // check for empty rect ! 33: ! 34: if (prcDst->left < prcDst->right) ! 35: { ! 36: prcDst->top = max(prcSrc1->top, prcSrc2->top); ! 37: prcDst->bottom = min(prcSrc1->bottom, prcSrc2->bottom); ! 38: ! 39: // check for empty rect ! 40: ! 41: if (prcDst->top < prcDst->bottom) ! 42: return(TRUE); // not empty ! 43: } ! 44: ! 45: // empty rect ! 46: ! 47: *prcDst = rclEmpty; ! 48: ! 49: return(FALSE); ! 50: } ! 51: ! 52: /******************************Public*Routine******************************\ ! 53: * BOOL bPuntScreenToScreenCopyBits(ppdev, pco, pxlo, prclDest, pptlSrc) ! 54: * ! 55: * Performs a screen-to-screen CopyBits entirely using an intermediate ! 56: * temporary buffer and GDI. ! 57: * ! 58: * We found that on most machines it was faster to have the engine copy ! 59: * the source to a buffer, then blit the buffer to the destination, than ! 60: * to have optimized ASM code that copies a word at a time. The reason? ! 61: * The engine does d-word moves, which are faster than word moves even ! 62: * going over the bus to a 16 bit display device. ! 63: * ! 64: * We could also write optimized ASM code that does d-word moves, but the ! 65: * win will be marginal, we're time constrained, we also need a routine ! 66: * like this to handle complex clip objects and palette translates, and ! 67: * most of the other times we can use planar copies for important things ! 68: * like scrolls, anyways. ! 69: * ! 70: \**************************************************************************/ ! 71: ! 72: BOOL bPuntScreenToScreenCopyBits( ! 73: PPDEV ppdev, ! 74: CLIPOBJ* pco, ! 75: XLATEOBJ* pxlo, ! 76: RECTL* prclDest, ! 77: POINTL* pptlSrc) ! 78: { ! 79: RECTL rclDest; ! 80: POINTL ptlSrc; ! 81: BOOL b = TRUE; ! 82: ! 83: SURFOBJ* pso = ppdev->pSurfObj; ! 84: SURFOBJ* psoTmp = ppdev->psoTmp; ! 85: ! 86: if (prclDest->top < pptlSrc->y) ! 87: { ! 88: //////////////////////////////////////////////////////////////// ! 89: // Do a top-to-bottom copy: ! 90: //////////////////////////////////////////////////////////////// ! 91: ! 92: LONG ySrcBottom; ! 93: LONG yDestBottom; ! 94: ! 95: LONG yDestTop = prclDest->top; ! 96: LONG ySrcTop = pptlSrc->y; ! 97: LONG ySrcLast = ySrcTop + (prclDest->bottom - prclDest->top); ! 98: ! 99: if (ySrcTop < ppdev->rcl1WindowClip.top || ! 100: ySrcTop >= ppdev->rcl1WindowClip.bottom) ! 101: { ! 102: ppdev->pfnBankControl(ppdev, ySrcTop, JustifyTop); ! 103: } ! 104: ! 105: pso->pvScan0 = ppdev->pvBitmapStart; ! 106: ! 107: while (TRUE) ! 108: { ! 109: // Copy an entire source bank into the temporary buffer: ! 110: ! 111: ySrcBottom = min(ySrcLast, ppdev->rcl1WindowClip.bottom); ! 112: ! 113: ptlSrc.x = pptlSrc->x; ! 114: ptlSrc.y = ySrcTop; ! 115: ! 116: rclDest.left = prclDest->left; ! 117: rclDest.top = 0; ! 118: rclDest.right = prclDest->right; ! 119: rclDest.bottom = ySrcBottom - ySrcTop; ! 120: ! 121: b &= EngCopyBits(psoTmp, pso, NULL, NULL, &rclDest, &ptlSrc); ! 122: ! 123: yDestBottom = yDestTop + rclDest.bottom; ! 124: ! 125: if (ppdev->rcl1WindowClip.top >= yDestBottom) ! 126: { ! 127: ppdev->pfnBankControl(ppdev, yDestBottom - 1, JustifyBottom); ! 128: pso->pvScan0 = ppdev->pvBitmapStart; ! 129: } ! 130: ! 131: while (TRUE) ! 132: { ! 133: // Copy the temporary buffer into one or more destination ! 134: // banks: ! 135: ! 136: LONG yThisTop; ! 137: LONG yThisBottom; ! 138: LONG yOffset; ! 139: ! 140: yThisBottom = min(yDestBottom, ppdev->rcl1WindowClip.bottom); ! 141: yThisTop = max(yDestTop, ppdev->rcl1WindowClip.top); ! 142: yOffset = yThisTop - yDestTop; ! 143: ! 144: ptlSrc.x = prclDest->left; ! 145: ptlSrc.y = yOffset; ! 146: ! 147: rclDest.left = prclDest->left; ! 148: rclDest.top = yThisTop; ! 149: rclDest.right = prclDest->right; ! 150: rclDest.bottom = yThisBottom; ! 151: ! 152: b &= EngCopyBits(pso, psoTmp, pco, pxlo, &rclDest, &ptlSrc); ! 153: ! 154: if (yOffset == 0) ! 155: break; ! 156: ! 157: ppdev->pfnBankControl(ppdev, yThisTop - 1, JustifyBottom); ! 158: pso->pvScan0 = ppdev->pvBitmapStart; ! 159: } ! 160: ! 161: if (ySrcBottom >= ySrcLast) ! 162: break; ! 163: ! 164: yDestTop = yDestBottom; ! 165: ySrcTop = ySrcBottom; ! 166: ! 167: ppdev->pfnBankControl(ppdev, ySrcTop, JustifyTop); ! 168: pso->pvScan0 = ppdev->pvBitmapStart; ! 169: } ! 170: } ! 171: else ! 172: { ! 173: //////////////////////////////////////////////////////////////// ! 174: // Do a bottom-to-top copy: ! 175: //////////////////////////////////////////////////////////////// ! 176: ! 177: LONG ySrcTop; ! 178: LONG yDestTop; ! 179: ! 180: LONG yDestBottom = prclDest->bottom; ! 181: LONG ySrcFirst = pptlSrc->y; ! 182: LONG ySrcBottom = ySrcFirst + (prclDest->bottom - prclDest->top); ! 183: ! 184: if (ySrcBottom <= ppdev->rcl1WindowClip.top || ! 185: ySrcBottom > ppdev->rcl1WindowClip.bottom) ! 186: { ! 187: ppdev->pfnBankControl(ppdev, ySrcBottom - 1, JustifyBottom); ! 188: } ! 189: ! 190: pso->pvScan0 = ppdev->pvBitmapStart; ! 191: ! 192: while (TRUE) ! 193: { ! 194: // Copy an entire source bank into the temporary buffer: ! 195: ! 196: ySrcTop = max(ySrcFirst, ppdev->rcl1WindowClip.top); ! 197: ! 198: ptlSrc.x = pptlSrc->x; ! 199: ptlSrc.y = ySrcTop; ! 200: ! 201: rclDest.left = prclDest->left; ! 202: rclDest.top = 0; ! 203: rclDest.right = prclDest->right; ! 204: rclDest.bottom = ySrcBottom - ySrcTop; ! 205: ! 206: b &= EngCopyBits(psoTmp, pso, NULL, NULL, &rclDest, &ptlSrc); ! 207: ! 208: yDestTop = yDestBottom - rclDest.bottom; ! 209: ! 210: if (ppdev->rcl1WindowClip.bottom <= yDestTop) ! 211: { ! 212: ppdev->pfnBankControl(ppdev, yDestTop, JustifyTop); ! 213: pso->pvScan0 = ppdev->pvBitmapStart; ! 214: } ! 215: ! 216: while (TRUE) ! 217: { ! 218: // Copy the temporary buffer into one or more destination ! 219: // banks: ! 220: ! 221: LONG yThisTop; ! 222: LONG yThisBottom; ! 223: LONG yOffset; ! 224: ! 225: yThisTop = max(yDestTop, ppdev->rcl1WindowClip.top); ! 226: yThisBottom = min(yDestBottom, ppdev->rcl1WindowClip.bottom); ! 227: yOffset = yThisTop - yDestTop; ! 228: ! 229: ptlSrc.x = prclDest->left; ! 230: ptlSrc.y = yOffset; ! 231: ! 232: rclDest.left = prclDest->left; ! 233: rclDest.top = yThisTop; ! 234: rclDest.right = prclDest->right; ! 235: rclDest.bottom = yThisBottom; ! 236: ! 237: b &= EngCopyBits(pso, psoTmp, pco, pxlo, &rclDest, &ptlSrc); ! 238: ! 239: if (yThisBottom == yDestBottom) ! 240: break; ! 241: ! 242: ppdev->pfnBankControl(ppdev, yThisBottom, JustifyTop); ! 243: pso->pvScan0 = ppdev->pvBitmapStart; ! 244: } ! 245: ! 246: if (ySrcTop <= ySrcFirst) ! 247: break; ! 248: ! 249: yDestBottom = yDestTop; ! 250: ySrcBottom = ySrcTop; ! 251: ! 252: ppdev->pfnBankControl(ppdev, ySrcBottom - 1, JustifyBottom); ! 253: pso->pvScan0 = ppdev->pvBitmapStart; ! 254: } ! 255: } ! 256: ! 257: return(b); ! 258: } ! 259: ! 260: /******************************Public*Routine******************************\ ! 261: * BOOL bPuntScreenToScreenBitBlt(...) ! 262: * ! 263: * Performs a screen-to-screen BitBlt entirely using an intermediate temporary ! 264: * buffer and GDI. ! 265: * ! 266: * This function is basically a clone of bPuntScreenToScreenCopyBits, ! 267: * except that it can handle funky ROPs and stuff. ! 268: \**************************************************************************/ ! 269: ! 270: BOOL bPuntScreenToScreenBitBlt( ! 271: PPDEV ppdev, ! 272: SURFOBJ* psoMask, ! 273: CLIPOBJ* pco, ! 274: XLATEOBJ* pxlo, ! 275: RECTL* prclDest, ! 276: POINTL* pptlSrc, ! 277: POINTL* pptlMask, ! 278: BRUSHOBJ* pbo, ! 279: POINTL* pptlBrush, ! 280: ROP4 rop4) ! 281: { ! 282: RECTL rclDest; // Temporary destination rectangle ! 283: POINTL ptlSrc; // Temporary source point ! 284: POINTL ptlMask; // Temporary mask offset ! 285: POINTL ptlMaskAdjust; // Adjustment for mask offset ! 286: BOOL b = TRUE; ! 287: ! 288: SURFOBJ* pso = ppdev->pSurfObj; ! 289: SURFOBJ* psoTmp = ppdev->psoTmp; ! 290: ! 291: if (psoMask != NULL) ! 292: { ! 293: ptlMaskAdjust.x = prclDest->left - pptlMask->x; ! 294: ptlMaskAdjust.y = prclDest->top - pptlMask->y; ! 295: } ! 296: ! 297: if (prclDest->top < pptlSrc->y) ! 298: { ! 299: //////////////////////////////////////////////////////////////// ! 300: // Do a top-to-bottom copy: ! 301: //////////////////////////////////////////////////////////////// ! 302: ! 303: LONG ySrcBottom; ! 304: LONG yDestBottom; ! 305: ! 306: LONG yDestTop = prclDest->top; ! 307: LONG ySrcTop = pptlSrc->y; ! 308: LONG ySrcLast = ySrcTop + (prclDest->bottom - prclDest->top); ! 309: ! 310: if (ySrcTop < ppdev->rcl1WindowClip.top || ! 311: ySrcTop >= ppdev->rcl1WindowClip.bottom) ! 312: { ! 313: ppdev->pfnBankControl(ppdev, ySrcTop, JustifyTop); ! 314: } ! 315: ! 316: pso->pvScan0 = ppdev->pvBitmapStart; ! 317: ! 318: while (TRUE) ! 319: { ! 320: // Copy an entire source bank into the temporary buffer: ! 321: ! 322: ySrcBottom = min(ySrcLast, ppdev->rcl1WindowClip.bottom); ! 323: ! 324: ptlSrc.x = pptlSrc->x; ! 325: ptlSrc.y = ySrcTop; ! 326: ! 327: rclDest.left = prclDest->left; ! 328: rclDest.top = 0; ! 329: rclDest.right = prclDest->right; ! 330: rclDest.bottom = ySrcBottom - ySrcTop; ! 331: ! 332: b &= EngCopyBits(psoTmp, pso, NULL, NULL, &rclDest, &ptlSrc); ! 333: ! 334: yDestBottom = yDestTop + rclDest.bottom; ! 335: ! 336: if (ppdev->rcl1WindowClip.top >= yDestBottom) ! 337: { ! 338: ppdev->pfnBankControl(ppdev, yDestBottom - 1, JustifyBottom); ! 339: pso->pvScan0 = ppdev->pvBitmapStart; ! 340: } ! 341: ! 342: while (TRUE) ! 343: { ! 344: // Copy the temporary buffer into one or more destination ! 345: // banks: ! 346: ! 347: LONG yThisTop; ! 348: LONG yThisBottom; ! 349: LONG yOffset; ! 350: ! 351: yThisBottom = min(yDestBottom, ppdev->rcl1WindowClip.bottom); ! 352: yThisTop = max(yDestTop, ppdev->rcl1WindowClip.top); ! 353: yOffset = yThisTop - yDestTop; ! 354: ! 355: ptlSrc.x = prclDest->left; ! 356: ptlSrc.y = yOffset; ! 357: ! 358: rclDest.left = prclDest->left; ! 359: rclDest.top = yThisTop; ! 360: rclDest.right = prclDest->right; ! 361: rclDest.bottom = yThisBottom; ! 362: ! 363: ptlMask.x = rclDest.left - ptlMaskAdjust.x; ! 364: ptlMask.y = rclDest.top - ptlMaskAdjust.y; ! 365: ! 366: b &= EngBitBlt(pso, psoTmp, psoMask, pco, pxlo, &rclDest, ! 367: &ptlSrc, &ptlMask, pbo, pptlBrush, rop4); ! 368: ! 369: if (yOffset == 0) ! 370: break; ! 371: ! 372: ppdev->pfnBankControl(ppdev, yThisTop - 1, JustifyBottom); ! 373: pso->pvScan0 = ppdev->pvBitmapStart; ! 374: } ! 375: ! 376: if (ySrcBottom >= ySrcLast) ! 377: break; ! 378: ! 379: yDestTop = yDestBottom; ! 380: ySrcTop = ySrcBottom; ! 381: ! 382: ppdev->pfnBankControl(ppdev, ySrcTop, JustifyTop); ! 383: pso->pvScan0 = ppdev->pvBitmapStart; ! 384: } ! 385: } ! 386: else ! 387: { ! 388: //////////////////////////////////////////////////////////////// ! 389: // Do a bottom-to-top copy: ! 390: //////////////////////////////////////////////////////////////// ! 391: ! 392: LONG ySrcTop; ! 393: LONG yDestTop; ! 394: ! 395: LONG yDestBottom = prclDest->bottom; ! 396: LONG ySrcFirst = pptlSrc->y; ! 397: LONG ySrcBottom = ySrcFirst + (prclDest->bottom - prclDest->top); ! 398: ! 399: if (ySrcBottom <= ppdev->rcl1WindowClip.top || ! 400: ySrcBottom > ppdev->rcl1WindowClip.bottom) ! 401: { ! 402: ppdev->pfnBankControl(ppdev, ySrcBottom - 1, JustifyBottom); ! 403: } ! 404: ! 405: pso->pvScan0 = ppdev->pvBitmapStart; ! 406: ! 407: while (TRUE) ! 408: { ! 409: // Copy an entire source bank into the temporary buffer: ! 410: ! 411: ySrcTop = max(ySrcFirst, ppdev->rcl1WindowClip.top); ! 412: ! 413: ptlSrc.x = pptlSrc->x; ! 414: ptlSrc.y = ySrcTop; ! 415: ! 416: rclDest.left = prclDest->left; ! 417: rclDest.top = 0; ! 418: rclDest.right = prclDest->right; ! 419: rclDest.bottom = ySrcBottom - ySrcTop; ! 420: ! 421: b &= EngCopyBits(psoTmp, pso, NULL, NULL, &rclDest, &ptlSrc); ! 422: ! 423: yDestTop = yDestBottom - rclDest.bottom; ! 424: ! 425: if (ppdev->rcl1WindowClip.bottom <= yDestTop) ! 426: { ! 427: ppdev->pfnBankControl(ppdev, yDestTop, JustifyTop); ! 428: pso->pvScan0 = ppdev->pvBitmapStart; ! 429: } ! 430: ! 431: while (TRUE) ! 432: { ! 433: // Copy the temporary buffer into one or more destination ! 434: // banks: ! 435: ! 436: LONG yThisTop; ! 437: LONG yThisBottom; ! 438: LONG yOffset; ! 439: ! 440: yThisTop = max(yDestTop, ppdev->rcl1WindowClip.top); ! 441: yThisBottom = min(yDestBottom, ppdev->rcl1WindowClip.bottom); ! 442: yOffset = yThisTop - yDestTop; ! 443: ! 444: ptlSrc.x = prclDest->left; ! 445: ptlSrc.y = yOffset; ! 446: ! 447: rclDest.left = prclDest->left; ! 448: rclDest.top = yThisTop; ! 449: rclDest.right = prclDest->right; ! 450: rclDest.bottom = yThisBottom; ! 451: ! 452: ptlMask.x = rclDest.left - ptlMaskAdjust.x; ! 453: ptlMask.y = rclDest.top - ptlMaskAdjust.y; ! 454: ! 455: b &= EngBitBlt(pso, psoTmp, psoMask, pco, pxlo, &rclDest, ! 456: &ptlSrc, &ptlMask, pbo, pptlBrush, rop4); ! 457: ! 458: if (yThisBottom == yDestBottom) ! 459: break; ! 460: ! 461: ppdev->pfnBankControl(ppdev, yThisBottom, JustifyTop); ! 462: pso->pvScan0 = ppdev->pvBitmapStart; ! 463: } ! 464: ! 465: if (ySrcTop <= ySrcFirst) ! 466: break; ! 467: ! 468: yDestBottom = yDestTop; ! 469: ySrcBottom = ySrcTop; ! 470: ! 471: ppdev->pfnBankControl(ppdev, ySrcBottom - 1, JustifyBottom); ! 472: pso->pvScan0 = ppdev->pvBitmapStart; ! 473: } ! 474: } ! 475: ! 476: return(b); ! 477: } ! 478: ! 479: /******************************Public*Data*********************************\ ! 480: * ROP to mix translation table ! 481: * ! 482: * Table to translate ternary raster ops to mixes (binary raster ops). Ternary ! 483: * raster ops that can't be translated to mixes are translated to 0 (0 is not ! 484: * a valid mix). ! 485: * ! 486: \**************************************************************************/ ! 487: ! 488: UCHAR jRop3ToMix[256] = { ! 489: R2_BLACK, 0, 0, 0, 0, R2_NOTMERGEPEN, 0, 0, ! 490: 0, 0, R2_MASKNOTPEN, 0, 0, 0, 0, R2_NOTCOPYPEN, ! 491: 0, 0, 0, 0, 0, 0, 0, 0, ! 492: 0, 0, 0, 0, 0, 0, 0, 0, ! 493: 0, 0, 0, 0, 0, 0, 0, 0, ! 494: 0, 0, 0, 0, 0, 0, 0, 0, ! 495: 0, 0, 0, 0, 0, 0, 0, 0, ! 496: 0, 0, 0, 0, 0, 0, 0, 0, ! 497: 0, 0, 0, 0, 0, 0, 0, 0, ! 498: 0, 0, 0, 0, 0, 0, 0, 0, ! 499: R2_MASKPENNOT, 0, 0, 0, 0, R2_NOT, 0, 0, ! 500: 0, 0, R2_XORPEN, 0, 0, 0, 0, R2_NOTMASKPEN, ! 501: 0, 0, 0, 0, 0, 0, 0, 0, ! 502: 0, 0, 0, 0, 0, 0, 0, 0, ! 503: 0, 0, 0, 0, 0, 0, 0, 0, ! 504: 0, 0, 0, 0, 0, 0, 0, 0, ! 505: 0, 0, 0, 0, 0, 0, 0, 0, ! 506: 0, 0, 0, 0, 0, 0, 0, 0, ! 507: 0, 0, 0, 0, 0, 0, 0, 0, ! 508: 0, 0, 0, 0, 0, 0, 0, 0, ! 509: R2_MASKPEN, 0, 0, 0, 0, R2_NOTXORPEN, 0, 0, ! 510: 0, 0, R2_NOP, 0, 0, 0, 0, R2_MERGENOTPEN, ! 511: 0, 0, 0, 0, 0, 0, 0, 0, ! 512: 0, 0, 0, 0, 0, 0, 0, 0, ! 513: 0, 0, 0, 0, 0, 0, 0, 0, ! 514: 0, 0, 0, 0, 0, 0, 0, 0, ! 515: 0, 0, 0, 0, 0, 0, 0, 0, ! 516: 0, 0, 0, 0, 0, 0, 0, 0, ! 517: 0, 0, 0, 0, 0, 0, 0, 0, ! 518: 0, 0, 0, 0, 0, 0, 0, 0, ! 519: R2_COPYPEN, 0, 0, 0, 0, R2_MERGEPENNOT, 0, 0, ! 520: 0, 0, R2_MERGEPEN, 0, 0, 0, 0, R2_WHITE ! 521: }; ! 522: ! 523: /******************************Public*Routine******************************\ ! 524: * BOOL DrvBitBlt(psoDest, psoSrc, psoMask, pco, pxlo, prclDest, pptlSrc, ! 525: * pptlMask, pbo, pptlBrush, rop4) ! 526: * ! 527: * This routine will handle any blit. Perhaps glacially, but it will be ! 528: * handled. ! 529: \**************************************************************************/ ! 530: ! 531: BOOL DrvBitBlt( ! 532: SURFOBJ* psoDest, ! 533: SURFOBJ* psoSrc, ! 534: SURFOBJ* psoMask, ! 535: CLIPOBJ* pco, ! 536: XLATEOBJ* pxlo, ! 537: RECTL* prclDest, ! 538: POINTL* pptlSrc, ! 539: POINTL* pptlMask, ! 540: BRUSHOBJ* pbo, ! 541: POINTL* pptlBrush, ! 542: ROP4 rop4) ! 543: { ! 544: BOOL b; ! 545: POINTL ptlSrc; ! 546: RECTL rclDest; ! 547: PPDEV ppdev; ! 548: SURFOBJ* pso; ! 549: MIX mix; // Mix, when solid fill performed ! 550: BYTE jClipping; ! 551: RECTL rclTmp; ! 552: POINTL ptlTmp; ! 553: BBENUM bben; // Clip enumerator ! 554: BOOL bMore; // Clip continuation flag ! 555: POINTL ptlMask; // Temporary mask for engine call-backs ! 556: POINTL ptlMaskAdjust; // Adjustment for mask ! 557: INT iCopyDir; ! 558: ! 559: RBRUSH_COLOR rbc; // Pointer to RBRUSH or iSolidColor value ! 560: PFNFILL pfnFill = vTrgBlt; // Pointer to appropriate fill routine ! 561: // (solid color by default) ! 562: ! 563: // Set up the clipping type ! 564: if (pco == (CLIPOBJ *) NULL) { ! 565: // No CLIPOBJ provided, so we don't have to worry about clipping ! 566: jClipping = DC_TRIVIAL; ! 567: } else { ! 568: // Use the CLIPOBJ-provided clipping ! 569: jClipping = pco->iDComplexity; ! 570: } ! 571: ! 572: // Handle solid fills to the VGA surface with special-case code if planar ! 573: // mode is supported. ! 574: // LATER handle non-planar also ! 575: ! 576: if (psoDest->iType == STYPE_DEVICE) { ! 577: ! 578: // Destination is the VGA surface ! 579: ! 580: // Masked cases must be handled differently ! 581: ! 582: if ((((PPDEV) psoDest->dhsurf)->fl & DRIVER_PLANAR_CAPABLE) && ! 583: ((rop4 & 0xFF) == ((rop4 >> 8) & 0xFF))) { ! 584: ! 585: // Special-case static code for no-mask cases ! 586: ! 587: // Calculate mix from ROP if possible (not possible if it's truly a ! 588: // ternary rop or a real rop4, but we can treat all pure binary ! 589: // rops as mixes rather than rop4s) ! 590: mix = jRop3ToMix[rop4 & 0xFF]; ! 591: ! 592: switch (mix) { ! 593: case R2_MASKNOTPEN: ! 594: case R2_NOTCOPYPEN: ! 595: case R2_XORPEN: ! 596: case R2_MASKPEN: ! 597: case R2_NOTXORPEN: ! 598: case R2_MERGENOTPEN: ! 599: case R2_COPYPEN: ! 600: case R2_MERGEPEN: ! 601: case R2_NOTMERGEPEN: ! 602: case R2_MASKPENNOT: ! 603: case R2_NOTMASKPEN: ! 604: case R2_MERGEPENNOT: ! 605: ! 606: // vTrgBlt can only handle solid color fills ! 607: ! 608: if (pbo->iSolidColor != 0xffffffff) ! 609: { ! 610: rbc.iSolidColor = pbo->iSolidColor; ! 611: } ! 612: else ! 613: { ! 614: rbc.prb = (RBRUSH*) pbo->pvRbrush; ! 615: if (rbc.prb == NULL) ! 616: { ! 617: rbc.prb = (RBRUSH*) BRUSHOBJ_pvGetRbrush(pbo); ! 618: if (rbc.prb == NULL) ! 619: { ! 620: // If we haven't realized the brush, punt the call ! 621: // to the engine: ! 622: ! 623: break; ! 624: } ! 625: } ! 626: if (!(rbc.prb->fl & RBRUSH_BLACKWHITE) && ! 627: (mix != R2_COPYPEN)) ! 628: { ! 629: // Only black/white brushes can handle ROPs other ! 630: // than COPYPEN: ! 631: ! 632: break; ! 633: } ! 634: ! 635: if (rbc.prb->fl & RBRUSH_NCOLOR) ! 636: pfnFill = vColorPat; ! 637: else ! 638: pfnFill = vMonoPat; ! 639: } ! 640: ! 641: // Rops that are implicit solid colors ! 642: ! 643: case R2_NOT: ! 644: case R2_WHITE: ! 645: case R2_BLACK: ! 646: // We can do a special-case solid fill ! 647: ! 648: switch(jClipping) { ! 649: case DC_TRIVIAL: ! 650: ! 651: // Just fill the rectangle: ! 652: ! 653: (*pfnFill)((PPDEV) psoDest->dhsurf, 1, ! 654: prclDest, mix, rbc, pptlBrush); ! 655: ! 656: break; ! 657: ! 658: case DC_RECT: ! 659: ! 660: // Clip the solid fill to the clip rectangle ! 661: if (!bIntersectRect(&rclTmp, prclDest, ! 662: &pco->rclBounds)) ! 663: return(TRUE); ! 664: ! 665: // Fill the clipped rectangle ! 666: ! 667: (*pfnFill)((PPDEV) psoDest->dhsurf, 1, ! 668: &rclTmp, mix, rbc, pptlBrush); ! 669: ! 670: break; ! 671: ! 672: case DC_COMPLEX: ! 673: ! 674: ppdev = (PPDEV) psoDest->dhsurf; ! 675: ! 676: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, ! 677: CD_ANY, BB_RECT_LIMIT); ! 678: ! 679: do { ! 680: bMore = CLIPOBJ_bEnum(pco,(ULONG) sizeof(bben), ! 681: (PVOID) &bben); ! 682: ! 683: if (bben.c > 0) ! 684: { ! 685: RECTL* prclEnd = &bben.arcl[bben.c]; ! 686: RECTL* prcl = &bben.arcl[0]; ! 687: ! 688: do { ! 689: bIntersectRect(prcl, prcl, prclDest); ! 690: prcl++; ! 691: ! 692: } while (prcl < prclEnd); ! 693: ! 694: (*pfnFill)(ppdev, bben.c, bben.arcl, ! 695: mix, rbc, pptlBrush); ! 696: } ! 697: ! 698: } while(bMore); ! 699: } ! 700: ! 701: case R2_NOP: ! 702: return(TRUE); ! 703: ! 704: default: ! 705: break; ! 706: } ! 707: } ! 708: } ! 709: ! 710: // Get the correct surface object for the target and the source ! 711: ! 712: if (psoDest->iType == STYPE_DEVICE) { ! 713: ! 714: if ((psoSrc != NULL) && (psoSrc->iType == STYPE_DEVICE)) { ! 715: ! 716: //////////////////////////////////////////////////////////////// ! 717: // BitBlt screen-to-screen: ! 718: //////////////////////////////////////////////////////////////// ! 719: ! 720: ppdev = (PPDEV) psoDest->dhsurf; ! 721: ! 722: // See if we can do a simple CopyBits: ! 723: ! 724: if (rop4 == 0x0000CCCC) ! 725: { ! 726: ppdev = (PPDEV) psoDest->dhsurf; ! 727: ! 728: // We can handle quadpixel-aligned screen-to-screen blts with ! 729: // no translation: ! 730: ! 731: if ((((pptlSrc->x ^ prclDest->left) & 3) == 0) && ! 732: (ppdev->fl & DRIVER_PLANAR_CAPABLE) && ! 733: ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL))) ! 734: { ! 735: switch(jClipping) ! 736: { ! 737: case DC_TRIVIAL: ! 738: vPlanarCopyBits(ppdev, prclDest, pptlSrc); ! 739: return(TRUE); ! 740: ! 741: case DC_RECT: ! 742: ! 743: // Clip the target rectangle to the clip rectangle: ! 744: ! 745: if (!bIntersectRect(&rclTmp, prclDest, &pco->rclBounds)) ! 746: { ! 747: DISPDBG((0, "DrvBitBlt: Nothing to draw.")); ! 748: return(TRUE); ! 749: } ! 750: ! 751: ptlTmp.x = pptlSrc->x + rclTmp.left - prclDest->left; ! 752: ptlTmp.y = pptlSrc->y + rclTmp.top - prclDest->top; ! 753: ! 754: vPlanarCopyBits(ppdev, &rclTmp, &ptlTmp); ! 755: return(TRUE); ! 756: ! 757: case DC_COMPLEX: ! 758: if (pptlSrc->y >= prclDest->top) ! 759: { ! 760: if (pptlSrc->x >= prclDest->left) ! 761: iCopyDir = CD_RIGHTDOWN; ! 762: else ! 763: iCopyDir = CD_LEFTDOWN; ! 764: } ! 765: else ! 766: { ! 767: if (pptlSrc->x >= prclDest->left) ! 768: iCopyDir = CD_RIGHTUP; ! 769: else ! 770: iCopyDir = CD_LEFTUP; ! 771: } ! 772: ! 773: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, iCopyDir, 0); ! 774: ! 775: do { ! 776: RECTL* prcl; ! 777: RECTL* prclEnd; ! 778: ! 779: bMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(bben), ! 780: (PVOID) &bben); ! 781: ! 782: prclEnd = &bben.arcl[bben.c]; ! 783: for (prcl = bben.arcl; prcl < prclEnd; prcl++) ! 784: { ! 785: if (bIntersectRect(prcl, prclDest, prcl)) ! 786: { ! 787: ptlTmp.x = pptlSrc->x + prcl->left - prclDest->left; ! 788: ptlTmp.y = pptlSrc->y + prcl->top - prclDest->top; ! 789: ! 790: vPlanarCopyBits(ppdev, prcl, &ptlTmp); ! 791: } ! 792: } ! 793: } while (bMore); ! 794: ! 795: return(TRUE); ! 796: } ! 797: } ! 798: ! 799: // Can't handle in hardware, so punt: ! 800: ! 801: return(bPuntScreenToScreenCopyBits(ppdev, ! 802: pco, ! 803: pxlo, ! 804: prclDest, ! 805: pptlSrc)); ! 806: } ! 807: ! 808: // It's more complicated than a CopyBits, so punt it: ! 809: ! 810: return(bPuntScreenToScreenBitBlt(ppdev, ! 811: psoMask, ! 812: pco, ! 813: pxlo, ! 814: prclDest, ! 815: pptlSrc, ! 816: pptlMask, ! 817: pbo, ! 818: pptlBrush, ! 819: rop4)); ! 820: } ! 821: ! 822: //////////////////////////////////////////////////////////////// ! 823: // BitBlt to screen: ! 824: //////////////////////////////////////////////////////////////// ! 825: ! 826: ppdev = (PPDEV) psoDest->dhsurf; ! 827: ! 828: if ((rop4 == 0x0000CCCC) && ! 829: (psoSrc->iBitmapFormat == BMF_8BPP) && ! 830: ((pxlo == NULL) || (pxlo->flXlate == XO_TRIVIAL))) ! 831: { ! 832: // We have special code for the common 8bpp from memory to screen ! 833: // with no ROPs: ! 834: ! 835: switch(jClipping) ! 836: { ! 837: case DC_TRIVIAL: ! 838: vSrcCopy8bpp(ppdev, prclDest, pptlSrc, ! 839: psoSrc->lDelta, psoSrc->pvScan0); ! 840: return(TRUE); ! 841: ! 842: case DC_RECT: ! 843: ! 844: // Clip the blt to the clip rectangle ! 845: ! 846: bIntersectRect(&rclTmp, prclDest, &pco->rclBounds); ! 847: ! 848: ptlTmp.x = pptlSrc->x + rclTmp.left - prclDest->left; ! 849: ptlTmp.y = pptlSrc->y + rclTmp.top - prclDest->top; ! 850: ! 851: vSrcCopy8bpp(ppdev, &rclTmp, &ptlTmp, ! 852: psoSrc->lDelta, psoSrc->pvScan0); ! 853: ! 854: return(TRUE); ! 855: ! 856: case DC_COMPLEX: ! 857: ! 858: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, ! 859: CD_ANY, BB_RECT_LIMIT); ! 860: ! 861: do { ! 862: bMore = CLIPOBJ_bEnum(pco,(ULONG) sizeof(bben), ! 863: (PVOID) &bben); ! 864: ! 865: if (bben.c > 0) ! 866: { ! 867: RECTL* prclEnd = &bben.arcl[bben.c]; ! 868: RECTL* prcl = &bben.arcl[0]; ! 869: ! 870: do { ! 871: bIntersectRect(prcl, prcl, prclDest); ! 872: ! 873: ptlTmp.x = pptlSrc->x + prcl->left ! 874: - prclDest->left; ! 875: ptlTmp.y = pptlSrc->y + prcl->top ! 876: - prclDest->top; ! 877: ! 878: vSrcCopy8bpp(ppdev, prcl, &ptlTmp, ! 879: psoSrc->lDelta, psoSrc->pvScan0); ! 880: ! 881: prcl++; ! 882: ! 883: } while (prcl < prclEnd); ! 884: } ! 885: ! 886: } while(bMore); ! 887: ! 888: return(TRUE); ! 889: } ! 890: } ! 891: ! 892: // Punt the memory-to-screen call back to the engine: ! 893: ! 894: if (psoMask != NULL) ! 895: { ! 896: ptlMaskAdjust.x = prclDest->left - pptlMask->x; ! 897: ptlMaskAdjust.y = prclDest->top - pptlMask->y; ! 898: } ! 899: ! 900: pso = ppdev->pSurfObj; ! 901: ! 902: vBankStartBltDest(ppdev, pso, pptlSrc, prclDest, &ptlSrc, &rclDest); ! 903: ! 904: do { ! 905: ptlMask.x = rclDest.left - ptlMaskAdjust.x; ! 906: ptlMask.y = rclDest.top - ptlMaskAdjust.y; ! 907: ! 908: b = EngBitBlt(pso, ! 909: psoSrc, ! 910: psoMask, ! 911: pco, ! 912: pxlo, ! 913: &rclDest, ! 914: &ptlSrc, ! 915: &ptlMask, ! 916: pbo, ! 917: pptlBrush, ! 918: rop4); ! 919: ! 920: } while (b && bBankEnumBltDest(ppdev, pso, pptlSrc, prclDest, ! 921: &ptlSrc, &rclDest)); ! 922: ! 923: return(b); ! 924: } ! 925: else if ((psoSrc != NULL) && (psoSrc->iType == STYPE_DEVICE)) ! 926: { ! 927: //////////////////////////////////////////////////////////////// ! 928: // BitBlt from screen: ! 929: //////////////////////////////////////////////////////////////// ! 930: ! 931: if (psoMask != NULL) ! 932: { ! 933: ptlMaskAdjust.x = prclDest->left - pptlMask->x; ! 934: ptlMaskAdjust.y = prclDest->top - pptlMask->y; ! 935: } ! 936: ! 937: ppdev = (PPDEV) psoSrc->dhsurf; ! 938: pso = ppdev->pSurfObj; ! 939: ! 940: vBankStartBltSrc(ppdev, pso, pptlSrc, prclDest, &ptlSrc, &rclDest); ! 941: ! 942: do { ! 943: ptlMask.x = rclDest.left - ptlMaskAdjust.x; ! 944: ptlMask.y = rclDest.top - ptlMaskAdjust.y; ! 945: ! 946: b = EngBitBlt(psoDest, ! 947: pso, ! 948: psoMask, ! 949: pco, ! 950: pxlo, ! 951: &rclDest, ! 952: &ptlSrc, ! 953: &ptlMask, ! 954: pbo, ! 955: pptlBrush, ! 956: rop4); ! 957: ! 958: } while (b && bBankEnumBltSrc(ppdev, pso, pptlSrc, prclDest, ! 959: &ptlSrc, &rclDest)); ! 960: ! 961: return(b); ! 962: } ! 963: ! 964: RIP("Got a funky format?"); ! 965: return(FALSE); ! 966: } ! 967: ! 968: /***************************************************************************\ ! 969: * DrvCopyBits ! 970: \***************************************************************************/ ! 971: ! 972: BOOL DrvCopyBits( ! 973: SURFOBJ* psoDest, ! 974: SURFOBJ* psoSrc, ! 975: CLIPOBJ* pco, ! 976: XLATEOBJ* pxlo, ! 977: RECTL* prclDest, ! 978: POINTL* pptlSrc) ! 979: { ! 980: BOOL b; ! 981: POINTL ptlSrc; ! 982: RECTL rclDest; ! 983: PPDEV ppdev; ! 984: SURFOBJ* pso; ! 985: BBENUM bben; ! 986: BOOL bMore; ! 987: BYTE jClipping; ! 988: POINTL ptlTmp; ! 989: RECTL rclTmp; ! 990: INT iCopyDir; ! 991: ! 992: // Get the correct surface object for the target and the source ! 993: ! 994: if (psoDest->iType == STYPE_DEVICE) ! 995: { ! 996: // We have to special case screen-to-screen operations: ! 997: ! 998: if ((psoSrc != NULL) && (psoSrc->iType == STYPE_DEVICE)) ! 999: { ! 1000: ! 1001: //////////////////////////////////////////////////////////////// ! 1002: // CopyBits screen-to-screen: ! 1003: //////////////////////////////////////////////////////////////// ! 1004: ! 1005: ppdev = (PPDEV) psoDest->dhsurf; ! 1006: ! 1007: // We check to see if we can do a planar copy, because usually ! 1008: // it will be faster. But the hardware has to be capable of ! 1009: // doing it, and the source and destination must be 4-pel ! 1010: // aligned. ! 1011: ! 1012: if ((((pptlSrc->x ^ prclDest->left) & 3) == 0) && ! 1013: (ppdev->fl & DRIVER_PLANAR_CAPABLE) && ! 1014: ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL))) ! 1015: { ! 1016: jClipping = (pco != NULL) ? pco->iDComplexity : DC_TRIVIAL; ! 1017: ! 1018: switch(jClipping) ! 1019: { ! 1020: case DC_TRIVIAL: ! 1021: vPlanarCopyBits(ppdev, prclDest, pptlSrc); ! 1022: return(TRUE); ! 1023: ! 1024: case DC_RECT: ! 1025: // Clip the target rectangle to the clip rectangle: ! 1026: ! 1027: if (!bIntersectRect(&rclTmp, prclDest, &pco->rclBounds)) ! 1028: { ! 1029: DISPDBG((0, "DrvCopyBits: Nothing to draw.")); ! 1030: return(TRUE); ! 1031: } ! 1032: ! 1033: ptlTmp.x = pptlSrc->x + rclTmp.left - prclDest->left; ! 1034: ptlTmp.y = pptlSrc->y + rclTmp.top - prclDest->top; ! 1035: ! 1036: vPlanarCopyBits(ppdev, &rclTmp, &ptlTmp); ! 1037: return(TRUE); ! 1038: ! 1039: case DC_COMPLEX: ! 1040: if (pptlSrc->y >= prclDest->top) ! 1041: { ! 1042: if (pptlSrc->x >= prclDest->left) ! 1043: iCopyDir = CD_RIGHTDOWN; ! 1044: else ! 1045: iCopyDir = CD_LEFTDOWN; ! 1046: } ! 1047: else ! 1048: { ! 1049: if (pptlSrc->x >= prclDest->left) ! 1050: iCopyDir = CD_RIGHTUP; ! 1051: else ! 1052: iCopyDir = CD_LEFTUP; ! 1053: } ! 1054: ! 1055: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, iCopyDir, 0); ! 1056: ! 1057: do { ! 1058: RECTL* prcl; ! 1059: RECTL* prclEnd; ! 1060: ! 1061: bMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(bben), ! 1062: (PVOID) &bben); ! 1063: ! 1064: prclEnd = &bben.arcl[bben.c]; ! 1065: for (prcl = bben.arcl; prcl < prclEnd; prcl++) ! 1066: { ! 1067: if (bIntersectRect(prcl, prclDest, prcl)) ! 1068: { ! 1069: ptlTmp.x = pptlSrc->x + prcl->left - prclDest->left; ! 1070: ptlTmp.y = pptlSrc->y + prcl->top - prclDest->top; ! 1071: ! 1072: vPlanarCopyBits(ppdev, prcl, &ptlTmp); ! 1073: } ! 1074: } ! 1075: } while (bMore); ! 1076: ! 1077: return(TRUE); ! 1078: } ! 1079: } ! 1080: ! 1081: return(bPuntScreenToScreenCopyBits(ppdev, ! 1082: pco, ! 1083: pxlo, ! 1084: prclDest, ! 1085: pptlSrc)); ! 1086: } ! 1087: ! 1088: //////////////////////////////////////////////////////////////// ! 1089: // CopyBits to screen: ! 1090: //////////////////////////////////////////////////////////////// ! 1091: ! 1092: ppdev = (PPDEV) psoDest->dhsurf; ! 1093: ! 1094: if ((psoSrc->iBitmapFormat == BMF_8BPP) && ! 1095: ((pxlo == NULL) || (pxlo->flXlate == XO_TRIVIAL))) ! 1096: { ! 1097: // We have special code for the common 8bpp from memory to screen ! 1098: // with no ROPs: ! 1099: ! 1100: jClipping = (pco != NULL) ? pco->iDComplexity : DC_TRIVIAL; ! 1101: ! 1102: switch(jClipping) ! 1103: { ! 1104: case DC_TRIVIAL: ! 1105: vSrcCopy8bpp(ppdev, prclDest, pptlSrc, ! 1106: psoSrc->lDelta, psoSrc->pvScan0); ! 1107: return(TRUE); ! 1108: ! 1109: case DC_RECT: ! 1110: ! 1111: // Clip the blt to the clip rectangle ! 1112: ! 1113: bIntersectRect(&rclTmp, prclDest, &pco->rclBounds); ! 1114: ! 1115: ptlTmp.x = pptlSrc->x + rclTmp.left - prclDest->left; ! 1116: ptlTmp.y = pptlSrc->y + rclTmp.top - prclDest->top; ! 1117: ! 1118: vSrcCopy8bpp(ppdev, &rclTmp, &ptlTmp, ! 1119: psoSrc->lDelta, psoSrc->pvScan0); ! 1120: ! 1121: return(TRUE); ! 1122: ! 1123: case DC_COMPLEX: ! 1124: ! 1125: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, ! 1126: CD_ANY, BB_RECT_LIMIT); ! 1127: ! 1128: do { ! 1129: bMore = CLIPOBJ_bEnum(pco,(ULONG) sizeof(bben), ! 1130: (PVOID) &bben); ! 1131: ! 1132: if (bben.c > 0) ! 1133: { ! 1134: RECTL* prclEnd = &bben.arcl[bben.c]; ! 1135: RECTL* prcl = &bben.arcl[0]; ! 1136: ! 1137: do { ! 1138: bIntersectRect(prcl, prcl, prclDest); ! 1139: ! 1140: ptlTmp.x = pptlSrc->x + prcl->left ! 1141: - prclDest->left; ! 1142: ptlTmp.y = pptlSrc->y + prcl->top ! 1143: - prclDest->top; ! 1144: ! 1145: vSrcCopy8bpp(ppdev, prcl, &ptlTmp, ! 1146: psoSrc->lDelta, psoSrc->pvScan0); ! 1147: ! 1148: prcl++; ! 1149: ! 1150: } while (prcl < prclEnd); ! 1151: } ! 1152: ! 1153: } while(bMore); ! 1154: ! 1155: return(TRUE); ! 1156: } ! 1157: } ! 1158: ! 1159: // Fall back to the engine: ! 1160: ! 1161: pso = ppdev->pSurfObj; ! 1162: vBankStartBltDest(ppdev, pso, pptlSrc, prclDest, &ptlSrc, &rclDest); ! 1163: ! 1164: do { ! 1165: b = EngCopyBits(pso, ! 1166: psoSrc, ! 1167: pco, ! 1168: pxlo, ! 1169: &rclDest, ! 1170: &ptlSrc); ! 1171: ! 1172: } while (b && bBankEnumBltDest(ppdev, pso, pptlSrc, prclDest, ! 1173: &ptlSrc, &rclDest)); ! 1174: ! 1175: return(b); ! 1176: } ! 1177: else if ((psoSrc != NULL) && (psoSrc->iType == STYPE_DEVICE)) ! 1178: { ! 1179: //////////////////////////////////////////////////////////////// ! 1180: // CopyBits from screen: ! 1181: //////////////////////////////////////////////////////////////// ! 1182: ! 1183: ppdev = (PPDEV) psoSrc->dhsurf; ! 1184: pso = ppdev->pSurfObj; ! 1185: ! 1186: vBankStartBltSrc(ppdev, pso, pptlSrc, prclDest, &ptlSrc, &rclDest); ! 1187: ! 1188: do { ! 1189: b = EngCopyBits(psoDest, ! 1190: pso, ! 1191: pco, ! 1192: pxlo, ! 1193: &rclDest, ! 1194: &ptlSrc); ! 1195: ! 1196: } while (b && bBankEnumBltSrc(ppdev, pso, pptlSrc, prclDest, ! 1197: &ptlSrc, &rclDest)); ! 1198: ! 1199: return(b); ! 1200: } ! 1201: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.