1 2 #include <win32k.h> 3 #include "../diblib/DibLib_interface.h" 4 DBG_DEFAULT_CHANNEL(GdiFont); 5 6 #define SURFOBJ_flags(pso) (CONTAINING_RECORD(pso, SURFACE, SurfObj)->flags) 7 8 // FIXME this needs to be updated, once we use the new structure 9 extern XCLIPOBJ gxcoTrivial; 10 /* 11 { 12 {0, {LONG_MIN, LONG_MIN, LONG_MAX, LONG_MAX}, DC_TRIVIAL, FC_RECT, TC_RECTANGLES, 0}, 13 0, 0, 0 14 }; 15 */ 16 17 static 18 void 19 CalculateCoordinates( 20 PBLTDATA pbltdata, 21 PRECTL prclClipped, 22 PRECTL prclOrg, 23 PPOINTL pptlSrc, 24 PPOINTL pptlMask, 25 PPOINTL pptlPat, 26 PSIZEL psizlPat) 27 { 28 ULONG cx, cy; 29 30 /* Calculate width and height of this rect */ 31 pbltdata->ulWidth = prclClipped->right - prclClipped->left; 32 pbltdata->ulHeight = prclClipped->bottom - prclClipped->top; 33 34 /* Calculate the x offset to the origin coordinates */ 35 if (pbltdata->siDst.iFormat == 0) 36 cx = (prclClipped->right - 1 - prclOrg->left); 37 else 38 cx = (prclClipped->left - prclOrg->left); 39 40 /* Calculate the y offset to the origin coordinates */ 41 if (pbltdata->dy < 0) 42 cy = (prclClipped->bottom - 1 - prclOrg->top); 43 else 44 cy = (prclClipped->top - prclOrg->top); 45 46 /* Calculate the target start point */ 47 pbltdata->siDst.ptOrig.x = prclOrg->left + cx; 48 pbltdata->siDst.ptOrig.y = prclOrg->top + cy; 49 50 /* Calculate start position for target */ 51 pbltdata->siDst.pjBase = pbltdata->siDst.pvScan0; 52 pbltdata->siDst.pjBase += pbltdata->siDst.ptOrig.y * pbltdata->siDst.lDelta; 53 pbltdata->siDst.pjBase += pbltdata->siDst.ptOrig.x * pbltdata->siDst.jBpp / 8; 54 55 if (pptlSrc) 56 { 57 /* Calculate start point and bitpointer for source */ 58 pbltdata->siSrc.ptOrig.x = pptlSrc->x + cx; 59 pbltdata->siSrc.ptOrig.y = pptlSrc->y + cy; 60 pbltdata->siSrc.pjBase = pbltdata->siSrc.pvScan0; 61 pbltdata->siSrc.pjBase += pbltdata->siSrc.ptOrig.y * pbltdata->siSrc.lDelta; 62 pbltdata->siSrc.pjBase += pbltdata->siSrc.ptOrig.x * pbltdata->siSrc.jBpp / 8; 63 } 64 65 if (pptlMask) 66 { 67 /* Calculate start point and bitpointer for mask */ 68 pbltdata->siMsk.ptOrig.x = pptlMask->x + cx; 69 pbltdata->siMsk.ptOrig.y = pptlMask->y + cy; 70 pbltdata->siMsk.pjBase = pbltdata->siMsk.pvScan0; 71 pbltdata->siMsk.pjBase += pbltdata->siMsk.ptOrig.y * pbltdata->siMsk.lDelta; 72 pbltdata->siMsk.pjBase += pbltdata->siMsk.ptOrig.x * pbltdata->siMsk.jBpp / 8; 73 } 74 75 if (pptlPat) 76 { 77 /* Calculate start point and bitpointer for pattern */ 78 pbltdata->siPat.ptOrig.x = (pptlPat->x + cx) % psizlPat->cx; 79 pbltdata->siPat.ptOrig.y = (pptlPat->y + cy) % psizlPat->cy; 80 pbltdata->siPat.pjBase = pbltdata->siPat.pvScan0; 81 82 /* Check for bottom-up case */ 83 if (pbltdata->dy < 0) 84 { 85 pbltdata->siPat.pjBase += (psizlPat->cy - 1) * pbltdata->siPat.lDelta; 86 pbltdata->siPat.ptOrig.y = psizlPat->cy - 1 - pbltdata->siPat.ptOrig.y; 87 } 88 89 /* Check for right-to-left case */ 90 if (pbltdata->siDst.iFormat == 0) 91 { 92 pbltdata->siPat.pjBase += (psizlPat->cx - 1) * pbltdata->siMsk.jBpp / 8; 93 pbltdata->siPat.ptOrig.x = psizlPat->cx - 1 - pbltdata->siPat.ptOrig.x; 94 } 95 } 96 } 97 98 BOOL 99 APIENTRY 100 EngBitBlt( 101 _Inout_ SURFOBJ *psoTrg, 102 _In_opt_ SURFOBJ *psoSrc, 103 _In_opt_ SURFOBJ *psoMask, 104 _In_opt_ CLIPOBJ *pco, 105 _In_opt_ XLATEOBJ *pxlo, 106 _In_ RECTL *prclTrg, 107 _When_(psoSrc, _In_) POINTL *pptlSrc, 108 _When_(psoMask, _In_) POINTL *pptlMask, 109 _In_opt_ BRUSHOBJ *pbo, 110 _When_(pbo, _In_) POINTL *pptlBrush, 111 _In_ ROP4 rop4) 112 { 113 BLTDATA bltdata; 114 ULONG i, iFunctionIndex, iDirection = CD_ANY; 115 RECTL rcTrg; 116 PFN_DIBFUNCTION pfnBitBlt; 117 BOOL bEnumMore; 118 RECT_ENUM rcenum; 119 PSIZEL psizlPat; 120 SURFOBJ *psoPattern; 121 122 //static int count = 0; 123 //if (++count >= 1230) __debugbreak(); 124 125 /* Sanity checks */ 126 ASSERT(psoTrg); 127 ASSERT(psoTrg->iBitmapFormat >= BMF_1BPP); 128 ASSERT(psoTrg->iBitmapFormat <= BMF_32BPP); 129 ASSERT(prclTrg); 130 ASSERT(prclTrg->left >= 0); 131 ASSERT(prclTrg->top >= 0); 132 ASSERT(prclTrg->right <= psoTrg->sizlBitmap.cx); 133 ASSERT(prclTrg->bottom <= psoTrg->sizlBitmap.cy); 134 135 rcTrg = *prclTrg; 136 137 bltdata.dy = 1; 138 bltdata.rop4 = rop4; 139 bltdata.apfnDoRop[0] = gapfnRop[ROP4_BKGND(rop4)]; 140 bltdata.apfnDoRop[1] = gapfnRop[ROP4_FGND(rop4)]; 141 if (!pxlo) pxlo = &gexloTrivial.xlo; 142 bltdata.pxlo = pxlo; 143 bltdata.pfnXlate = XLATEOBJ_pfnXlate(pxlo); 144 145 /* Check if the ROP uses a source */ 146 if (ROP4_USES_SOURCE(rop4)) 147 { 148 /* Sanity checks */ 149 ASSERT(psoSrc); 150 ASSERT(psoSrc->iBitmapFormat >= BMF_1BPP); 151 ASSERT(psoSrc->iBitmapFormat <= BMF_32BPP); 152 ASSERT(pptlSrc); 153 ASSERT(pptlSrc->x >= 0); 154 ASSERT(pptlSrc->y >= 0); 155 ASSERT(pptlSrc->x <= psoSrc->sizlBitmap.cx); 156 ASSERT(pptlSrc->y <= psoSrc->sizlBitmap.cy); 157 158 /* Check if source and target are equal */ 159 if (psoSrc == psoTrg) 160 { 161 /* Analyze the copying direction */ 162 if (rcTrg.top > pptlSrc->y) 163 { 164 /* Need to copy from bottom to top */ 165 iDirection = rcTrg.left < pptlSrc->x ? CD_RIGHTUP : CD_LEFTUP; 166 bltdata.dy = -1; 167 } 168 else 169 iDirection = rcTrg.left < pptlSrc->x ? CD_RIGHTDOWN : CD_LEFTDOWN; 170 171 /* Check for special right to left case */ 172 if ((rcTrg.top == pptlSrc->y) && (rcTrg.left > pptlSrc->x)) 173 { 174 /* Use 0 as target format to get special right to left versions */ 175 bltdata.siDst.iFormat = 0; 176 bltdata.siSrc.iFormat = psoSrc->iBitmapFormat; 177 //__debugbreak(); 178 } 179 else 180 { 181 /* Use 0 as source format to get special equal surface versions */ 182 bltdata.siDst.iFormat = psoTrg->iBitmapFormat; 183 bltdata.siSrc.iFormat = 0; 184 } 185 } 186 else 187 { 188 bltdata.siDst.iFormat = psoTrg->iBitmapFormat; 189 bltdata.siSrc.iFormat = psoSrc->iBitmapFormat; 190 } 191 192 /* Set the source format info */ 193 bltdata.siSrc.pvScan0 = psoSrc->pvScan0; 194 bltdata.siSrc.lDelta = psoSrc->lDelta; 195 bltdata.siSrc.cjAdvanceY = bltdata.dy * psoSrc->lDelta; 196 bltdata.siSrc.jBpp = gajBitsPerFormat[psoSrc->iBitmapFormat]; 197 } 198 else 199 { 200 bltdata.siDst.iFormat = psoTrg->iBitmapFormat; 201 } 202 203 /* Set the destination format info */ 204 bltdata.siDst.pvScan0 = psoTrg->pvScan0; 205 bltdata.siDst.lDelta = psoTrg->lDelta; 206 bltdata.siDst.cjAdvanceY = bltdata.dy * psoTrg->lDelta; 207 bltdata.siDst.jBpp = gajBitsPerFormat[psoTrg->iBitmapFormat]; 208 209 /* Check if the ROP uses a pattern / brush */ 210 if (ROP4_USES_PATTERN(rop4)) 211 { 212 /* Must have a brush */ 213 NT_ASSERT(pbo); // FIXME: test this! 214 215 /* Copy the solid color */ 216 bltdata.ulSolidColor = pbo->iSolidColor; 217 218 /* Check if this is a pattern brush */ 219 if (pbo->iSolidColor == 0xFFFFFFFF) 220 { 221 /* Get the realized pattern bitmap */ 222 psoPattern = BRUSHOBJ_psoPattern(pbo); 223 if (!psoPattern) 224 { 225 __debugbreak(); 226 return FALSE; 227 } 228 229 /* Set the pattern format info */ 230 bltdata.siPat.iFormat = psoPattern->iBitmapFormat; 231 bltdata.siPat.pvScan0 = psoPattern->pvScan0; 232 bltdata.siPat.lDelta = psoPattern->lDelta; 233 bltdata.siPat.cjAdvanceY = bltdata.dy * psoPattern->lDelta; 234 bltdata.siPat.jBpp = gajBitsPerFormat[psoPattern->iBitmapFormat]; 235 236 bltdata.ulPatWidth = psoPattern->sizlBitmap.cx; 237 bltdata.ulPatHeight = psoPattern->sizlBitmap.cy; 238 239 psizlPat = &psoPattern->sizlBitmap; 240 } 241 else 242 { 243 pptlBrush = NULL; 244 psizlPat = NULL; 245 } 246 } 247 else 248 { 249 pptlBrush = NULL; 250 psizlPat = NULL; 251 } 252 253 /* Check if the ROP uses a mask */ 254 if (ROP4_USES_MASK(rop4)) 255 { 256 //__debugbreak(); 257 258 /* Check if we don't have a mask surface */ 259 if (psoMask == NULL) 260 { 261 /* Must have a brush */ 262 NT_ASSERT(pbo); // FIXME: test this! 263 264 /* Check if the BRUSHOBJ can provide the mask */ 265 psoMask = BRUSHOBJ_psoMask(pbo); 266 if (psoMask == NULL) 267 { 268 /* We have no mask, assume the mask is all foreground */ 269 rop4 = (rop4 & 0xFF) || ((rop4 & 0xFF) << 8); 270 } 271 } 272 273 /* Set the mask format info */ 274 bltdata.siMsk.iFormat = psoMask->iBitmapFormat; 275 bltdata.siMsk.pvScan0 = psoMask->pvScan0; 276 bltdata.siMsk.lDelta = psoMask->lDelta; 277 bltdata.siMsk.cjAdvanceY = bltdata.dy * psoMask->lDelta; 278 bltdata.siMsk.jBpp = 1; 279 280 /* Calculate the masking function index */ 281 iFunctionIndex = ROP4_USES_PATTERN(rop4) ? 1 : 0; 282 iFunctionIndex |= ROP4_USES_SOURCE(rop4) ? 2 : 0; 283 iFunctionIndex |= ROP4_USES_DEST(rop4) ? 4 : 0; 284 285 /* Get the masking function */ 286 pfnBitBlt = gapfnMaskFunction[iFunctionIndex]; 287 } 288 else 289 { 290 /* Get the function index from the foreground ROP index*/ 291 iFunctionIndex = gajIndexPerRop[ROP4_FGND(rop4)]; 292 293 /* Get the dib function */ 294 pfnBitBlt = gapfnDibFunction[iFunctionIndex]; 295 } 296 297 /* If no clip object is given, use trivial one */ 298 if (!pco) pco = (CLIPOBJ*)&gxcoTrivial; 299 300 /* Check if we need to enumerate rects */ 301 if (pco->iDComplexity == DC_COMPLEX) 302 { 303 /* Start the enumeration of the clip object */ 304 CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, iDirection, 0); 305 bEnumMore = CLIPOBJ_bEnum(pco, sizeof(rcenum), (ULONG*)&rcenum); 306 } 307 else if (pco->iDComplexity == DC_RECT) 308 { 309 /* Use the clip bounds */ 310 rcenum.arcl[0] = pco->rclBounds; 311 rcenum.c = 1; 312 bEnumMore = FALSE; 313 } 314 else 315 { 316 /* Use the target rect */ 317 rcenum.arcl[0] = rcTrg; 318 rcenum.c = 1; 319 bEnumMore = FALSE; 320 } 321 322 /* Enter enumeration loop */ 323 while (TRUE) 324 { 325 /* Loop all rectangles we got */ 326 for (i = 0; i < rcenum.c; i++) 327 { 328 /* Intersect this rect with the target rect */ 329 if (!RECTL_bIntersectRect(&rcenum.arcl[i], &rcenum.arcl[i], &rcTrg)) 330 { 331 /* This rect is outside the bounds, continue */ 332 continue; 333 } 334 335 /* Calculate coordinates and pointers */ 336 CalculateCoordinates(&bltdata, 337 &rcenum.arcl[i], 338 prclTrg, 339 pptlSrc, 340 pptlMask, 341 pptlBrush, 342 psizlPat); 343 344 /* Call the dib function */ 345 pfnBitBlt(&bltdata); 346 } 347 348 /* Bail out, when there's nothing more to do */ 349 if(!bEnumMore) break; 350 351 /* Enumerate more rectangles */ 352 bEnumMore = CLIPOBJ_bEnum(pco, sizeof(rcenum), (ULONG*)&rcenum); 353 } 354 355 return TRUE; 356 } 357 358 359 static 360 VOID 361 AdjustOffsetAndSize( 362 _Out_ PPOINTL pptOffset, 363 _Out_ PSIZEL psizTrg, 364 _In_ PPOINTL pptlSrc, 365 _In_ PSIZEL psizSrc) 366 { 367 LONG x, y, cxMax, cyMax; 368 369 x = pptlSrc->x + pptOffset->x; 370 if (x < 0) pptOffset->x -= x, x = 0; 371 372 cxMax = psizSrc->cx - x; 373 if (psizTrg->cx > cxMax) psizTrg->cx = cxMax; 374 375 y = pptlSrc->y + pptOffset->y; 376 if (y < 0) pptOffset->y -= y, y = 0; 377 378 cyMax = psizSrc->cy - y; 379 if (psizTrg->cy > cyMax) psizTrg->cy = cyMax; 380 } 381 382 BOOL 383 APIENTRY 384 IntEngBitBlt( 385 _Inout_ SURFOBJ *psoTrg, 386 _In_opt_ SURFOBJ *psoSrc, 387 _In_opt_ SURFOBJ *psoMask, 388 _In_opt_ CLIPOBJ *pco, 389 _In_opt_ XLATEOBJ *pxlo, 390 _In_ RECTL *prclTrg, 391 _When_(psoSrc, _In_) POINTL *pptlSrc, 392 _When_(psoMask, _In_) POINTL *pptlMask, 393 _In_opt_ BRUSHOBJ *pbo, 394 _When_(pbo, _In_) POINTL *pptlBrush, 395 _In_ ROP4 rop4) 396 { 397 BOOL bResult; 398 RECTL rcClipped; 399 POINTL ptOffset, ptSrc, ptMask, ptBrush; 400 SIZEL sizTrg; 401 PFN_DrvBitBlt pfnBitBlt; 402 403 //__debugbreak(); 404 405 /* Sanity checks */ 406 ASSERT(IS_VALID_ROP4(rop4)); 407 ASSERT(psoTrg); 408 ASSERT(psoTrg->iBitmapFormat >= BMF_1BPP); 409 ASSERT(psoTrg->iBitmapFormat <= BMF_32BPP); 410 ASSERT(prclTrg); 411 412 /* Clip the target rect to the extents of the target surface */ 413 if (!RECTL_bClipRectBySize(&rcClipped, prclTrg, &psoTrg->sizlBitmap)) 414 { 415 /* Nothing left */ 416 return TRUE; 417 } 418 419 /* If no clip object is given, use trivial one */ 420 if (!pco) pco = (CLIPOBJ*)&gxcoTrivial; 421 422 /* Check if there is something to clip */ 423 if (pco->iDComplexity != DC_TRIVIAL) 424 { 425 /* Clip the target rect to the bounds of the clipping region */ 426 if (!RECTL_bIntersectRect(&rcClipped, &rcClipped, &pco->rclBounds)) 427 { 428 /* Nothing left */ 429 return TRUE; 430 } 431 } 432 433 /* Don't pass a clip object with a single rectangle */ 434 if (pco->iDComplexity == DC_RECT) pco = (CLIPOBJ*)&gxcoTrivial; 435 436 /* Calculate initial offset and size */ 437 ptOffset.x = rcClipped.left - prclTrg->left; 438 ptOffset.y = rcClipped.top - prclTrg->top; 439 sizTrg.cx = rcClipped.right - rcClipped.left; 440 sizTrg.cy = rcClipped.bottom - rcClipped.top; 441 442 /* Check if the ROP uses a source */ 443 if (ROP4_USES_SOURCE(rop4)) 444 { 445 /* Must have a source surface and point */ 446 ASSERT(psoSrc); 447 ASSERT(pptlSrc); 448 449 /* Get the source point */ 450 ptSrc = *pptlSrc; 451 452 /* Clip against the extents of the source surface */ 453 AdjustOffsetAndSize(&ptOffset, &sizTrg, &ptSrc, &psoSrc->sizlBitmap); 454 } 455 else 456 { 457 psoSrc = NULL; 458 ptSrc.x = 0; 459 ptSrc.y = 0; 460 } 461 462 /* Check if the ROP uses a mask */ 463 if (ROP4_USES_MASK(rop4)) 464 { 465 /* Must have a mask surface and point */ 466 ASSERT(psoMask); 467 ASSERT(pptlMask); 468 469 /* Get the mask point */ 470 ptMask = *pptlMask; 471 472 /* Clip against the extents of the mask surface */ 473 AdjustOffsetAndSize(&ptOffset, &sizTrg, &ptMask, &psoMask->sizlBitmap); 474 } 475 else 476 { 477 psoMask = NULL; 478 ptMask.x = 0; 479 ptMask.y = 0; 480 } 481 482 /* Check if all has been clipped away */ 483 if ((sizTrg.cx <= 0) || (sizTrg.cy <= 0)) 484 return TRUE; 485 486 /* Adjust the points */ 487 ptSrc.x += ptOffset.x; 488 ptSrc.y += ptOffset.y; 489 ptMask.x += ptOffset.x; 490 ptMask.y += ptOffset.y; 491 492 /* Check if we have a brush origin */ 493 if (pptlBrush) 494 { 495 /* calculate the new brush origin */ 496 ptBrush.x = pptlBrush->x + ptOffset.x; 497 ptBrush.y = pptlBrush->y + ptOffset.y; 498 } 499 500 /* Recalculate the target rect */ 501 rcClipped.left = prclTrg->left + ptOffset.x; 502 rcClipped.top = prclTrg->top + ptOffset.y; 503 rcClipped.right = rcClipped.left + sizTrg.cx; 504 rcClipped.bottom = rcClipped.top + sizTrg.cy; 505 506 /* Is the target surface device managed? */ 507 if (SURFOBJ_flags(psoTrg) & HOOK_BITBLT) 508 { 509 /* Is the source a different device managed surface? */ 510 if (psoSrc && (psoSrc->hdev != psoTrg->hdev) && 511 (SURFOBJ_flags(psoSrc) & HOOK_BITBLT)) 512 { 513 ERR("Need to copy to standard bitmap format!\n"); 514 ASSERT(FALSE); 515 } 516 517 pfnBitBlt = GDIDEVFUNCS(psoTrg).BitBlt; 518 } 519 /* Otherwise is the source surface device managed? */ 520 else if (psoSrc && (SURFOBJ_flags(psoSrc) & HOOK_BITBLT)) 521 { 522 pfnBitBlt = GDIDEVFUNCS(psoSrc).BitBlt; 523 } 524 else 525 { 526 pfnBitBlt = EngBitBlt; 527 } 528 529 bResult = pfnBitBlt(psoTrg, 530 psoSrc, 531 psoMask, 532 pco, 533 pxlo, 534 &rcClipped, 535 psoSrc ? &ptSrc : NULL, 536 psoMask ? &ptMask : NULL, 537 pbo, 538 pptlBrush ? &ptBrush : NULL, 539 rop4); 540 541 // FIXME: cleanup temp surface! 542 543 return bResult; 544 } 545 546 BOOL 547 APIENTRY 548 NtGdiEngBitBlt( 549 IN SURFOBJ *psoTrgUMPD, 550 IN SURFOBJ *psoSrcUMPD, 551 IN SURFOBJ *psoMaskUMPD, 552 IN CLIPOBJ *pcoUMPD, 553 IN XLATEOBJ *pxloUMPD, 554 IN RECTL *prclTrg, 555 IN POINTL *pptlSrc, 556 IN POINTL *pptlMask, 557 IN BRUSHOBJ *pboUMPD, 558 IN POINTL *pptlBrush, 559 IN ROP4 rop4) 560 { 561 RECTL rclTrg; 562 POINTL ptlSrc, ptlMask, ptlBrush; 563 HSURF hsurfTrg, hsurfSrc = NULL, hsurfMask = NULL; 564 HANDLE hBrushObj; // HUMPDOBJ 565 SURFOBJ *psoTrg, *psoSrc, *psoMask; 566 CLIPOBJ *pco; 567 XLATEOBJ *pxlo; 568 BRUSHOBJ *pbo; 569 BOOL bResult; 570 571 _SEH2_TRY 572 { 573 ProbeForRead(prclTrg, sizeof(RECTL), 1); 574 rclTrg = *prclTrg; 575 576 ProbeForRead(psoTrgUMPD, sizeof(SURFOBJ), 1); 577 hsurfTrg = psoTrgUMPD->hsurf; 578 579 if (ROP4_USES_SOURCE(rop4)) 580 { 581 ProbeForRead(pptlSrc, sizeof(POINTL), 1); 582 ptlSrc = *pptlSrc; 583 584 ProbeForRead(psoSrcUMPD, sizeof(SURFOBJ), 1); 585 hsurfSrc = psoSrcUMPD->hsurf; 586 } 587 588 if (ROP4_USES_MASK(rop4)) 589 { 590 ProbeForRead(pptlMask, sizeof(POINTL), 1); 591 ptlMask = *pptlMask; 592 593 ProbeForRead(psoMaskUMPD, sizeof(SURFOBJ), 1); 594 hsurfMask = psoMaskUMPD->hsurf; 595 } 596 597 if (ROP4_USES_PATTERN(rop4)) 598 { 599 ProbeForRead(pptlBrush, sizeof(POINTL), 1); 600 ptlBrush = *pptlBrush; 601 602 ProbeForRead(psoSrcUMPD, sizeof(SURFOBJ), 1); 603 hBrushObj = pboUMPD->pvRbrush; // FIXME 604 } 605 } 606 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 607 { 608 _SEH2_YIELD(return FALSE); 609 } 610 _SEH2_END; 611 612 // FIXME: these need to be converted/locked! 613 psoTrg = NULL; 614 psoSrc = NULL; 615 psoMask = NULL; 616 pco = NULL; 617 pxlo = NULL; 618 pbo = NULL; 619 620 bResult = EngBitBlt(psoTrg, 621 psoSrc, 622 psoMask, 623 pco, 624 pxlo, 625 &rclTrg, 626 pptlSrc ? &ptlSrc : NULL, 627 pptlMask ? &ptlMask : NULL, 628 pbo, 629 pptlBrush ? &ptlBrush : NULL, 630 rop4); 631 632 return bResult; 633 } 634 635 BOOL 636 APIENTRY 637 EngCopyBits( 638 SURFOBJ *psoTrg, 639 SURFOBJ *psoSrc, 640 CLIPOBJ *pco, 641 XLATEOBJ *pxlo, 642 RECTL *prclTrg, 643 POINTL *pptlSrc) 644 { 645 PFN_DrvCopyBits pfnCopyBits; 646 647 /* Is the target surface device managed? */ 648 if (SURFOBJ_flags(psoTrg) & HOOK_COPYBITS) 649 { 650 pfnCopyBits = GDIDEVFUNCS(psoTrg).CopyBits; 651 } 652 if (SURFOBJ_flags(psoSrc) & HOOK_COPYBITS) 653 { 654 pfnCopyBits = GDIDEVFUNCS(psoSrc).CopyBits; 655 } 656 else 657 { 658 /* Use SRCCOPY for 2 bitmaps */ 659 return EngBitBlt(psoTrg, 660 psoSrc, 661 NULL, 662 pco, 663 pxlo, 664 prclTrg, 665 pptlSrc, 666 NULL, 667 NULL, 668 NULL, 669 ROP4_SRCCOPY); 670 } 671 672 /* Forward to the driver */ 673 return pfnCopyBits(psoTrg, psoSrc, pco, pxlo, prclTrg, pptlSrc); 674 } 675 676 BOOL 677 APIENTRY 678 IntEngCopyBits( 679 SURFOBJ *psoTrg, 680 SURFOBJ *psoSrc, 681 CLIPOBJ *pco, 682 XLATEOBJ *pxlo, 683 RECTL *prclTrg, 684 POINTL *pptlSrc) 685 { 686 return EngCopyBits(psoTrg, psoSrc, pco, pxlo, prclTrg, pptlSrc); 687 } 688