2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: GDI alpha blending functions
5 * FILE: win32ss/gdi/eng/alphablend.c
6 * PROGRAMER: Jason Filby
21 _Inout_ SURFOBJ
*psoDest
,
22 _In_ SURFOBJ
*psoSource
,
23 _In_opt_ CLIPOBJ
*ClipRegion
,
24 _In_opt_ XLATEOBJ
*ColorTranslation
,
26 _In_ RECTL
*SourceRect
,
27 _In_ BLENDOBJ
*BlendObj
)
35 INTENG_ENTER_LEAVE EnterLeaveSource
;
36 INTENG_ENTER_LEAVE EnterLeaveDest
;
45 DPRINT("EngAlphaBlend(psoDest:0x%p, psoSource:0x%p, ClipRegion:0x%p, ColorTranslation:0x%p,\n", psoDest
, psoSource
, ClipRegion
, ColorTranslation
);
46 DPRINT(" DestRect:{0x%x, 0x%x, 0x%x, 0x%x}, SourceRect:{0x%x, 0x%x, 0x%x, 0x%x},\n",
47 DestRect
->left
, DestRect
->top
, DestRect
->right
, DestRect
->bottom
,
48 SourceRect
->left
, SourceRect
->top
, SourceRect
->right
, SourceRect
->bottom
);
49 DPRINT(" BlendObj:{0x%x, 0x%x, 0x%x, 0x%x}\n", BlendObj
->BlendFunction
.BlendOp
,
50 BlendObj
->BlendFunction
.BlendFlags
, BlendObj
->BlendFunction
.SourceConstantAlpha
,
51 BlendObj
->BlendFunction
.AlphaFormat
);
54 OutputRect
= *DestRect
;
55 RECTL_vMakeWellOrdered(&OutputRect
);
58 InputRect
= *SourceRect
;
59 RECTL_vMakeWellOrdered(&InputRect
);
60 if ( (InputRect
.top
< 0) || (InputRect
.bottom
< 0) ||
61 (InputRect
.left
< 0) || (InputRect
.right
< 0) ||
62 InputRect
.right
> psoSource
->sizlBitmap
.cx
||
63 InputRect
.bottom
> psoSource
->sizlBitmap
.cy
)
65 EngSetLastError(ERROR_INVALID_PARAMETER
);
69 if (psoDest
== psoSource
&&
70 !(OutputRect
.left
>= SourceRect
->right
|| InputRect
.left
>= OutputRect
.right
||
71 OutputRect
.top
>= SourceRect
->bottom
|| InputRect
.top
>= OutputRect
.bottom
))
73 DPRINT1("Source and destination rectangles overlap!\n");
77 if (BlendObj
->BlendFunction
.BlendOp
!= AC_SRC_OVER
)
79 DPRINT1("BlendOp != AC_SRC_OVER (0x%x)\n", BlendObj
->BlendFunction
.BlendOp
);
82 if (BlendObj
->BlendFunction
.BlendFlags
!= 0)
84 DPRINT1("BlendFlags != 0 (0x%x)\n", BlendObj
->BlendFunction
.BlendFlags
);
87 if ((BlendObj
->BlendFunction
.AlphaFormat
& ~AC_SRC_ALPHA
) != 0)
89 DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendObj
->BlendFunction
.AlphaFormat
);
93 /* Check if there is anything to draw */
94 if (ClipRegion
!= NULL
&&
95 (ClipRegion
->rclBounds
.left
>= ClipRegion
->rclBounds
.right
||
96 ClipRegion
->rclBounds
.top
>= ClipRegion
->rclBounds
.bottom
))
102 /* Now call the DIB function */
103 if (!IntEngEnter(&EnterLeaveSource
, psoSource
, &InputRect
, TRUE
, &Translate
, &InputObj
))
107 InputRect
.left
+= Translate
.x
;
108 InputRect
.right
+= Translate
.x
;
109 InputRect
.top
+= Translate
.y
;
110 InputRect
.bottom
+= Translate
.y
;
112 if (!IntEngEnter(&EnterLeaveDest
, psoDest
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
116 OutputRect
.left
+= Translate
.x
;
117 OutputRect
.right
+= Translate
.x
;
118 OutputRect
.top
+= Translate
.y
;
119 OutputRect
.bottom
+= Translate
.y
;
121 ASSERT(InputRect
.left
<= InputRect
.right
&& InputRect
.top
<= InputRect
.bottom
);
124 ClippingType
= (ClipRegion
== NULL
) ? DC_TRIVIAL
: ClipRegion
->iDComplexity
;
125 switch (ClippingType
)
128 Ret
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_AlphaBlend(
129 OutputObj
, InputObj
, &OutputRect
, &InputRect
, ClipRegion
, ColorTranslation
, BlendObj
);
133 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
134 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
135 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
136 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
137 if (RECTL_bIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
139 /* take into acount clipping results when calculating new input rect (scaled to input rect size) */
140 Rect
.left
= InputRect
.left
+ (CombinedRect
.left
- OutputRect
.left
) * (InputRect
.right
- InputRect
.left
) / (OutputRect
.right
- OutputRect
.left
);
141 Rect
.right
= InputRect
.right
+ (CombinedRect
.right
- OutputRect
.right
) * (InputRect
.right
- InputRect
.left
) / (OutputRect
.right
- OutputRect
.left
);
142 Rect
.top
= InputRect
.top
+ (CombinedRect
.top
- OutputRect
.top
) * (InputRect
.bottom
- InputRect
.top
) / (OutputRect
.bottom
- OutputRect
.top
);
143 Rect
.bottom
= InputRect
.bottom
+ (CombinedRect
.bottom
- OutputRect
.bottom
) * (InputRect
.bottom
- InputRect
.top
) / (OutputRect
.bottom
- OutputRect
.top
);
145 /* Aplha blend one rect */
146 Ret
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_AlphaBlend(
147 OutputObj
, InputObj
, &CombinedRect
, &Rect
, ClipRegion
, ColorTranslation
, BlendObj
);
153 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, CD_ANY
, 0);
156 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
),
159 for (i
= 0; i
< RectEnum
.c
; i
++)
161 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
162 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
163 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
164 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
165 if (RECTL_bIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
167 /* take into acount clipping results when calculating new input rect (scaled to input rect size) */
168 Rect
.left
= InputRect
.left
+ (CombinedRect
.left
- OutputRect
.left
) * (InputRect
.right
- InputRect
.left
) / (OutputRect
.right
- OutputRect
.left
);
169 Rect
.right
= InputRect
.right
+ (CombinedRect
.right
- OutputRect
.right
) * (InputRect
.right
- InputRect
.left
) / (OutputRect
.right
- OutputRect
.left
);
170 Rect
.top
= InputRect
.top
+ (CombinedRect
.top
- OutputRect
.top
) * (InputRect
.bottom
- InputRect
.top
) / (OutputRect
.bottom
- OutputRect
.top
);
171 Rect
.bottom
= InputRect
.bottom
+ (CombinedRect
.bottom
- OutputRect
.bottom
) * (InputRect
.bottom
- InputRect
.top
) / (OutputRect
.bottom
- OutputRect
.top
);
173 /* Alpha blend one rect */
174 Ret
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_AlphaBlend(
175 OutputObj
, InputObj
, &CombinedRect
, &Rect
, ClipRegion
, ColorTranslation
, BlendObj
) && Ret
;
188 IntEngLeave(&EnterLeaveDest
);
189 IntEngLeave(&EnterLeaveSource
);
197 _Inout_ SURFOBJ
*psoDest
,
198 _In_ SURFOBJ
*psoSource
,
199 _In_opt_ CLIPOBJ
*pco
,
200 _In_opt_ XLATEOBJ
*pxlo
,
201 _In_ RECTL
*prclDest
,
203 _In_ BLENDOBJ
*pBlendObj
)
214 /* If no clip object is given, use trivial one */
215 if (!pco
) pco
= &gxcoTrivial
.ClipObj
;
217 /* Check if there is anything to draw */
218 if ((pco
->rclBounds
.left
>= pco
->rclBounds
.right
) ||
219 (pco
->rclBounds
.top
>= pco
->rclBounds
.bottom
))
225 psurfDest
= CONTAINING_RECORD(psoDest
, SURFACE
, SurfObj
);
227 /* Call the driver's DrvAlphaBlend if available */
228 if (psurfDest
->flags
& HOOK_ALPHABLEND
)
230 ret
= GDIDEVFUNCS(psoDest
).AlphaBlend(
231 psoDest
, psoSource
, pco
, pxlo
,
232 prclDest
, prclSrc
, pBlendObj
);
237 ret
= EngAlphaBlend(psoDest
, psoSource
, pco
, pxlo
,
238 prclDest
, prclSrc
, pBlendObj
);
249 NtGdiEngAlphaBlend(IN SURFOBJ
*psoDest
,
250 IN SURFOBJ
*psoSource
,
251 IN CLIPOBJ
*ClipRegion
,
252 IN XLATEOBJ
*ColorTranslation
,
253 IN PRECTL upDestRect
,
254 IN PRECTL upSourceRect
,
255 IN BLENDOBJ
*BlendObj
)
262 ProbeForRead(upDestRect
, sizeof(RECTL
), 1);
263 RtlCopyMemory(&DestRect
,upDestRect
, sizeof(RECTL
));
265 ProbeForRead(upSourceRect
, sizeof(RECTL
), 1);
266 RtlCopyMemory(&SourceRect
, upSourceRect
, sizeof(RECTL
));
269 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
271 _SEH2_YIELD(return FALSE
);
275 return EngAlphaBlend(psoDest
, psoSource
, ClipRegion
, ColorTranslation
, &DestRect
, &SourceRect
, BlendObj
);