2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: GDI alpha blending functions
5 * FILE: subsystems/win32/win32k/eng/alphablend.c
6 * PROGRAMER: Jason Filby
20 EngAlphaBlend(IN SURFOBJ
*psoDest
,
21 IN SURFOBJ
*psoSource
,
22 IN CLIPOBJ
*ClipRegion
,
23 IN XLATEOBJ
*ColorTranslation
,
26 IN BLENDOBJ
*BlendObj
)
28 RECTL SourceStretchedRect
;
29 SIZEL SourceStretchedSize
;
30 HBITMAP SourceStretchedBitmap
= 0;
31 SURFOBJ
* SourceStretchedObj
= NULL
;
38 INTENG_ENTER_LEAVE EnterLeaveSource
;
39 INTENG_ENTER_LEAVE EnterLeaveDest
;
49 DPRINT("EngAlphaBlend(psoDest:0x%p, psoSource:0x%p, ClipRegion:0x%p, ColorTranslation:0x%p,\n", psoDest
, psoSource
, ClipRegion
, ColorTranslation
);
50 DPRINT(" DestRect:{0x%x, 0x%x, 0x%x, 0x%x}, SourceRect:{0x%x, 0x%x, 0x%x, 0x%x},\n",
51 DestRect
->left
, DestRect
->top
, DestRect
->right
, DestRect
->bottom
,
52 SourceRect
->left
, SourceRect
->top
, SourceRect
->right
, SourceRect
->bottom
);
53 DPRINT(" BlendObj:{0x%x, 0x%x, 0x%x, 0x%x}\n", BlendObj
->BlendFunction
.BlendOp
,
54 BlendObj
->BlendFunction
.BlendFlags
, BlendObj
->BlendFunction
.SourceConstantAlpha
,
55 BlendObj
->BlendFunction
.AlphaFormat
);
58 OutputRect
= *DestRect
;
59 if (OutputRect
.right
< OutputRect
.left
)
61 OutputRect
.left
= DestRect
->right
;
62 OutputRect
.right
= DestRect
->left
;
64 if (OutputRect
.bottom
< OutputRect
.top
)
66 OutputRect
.left
= DestRect
->right
;
67 OutputRect
.right
= DestRect
->left
;
71 InputRect
= *SourceRect
;
72 if ( (InputRect
.top
< 0) || (InputRect
.bottom
< 0) ||
73 (InputRect
.left
< 0) || (InputRect
.right
< 0) ||
74 InputRect
.right
> psoSource
->sizlBitmap
.cx
||
75 InputRect
.bottom
> psoSource
->sizlBitmap
.cy
)
77 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
81 if (psoDest
== psoSource
&&
82 !(OutputRect
.left
>= SourceRect
->right
|| InputRect
.left
>= OutputRect
.right
||
83 OutputRect
.top
>= SourceRect
->bottom
|| InputRect
.top
>= OutputRect
.bottom
))
85 DPRINT1("Source and destination rectangles overlap!\n");
89 if (BlendObj
->BlendFunction
.BlendOp
!= AC_SRC_OVER
)
91 DPRINT1("BlendOp != AC_SRC_OVER (0x%x)\n", BlendObj
->BlendFunction
.BlendOp
);
94 if (BlendObj
->BlendFunction
.BlendFlags
!= 0)
96 DPRINT1("BlendFlags != 0 (0x%x)\n", BlendObj
->BlendFunction
.BlendFlags
);
99 if ((BlendObj
->BlendFunction
.AlphaFormat
& ~AC_SRC_ALPHA
) != 0)
101 DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendObj
->BlendFunction
.AlphaFormat
);
105 /* Check if there is anything to draw */
106 if (ClipRegion
!= NULL
&&
107 (ClipRegion
->rclBounds
.left
>= ClipRegion
->rclBounds
.right
||
108 ClipRegion
->rclBounds
.top
>= ClipRegion
->rclBounds
.bottom
))
114 /* Stretch source if needed */
115 if (OutputRect
.right
- OutputRect
.left
!= InputRect
.right
- InputRect
.left
||
116 OutputRect
.bottom
- OutputRect
.top
!= InputRect
.bottom
- InputRect
.top
)
118 SourceStretchedSize
.cx
= OutputRect
.right
- OutputRect
.left
;
119 SourceStretchedSize
.cy
= OutputRect
.bottom
- OutputRect
.top
;
120 Width
= DIB_GetDIBWidthBytes(SourceStretchedSize
.cx
, BitsPerFormat(psoSource
->iBitmapFormat
));
121 /* FIXME: Maybe it is a good idea to use EngCreateDeviceBitmap and IntEngStretchBlt
122 if possible to get a HW accelerated stretch. */
123 SourceStretchedBitmap
= EngCreateBitmap(SourceStretchedSize
, Width
, psoSource
->iBitmapFormat
,
124 BMF_TOPDOWN
| BMF_NOZEROINIT
, NULL
);
125 if (SourceStretchedBitmap
== 0)
127 DPRINT1("EngCreateBitmap failed!\n");
130 SourceStretchedObj
= EngLockSurface((HSURF
)SourceStretchedBitmap
);
131 if (SourceStretchedObj
== NULL
)
133 DPRINT1("EngLockSurface failed!\n");
134 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
138 SourceStretchedRect
.left
= 0;
139 SourceStretchedRect
.right
= SourceStretchedSize
.cx
;
140 SourceStretchedRect
.top
= 0;
141 SourceStretchedRect
.bottom
= SourceStretchedSize
.cy
;
142 if (!IntEngStretchBlt(SourceStretchedObj
, psoSource
, NULL
, NULL
, NULL
,
143 &SourceStretchedRect
, SourceRect
,
144 NULL
, NULL
, NULL
, ROP3_TO_ROP4(SRCCOPY
)))
146 DPRINT1("EngStretchBlt failed!\n");
147 EngFreeMem(SourceStretchedObj
->pvBits
);
148 EngUnlockSurface(SourceStretchedObj
);
149 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
152 InputRect
.top
= SourceStretchedRect
.top
;
153 InputRect
.bottom
= SourceStretchedRect
.bottom
;
154 InputRect
.left
= SourceStretchedRect
.left
;
155 InputRect
.right
= SourceStretchedRect
.right
;
156 psoSource
= SourceStretchedObj
;
159 /* Now call the DIB function */
160 if (!IntEngEnter(&EnterLeaveSource
, psoSource
, &InputRect
, TRUE
, &Translate
, &InputObj
))
162 if (SourceStretchedObj
!= NULL
)
164 EngFreeMem(SourceStretchedObj
->pvBits
);
165 EngUnlockSurface(SourceStretchedObj
);
167 if (SourceStretchedBitmap
!= 0)
169 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
173 InputRect
.left
+= Translate
.x
;
174 InputRect
.right
+= Translate
.x
;
175 InputRect
.top
+= Translate
.y
;
176 InputRect
.bottom
+= Translate
.y
;
178 if (!IntEngEnter(&EnterLeaveDest
, psoDest
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
180 IntEngLeave(&EnterLeaveSource
);
181 if (SourceStretchedObj
!= NULL
)
183 EngFreeMem(SourceStretchedObj
->pvBits
);
184 EngUnlockSurface(SourceStretchedObj
);
186 if (SourceStretchedBitmap
!= 0)
188 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
192 OutputRect
.left
+= Translate
.x
;
193 OutputRect
.right
+= Translate
.x
;
194 OutputRect
.top
+= Translate
.y
;
195 OutputRect
.bottom
+= Translate
.y
;
198 ClippingType
= (ClipRegion
== NULL
) ? DC_TRIVIAL
: ClipRegion
->iDComplexity
;
199 switch (ClippingType
)
202 Ret
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_AlphaBlend(
203 OutputObj
, InputObj
, &OutputRect
, &InputRect
, ClipRegion
, ColorTranslation
, BlendObj
);
207 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
208 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
209 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
210 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
211 if (RECTL_bIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
213 Rect
.left
= InputRect
.left
+ CombinedRect
.left
- OutputRect
.left
;
214 Rect
.right
= InputRect
.right
+ CombinedRect
.right
- OutputRect
.right
;
215 Rect
.top
= InputRect
.top
+ CombinedRect
.top
- OutputRect
.top
;
216 Rect
.bottom
= InputRect
.bottom
+ CombinedRect
.bottom
- OutputRect
.bottom
;
217 Ret
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_AlphaBlend(
218 OutputObj
, InputObj
, &CombinedRect
, &Rect
, ClipRegion
, ColorTranslation
, BlendObj
);
224 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, CD_ANY
, 0);
227 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
),
230 for (i
= 0; i
< RectEnum
.c
; i
++)
232 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
233 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
234 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
235 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
236 if (RECTL_bIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
238 Rect
.left
= InputRect
.left
+ CombinedRect
.left
- OutputRect
.left
;
239 Rect
.right
= InputRect
.right
+ CombinedRect
.right
- OutputRect
.right
;
240 Rect
.top
= InputRect
.top
+ CombinedRect
.top
- OutputRect
.top
;
241 Rect
.bottom
= InputRect
.bottom
+ CombinedRect
.bottom
- OutputRect
.bottom
;
242 Ret
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_AlphaBlend(
243 OutputObj
, InputObj
, &CombinedRect
, &Rect
, ClipRegion
, ColorTranslation
, BlendObj
) && Ret
;
256 IntEngLeave(&EnterLeaveDest
);
257 IntEngLeave(&EnterLeaveSource
);
259 if (SourceStretchedObj
!= NULL
)
261 EngFreeMem(SourceStretchedObj
->pvBits
);
262 EngUnlockSurface(SourceStretchedObj
);
264 if (SourceStretchedBitmap
!= 0)
266 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
273 IntEngAlphaBlend(IN SURFOBJ
*psoDest
,
274 IN SURFOBJ
*psoSource
,
275 IN CLIPOBJ
*ClipRegion
,
276 IN XLATEOBJ
*ColorTranslation
,
278 IN PRECTL SourceRect
,
279 IN BLENDOBJ
*BlendObj
)
283 SURFACE
*psurfSource
;
286 psurfDest
= CONTAINING_RECORD(psoDest
, SURFACE
, SurfObj
);
289 psurfSource
= CONTAINING_RECORD(psoSource
, SURFACE
, SurfObj
);
294 /* Check if there is anything to draw */
295 if (ClipRegion
!= NULL
&&
296 (ClipRegion
->rclBounds
.left
>= ClipRegion
->rclBounds
.right
||
297 ClipRegion
->rclBounds
.top
>= ClipRegion
->rclBounds
.bottom
))
303 /* Call the driver's DrvAlphaBlend if available */
304 if (psurfDest
->flags
& HOOK_ALPHABLEND
)
306 ret
= GDIDEVFUNCS(psoDest
).AlphaBlend(
307 psoDest
, psoSource
, ClipRegion
, ColorTranslation
,
308 DestRect
, SourceRect
, BlendObj
);
313 ret
= EngAlphaBlend(psoDest
, psoSource
, ClipRegion
, ColorTranslation
,
314 DestRect
, SourceRect
, BlendObj
);
325 NtGdiEngAlphaBlend(IN SURFOBJ
*psoDest
,
326 IN SURFOBJ
*psoSource
,
327 IN CLIPOBJ
*ClipRegion
,
328 IN XLATEOBJ
*ColorTranslation
,
329 IN PRECTL upDestRect
,
330 IN PRECTL upSourceRect
,
331 IN BLENDOBJ
*BlendObj
)
338 ProbeForRead(upDestRect
, sizeof(RECTL
), 1);
339 RtlCopyMemory(&DestRect
,upDestRect
, sizeof(RECTL
));
341 ProbeForRead(upSourceRect
, sizeof(RECTL
), 1);
342 RtlCopyMemory(&SourceRect
, upSourceRect
, sizeof(RECTL
));
345 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
347 _SEH2_YIELD(return FALSE
);
351 return EngAlphaBlend(psoDest
, psoSource
, ClipRegion
, ColorTranslation
, &DestRect
, &SourceRect
, BlendObj
);