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