xref: /reactos/win32ss/gdi/eng/bitblt_new.c (revision 2170901e)
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
CalculateCoordinates(PBLTDATA pbltdata,PRECTL prclClipped,PRECTL prclOrg,PPOINTL pptlSrc,PPOINTL pptlMask,PPOINTL pptlPat,PSIZEL psizlPat)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
EngBitBlt(_Inout_ SURFOBJ * psoTrg,_In_opt_ SURFOBJ * psoSrc,_In_opt_ SURFOBJ * psoMask,_In_opt_ CLIPOBJ * pco,_In_opt_ XLATEOBJ * pxlo,_In_ RECTL * prclTrg,_When_ (psoSrc,_In_)POINTL * pptlSrc,_When_ (psoMask,_In_)POINTL * pptlMask,_In_opt_ BRUSHOBJ * pbo,_When_ (pbo,_In_)POINTL * pptlBrush,_In_ ROP4 rop4)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
AdjustOffsetAndSize(_Out_ PPOINTL pptOffset,_Out_ PSIZEL psizTrg,_In_ PPOINTL pptlSrc,_In_ PSIZEL psizSrc)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
IntEngBitBlt(_Inout_ SURFOBJ * psoTrg,_In_opt_ SURFOBJ * psoSrc,_In_opt_ SURFOBJ * psoMask,_In_opt_ CLIPOBJ * pco,_In_opt_ XLATEOBJ * pxlo,_In_ RECTL * prclTrg,_When_ (psoSrc,_In_)POINTL * pptlSrc,_When_ (psoMask,_In_)POINTL * pptlMask,_In_opt_ BRUSHOBJ * pbo,_When_ (pbo,_In_)POINTL * pptlBrush,_In_ ROP4 rop4)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
NtGdiEngBitBlt(IN SURFOBJ * psoTrgUMPD,IN SURFOBJ * psoSrcUMPD,IN SURFOBJ * psoMaskUMPD,IN CLIPOBJ * pcoUMPD,IN XLATEOBJ * pxloUMPD,IN RECTL * prclTrg,IN POINTL * pptlSrc,IN POINTL * pptlMask,IN BRUSHOBJ * pboUMPD,IN POINTL * pptlBrush,IN ROP4 rop4)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
EngCopyBits(SURFOBJ * psoTrg,SURFOBJ * psoSrc,CLIPOBJ * pco,XLATEOBJ * pxlo,RECTL * prclTrg,POINTL * pptlSrc)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
IntEngCopyBits(SURFOBJ * psoTrg,SURFOBJ * psoSrc,CLIPOBJ * pco,XLATEOBJ * pxlo,RECTL * prclTrg,POINTL * pptlSrc)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