d3d9: Add a test for GetContainer (Volumes & Surfaces).
[wine] / dlls / ddraw / clipper.c
1 /*              DirectDrawClipper implementation
2  *
3  * Copyright 2000 Marcus Meissner
4  * Copyright 2000 TransGaming Technologies Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22
23 #include <stdarg.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wingdi.h"
30 #include "ddraw.h"
31 #include "winerror.h"
32
33 #include "ddraw_private.h"
34
35 #include "wine/debug.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
38
39 /******************************************************************************
40  *                      DirectDrawCreateClipper (DDRAW.@)
41  */
42
43 static const IDirectDrawClipperVtbl DDRAW_Clipper_VTable;
44
45 HRESULT WINAPI DirectDrawCreateClipper(
46     DWORD dwFlags, LPDIRECTDRAWCLIPPER *lplpDDClipper, LPUNKNOWN pUnkOuter
47 ) {
48     IDirectDrawClipperImpl* This;
49     TRACE("(%08lx,%p,%p)\n", dwFlags, lplpDDClipper, pUnkOuter);
50
51     if (pUnkOuter != NULL) return CLASS_E_NOAGGREGATION;
52
53     This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
54                      sizeof(IDirectDrawClipperImpl));
55     if (This == NULL) return E_OUTOFMEMORY;
56
57     ICOM_INIT_INTERFACE(This, IDirectDrawClipper, DDRAW_Clipper_VTable);
58     This->ref = 1;
59     This->hWnd = 0;
60     This->ddraw_owner = NULL;
61
62     *lplpDDClipper = ICOM_INTERFACE(This, IDirectDrawClipper);
63     return DD_OK;
64 }
65
66 /* This is the classfactory implementation. */
67 HRESULT DDRAW_CreateDirectDrawClipper(IUnknown* pUnkOuter, REFIID riid,
68                                       LPVOID* ppObj)
69 {
70     HRESULT hr;
71     LPDIRECTDRAWCLIPPER pClip;
72
73     hr = DirectDrawCreateClipper(0, &pClip, pUnkOuter);
74     if (FAILED(hr)) return hr;
75
76     hr = IDirectDrawClipper_QueryInterface(pClip, riid, ppObj);
77     IDirectDrawClipper_Release(pClip);
78     return hr;
79 }
80
81 /******************************************************************************
82  *                      IDirectDrawClipper
83  */
84 HRESULT WINAPI Main_DirectDrawClipper_SetHwnd(
85     LPDIRECTDRAWCLIPPER iface, DWORD dwFlags, HWND hWnd
86 ) {
87     IDirectDrawClipperImpl *This = (IDirectDrawClipperImpl *)iface;
88
89     TRACE("(%p)->(0x%08lx,0x%08lx)\n", This, dwFlags, (DWORD)hWnd);
90     if( dwFlags ) {
91         FIXME("dwFlags = 0x%08lx, not supported.\n",dwFlags);
92         return DDERR_INVALIDPARAMS;
93     }
94
95     This->hWnd = hWnd;
96     return DD_OK;
97 }
98
99 static void Main_DirectDrawClipper_Destroy(IDirectDrawClipperImpl* This)
100 {
101     if (This->ddraw_owner != NULL)
102         Main_DirectDraw_RemoveClipper(This->ddraw_owner, This);
103
104     HeapFree(GetProcessHeap(), 0 ,This);
105 }
106
107 void Main_DirectDrawClipper_ForceDestroy(IDirectDrawClipperImpl* This)
108 {
109     WARN("deleting clipper %p with refcnt %lu\n", This, This->ref);
110     Main_DirectDrawClipper_Destroy(This);
111 }
112
113 ULONG WINAPI Main_DirectDrawClipper_Release(LPDIRECTDRAWCLIPPER iface) {
114     IDirectDrawClipperImpl *This = (IDirectDrawClipperImpl *)iface;
115     ULONG ref = InterlockedDecrement(&This->ref);
116
117     TRACE("(%p)->() decrementing from %lu.\n", This, ref + 1);
118
119     if (ref == 0)
120     {
121         Main_DirectDrawClipper_Destroy(This);
122         return 0;
123     }
124     else return ref;
125 }
126
127 /***********************************************************************
128 *           IDirectDrawClipper::GetClipList
129 *
130 * Retrieve a copy of the clip list
131 *
132 * PARAMS
133 *  lpRect  Rectangle to be used to clip the clip list or NULL for the
134 *          entire clip list
135 *  lpClipList structure for the resulting copy of the clip list.
136            If NULL, fills lpdwSize up to the number of bytes necessary to hold
137            the entire clip.
138 *  lpdwSize Size of resulting clip list; size of the buffer at lpClipList
139            or, if lpClipList is NULL, receives the required size of the buffer
140            in bytes
141 * RETURNS
142 *  Either DD_OK or DDERR_*
143 */
144 HRESULT WINAPI Main_DirectDrawClipper_GetClipList(
145     LPDIRECTDRAWCLIPPER iface, LPRECT lpRect, LPRGNDATA lpClipList,
146     LPDWORD lpdwSize)
147 {
148     IDirectDrawClipperImpl *This = (IDirectDrawClipperImpl *)iface;
149
150     TRACE("(%p,%p,%p,%p)\n", This, lpRect, lpClipList, lpdwSize);
151
152     if (This->hWnd)
153     {
154         HDC hDC = GetDCEx(This->hWnd, NULL, DCX_WINDOW);
155         if (hDC)
156         {
157             HRGN hRgn = CreateRectRgn(0,0,0,0);
158             if (GetRandomRgn(hDC, hRgn, SYSRGN))
159             {
160                 if (GetVersion() & 0x80000000)
161                 {
162                     /* map region to screen coordinates */
163                     POINT org;
164                     GetDCOrgEx( hDC, &org );
165                     OffsetRgn( hRgn, org.x, org.y );
166                 }
167                 if (lpRect)
168                 {
169                     HRGN hRgnClip = CreateRectRgn(lpRect->left, lpRect->top,
170                         lpRect->right, lpRect->bottom);
171                     CombineRgn(hRgn, hRgn, hRgnClip, RGN_AND);
172                     DeleteObject(hRgnClip);
173                 }
174                 *lpdwSize = GetRegionData(hRgn, *lpdwSize, lpClipList);
175             }
176             DeleteObject(hRgn);
177             ReleaseDC(This->hWnd, hDC);
178         }
179         return DD_OK;
180     }
181     else
182     {
183         static int warned = 0;
184         if (warned++ < 10)
185             FIXME("(%p,%p,%p,%p),stub!\n",This,lpRect,lpClipList,lpdwSize);
186         if (lpdwSize) *lpdwSize=0;
187         return DDERR_NOCLIPLIST;
188     }
189 }
190
191 /***********************************************************************
192 *           IDirectDrawClipper::SetClipList
193 *
194 * Sets or deletes (if lprgn is NULL) the clip list
195 *
196 * PARAMS
197 *  lprgn   Pointer to a LRGNDATA structure or NULL
198 *  dwFlags not used, must be 0
199 * RETURNS
200 *  Either DD_OK or DDERR_*
201 */
202 HRESULT WINAPI Main_DirectDrawClipper_SetClipList(
203     LPDIRECTDRAWCLIPPER iface,LPRGNDATA lprgn,DWORD dwFlag
204 ) {
205     IDirectDrawClipperImpl *This = (IDirectDrawClipperImpl *)iface;
206     static int warned = 0;
207     if (warned++ < 10 || lprgn == NULL)
208         FIXME("(%p,%p,%ld),stub!\n",This,lprgn,dwFlag);
209     return DD_OK;
210 }
211
212 HRESULT WINAPI Main_DirectDrawClipper_QueryInterface(
213     LPDIRECTDRAWCLIPPER iface, REFIID riid, LPVOID* ppvObj
214 ) {
215     IDirectDrawClipperImpl *This = (IDirectDrawClipperImpl *)iface;
216
217     if (IsEqualGUID(&IID_IUnknown, riid)
218         || IsEqualGUID(&IID_IDirectDrawClipper, riid))
219     {
220         *ppvObj = ICOM_INTERFACE(This, IDirectDrawClipper);
221         InterlockedIncrement(&This->ref);
222         return S_OK;
223     }
224     else
225     {
226         return E_NOINTERFACE;
227     }
228 }
229
230 ULONG WINAPI Main_DirectDrawClipper_AddRef( LPDIRECTDRAWCLIPPER iface )
231 {
232     IDirectDrawClipperImpl *This = (IDirectDrawClipperImpl *)iface;
233     ULONG ref = InterlockedIncrement(&This->ref);
234
235     TRACE("(%p)->() incrementing from %lu.\n", This, ref - 1);
236
237     return ref;
238 }
239
240 HRESULT WINAPI Main_DirectDrawClipper_GetHWnd(
241     LPDIRECTDRAWCLIPPER iface, HWND* hWndPtr
242 ) {
243     IDirectDrawClipperImpl *This = (IDirectDrawClipperImpl *)iface;
244     TRACE("(%p)->(%p)\n", This, hWndPtr);
245
246     *hWndPtr = This->hWnd;
247
248     return DD_OK;
249 }
250
251 HRESULT WINAPI Main_DirectDrawClipper_Initialize(
252      LPDIRECTDRAWCLIPPER iface, LPDIRECTDRAW lpDD, DWORD dwFlags
253 ) {
254     IDirectDrawImpl* pOwner;
255     IDirectDrawClipperImpl *This = (IDirectDrawClipperImpl *)iface;
256     TRACE("(%p)->(%p,0x%08lx)\n", This, lpDD, dwFlags);
257
258     if (This->ddraw_owner != NULL) return DDERR_ALREADYINITIALIZED;
259
260     pOwner = ICOM_OBJECT(IDirectDrawImpl, IDirectDraw, lpDD);
261     This->ddraw_owner = pOwner;
262     Main_DirectDraw_AddClipper(pOwner, This);
263
264     return DD_OK;
265 }
266
267 HRESULT WINAPI Main_DirectDrawClipper_IsClipListChanged(
268     LPDIRECTDRAWCLIPPER iface, BOOL* lpbChanged
269 ) {
270     IDirectDrawClipperImpl *This = (IDirectDrawClipperImpl *)iface;
271     FIXME("(%p)->(%p),stub!\n",This,lpbChanged);
272
273     /* XXX What is safest? */
274     *lpbChanged = FALSE;
275
276     return DD_OK;
277 }
278
279 static const IDirectDrawClipperVtbl DDRAW_Clipper_VTable =
280 {
281     Main_DirectDrawClipper_QueryInterface,
282     Main_DirectDrawClipper_AddRef,
283     Main_DirectDrawClipper_Release,
284     Main_DirectDrawClipper_GetClipList,
285     Main_DirectDrawClipper_GetHWnd,
286     Main_DirectDrawClipper_Initialize,
287     Main_DirectDrawClipper_IsClipListChanged,
288     Main_DirectDrawClipper_SetClipList,
289     Main_DirectDrawClipper_SetHwnd
290 };