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