6ef2a38628efe5f201c543c75cdc9ee29baaf124
[reactos.git] / reactos / dll / directx / ddraw / Ddraw / ddraw_displaymode.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS DirectX
5 * FILE: ddraw/ddraw/ddraw_displaymode.c
6 * PURPOSE: IDirectDraw7 Implementation
7 * PROGRAMMER: Maarten Bosma, Magnus Olsen (add seh support)
8 *
9 */
10
11
12 #include "rosdraw.h"
13
14 HRESULT WINAPI
15 Main_DirectDraw_EnumDisplayModes(LPDDRAWI_DIRECTDRAW_INT This, DWORD dwFlags,
16 LPDDSURFACEDESC pDDSD, LPVOID pContext, LPDDENUMMODESCALLBACK pCallback)
17 {
18 HRESULT ret = DD_OK;
19 INT iMode = 0;
20 DEVMODE DevMode;
21
22 DX_WINDBG_trace();
23
24 ZeroMemory(&DevMode, sizeof(DEVMODE));
25
26 _SEH2_TRY
27 {
28
29 if (pDDSD != NULL)
30 {
31 if (pDDSD->dwSize != sizeof(DDSURFACEDESC))
32 {
33 ret = DDERR_INVALIDPARAMS;
34 }
35 }
36
37 if (IsBadCodePtr((LPVOID)pCallback))
38 {
39 ret = DDERR_INVALIDPARAMS;
40 }
41 else if ( ret == DD_OK)
42 {
43
44 DevMode.dmSize = sizeof(DEVMODE);
45
46 while (EnumDisplaySettingsEx(NULL, iMode, &DevMode, 0) == TRUE)
47 {
48 DDSURFACEDESC SurfaceDesc;
49
50 ZeroMemory(&SurfaceDesc, sizeof(DDSURFACEDESC));
51
52 iMode++;
53
54 SurfaceDesc.dwSize = sizeof (DDSURFACEDESC);
55 SurfaceDesc.dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_REFRESHRATE | DDSD_WIDTH | DDSD_PIXELFORMAT;
56 SurfaceDesc.dwHeight = DevMode.dmPelsHeight;
57 SurfaceDesc.dwWidth = DevMode.dmPelsWidth;
58 SurfaceDesc.lPitch = DevMode.dmPelsWidth * DevMode.dmBitsPerPel / 8;
59 SurfaceDesc.dwRefreshRate = DevMode.dmDisplayFrequency;
60
61 SurfaceDesc.ddpfPixelFormat.dwSize = sizeof (DDPIXELFORMAT);
62 SurfaceDesc.ddpfPixelFormat.dwFlags = DDPF_RGB;
63 // FIXME: get these
64 /*
65 SurfaceDesc.ddpfPixelFormat.dwRBitMask =
66 SurfaceDesc.ddpfPixelFormat.dwGBitMask =
67 SurfaceDesc.ddpfPixelFormat.dwBBitMask =
68 SurfaceDesc.ddpfPixelFormat.dwRGBAlphaBitMask =
69 */
70 SurfaceDesc.ddpfPixelFormat.dwRGBBitCount = DevMode.dmBitsPerPel;
71
72 // FIXME1: This->lpLcl->lpGbl->dwMonitorFrequency is not set !
73 if(dwFlags & DDEDM_REFRESHRATES && SurfaceDesc.dwRefreshRate != This->lpLcl->lpGbl->dwMonitorFrequency)
74 {
75 //continue; // FIXME2: what is SurfaceDesc.dwRefreshRate supposed to be set to ?
76 }
77
78 // FIXME: Take case when DDEDM_STANDARDVGAMODES flag is not set in account
79
80 if(pDDSD)
81 {
82 if(pDDSD->dwFlags & DDSD_HEIGHT && pDDSD->dwHeight != SurfaceDesc.dwHeight)
83 continue;
84
85 else if(pDDSD->dwFlags & DDSD_WIDTH && pDDSD->dwWidth != SurfaceDesc.dwWidth)
86 continue;
87
88 else if(pDDSD->dwFlags & DDSD_PITCH && pDDSD->lPitch != SurfaceDesc.lPitch)
89 continue;
90
91 else if(pDDSD->dwFlags & DDSD_REFRESHRATE && pDDSD->dwRefreshRate != SurfaceDesc.dwRefreshRate)
92 continue;
93
94 else if(pDDSD->dwFlags & DDSD_PIXELFORMAT && pDDSD->ddpfPixelFormat.dwRGBBitCount != SurfaceDesc.ddpfPixelFormat.dwRGBBitCount)
95 continue; // FIXME: test for the other members of ddpfPixelFormat as well
96 }
97
98 if((*pCallback)(&SurfaceDesc, pContext) == DDENUMRET_CANCEL)
99 break;
100 }
101 }
102
103 }
104 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
105 {
106 }
107 _SEH2_END;
108
109 return ret;
110 }
111
112 HRESULT WINAPI
113 Main_DirectDraw_EnumDisplayModes4(LPDDRAWI_DIRECTDRAW_INT This, DWORD dwFlags,
114 LPDDSURFACEDESC2 pDDSD, LPVOID pContext, LPDDENUMMODESCALLBACK2 pCallback)
115 {
116 HRESULT ret = DD_OK;
117 INT iMode = 0;
118 DEVMODE DevMode;
119
120 DX_WINDBG_trace();
121
122 ZeroMemory(&DevMode, sizeof(DEVMODE));
123
124 _SEH2_TRY
125 {
126
127 if (pDDSD != NULL)
128 {
129 if (pDDSD->dwSize != sizeof(DDSURFACEDESC2))
130 {
131 ret = DDERR_INVALIDPARAMS;
132 }
133 }
134
135 if (IsBadCodePtr((LPVOID)pCallback))
136 {
137 ret = DDERR_INVALIDPARAMS;
138 }
139 else if ( ret == DD_OK)
140 {
141
142 DevMode.dmSize = sizeof(DEVMODE);
143
144 while (EnumDisplaySettingsEx(NULL, iMode, &DevMode, 0) == TRUE)
145 {
146 DDSURFACEDESC2 SurfaceDesc;
147
148 ZeroMemory(&SurfaceDesc, sizeof(DDSURFACEDESC2));
149
150 iMode++;
151
152 SurfaceDesc.dwSize = sizeof (DDSURFACEDESC2);
153 SurfaceDesc.dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_REFRESHRATE | DDSD_WIDTH | DDSD_PIXELFORMAT;
154 SurfaceDesc.dwHeight = DevMode.dmPelsHeight;
155 SurfaceDesc.dwWidth = DevMode.dmPelsWidth;
156 SurfaceDesc.lPitch = DevMode.dmPelsWidth * DevMode.dmBitsPerPel / 8;
157 SurfaceDesc.dwRefreshRate = DevMode.dmDisplayFrequency;
158
159 SurfaceDesc.ddpfPixelFormat.dwSize = sizeof (DDPIXELFORMAT);
160 SurfaceDesc.ddpfPixelFormat.dwFlags = DDPF_RGB;
161 // FIXME: get these
162 /*
163 SurfaceDesc.ddpfPixelFormat.dwRBitMask =
164 SurfaceDesc.ddpfPixelFormat.dwGBitMask =
165 SurfaceDesc.ddpfPixelFormat.dwBBitMask =
166 SurfaceDesc.ddpfPixelFormat.dwRGBAlphaBitMask =
167 */
168 SurfaceDesc.ddpfPixelFormat.dwRGBBitCount = DevMode.dmBitsPerPel;
169
170 // FIXME1: This->lpLcl->lpGbl->dwMonitorFrequency is not set !
171 if(dwFlags & DDEDM_REFRESHRATES && SurfaceDesc.dwRefreshRate != This->lpLcl->lpGbl->dwMonitorFrequency)
172 {
173 //continue; // FIXME2: what is SurfaceDesc.dwRefreshRate supposed to be set to ?
174 }
175
176 // FIXME: Take case when DDEDM_STANDARDVGAMODES flag is not set in account
177
178 if(pDDSD)
179 {
180 if(pDDSD->dwFlags & DDSD_HEIGHT && pDDSD->dwHeight != SurfaceDesc.dwHeight)
181 continue;
182
183 else if(pDDSD->dwFlags & DDSD_WIDTH && pDDSD->dwWidth != SurfaceDesc.dwWidth)
184 continue;
185
186 else if(pDDSD->dwFlags & DDSD_PITCH && pDDSD->lPitch != SurfaceDesc.lPitch)
187 continue;
188
189 else if(pDDSD->dwFlags & DDSD_REFRESHRATE && pDDSD->dwRefreshRate != SurfaceDesc.dwRefreshRate)
190 continue;
191
192 else if(pDDSD->dwFlags & DDSD_PIXELFORMAT && pDDSD->ddpfPixelFormat.dwRGBBitCount != SurfaceDesc.ddpfPixelFormat.dwRGBBitCount)
193 continue; // FIXME: test for the other members of ddpfPixelFormat as well
194 }
195
196 if((*pCallback)(&SurfaceDesc, pContext) == DDENUMRET_CANCEL)
197 break;
198 }
199 }
200
201 }
202 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
203 {
204 }
205 _SEH2_END;
206
207 return ret;
208 }
209
210 HRESULT WINAPI
211 Main_DirectDraw_SetDisplayMode (LPDDRAWI_DIRECTDRAW_INT This, DWORD dwWidth, DWORD dwHeight, DWORD dwBPP)
212 {
213 DX_WINDBG_trace();
214
215 return Main_DirectDraw_SetDisplayMode2 (This, dwWidth, dwHeight, dwBPP, 0, 0 );
216 }
217
218 HRESULT WINAPI
219 Main_DirectDraw_SetDisplayMode2 (LPDDRAWI_DIRECTDRAW_INT This, DWORD dwWidth, DWORD dwHeight,
220 DWORD dwBPP, DWORD dwRefreshRate, DWORD dwFlags)
221 {
222 HRESULT ret = DD_OK;
223 DX_WINDBG_trace();
224
225 _SEH2_TRY
226 {
227 // FIXME: Check primary if surface is locked / busy etc.
228
229 // Check Parameters
230 if(dwFlags != 0)
231 {
232 ret = DDERR_INVALIDPARAMS;
233 }
234 else
235 {
236 if ((!dwHeight || This->lpLcl->lpGbl->vmiData.dwDisplayHeight == dwHeight) &&
237 (!dwWidth || This->lpLcl->lpGbl->vmiData.dwDisplayWidth == dwWidth) &&
238 (!dwBPP || This->lpLcl->lpGbl->vmiData.ddpfDisplay.dwRGBBitCount == dwBPP) &&
239 (!dwRefreshRate || This->lpLcl->lpGbl->dwMonitorFrequency == dwRefreshRate))
240 {
241 ret = DD_OK; // nothing to do here for us
242 }
243 else
244 {
245 LONG retval;
246 // Here we go
247 DEVMODE DevMode;
248 ZeroMemory(&DevMode, sizeof(DEVMODE));
249 DevMode.dmSize = sizeof(DEVMODE);
250
251 if (dwHeight)
252 DevMode.dmFields |= DM_PELSHEIGHT;
253 if (dwWidth)
254 DevMode.dmFields |= DM_PELSWIDTH;
255 if (dwBPP)
256 DevMode.dmFields |= DM_BITSPERPEL;
257 if (dwRefreshRate)
258 DevMode.dmFields |= DM_DISPLAYFREQUENCY;
259
260 DevMode.dmPelsHeight = dwHeight;
261 DevMode.dmPelsWidth = dwWidth;
262 DevMode.dmBitsPerPel = dwBPP;
263 DevMode.dmDisplayFrequency = dwRefreshRate;
264
265 DX_WINDBG_trace_res(dwWidth, dwHeight,dwBPP, dwRefreshRate);
266
267 retval = ChangeDisplaySettings(&DevMode, CDS_FULLSCREEN);
268 /* FIXME: Are we supposed to set CDS_SET_PRIMARY as well ? */
269
270 if(retval == DISP_CHANGE_BADMODE)
271 {
272 /* Note : it seam ms ddraw ignore this and try using the bad mode any case.
273 * tested with Ati HD2400 that only support 16 and 32 Bpp in windows
274 */
275 DX_STUB_str("Warning ChangeDisplaySettings return DISP_CHANGE_BADMODE, but ddraw.dll ignore it\n");
276
277 //ret = DDERR_UNSUPPORTED;
278 BOOL ModeChanged;
279 This->lpLcl->lpGbl->hDD = This->lpLcl->hDD;
280 DdReenableDirectDrawObject(This->lpLcl->lpGbl, &ModeChanged);
281 StartDirectDraw((LPDIRECTDRAW)This, 0, TRUE);
282 }
283 else if(retval != DISP_CHANGE_SUCCESSFUL)
284 {
285 ret = DDERR_GENERIC;
286 }
287 else
288 {
289 // Update Interals
290 BOOL ModeChanged;
291 This->lpLcl->lpGbl->hDD = This->lpLcl->hDD;
292 DdReenableDirectDrawObject(This->lpLcl->lpGbl, &ModeChanged);
293 StartDirectDraw((LPDIRECTDRAW)This, 0, TRUE);
294 }
295 }
296 }
297 }
298 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
299 {
300 }
301 _SEH2_END;
302
303 return ret;
304 }
305
306 HRESULT WINAPI
307 Main_DirectDraw_RestoreDisplayMode (LPDDRAWI_DIRECTDRAW_INT This)
308 {
309 DX_WINDBG_trace();
310
311 _SEH2_TRY
312 {
313 BOOL ModeChanged;
314
315 ChangeDisplaySettings(NULL, 0);
316
317 // Update Interals
318
319
320 This->lpLcl->lpGbl->hDD = This->lpLcl->hDD;
321 DdReenableDirectDrawObject(This->lpLcl->lpGbl, &ModeChanged);
322 StartDirectDraw((LPDIRECTDRAW)This, 0, TRUE);
323 }
324 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
325 {
326 }
327 _SEH2_END;
328
329
330 return DD_OK;
331 }
332
333 HRESULT WINAPI
334 Main_DirectDraw_GetMonitorFrequency (LPDDRAWI_DIRECTDRAW_INT This, LPDWORD lpFreq)
335 {
336 HRESULT retVal = DD_OK;
337 DX_WINDBG_trace();
338
339 _SEH2_TRY
340 {
341 if(IsBadWritePtr(lpFreq,sizeof(LPDWORD)))
342 {
343 retVal = DDERR_INVALIDPARAMS;
344 }
345 else
346 {
347 if (This->lpLcl->lpGbl->dwMonitorFrequency)
348 {
349 *lpFreq = This->lpLcl->lpGbl->dwMonitorFrequency;
350 }
351 else
352 {
353 retVal = DDERR_UNSUPPORTED;
354 }
355 }
356 }
357 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
358 {
359 retVal = DD_FALSE;
360 }
361 _SEH2_END;
362
363 return retVal;
364 }
365
366 HRESULT WINAPI
367 Main_DirectDraw_GetDisplayMode (LPDDRAWI_DIRECTDRAW_INT This, LPDDSURFACEDESC pDDSD)
368 {
369 HRESULT retVal = DD_OK;
370 DX_WINDBG_trace();
371
372 _SEH2_TRY
373 {
374 if(IsBadWritePtr(pDDSD,sizeof(LPDDSURFACEDESC)))
375 {
376 retVal = DDERR_INVALIDPARAMS;
377 }
378 else if (pDDSD->dwSize != sizeof(DDSURFACEDESC))
379 {
380 retVal = DDERR_INVALIDPARAMS;
381 }
382 else
383 {
384 // FIXME: More stucture members might need to be filled
385
386 pDDSD->dwFlags |= DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_PITCH | DDSD_REFRESHRATE;
387 pDDSD->dwHeight = This->lpLcl->lpGbl->vmiData.dwDisplayHeight;
388 pDDSD->dwWidth = This->lpLcl->lpGbl->vmiData.dwDisplayWidth;
389 pDDSD->ddpfPixelFormat = This->lpLcl->lpGbl->vmiData.ddpfDisplay;
390 pDDSD->dwRefreshRate = This->lpLcl->lpGbl->dwMonitorFrequency;
391 pDDSD->lPitch = This->lpLcl->lpGbl->vmiData.lDisplayPitch;
392 }
393 }
394 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
395 {
396 }
397 _SEH2_END;
398
399 return retVal;
400 }
401
402 HRESULT WINAPI
403 Main_DirectDraw_GetDisplayMode4 (LPDDRAWI_DIRECTDRAW_INT This, LPDDSURFACEDESC2 pDDSD)
404 {
405 HRESULT retVal = DD_OK;
406 DX_WINDBG_trace();
407
408 _SEH2_TRY
409 {
410 if(IsBadWritePtr(pDDSD,sizeof(LPDDSURFACEDESC2)))
411 {
412 retVal = DDERR_INVALIDPARAMS;
413 }
414 else if (pDDSD->dwSize != sizeof(DDSURFACEDESC2))
415 {
416 retVal = DDERR_INVALIDPARAMS;
417 }
418 else
419 {
420 // FIXME: More stucture members might need to be filled
421
422 pDDSD->dwFlags |= DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_PITCH | DDSD_REFRESHRATE;
423 pDDSD->dwHeight = This->lpLcl->lpGbl->vmiData.dwDisplayHeight;
424 pDDSD->dwWidth = This->lpLcl->lpGbl->vmiData.dwDisplayWidth;
425 pDDSD->ddpfPixelFormat = This->lpLcl->lpGbl->vmiData.ddpfDisplay;
426 pDDSD->dwRefreshRate = This->lpLcl->lpGbl->dwMonitorFrequency;
427 pDDSD->lPitch = This->lpLcl->lpGbl->vmiData.lDisplayPitch;
428 }
429 }
430 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
431 {
432 }
433 _SEH2_END;
434
435 return retVal;
436 }