Fix another bug thanks to GreatLord.
[reactos.git] / reactos / lib / ddraw / main / ddraw.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS
5 * FILE: lib/ddraw/main/ddraw.c
6 * PURPOSE: DirectDraw Implementation
7 * PROGRAMMER: Magnus Olsen, Maarten Bosma
8 *
9 */
10
11 #include "rosdraw.h"
12
13
14 HRESULT WINAPI Main_DirectDraw_Initialize (LPDIRECTDRAW7 iface, LPGUID lpGUID)
15 {
16 IDirectDrawImpl* This = (IDirectDrawImpl*)iface;
17 HRESULT ret;
18
19 // this if it is not called by DirectDrawCreate
20 if(FALSE)
21 return DDERR_ALREADYINITIALIZED;
22
23 // save the parameter
24 This->lpGUID = lpGUID;
25
26 // get the HDC
27 This->hdc = GetWindowDC(GetDesktopWindow());
28 This->Height = GetDeviceCaps(This->hdc, HORZRES);
29 This->Width = GetDeviceCaps(This->hdc, VERTRES);
30 This->Bpp = GetDeviceCaps(This->hdc, BITSPIXEL);
31
32 // call software first
33 if((ret = Hal_DirectDraw_Initialize (iface)) != DD_OK)
34 return ret;
35
36 // ... then overwrite with hal
37 if((ret = Hel_DirectDraw_Initialize (iface)) != DD_OK)
38 return ret;
39
40 return DD_OK;
41 }
42
43 HRESULT WINAPI Main_DirectDraw_SetCooperativeLevel (LPDIRECTDRAW7 iface, HWND hwnd, DWORD cooplevel)
44 {
45 // TODO:
46 // - create a scaner that check which driver we should get the HDC from
47 // for now we always asume it is the active dirver that should be use.
48 // - allow more Flags
49
50 IDirectDrawImpl* This = (IDirectDrawImpl*)iface;
51 HRESULT ret;
52
53 // check the parameters
54 if (This->cooperative_level == cooplevel && This->window == hwnd)
55 return DD_OK;
56
57 if (This->window)
58 return DDERR_HWNDALREADYSET;
59
60 if (This->cooperative_level)
61 return DDERR_EXCLUSIVEMODEALREADYSET;
62
63 if ((cooplevel&DDSCL_EXCLUSIVE) && !(cooplevel&DDSCL_FULLSCREEN))
64 return DDERR_INVALIDPARAMS;
65
66 if (cooplevel&DDSCL_NORMAL && cooplevel&DDSCL_FULLSCREEN)
67 return DDERR_INVALIDPARAMS;
68
69 // set the data
70 This->window = hwnd;
71 This->hdc = GetDC(hwnd);
72 This->cooperative_level = cooplevel;
73
74 if((ret = Hel_DirectDraw_SetCooperativeLevel (iface)) != DD_OK)
75 return ret;
76
77 if((ret = Hal_DirectDraw_SetCooperativeLevel (iface)) != DD_OK)
78 return ret;
79
80 return DD_OK;
81 }
82
83 HRESULT WINAPI Main_DirectDraw_SetDisplayMode (LPDIRECTDRAW7 iface, DWORD dwWidth, DWORD dwHeight,
84 DWORD dwBPP, DWORD dwRefreshRate, DWORD dwFlags)
85 {
86 IDirectDrawImpl* This = (IDirectDrawImpl*)iface;
87
88 // this only for exclusive mode
89 if(!(This->cooperative_level & DDSCL_EXCLUSIVE))
90 return DDERR_NOEXCLUSIVEMODE;
91
92 // change the resolution using normal WinAPI function
93 DEVMODE mode;
94 mode.dmSize = sizeof(mode);
95 mode.dmPelsWidth = dwWidth;
96 mode.dmPelsHeight = dwHeight;
97 mode.dmBitsPerPel = dwBPP;
98 mode.dmDisplayFrequency = dwRefreshRate;
99 mode.dmFields = 0;
100
101 if(dwWidth)
102 mode.dmFields |= DM_PELSWIDTH;
103 if(dwHeight)
104 mode.dmFields |= DM_PELSHEIGHT;
105 if(dwBPP)
106 mode.dmFields |= DM_BITSPERPEL;
107 if(dwRefreshRate)
108 mode.dmFields |= DM_DISPLAYFREQUENCY;
109
110 if (ChangeDisplaySettings(&mode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
111 return DDERR_UNSUPPORTEDMODE;
112
113 // TODO: reactivate ddraw object, maximize window, set it in foreground
114 // and set excluive mode (if implemented by the driver)
115
116 if(dwWidth)
117 This->Height = dwWidth;
118 if(dwHeight)
119 This->Width = dwHeight;
120 if(dwBPP)
121 This->Bpp = dwBPP;
122
123 return DD_OK;
124 }
125
126 HRESULT WINAPI Main_DirectDraw_CreateSurface (LPDIRECTDRAW7 iface, LPDDSURFACEDESC2 pDDSD,
127 LPDIRECTDRAWSURFACE7 *ppSurf, IUnknown *pUnkOuter)
128 {
129 if (pUnkOuter!=NULL)
130 return DDERR_INVALIDPARAMS;
131
132 if(sizeof(DDSURFACEDESC2)!=pDDSD->dwSize)
133 return DDERR_UNSUPPORTED;
134
135 // the nasty com stuff
136 IDirectDrawSurfaceImpl* That;
137
138 That = (IDirectDrawSurfaceImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectDrawSurfaceImpl));
139
140 if (That == NULL)
141 return E_OUTOFMEMORY;
142
143 That->lpVtbl = &DDrawSurface_VTable;
144 That->ref = 1;
145 *ppSurf = (LPDIRECTDRAWSURFACE7)That;
146
147 // the real surface object creation
148 return That->lpVtbl->Initialize (*ppSurf, (LPDIRECTDRAW)iface, pDDSD);
149 }
150
151 ULONG WINAPI Main_DirectDraw_AddRef (LPDIRECTDRAW7 iface)
152 {
153 IDirectDrawImpl* This = (IDirectDrawImpl*)iface;
154 ULONG ref = InterlockedIncrement(&This->ref);
155
156 return ref;
157 }
158
159 ULONG WINAPI Main_DirectDraw_Release (LPDIRECTDRAW7 iface)
160 {
161 IDirectDrawImpl* This = (IDirectDrawImpl*)iface;
162 ULONG ref = InterlockedDecrement(&This->ref);
163
164 if (ref == 0)
165 {
166 // set resoltion back to the one in registry
167 if(This->cooperative_level & DDSCL_EXCLUSIVE)
168 ChangeDisplaySettings(NULL, 0);
169
170 HeapFree(GetProcessHeap(), 0, This);
171 }
172
173 return ref;
174 }
175
176 /**** Stubs ****/
177
178 HRESULT WINAPI Main_DirectDraw_QueryInterface (LPDIRECTDRAW7 iface,REFIID refiid,LPVOID *obj)
179 {
180 return DDERR_UNSUPPORTED;
181 }
182
183 HRESULT WINAPI Main_DirectDraw_Compact(LPDIRECTDRAW7 iface)
184 {
185 return DDERR_UNSUPPORTED;
186 }
187
188 HRESULT WINAPI Main_DirectDraw_CreateClipper(LPDIRECTDRAW7 iface, DWORD dwFlags,
189 LPDIRECTDRAWCLIPPER *ppClipper, IUnknown *pUnkOuter)
190 {
191 return DDERR_UNSUPPORTED;
192 }
193 HRESULT WINAPI Main_DirectDraw_CreatePalette(LPDIRECTDRAW7 iface, DWORD dwFlags,
194 LPPALETTEENTRY palent,LPDIRECTDRAWPALETTE* ppPalette,LPUNKNOWN pUnknown)
195 {
196 return DDERR_UNSUPPORTED;
197 }
198
199 HRESULT WINAPI Main_DirectDraw_DuplicateSurface(LPDIRECTDRAW7 iface, LPDIRECTDRAWSURFACE7 src,
200 LPDIRECTDRAWSURFACE7* dst)
201 {
202 return DDERR_UNSUPPORTED;
203 }
204
205 HRESULT WINAPI Main_DirectDraw_EnumDisplayModes(LPDIRECTDRAW7 iface, DWORD dwFlags,
206 LPDDSURFACEDESC2 pDDSD, LPVOID context, LPDDENUMMODESCALLBACK2 callback)
207 {
208 return DDERR_UNSUPPORTED;
209 }
210
211 HRESULT WINAPI Main_DirectDraw_EnumSurfaces(LPDIRECTDRAW7 iface, DWORD dwFlags,
212 LPDDSURFACEDESC2 lpDDSD2, LPVOID context,
213 LPDDENUMSURFACESCALLBACK7 callback)
214 {
215 return DDERR_UNSUPPORTED;
216 }
217
218 HRESULT WINAPI Main_DirectDraw_FlipToGDISurface(LPDIRECTDRAW7 iface)
219 {
220 return DDERR_UNSUPPORTED;
221 }
222
223 HRESULT WINAPI Main_DirectDraw_GetCaps(LPDIRECTDRAW7 iface, LPDDCAPS pDriverCaps,
224 LPDDCAPS pHELCaps)
225 {
226 return DDERR_UNSUPPORTED;
227 }
228
229 HRESULT WINAPI Main_DirectDraw_GetDisplayMode(LPDIRECTDRAW7 iface, LPDDSURFACEDESC2 pDDSD)
230 {
231 return DDERR_UNSUPPORTED;
232 }
233
234
235 HRESULT WINAPI Main_DirectDraw_GetFourCCCodes(LPDIRECTDRAW7 iface, LPDWORD pNumCodes, LPDWORD pCodes)
236 {
237 return DDERR_UNSUPPORTED;
238 }
239
240 HRESULT WINAPI Main_DirectDraw_GetGDISurface(LPDIRECTDRAW7 iface,
241 LPDIRECTDRAWSURFACE7 *lplpGDIDDSSurface)
242 {
243 return DDERR_UNSUPPORTED;
244 }
245
246 HRESULT WINAPI Main_DirectDraw_GetMonitorFrequency(LPDIRECTDRAW7 iface,LPDWORD freq)
247 {
248 return DDERR_UNSUPPORTED;
249 }
250
251 HRESULT WINAPI Main_DirectDraw_GetScanLine(LPDIRECTDRAW7 iface, LPDWORD lpdwScanLine)
252 {
253 return DDERR_UNSUPPORTED;
254 }
255
256 HRESULT WINAPI Main_DirectDraw_GetVerticalBlankStatus(LPDIRECTDRAW7 iface, LPBOOL status)
257 {
258 return DDERR_UNSUPPORTED;
259 }
260
261 HRESULT WINAPI Main_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface)
262 {
263 return DDERR_UNSUPPORTED;
264 }
265
266 HRESULT WINAPI Main_DirectDraw_WaitForVerticalBlank(LPDIRECTDRAW7 iface, DWORD dwFlags,
267 HANDLE h)
268 {
269
270 return DDERR_UNSUPPORTED;
271 }
272
273 HRESULT WINAPI Main_DirectDraw_GetAvailableVidMem(LPDIRECTDRAW7 iface, LPDDSCAPS2 ddscaps,
274 LPDWORD total, LPDWORD free)
275 {
276
277 return DDERR_UNSUPPORTED;
278 }
279
280 HRESULT WINAPI Main_DirectDraw_GetSurfaceFromDC(LPDIRECTDRAW7 iface, HDC hdc,
281 LPDIRECTDRAWSURFACE7 *lpDDS)
282 {
283 return DDERR_UNSUPPORTED;
284 }
285
286 HRESULT WINAPI Main_DirectDraw_RestoreAllSurfaces(LPDIRECTDRAW7 iface)
287 {
288 return DDERR_UNSUPPORTED;
289 }
290
291 HRESULT WINAPI Main_DirectDraw_TestCooperativeLevel(LPDIRECTDRAW7 iface)
292 {
293 return DDERR_UNSUPPORTED;
294 }
295
296 HRESULT WINAPI Main_DirectDraw_GetDeviceIdentifier(LPDIRECTDRAW7 iface,
297 LPDDDEVICEIDENTIFIER2 pDDDI, DWORD dwFlags)
298 {
299 return DDERR_UNSUPPORTED;
300 }
301
302 HRESULT WINAPI Main_DirectDraw_StartModeTest(LPDIRECTDRAW7 iface, LPSIZE pModes,
303 DWORD dwNumModes, DWORD dwFlags)
304 {
305 return DDERR_UNSUPPORTED;
306 }
307
308 HRESULT WINAPI Main_DirectDraw_EvaluateMode(LPDIRECTDRAW7 iface,DWORD a,DWORD* b)
309 {
310 return DDERR_UNSUPPORTED;
311 }
312
313 IDirectDraw7Vtbl DirectDraw_VTable =
314 {
315 Main_DirectDraw_QueryInterface,
316 Main_DirectDraw_AddRef,
317 Main_DirectDraw_Release,
318 Main_DirectDraw_Compact,
319 Main_DirectDraw_CreateClipper,
320 Main_DirectDraw_CreatePalette,
321 Main_DirectDraw_CreateSurface,
322 Main_DirectDraw_DuplicateSurface,
323 Main_DirectDraw_EnumDisplayModes,
324 Main_DirectDraw_EnumSurfaces,
325 Main_DirectDraw_FlipToGDISurface,
326 Main_DirectDraw_GetCaps,
327 Main_DirectDraw_GetDisplayMode,
328 Main_DirectDraw_GetFourCCCodes,
329 Main_DirectDraw_GetGDISurface,
330 Main_DirectDraw_GetMonitorFrequency,
331 Main_DirectDraw_GetScanLine,
332 Main_DirectDraw_GetVerticalBlankStatus,
333 Main_DirectDraw_Initialize,
334 Main_DirectDraw_RestoreDisplayMode,
335 Main_DirectDraw_SetCooperativeLevel,
336 Main_DirectDraw_SetDisplayMode,
337 Main_DirectDraw_WaitForVerticalBlank,
338 Main_DirectDraw_GetAvailableVidMem,
339 Main_DirectDraw_GetSurfaceFromDC,
340 Main_DirectDraw_RestoreAllSurfaces,
341 Main_DirectDraw_TestCooperativeLevel,
342 Main_DirectDraw_GetDeviceIdentifier,
343 Main_DirectDraw_StartModeTest,
344 Main_DirectDraw_EvaluateMode
345 };