[SHELLBTRFS] Add a PCH.
[reactos.git] / win32ss / gdi / eng / bitblt_new.c
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 rcClipped.left = max(prclTrg->left, 0);
414 rcClipped.top = max(prclTrg->top, 0);
415 rcClipped.right = min(prclTrg->right, psoTrg->sizlBitmap.cx);
416 rcClipped.bottom = min(prclTrg->bottom, psoTrg->sizlBitmap.cy);
417
418 /* If no clip object is given, use trivial one */
419 if (!pco) pco = (CLIPOBJ*)&gxcoTrivial;
420
421 /* Check if there is something to clip */
422 if (pco->iDComplexity != DC_TRIVIAL)
423 {
424 /* Clip the target rect to the bounds of the clipping region */
425 if (!RECTL_bIntersectRect(&rcClipped, &rcClipped, &pco->rclBounds))
426 {
427 /* Nothing left */
428 return TRUE;
429 }
430 }
431
432 /* Don't pass a clip object with a single rectangle */
433 if (pco->iDComplexity == DC_RECT) pco = (CLIPOBJ*)&gxcoTrivial;
434
435 /* Calculate initial offset and size */
436 ptOffset.x = rcClipped.left - prclTrg->left;
437 ptOffset.y = rcClipped.top - prclTrg->top;
438 sizTrg.cx = rcClipped.right - rcClipped.left;
439 sizTrg.cy = rcClipped.bottom - rcClipped.top;
440
441 /* Check if the ROP uses a source */
442 if (ROP4_USES_SOURCE(rop4))
443 {
444 /* Must have a source surface and point */
445 ASSERT(psoSrc);
446 ASSERT(pptlSrc);
447
448 /* Get the source point */
449 ptSrc = *pptlSrc;
450
451 /* Clip against the extents of the source surface */
452 AdjustOffsetAndSize(&ptOffset, &sizTrg, &ptSrc, &psoSrc->sizlBitmap);
453 }
454 else
455 {
456 psoSrc = NULL;
457 ptSrc.x = 0;
458 ptSrc.y = 0;
459 }
460
461 /* Check if the ROP uses a mask */
462 if (ROP4_USES_MASK(rop4))
463 {
464 /* Must have a mask surface and point */
465 ASSERT(psoMask);
466 ASSERT(pptlMask);
467
468 /* Get the mask point */
469 ptMask = *pptlMask;
470
471 /* Clip against the extents of the mask surface */
472 AdjustOffsetAndSize(&ptOffset, &sizTrg, &ptMask, &psoMask->sizlBitmap);
473 }
474 else
475 {
476 psoMask = NULL;
477 ptMask.x = 0;
478 ptMask.y = 0;
479 }
480
481 /* Check if all has been clipped away */
482 if ((sizTrg.cx <= 0) || (sizTrg.cy <= 0))
483 return TRUE;
484
485 /* Adjust the points */
486 ptSrc.x += ptOffset.x;
487 ptSrc.y += ptOffset.y;
488 ptMask.x += ptOffset.x;
489 ptMask.y += ptOffset.y;
490
491 /* Check if we have a brush origin */
492 if (pptlBrush)
493 {
494 /* calculate the new brush origin */
495 ptBrush.x = pptlBrush->x + ptOffset.x;
496 ptBrush.y = pptlBrush->y + ptOffset.y;
497 }
498
499 /* Recalculate the target rect */
500 rcClipped.left = prclTrg->left + ptOffset.x;
501 rcClipped.top = prclTrg->top + ptOffset.y;
502 rcClipped.right = rcClipped.left + sizTrg.cx;
503 rcClipped.bottom = rcClipped.top + sizTrg.cy;
504
505 /* Is the target surface device managed? */
506 if (SURFOBJ_flags(psoTrg) & HOOK_BITBLT)
507 {
508 /* Is the source a different device managed surface? */
509 if (psoSrc && (psoSrc->hdev != psoTrg->hdev) &&
510 (SURFOBJ_flags(psoSrc) & HOOK_BITBLT))
511 {
512 ERR("Need to copy to standard bitmap format!\n");
513 ASSERT(FALSE);
514 }
515
516 pfnBitBlt = GDIDEVFUNCS(psoTrg).BitBlt;
517 }
518 /* Otherwise is the source surface device managed? */
519 else if (psoSrc && (SURFOBJ_flags(psoSrc) & HOOK_BITBLT))
520 {
521 pfnBitBlt = GDIDEVFUNCS(psoSrc).BitBlt;
522 }
523 else
524 {
525 pfnBitBlt = EngBitBlt;
526 }
527
528 bResult = pfnBitBlt(psoTrg,
529 psoSrc,
530 psoMask,
531 pco,
532 pxlo,
533 &rcClipped,
534 psoSrc ? &ptSrc : NULL,
535 psoMask ? &ptMask : NULL,
536 pbo,
537 pptlBrush ? &ptBrush : NULL,
538 rop4);
539
540 // FIXME: cleanup temp surface!
541
542 return bResult;
543 }
544
545 BOOL
546 APIENTRY
547 NtGdiEngBitBlt(
548 IN SURFOBJ *psoTrgUMPD,
549 IN SURFOBJ *psoSrcUMPD,
550 IN SURFOBJ *psoMaskUMPD,
551 IN CLIPOBJ *pcoUMPD,
552 IN XLATEOBJ *pxloUMPD,
553 IN RECTL *prclTrg,
554 IN POINTL *pptlSrc,
555 IN POINTL *pptlMask,
556 IN BRUSHOBJ *pboUMPD,
557 IN POINTL *pptlBrush,
558 IN ROP4 rop4)
559 {
560 RECTL rclTrg;
561 POINTL ptlSrc, ptlMask, ptlBrush;
562 HSURF hsurfTrg, hsurfSrc = NULL, hsurfMask = NULL;
563 HANDLE hBrushObj; // HUMPDOBJ
564 SURFOBJ *psoTrg, *psoSrc, *psoMask;
565 CLIPOBJ *pco;
566 XLATEOBJ *pxlo;
567 BRUSHOBJ *pbo;
568 BOOL bResult;
569
570 _SEH2_TRY
571 {
572 ProbeForRead(prclTrg, sizeof(RECTL), 1);
573 rclTrg = *prclTrg;
574
575 ProbeForRead(psoTrgUMPD, sizeof(SURFOBJ), 1);
576 hsurfTrg = psoTrgUMPD->hsurf;
577
578 if (ROP4_USES_SOURCE(rop4))
579 {
580 ProbeForRead(pptlSrc, sizeof(POINTL), 1);
581 ptlSrc = *pptlSrc;
582
583 ProbeForRead(psoSrcUMPD, sizeof(SURFOBJ), 1);
584 hsurfSrc = psoSrcUMPD->hsurf;
585 }
586
587 if (ROP4_USES_MASK(rop4))
588 {
589 ProbeForRead(pptlMask, sizeof(POINTL), 1);
590 ptlMask = *pptlMask;
591
592 ProbeForRead(psoMaskUMPD, sizeof(SURFOBJ), 1);
593 hsurfMask = psoMaskUMPD->hsurf;
594 }
595
596 if (ROP4_USES_PATTERN(rop4))
597 {
598 ProbeForRead(pptlBrush, sizeof(POINTL), 1);
599 ptlBrush = *pptlBrush;
600
601 ProbeForRead(psoSrcUMPD, sizeof(SURFOBJ), 1);
602 hBrushObj = pboUMPD->pvRbrush; // FIXME
603 }
604 }
605 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
606 {
607 _SEH2_YIELD(return FALSE);
608 }
609 _SEH2_END;
610
611 // FIXME: these need to be converted/locked!
612 psoTrg = NULL;
613 psoSrc = NULL;
614 psoMask = NULL;
615 pco = NULL;
616 pxlo = NULL;
617 pbo = NULL;
618
619 bResult = EngBitBlt(psoTrg,
620 psoSrc,
621 psoMask,
622 pco,
623 pxlo,
624 &rclTrg,
625 pptlSrc ? &ptlSrc : NULL,
626 pptlMask ? &ptlMask : NULL,
627 pbo,
628 pptlBrush ? &ptlBrush : NULL,
629 rop4);
630
631 return bResult;
632 }
633
634 BOOL
635 APIENTRY
636 EngCopyBits(
637 SURFOBJ *psoTrg,
638 SURFOBJ *psoSrc,
639 CLIPOBJ *pco,
640 XLATEOBJ *pxlo,
641 RECTL *prclTrg,
642 POINTL *pptlSrc)
643 {
644 PFN_DrvCopyBits pfnCopyBits;
645
646 /* Is the target surface device managed? */
647 if (SURFOBJ_flags(psoTrg) & HOOK_COPYBITS)
648 {
649 pfnCopyBits = GDIDEVFUNCS(psoTrg).CopyBits;
650 }
651 if (SURFOBJ_flags(psoSrc) & HOOK_COPYBITS)
652 {
653 pfnCopyBits = GDIDEVFUNCS(psoSrc).CopyBits;
654 }
655 else
656 {
657 /* Use SRCCOPY for 2 bitmaps */
658 return EngBitBlt(psoTrg,
659 psoSrc,
660 NULL,
661 pco,
662 pxlo,
663 prclTrg,
664 pptlSrc,
665 NULL,
666 NULL,
667 NULL,
668 ROP4_SRCCOPY);
669 }
670
671 /* Forward to the driver */
672 return pfnCopyBits(psoTrg, psoSrc, pco, pxlo, prclTrg, pptlSrc);
673 }
674
675 BOOL
676 APIENTRY
677 IntEngCopyBits(
678 SURFOBJ *psoTrg,
679 SURFOBJ *psoSrc,
680 CLIPOBJ *pco,
681 XLATEOBJ *pxlo,
682 RECTL *prclTrg,
683 POINTL *pptlSrc)
684 {
685 return EngCopyBits(psoTrg, psoSrc, pco, pxlo, prclTrg, pptlSrc);
686 }