ReactOS  0.4.11-dev-195-gef016bf
alphablend.c
Go to the documentation of this file.
1 /*
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
7  */
8 
9 #include <win32k.h>
10 
11 #define NDEBUG
12 #include <debug.h>
13 
14 
15 /*
16  * @implemented
17  */
18 BOOL
21  _Inout_ SURFOBJ *psoDest,
22  _In_ SURFOBJ *psoSource,
23  _In_opt_ CLIPOBJ *ClipRegion,
24  _In_opt_ XLATEOBJ *ColorTranslation,
25  _In_ RECTL *DestRect,
26  _In_ RECTL *SourceRect,
27  _In_ BLENDOBJ *BlendObj)
28 {
29  RECTL InputRect;
30  RECTL OutputRect;
31  RECTL ClipRect;
32  RECTL CombinedRect;
33  RECTL Rect;
34  POINTL Translate;
35  INTENG_ENTER_LEAVE EnterLeaveSource;
36  INTENG_ENTER_LEAVE EnterLeaveDest;
37  SURFOBJ* InputObj;
38  SURFOBJ* OutputObj;
39  LONG ClippingType;
40  RECT_ENUM RectEnum;
41  BOOL EnumMore;
42  ULONG i;
43  BOOLEAN Ret;
44 
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);
52 
53  /* Validate output */
54  OutputRect = *DestRect;
55  RECTL_vMakeWellOrdered(&OutputRect);
56 
57  /* Validate input */
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 )
64  {
66  return FALSE;
67  }
68 
69  if (psoDest == psoSource &&
70  !(OutputRect.left >= SourceRect->right || InputRect.left >= OutputRect.right ||
71  OutputRect.top >= SourceRect->bottom || InputRect.top >= OutputRect.bottom))
72  {
73  DPRINT1("Source and destination rectangles overlap!\n");
74  return FALSE;
75  }
76 
77  if (BlendObj->BlendFunction.BlendOp != AC_SRC_OVER)
78  {
79  DPRINT1("BlendOp != AC_SRC_OVER (0x%x)\n", BlendObj->BlendFunction.BlendOp);
80  return FALSE;
81  }
82  if (BlendObj->BlendFunction.BlendFlags != 0)
83  {
84  DPRINT1("BlendFlags != 0 (0x%x)\n", BlendObj->BlendFunction.BlendFlags);
85  return FALSE;
86  }
87  if ((BlendObj->BlendFunction.AlphaFormat & ~AC_SRC_ALPHA) != 0)
88  {
89  DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendObj->BlendFunction.AlphaFormat);
90  return FALSE;
91  }
92 
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))
97  {
98  /* Nothing to do */
99  return TRUE;
100  }
101 
102  /* Now call the DIB function */
103  if (!IntEngEnter(&EnterLeaveSource, psoSource, &InputRect, TRUE, &Translate, &InputObj))
104  {
105  return FALSE;
106  }
107  InputRect.left += Translate.x;
108  InputRect.right += Translate.x;
109  InputRect.top += Translate.y;
110  InputRect.bottom += Translate.y;
111 
112  if (!IntEngEnter(&EnterLeaveDest, psoDest, &OutputRect, FALSE, &Translate, &OutputObj))
113  {
114  return FALSE;
115  }
116  OutputRect.left += Translate.x;
117  OutputRect.right += Translate.x;
118  OutputRect.top += Translate.y;
119  OutputRect.bottom += Translate.y;
120 
121  ASSERT(InputRect.left <= InputRect.right && InputRect.top <= InputRect.bottom);
122 
123  Ret = FALSE;
124  ClippingType = (ClipRegion == NULL) ? DC_TRIVIAL : ClipRegion->iDComplexity;
125  switch (ClippingType)
126  {
127  case DC_TRIVIAL:
129  OutputObj, InputObj, &OutputRect, &InputRect, ClipRegion, ColorTranslation, BlendObj);
130  break;
131 
132  case DC_RECT:
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))
138  {
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);
144 
145  /* Aplha blend one rect */
147  OutputObj, InputObj, &CombinedRect, &Rect, ClipRegion, ColorTranslation, BlendObj);
148  }
149  break;
150 
151  case DC_COMPLEX:
152  Ret = TRUE;
153  CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, CD_ANY, 0);
154  do
155  {
156  EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum),
157  (PVOID) &RectEnum);
158 
159  for (i = 0; i < RectEnum.c; i++)
160  {
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))
166  {
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);
172 
173  /* Alpha blend one rect */
175  OutputObj, InputObj, &CombinedRect, &Rect, ClipRegion, ColorTranslation, BlendObj) && Ret;
176  }
177  }
178  }
179  while (EnumMore);
180  break;
181 
182  default:
184  ASSERT(FALSE);
185  break;
186  }
187 
188  IntEngLeave(&EnterLeaveDest);
189  IntEngLeave(&EnterLeaveSource);
190 
191  return Ret;
192 }
193 
194 BOOL
195 APIENTRY
197  _Inout_ SURFOBJ *psoDest,
198  _In_ SURFOBJ *psoSource,
202  _In_ RECTL *prclSrc,
204 {
205  BOOL ret = FALSE;
206  SURFACE *psurfDest;
207 
208  ASSERT(psoDest);
209  ASSERT(psoSource);
210  ASSERT(prclDest);
211  ASSERT(prclSrc);
212  //ASSERT(pBlendObj);
213 
214  /* If no clip object is given, use trivial one */
215  if (!pco) pco = (CLIPOBJ *)&gxcoTrivial;
216 
217  /* Check if there is anything to draw */
218  if ((pco->rclBounds.left >= pco->rclBounds.right) ||
219  (pco->rclBounds.top >= pco->rclBounds.bottom))
220  {
221  /* Nothing to do */
222  return TRUE;
223  }
224 
225  psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj);
226 
227  /* Call the driver's DrvAlphaBlend if available */
228  if (psurfDest->flags & HOOK_ALPHABLEND)
229  {
230  ret = GDIDEVFUNCS(psoDest).AlphaBlend(
231  psoDest, psoSource, pco, pxlo,
232  prclDest, prclSrc, pBlendObj);
233  }
234 
235  if (!ret)
236  {
237  ret = EngAlphaBlend(psoDest, psoSource, pco, pxlo,
238  prclDest, prclSrc, pBlendObj);
239  }
240 
241  return ret;
242 }
243 
244 /*
245  * @implemented
246  */
247 BOOL
248 APIENTRY
250  IN SURFOBJ *psoSource,
251  IN CLIPOBJ *ClipRegion,
252  IN XLATEOBJ *ColorTranslation,
253  IN PRECTL upDestRect,
254  IN PRECTL upSourceRect,
255  IN BLENDOBJ *BlendObj)
256 {
257  RECTL DestRect;
258  RECTL SourceRect;
259 
260  _SEH2_TRY
261  {
262  ProbeForRead(upDestRect, sizeof(RECTL), 1);
263  RtlCopyMemory(&DestRect,upDestRect, sizeof(RECTL));
264 
265  ProbeForRead(upSourceRect, sizeof(RECTL), 1);
266  RtlCopyMemory(&SourceRect, upSourceRect, sizeof(RECTL));
267 
268  }
270  {
271  _SEH2_YIELD(return FALSE);
272  }
273  _SEH2_END;
274 
275  return EngAlphaBlend(psoDest, psoSource, ClipRegion, ColorTranslation, &DestRect, &SourceRect, BlendObj);
276 }
277 
DWORD *typedef PVOID
Definition: winlogon.h:61
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
BOOL APIENTRY IntEngAlphaBlend(_Inout_ SURFOBJ *psoDest, _In_ SURFOBJ *psoSource, _In_opt_ CLIPOBJ *pco, _In_opt_ XLATEOBJ *pxlo, _In_ RECTL *prclDest, _In_ RECTL *prclSrc, _In_ BLENDOBJ *pBlendObj)
Definition: alphablend.c:196
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
XCLIPOBJ gxcoTrivial
Definition: bitblt.c:15
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define DC_TRIVIAL
Definition: winddi.h:259
long bottom
Definition: polytest.cpp:53
ULONG iBitmapFormat
Definition: winddi.h:1215
VOID FASTCALL RECTL_vMakeWellOrdered(_Inout_ RECTL *prcl)
Definition: rect.c:81
#define AC_SRC_ALPHA
Definition: alphablend.c:9
#define _In_opt_
Definition: no_sal2.h:213
LONG y
Definition: windef.h:320
_SEH2_TRY
Definition: create.c:4250
PFN_DIB_AlphaBlend DIB_AlphaBlend
Definition: dib.h:54
#define HOOK_ALPHABLEND
Definition: winddi.h:1435
long right
Definition: polytest.cpp:53
GLenum GLclampf GLint i
Definition: glfuncs.h:14
#define FALSE
Definition: types.h:117
long LONG
Definition: pedump.c:60
long top
Definition: polytest.cpp:53
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define APIENTRY
Definition: nt_native.h:48
smooth NULL
Definition: ftsmooth.c:416
#define CT_RECTANGLES
Definition: winddi.h:1317
void DPRINT(...)
Definition: polytest.cpp:61
switch(r->id)
Definition: btrfs.c:2676
BOOL APIENTRY NtGdiEngAlphaBlend(IN SURFOBJ *psoDest, IN SURFOBJ *psoSource, IN CLIPOBJ *ClipRegion, IN XLATEOBJ *ColorTranslation, IN PRECTL upDestRect, IN PRECTL upSourceRect, IN BLENDOBJ *BlendObj)
Definition: alphablend.c:249
long left
Definition: polytest.cpp:53
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_In_ SURFOBJ _In_ CLIPOBJ _In_opt_ XLATEOBJ _In_ RECTL _In_ RECTL * prclSrc
Definition: winddi.h:3414
unsigned char BOOLEAN
#define DC_RECT
Definition: winddi.h:260
unsigned int BOOL
Definition: ntddk_ex.h:94
#define _SEH2_YIELD(STMT_)
Definition: pseh2_64.h:8
ENGAPI ULONG APIENTRY CLIPOBJ_cEnumStart(_Inout_ CLIPOBJ *pco, _In_ BOOL bAll, _In_ ULONG iType, _In_ ULONG iDirection, _In_ ULONG cLimit)
Definition: clip.c:255
#define GDIDEVFUNCS(SurfObj)
Definition: surface.h:106
LONG x
Definition: windef.h:319
#define _Inout_
Definition: no_sal2.h:244
_In_ SURFOBJ _In_ CLIPOBJ _In_opt_ XLATEOBJ _In_ RECTL * prclDest
Definition: winddi.h:3414
BOOL APIENTRY IntEngEnter(PINTENG_ENTER_LEAVE EnterLeave, SURFOBJ *psoDest, RECTL *DestRect, BOOL ReadOnly, POINTL *Translate, SURFOBJ **ppsoOutput)
Definition: engmisc.c:15
int ret
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
#define AC_SRC_OVER
Definition: wingdi.h:1350
_In_ SURFOBJ _In_ CLIPOBJ * pco
Definition: winddi.h:3414
BOOL APIENTRY EngAlphaBlend(_Inout_ SURFOBJ *psoDest, _In_ SURFOBJ *psoSource, _In_opt_ CLIPOBJ *ClipRegion, _In_opt_ XLATEOBJ *ColorTranslation, _In_ RECTL *DestRect, _In_ RECTL *SourceRect, _In_ BLENDOBJ *BlendObj)
Definition: alphablend.c:20
#define _In_
Definition: no_sal2.h:204
#define DC_COMPLEX
Definition: winddi.h:261
_SEH2_END
Definition: create.c:4424
DIB_FUNCTIONS DibFunctionsForBitmapFormat[]
Definition: dib.c:20
_In_ SURFOBJ _In_ CLIPOBJ _In_opt_ XLATEOBJ _In_ RECTL _In_ RECTL _In_ BLENDOBJ * pBlendObj
Definition: winddi.h:3414
FLONG flags
Definition: surface.h:10
#define DPRINT1
Definition: precomp.h:8
BOOL FASTCALL RECTL_bIntersectRect(_Out_ RECTL *prclDst, _In_ const RECTL *prcl1, _In_ const RECTL *prcl2)
Definition: rect.c:55
unsigned int ULONG
Definition: retypes.h:1
#define UNIMPLEMENTED
Definition: debug.h:114
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
BOOL APIENTRY IntEngLeave(PINTENG_ENTER_LEAVE EnterLeave)
Definition: engmisc.c:162
ENGAPI BOOL APIENTRY CLIPOBJ_bEnum(_In_ CLIPOBJ *pco, _In_ ULONG cj, _Out_bytecap_(cj) ULONG *pul)
Definition: clip.c:319
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:27
struct Rect Rect
#define CD_ANY
Definition: winddi.h:1326
_In_ SURFOBJ _In_ CLIPOBJ _In_opt_ XLATEOBJ * pxlo
Definition: winddi.h:3414