2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: GDI stretch blt functions
5 * FILE: subsystems/win32/win32k/eng/stretchblt.c
6 * PROGRAMER: Jason Filby
14 typedef BOOLEAN (APIENTRY
*PSTRETCHRECTFUNC
)(SURFOBJ
* OutputObj
,
17 XLATEOBJ
* ColorTranslation
,
25 static BOOLEAN APIENTRY
26 CallDibStretchBlt(SURFOBJ
* psoDest
,
29 XLATEOBJ
* ColorTranslation
,
37 POINTL RealBrushOrigin
;
38 SURFACE
* psurfPattern
;
39 PEBRUSHOBJ GdiBrush
= NULL
;
40 SURFOBJ
* PatternSurface
= NULL
;
44 if (BrushOrigin
== NULL
)
46 RealBrushOrigin
.x
= RealBrushOrigin
.y
= 0;
50 RealBrushOrigin
= *BrushOrigin
;
54 if (ROP4_USES_PATTERN(Rop4
) && pbo
&& pbo
->iSolidColor
== 0xFFFFFFFF)
56 GdiBrush
= CONTAINING_RECORD(pbo
, EBRUSHOBJ
, BrushObject
);
57 hbmPattern
= EBRUSHOBJ_pvGetEngBrush(GdiBrush
);
58 psurfPattern
= SURFACE_LockSurface(hbmPattern
);
61 PatternSurface
= &psurfPattern
->SurfObj
;
65 /* FIXME - What to do here? */
73 bResult
= DibFunctionsForBitmapFormat
[psoDest
->iBitmapFormat
].DIB_StretchBlt(
74 psoDest
, psoSource
, Mask
, PatternSurface
,
75 OutputRect
, InputRect
, MaskOrigin
, pbo
, &RealBrushOrigin
,
76 ColorTranslation
, NULL
, Rop4
);
81 SURFACE_UnlockSurface(psurfPattern
);
96 IN SURFOBJ
*psoSource
,
98 IN CLIPOBJ
*ClipRegion
,
99 IN XLATEOBJ
*ColorTranslation
,
100 IN COLORADJUSTMENT
*pca
,
101 IN POINTL
*BrushOrigin
,
104 IN POINTL
*MaskOrigin
,
112 INTENG_ENTER_LEAVE EnterLeaveSource
;
113 INTENG_ENTER_LEAVE EnterLeaveDest
;
116 PSTRETCHRECTFUNC BltRectFunc
;
118 POINTL AdjustedBrushOrigin
;
119 BOOL UsesSource
= ROP4_USES_SOURCE(ROP4
);
127 RECTL InputToCombinedRect
;
135 /* Determine clipping type */
136 if (ClipRegion
== (CLIPOBJ
*) NULL
)
138 clippingType
= DC_TRIVIAL
;
142 clippingType
= ClipRegion
->iDComplexity
;
147 /* Copy destination onto itself: nop */
151 OutputRect
= *prclDest
;
152 if (OutputRect
.right
< OutputRect
.left
)
154 OutputRect
.left
= prclDest
->right
;
155 OutputRect
.right
= prclDest
->left
;
157 if (OutputRect
.bottom
< OutputRect
.top
)
159 OutputRect
.top
= prclDest
->bottom
;
160 OutputRect
.bottom
= prclDest
->top
;
163 InputRect
= *prclSrc
;
171 if (! IntEngEnter(&EnterLeaveSource
, psoSource
, &InputRect
, TRUE
,
172 &Translate
, &psoInput
))
177 InputRect
.left
+= Translate
.x
;
178 InputRect
.right
+= Translate
.x
;
179 InputRect
.top
+= Translate
.y
;
180 InputRect
.bottom
+= Translate
.y
;
183 if (NULL
!= ClipRegion
)
185 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
187 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
188 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
190 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
192 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
193 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
195 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
197 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
198 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
200 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
202 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
203 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
207 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
209 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
213 IntEngLeave(&EnterLeaveSource
);
218 if (! IntEngEnter(&EnterLeaveDest
, psoDest
, &OutputRect
, FALSE
, &Translate
, &psoOutput
))
222 IntEngLeave(&EnterLeaveSource
);
227 OutputRect
.left
+= Translate
.x
;
228 OutputRect
.right
+= Translate
.x
;
229 OutputRect
.top
+= Translate
.y
;
230 OutputRect
.bottom
+= Translate
.y
;
234 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
235 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
239 AdjustedBrushOrigin
= Translate
;
242 BltRectFunc
= CallDibStretchBlt
;
244 DstHeight
= OutputRect
.bottom
- OutputRect
.top
;
245 DstWidth
= OutputRect
.right
- OutputRect
.left
;
246 SrcHeight
= InputRect
.bottom
- InputRect
.top
;
247 SrcWidth
= InputRect
.right
- InputRect
.left
;
248 switch (clippingType
)
251 Ret
= (*BltRectFunc
)(psoOutput
, psoInput
, Mask
,
252 ColorTranslation
, &OutputRect
, &InputRect
, MaskOrigin
,
253 pbo
, &AdjustedBrushOrigin
, ROP4
);
256 // Clip the blt to the clip rectangle
257 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
258 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
259 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
260 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
261 if (RECTL_bIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
263 InputToCombinedRect
.top
= InputRect
.top
+ (CombinedRect
.top
- OutputRect
.top
) * SrcHeight
/ DstHeight
;
264 InputToCombinedRect
.bottom
= InputRect
.top
+ (CombinedRect
.bottom
- OutputRect
.top
) * SrcHeight
/ DstHeight
;
265 InputToCombinedRect
.left
= InputRect
.left
+ (CombinedRect
.left
- OutputRect
.left
) * SrcWidth
/ DstWidth
;
266 InputToCombinedRect
.right
= InputRect
.left
+ (CombinedRect
.right
- OutputRect
.left
) * SrcWidth
/ DstWidth
;
267 Ret
= (*BltRectFunc
)(psoOutput
, psoInput
, Mask
,
270 &InputToCombinedRect
,
273 &AdjustedBrushOrigin
,
278 if (psoOutput
== psoInput
)
280 if (OutputRect
.top
< InputRect
.top
)
282 Direction
= OutputRect
.left
< InputRect
.left
?
283 CD_RIGHTDOWN
: CD_LEFTDOWN
;
287 Direction
= OutputRect
.left
< InputRect
.left
?
288 CD_RIGHTUP
: CD_LEFTUP
;
295 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, Direction
, 0);
298 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
),
300 for (i
= 0; i
< RectEnum
.c
; i
++)
302 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
303 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
304 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
305 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
306 if (RECTL_bIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
308 InputToCombinedRect
.top
= InputRect
.top
+ (CombinedRect
.top
- OutputRect
.top
) * SrcHeight
/ DstHeight
;
309 InputToCombinedRect
.bottom
= InputRect
.top
+ (CombinedRect
.bottom
- OutputRect
.top
) * SrcHeight
/ DstHeight
;
310 InputToCombinedRect
.left
= InputRect
.left
+ (CombinedRect
.left
- OutputRect
.left
) * SrcWidth
/ DstWidth
;
311 InputToCombinedRect
.right
= InputRect
.left
+ (CombinedRect
.right
- OutputRect
.left
) * SrcWidth
/ DstWidth
;
312 Ret
= (*BltRectFunc
)(psoOutput
, psoInput
, Mask
,
315 &InputToCombinedRect
,
318 &AdjustedBrushOrigin
,
327 IntEngLeave(&EnterLeaveDest
);
330 IntEngLeave(&EnterLeaveSource
);
343 IN SURFOBJ
*psoSource
,
345 IN CLIPOBJ
*ClipRegion
,
346 IN XLATEOBJ
*ColorTranslation
,
347 IN COLORADJUSTMENT
*pca
,
348 IN POINTL
*BrushOrigin
,
351 IN POINTL
*MaskOrigin
,
354 return EngStretchBltROP(
367 ROP3_TO_ROP4(SRCCOPY
));
371 IntEngStretchBlt(SURFOBJ
*psoDest
,
375 XLATEOBJ
*ColorTranslation
,
387 SURFACE
*psurfSource
= NULL
;
388 RECTL InputClippedRect
;
391 BOOL UsesSource
= ROP4_USES_SOURCE(ROP
);
392 LONG InputClWidth
, InputClHeight
, InputWidth
, InputHeight
;
395 psurfDest
= CONTAINING_RECORD(psoDest
, SURFACE
, SurfObj
);
399 InputClippedRect
= *DestRect
;
400 if (InputClippedRect
.right
< InputClippedRect
.left
)
402 InputClippedRect
.left
= DestRect
->right
;
403 InputClippedRect
.right
= DestRect
->left
;
405 if (InputClippedRect
.bottom
< InputClippedRect
.top
)
407 InputClippedRect
.top
= DestRect
->bottom
;
408 InputClippedRect
.bottom
= DestRect
->top
;
413 if (NULL
== SourceRect
|| NULL
== psoSource
)
417 InputRect
= *SourceRect
;
419 if (InputRect
.right
< InputRect
.left
||
420 InputRect
.bottom
< InputRect
.top
)
422 /* Everything clipped away, nothing to do */
429 if (!RECTL_bIntersectRect(&OutputRect
, &InputClippedRect
,
430 &ClipRegion
->rclBounds
))
434 /* Update source rect */
435 InputClWidth
= InputClippedRect
.right
- InputClippedRect
.left
;
436 InputClHeight
= InputClippedRect
.bottom
- InputClippedRect
.top
;
437 InputWidth
= InputRect
.right
- InputRect
.left
;
438 InputHeight
= InputRect
.bottom
- InputRect
.top
;
440 InputRect
.left
+= (InputWidth
* (OutputRect
.left
- InputClippedRect
.left
)) / InputClWidth
;
441 InputRect
.right
-= (InputWidth
* (InputClippedRect
.right
- OutputRect
.right
)) / InputClWidth
;
442 InputRect
.top
+= (InputHeight
* (OutputRect
.top
- InputClippedRect
.top
)) / InputClHeight
;
443 InputRect
.bottom
-= (InputHeight
* (InputClippedRect
.bottom
- OutputRect
.bottom
)) / InputClHeight
;
447 OutputRect
= InputClippedRect
;
450 if (pMaskOrigin
!= NULL
)
452 MaskOrigin
.x
= pMaskOrigin
->x
; MaskOrigin
.y
= pMaskOrigin
->y
;
457 SURFACE_LockBitmapBits(psurfDest
);
458 MouseSafetyOnDrawStart(psoDest
, OutputRect
.left
, OutputRect
.top
,
459 OutputRect
.right
, OutputRect
.bottom
);
463 psurfSource
= CONTAINING_RECORD(psoSource
, SURFACE
, SurfObj
);
464 if (psoSource
!= psoDest
)
466 SURFACE_LockBitmapBits(psurfSource
);
468 MouseSafetyOnDrawStart(psoSource
, InputRect
.left
, InputRect
.top
,
469 InputRect
.right
, InputRect
.bottom
);
472 /* Prepare color adjustment */
474 /* Call the driver's DrvStretchBlt if available */
475 if (psurfDest
->flHooks
& HOOK_STRETCHBLTROP
)
477 /* Drv->StretchBltROP (look at http://www.osronline.com/ddkx/graphics/ddifncs_0z3b.htm ) */
478 // FIXME: MaskOrigin is always NULL !
479 ret
= GDIDEVFUNCS(psoDest
).StretchBltROP(psoDest
, (UsesSource
) ? psoSource
: NULL
, MaskSurf
, ClipRegion
, ColorTranslation
,
480 &ca
, BrushOrigin
, &OutputRect
, &InputRect
, NULL
, COLORONCOLOR
, pbo
, ROP
);
485 // FIXME: see previous fixme
486 ret
= EngStretchBltROP(psoDest
, (UsesSource
) ? psoSource
: NULL
, MaskSurf
, ClipRegion
, ColorTranslation
,
487 &ca
, BrushOrigin
, &OutputRect
, &InputRect
, NULL
, COLORONCOLOR
, pbo
, ROP
);
492 MouseSafetyOnDrawEnd(psoSource
);
493 if (psoSource
!= psoDest
)
495 SURFACE_UnlockBitmapBits(psurfSource
);
498 MouseSafetyOnDrawEnd(psoDest
);
499 SURFACE_UnlockBitmapBits(psurfDest
);
508 IN SURFOBJ
*psoSource
,
510 IN CLIPOBJ
*ClipRegion
,
511 IN XLATEOBJ
*ColorTranslation
,
512 IN COLORADJUSTMENT
*pca
,
513 IN POINTL
*BrushOrigin
,
516 IN POINTL
*MaskOrigin
,
527 ProbeForRead(pca
, sizeof(COLORADJUSTMENT
), 1);
528 RtlCopyMemory(&ca
,pca
, sizeof(COLORADJUSTMENT
));
530 ProbeForRead(BrushOrigin
, sizeof(POINTL
), 1);
531 RtlCopyMemory(&lBrushOrigin
, BrushOrigin
, sizeof(POINTL
));
533 ProbeForRead(prclDest
, sizeof(RECTL
), 1);
534 RtlCopyMemory(&rclDest
, prclDest
, sizeof(RECTL
));
536 ProbeForRead(prclSrc
, sizeof(RECTL
), 1);
537 RtlCopyMemory(&rclSrc
, prclSrc
, sizeof(RECTL
));
539 ProbeForRead(MaskOrigin
, sizeof(POINTL
), 1);
540 RtlCopyMemory(&lMaskOrigin
, MaskOrigin
, sizeof(POINTL
));
543 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
545 _SEH2_YIELD(return FALSE
);
549 return EngStretchBlt(psoDest
, psoSource
, Mask
, ClipRegion
, ColorTranslation
, &ca
, &lBrushOrigin
, &rclDest
, &rclSrc
, &lMaskOrigin
, Mode
);