Fix some crach in ddraw.dll startup process for surface, we still got crach and surfa...
[reactos.git] / reactos / lib / ddraw / main / ddraw_main.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: IDirectDraw7 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
20
21 // this if it is not called by DirectDrawCreate
22 if(FALSE)
23 return DDERR_ALREADYINITIALIZED;
24
25 // save the parameter
26 This->lpGUID = lpGUID;
27
28 // get the HDC
29 This->hdc = GetWindowDC(GetDesktopWindow());
30 This->Height = GetDeviceCaps(This->hdc, VERTRES);
31 This->Width = GetDeviceCaps(This->hdc, HORZRES);
32 This->Bpp = GetDeviceCaps(This->hdc, BITSPIXEL);
33
34 // call software first
35 if((ret = Hal_DirectDraw_Initialize (iface)) != DD_OK)
36 return ret;
37
38 // ... then overwrite with hal
39 if((ret = Hel_DirectDraw_Initialize (iface)) != DD_OK)
40 return ret;
41
42
43 return DD_OK;
44 }
45
46 HRESULT WINAPI Main_DirectDraw_SetCooperativeLevel (LPDIRECTDRAW7 iface, HWND hwnd, DWORD cooplevel)
47 {
48 // TODO:
49 // - create a scaner that check which driver we should get the HDC from
50 // for now we always asume it is the active dirver that should be use.
51 // - allow more Flags
52
53 IDirectDrawImpl* This = (IDirectDrawImpl*)iface;
54
55 // check the parameters
56 if (This->cooperative_level == cooplevel && This->window == hwnd)
57 return DD_OK;
58
59 if (This->window)
60 return DDERR_HWNDALREADYSET;
61
62 if (This->cooperative_level)
63 return DDERR_EXCLUSIVEMODEALREADYSET;
64
65 if ((cooplevel&DDSCL_EXCLUSIVE) && !(cooplevel&DDSCL_FULLSCREEN))
66 return DDERR_INVALIDPARAMS;
67
68 if (cooplevel&DDSCL_NORMAL && cooplevel&DDSCL_FULLSCREEN)
69 return DDERR_INVALIDPARAMS;
70
71 // set the data
72 This->window = hwnd;
73 This->hdc = GetDC(hwnd);
74 This->cooperative_level = cooplevel;
75
76
77 if (This->DirectDrawGlobal.lpDDCBtmp->HALDD.dwFlags & DDHAL_CB32_SETEXCLUSIVEMODE)
78 {
79 return Hal_DirectDraw_SetCooperativeLevel (iface);
80 }
81
82 return Hel_DirectDraw_SetCooperativeLevel(iface);
83
84 }
85
86 HRESULT WINAPI Main_DirectDraw_SetDisplayMode (LPDIRECTDRAW7 iface, DWORD dwWidth, DWORD dwHeight,
87 DWORD dwBPP, DWORD dwRefreshRate, DWORD dwFlags)
88 {
89 DWORD ret;
90
91 /* FIXME implement hal setMode */
92 if((ret = Hal_DirectDraw_SetDisplayMode(iface, dwWidth, dwHeight,
93 dwBPP, dwRefreshRate, dwFlags)) == DD_OK)
94 {
95 return ret;
96 }
97
98 ret = Hel_DirectDraw_SetDisplayMode(iface, dwWidth, dwHeight, dwBPP, dwRefreshRate, dwFlags);
99
100 return ret;
101 }
102
103 ULONG WINAPI Main_DirectDraw_AddRef (LPDIRECTDRAW7 iface)
104 {
105 IDirectDrawImpl* This = (IDirectDrawImpl*)iface;
106 ULONG ref = InterlockedIncrement((PLONG)&This->DirectDrawGlobal.dwRefCnt);
107
108 return ref;
109 }
110
111 ULONG WINAPI Main_DirectDraw_Release (LPDIRECTDRAW7 iface)
112 {
113 IDirectDrawImpl* This = (IDirectDrawImpl*)iface;
114 ULONG ref = InterlockedDecrement((PLONG)&This->DirectDrawGlobal.dwRefCnt);
115
116 if (ref == 0)
117 {
118 // set resoltion back to the one in registry
119 if(This->cooperative_level & DDSCL_EXCLUSIVE)
120 ChangeDisplaySettings(NULL, 0);
121
122 HeapFree(GetProcessHeap(), 0, This);
123 }
124
125 return ref;
126 }
127
128 HRESULT WINAPI Main_DirectDraw_QueryInterface (
129 LPDIRECTDRAW7 iface, REFIID id, LPVOID *obj )
130 {
131 IDirectDrawImpl* This = (IDirectDrawImpl*)iface;
132
133 if (IsEqualGUID(&IID_IDirectDraw7, id))
134 {
135 *obj = &This->lpVtbl;
136 }
137 else if (IsEqualGUID(&IID_IDirectDraw, id))
138 {
139 *obj = &This->lpVtbl_v1;
140 }
141 else if (IsEqualGUID(&IID_IDirectDraw2, id))
142 {
143 *obj = &This->lpVtbl_v2;
144 }
145 else if (IsEqualGUID(&IID_IDirectDraw4, id))
146 {
147 *obj = &This->lpVtbl_v4;
148 }
149 else
150 {
151 *obj = NULL;
152 return E_NOINTERFACE;
153 }
154
155 Main_DirectDraw_AddRef(iface);
156 return S_OK;
157 }
158
159 HRESULT WINAPI Main_DirectDraw_CreateSurface (LPDIRECTDRAW7 iface, LPDDSURFACEDESC2 pDDSD,
160 LPDIRECTDRAWSURFACE7 *ppSurf, IUnknown *pUnkOuter)
161 {
162 if (pUnkOuter!=NULL)
163 return DDERR_INVALIDPARAMS;
164
165 if(sizeof(DDSURFACEDESC2)!=pDDSD->dwSize)
166 return DDERR_UNSUPPORTED;
167
168 // the nasty com stuff
169 IDirectDrawImpl* This = (IDirectDrawImpl*)iface;
170
171 IDirectDrawSurfaceImpl* That;
172
173 That = (IDirectDrawSurfaceImpl*)HeapAlloc(GetProcessHeap(), 0, sizeof(IDirectDrawSurfaceImpl));
174
175 if (That == NULL)
176 return E_OUTOFMEMORY;
177
178 ZeroMemory(That, sizeof(IDirectDrawSurfaceImpl));
179
180 That->lpVtbl = &DirectDrawSurface7_Vtable;
181 That->lpVtbl_v3 = &DDRAW_IDDS3_Thunk_VTable;
182
183 This->DirectDrawGlobal.dsList = (LPDDRAWI_DDRAWSURFACE_INT)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
184 sizeof(DDRAWI_DDRAWSURFACE_INT));
185
186 That->owner = (IDirectDrawImpl *)This;
187
188 That->owner->DirectDrawGlobal.dsList->dwIntRefCnt =1;
189
190 /* we alwasy set to use the DirectDrawSurface7_Vtable as internel */
191 That->owner->DirectDrawGlobal.dsList->lpVtbl = (PVOID) &DirectDrawSurface7_Vtable;
192
193
194 *ppSurf = (LPDIRECTDRAWSURFACE7)That;
195
196 // the real surface object creation
197 return That->lpVtbl->Initialize (*ppSurf, (LPDIRECTDRAW)iface, pDDSD);
198 }
199
200 HRESULT WINAPI Main_DirectDraw_CreateClipper(LPDIRECTDRAW7 iface, DWORD dwFlags,
201 LPDIRECTDRAWCLIPPER *ppClipper, IUnknown *pUnkOuter)
202 {
203 if (pUnkOuter!=NULL)
204 return DDERR_INVALIDPARAMS;
205
206 IDirectDrawClipperImpl* That;
207 That = (IDirectDrawClipperImpl*)HeapAlloc(GetProcessHeap(), 0, sizeof(IDirectDrawClipperImpl));
208
209 if (That == NULL)
210 return E_OUTOFMEMORY;
211
212 ZeroMemory(That, sizeof(IDirectDrawClipperImpl));
213
214 That->lpVtbl = &DirectDrawClipper_Vtable;
215 That->ref = 1;
216 *ppClipper = (LPDIRECTDRAWCLIPPER)That;
217
218 return That->lpVtbl->Initialize (*ppClipper, (LPDIRECTDRAW)iface, dwFlags);
219 }
220
221 // This function is exported by the dll
222 HRESULT WINAPI DirectDrawCreateClipper (DWORD dwFlags,
223 LPDIRECTDRAWCLIPPER* lplpDDClipper, LPUNKNOWN pUnkOuter)
224 {
225 return Main_DirectDraw_CreateClipper(NULL, dwFlags, lplpDDClipper, pUnkOuter);
226 }
227
228 HRESULT WINAPI Main_DirectDraw_CreatePalette(LPDIRECTDRAW7 iface, DWORD dwFlags,
229 LPPALETTEENTRY palent, LPDIRECTDRAWPALETTE* ppPalette, LPUNKNOWN pUnkOuter)
230 {
231 if (pUnkOuter!=NULL)
232 return DDERR_INVALIDPARAMS;
233
234 IDirectDrawPaletteImpl* That;
235 That = (IDirectDrawPaletteImpl*)HeapAlloc(GetProcessHeap(), 0, sizeof(IDirectDrawPaletteImpl));
236
237 if (That == NULL)
238 return E_OUTOFMEMORY;
239
240 ZeroMemory(That, sizeof(IDirectDrawPaletteImpl));
241
242 That->lpVtbl = &DirectDrawPalette_Vtable;
243 That->ref = 1;
244 *ppPalette = (LPDIRECTDRAWPALETTE)That;
245
246 return That->lpVtbl->Initialize (*ppPalette, (LPDIRECTDRAW)iface, dwFlags, palent);
247 }
248
249 /**** Stubs ****/
250
251 HRESULT WINAPI Main_DirectDraw_Compact(LPDIRECTDRAW7 iface)
252 {
253 DX_STUB;
254 }
255
256 HRESULT WINAPI Main_DirectDraw_DuplicateSurface(LPDIRECTDRAW7 iface, LPDIRECTDRAWSURFACE7 src,
257 LPDIRECTDRAWSURFACE7* dst)
258 {
259 DX_STUB;
260 }
261
262 HRESULT WINAPI Main_DirectDraw_EnumDisplayModes(LPDIRECTDRAW7 iface, DWORD dwFlags,
263 LPDDSURFACEDESC2 pDDSD, LPVOID context, LPDDENUMMODESCALLBACK2 callback)
264 {
265 DX_STUB;
266 }
267
268 HRESULT WINAPI Main_DirectDraw_EnumSurfaces(LPDIRECTDRAW7 iface, DWORD dwFlags,
269 LPDDSURFACEDESC2 lpDDSD2, LPVOID context,
270 LPDDENUMSURFACESCALLBACK7 callback)
271 {
272 DX_STUB;
273 }
274
275 HRESULT WINAPI Main_DirectDraw_FlipToGDISurface(LPDIRECTDRAW7 iface)
276 {
277 IDirectDrawImpl* This = (IDirectDrawImpl*)iface;
278
279 if (This->DirectDrawGlobal.lpDDCBtmp->HALDD.dwFlags & DDHAL_CB32_FLIPTOGDISURFACE)
280 {
281 return Hal_DirectDraw_FlipToGDISurface( iface);
282 }
283
284 return Hel_DirectDraw_FlipToGDISurface( iface);
285 }
286
287 HRESULT WINAPI Main_DirectDraw_GetCaps(LPDIRECTDRAW7 iface, LPDDCAPS pDriverCaps,
288 LPDDCAPS pHELCaps)
289 {
290 DWORD status = DD_FALSE;
291 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
292
293 if (pDriverCaps != NULL)
294 {
295 RtlCopyMemory(pDriverCaps,&This->DirectDrawGlobal.ddCaps,sizeof(DDCORECAPS));
296 status = DD_OK;
297 }
298
299 if (pHELCaps != NULL)
300 {
301 RtlCopyMemory(pDriverCaps,&This->DirectDrawGlobal.ddHELCaps,sizeof(DDCORECAPS));
302 status = DD_OK;
303 }
304
305 /* Both caps mixed ?? */
306 /* DDCORECAPS ddBothCaps; */
307
308 return status;
309 }
310
311 HRESULT WINAPI Main_DirectDraw_GetDisplayMode(LPDIRECTDRAW7 iface, LPDDSURFACEDESC2 pDDSD)
312 {
313 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
314
315 if (pDDSD == NULL)
316 {
317 return DD_FALSE;
318 }
319
320 pDDSD->dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_PITCH | DDSD_PIXELFORMAT | DDSD_REFRESHRATE | DDSD_WIDTH;
321 pDDSD->dwHeight = This->DirectDrawGlobal.vmiData.dwDisplayHeight;
322 pDDSD->dwWidth = This->DirectDrawGlobal.vmiData.dwDisplayWidth;
323
324 /* FIXME Do not use DUMMYUNIONNAME1 some how union lPitch does not see by the compiler
325 but rest of the union are visable. more header problem ???
326 */
327 pDDSD->DUMMYUNIONNAME1.lPitch = This->DirectDrawGlobal.vmiData.lDisplayPitch;
328
329
330 /* have not check where I should get hold of this info yet
331 DWORD dwBackBufferCount;
332 */
333
334 pDDSD->dwRefreshRate = This->DirectDrawGlobal.dwMonitorFrequency;
335
336 /* have not check where I should get hold of this info yet
337 DWORD dwAlphaBitDepth;
338 DWORD dwReserved;
339 LPVOID lpSurface;
340 union
341 {
342 DDCOLORKEY ddckCKDestOverlay;
343 DWORD dwEmptyFaceColor;
344 }
345 DDCOLORKEY ddckCKDestBlt;
346 DDCOLORKEY ddckCKSrcOverlay;
347 DDCOLORKEY ddckCKSrcBlt;
348 */
349
350
351 RtlCopyMemory(&pDDSD->ddpfPixelFormat,&This->DirectDrawGlobal.vmiData.ddpfDisplay,sizeof(DDPIXELFORMAT));
352 RtlCopyMemory(&pDDSD->ddsCaps,&This->DirectDrawGlobal.ddCaps,sizeof(DDCORECAPS));
353
354 /* have not check where I should get hold of this info yet
355 DWORD dwTextureStage;
356 */
357
358 return DD_OK;
359 }
360
361
362 HRESULT WINAPI Main_DirectDraw_GetFourCCCodes(LPDIRECTDRAW7 iface, LPDWORD pNumCodes, LPDWORD pCodes)
363 {
364 DX_STUB;
365 }
366
367 HRESULT WINAPI Main_DirectDraw_GetGDISurface(LPDIRECTDRAW7 iface,
368 LPDIRECTDRAWSURFACE7 *lplpGDIDDSSurface)
369 {
370 DX_STUB;
371 }
372
373 HRESULT WINAPI Main_DirectDraw_GetMonitorFrequency(LPDIRECTDRAW7 iface,LPDWORD freq)
374 {
375 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
376
377 if (freq == NULL)
378 {
379 return DD_FALSE;
380 }
381
382 *freq = This->DirectDrawGlobal.dwMonitorFrequency;
383 return DD_OK;
384 }
385
386 HRESULT WINAPI Main_DirectDraw_GetScanLine(LPDIRECTDRAW7 iface, LPDWORD lpdwScanLine)
387 {
388 IDirectDrawImpl* This = (IDirectDrawImpl*)iface;
389
390 if (This->DirectDrawGlobal.lpDDCBtmp->HALDD.dwFlags & DDHAL_CB32_GETSCANLINE)
391 {
392 return Hal_DirectDraw_GetScanLine( iface, lpdwScanLine);
393 }
394
395 return Hel_DirectDraw_GetScanLine( iface, lpdwScanLine);
396 }
397
398 HRESULT WINAPI Main_DirectDraw_GetVerticalBlankStatus(LPDIRECTDRAW7 iface, LPBOOL status)
399 {
400 DX_STUB;
401 }
402
403 HRESULT WINAPI Main_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface)
404 {
405 DX_STUB;
406 }
407
408 HRESULT WINAPI Main_DirectDraw_WaitForVerticalBlank(LPDIRECTDRAW7 iface, DWORD dwFlags,
409 HANDLE h)
410 {
411 IDirectDrawImpl* This = (IDirectDrawImpl*)iface;
412
413 if (This->DirectDrawGlobal.lpDDCBtmp->HALDD.dwFlags & DDHAL_CB32_WAITFORVERTICALBLANK)
414 {
415 return Hal_DirectDraw_WaitForVerticalBlank( iface, dwFlags, h);
416 }
417
418 return Hel_DirectDraw_WaitForVerticalBlank( iface, dwFlags, h);
419 }
420
421 HRESULT WINAPI Main_DirectDraw_GetAvailableVidMem(LPDIRECTDRAW7 iface, LPDDSCAPS2 ddscaps,
422 LPDWORD total, LPDWORD free)
423 {
424 IDirectDrawImpl* This = (IDirectDrawImpl*)iface;
425
426 if (This->DirectDrawGlobal.lpDDCBtmp->HALDDMiscellaneous.dwFlags & DDHAL_MISCCB32_GETAVAILDRIVERMEMORY)
427 {
428 return Hal_DirectDraw_GetAvailableVidMem (iface,ddscaps,total,free);
429 }
430
431 return Hel_DirectDraw_GetAvailableVidMem (iface,ddscaps,total,free);
432 }
433
434 HRESULT WINAPI Main_DirectDraw_GetSurfaceFromDC(LPDIRECTDRAW7 iface, HDC hdc,
435 LPDIRECTDRAWSURFACE7 *lpDDS)
436 {
437 DX_STUB;
438 }
439
440 HRESULT WINAPI Main_DirectDraw_RestoreAllSurfaces(LPDIRECTDRAW7 iface)
441 {
442 DX_STUB;
443 }
444
445 HRESULT WINAPI Main_DirectDraw_TestCooperativeLevel(LPDIRECTDRAW7 iface)
446 {
447 DX_STUB;
448 }
449
450 HRESULT WINAPI Main_DirectDraw_GetDeviceIdentifier(LPDIRECTDRAW7 iface,
451 LPDDDEVICEIDENTIFIER2 pDDDI, DWORD dwFlags)
452 {
453 DX_STUB;
454 }
455
456 HRESULT WINAPI Main_DirectDraw_StartModeTest(LPDIRECTDRAW7 iface, LPSIZE pModes,
457 DWORD dwNumModes, DWORD dwFlags)
458 {
459 DX_STUB;
460 }
461
462 HRESULT WINAPI Main_DirectDraw_EvaluateMode(LPDIRECTDRAW7 iface,DWORD a,DWORD* b)
463 {
464 DX_STUB;
465 }
466
467 IDirectDraw7Vtbl DirectDraw7_Vtable =
468 {
469 Main_DirectDraw_QueryInterface,
470 Main_DirectDraw_AddRef,
471 Main_DirectDraw_Release,
472 Main_DirectDraw_Compact,
473 Main_DirectDraw_CreateClipper,
474 Main_DirectDraw_CreatePalette,
475 Main_DirectDraw_CreateSurface,
476 Main_DirectDraw_DuplicateSurface,
477 Main_DirectDraw_EnumDisplayModes,
478 Main_DirectDraw_EnumSurfaces,
479 Main_DirectDraw_FlipToGDISurface,
480 Main_DirectDraw_GetCaps,
481 Main_DirectDraw_GetDisplayMode,
482 Main_DirectDraw_GetFourCCCodes,
483 Main_DirectDraw_GetGDISurface,
484 Main_DirectDraw_GetMonitorFrequency,
485 Main_DirectDraw_GetScanLine,
486 Main_DirectDraw_GetVerticalBlankStatus,
487 Main_DirectDraw_Initialize,
488 Main_DirectDraw_RestoreDisplayMode,
489 Main_DirectDraw_SetCooperativeLevel,
490 Main_DirectDraw_SetDisplayMode,
491 Main_DirectDraw_WaitForVerticalBlank,
492 Main_DirectDraw_GetAvailableVidMem,
493 Main_DirectDraw_GetSurfaceFromDC,
494 Main_DirectDraw_RestoreAllSurfaces,
495 Main_DirectDraw_TestCooperativeLevel,
496 Main_DirectDraw_GetDeviceIdentifier,
497 Main_DirectDraw_StartModeTest,
498 Main_DirectDraw_EvaluateMode
499 };