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