ntdll: Implement DVD_ReadStructure.
[wine] / dlls / ddraw / ddraw_user.c
1 /*      DirectDraw driver for User-based primary surfaces
2  *
3  * Copyright 2000-2001 TransGaming Technologies Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #include "config.h"
21
22 #include <assert.h>
23 #include <stdarg.h>
24 #include <string.h>
25
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "wingdi.h"
32 #include "winuser.h"
33 #include "ddraw.h"
34 #include "ddraw_private.h"
35 #include "wine/debug.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
38
39 static const IDirectDraw7Vtbl User_DirectDraw_VTable;
40
41 static const DDDEVICEIDENTIFIER2 user_device =
42 {
43     "display",
44     "User (and GDI)",
45     { { 0x00010001, 0x00010001 } },
46     0, 0, 0, 0,
47     /* fe38440c-8969-4283-bc73-749e7bc3c2eb */
48     {0xfe38440c,0x8969,0x428e, {0x73,0xbc,0x74,0x9e,0x7b,0xc3,0xc2,0xeb}},
49     0
50 };
51
52 static const DDPIXELFORMAT pixelformats[] =
53 {
54     /* 8bpp paletted */
55     { sizeof(DDPIXELFORMAT), DDPF_RGB|DDPF_PALETTEINDEXED8, 0, { 8 } },
56     /* 15bpp 5/5/5 */
57     { sizeof(DDPIXELFORMAT), DDPF_RGB, 0, { 16 }, { 0x7C00 }, { 0x3E0 },
58       { 0x1F } },
59     /* 16bpp 5/6/5 */
60     { sizeof(DDPIXELFORMAT), DDPF_RGB, 0, { 16 }, { 0xF800 }, { 0x7E0 },
61       { 0x1F } },
62     /* 24bpp 8/8/8 */
63     { sizeof(DDPIXELFORMAT), DDPF_RGB, 0, { 24 }, { 0xFF0000 },
64       { 0x00FF00 }, { 0x0000FF } },
65     /* 32bpp 8/8/8 */
66     { sizeof(DDPIXELFORMAT), DDPF_RGB, 0, { 32 }, { 0xFF0000 },
67       { 0x00FF00 }, { 0x0000FF } }
68 };
69
70 HRESULT User_DirectDraw_Create(const GUID* pGUID, LPDIRECTDRAW7* pIface,
71                                      IUnknown* pUnkOuter, BOOL ex);
72 HRESULT User_DirectDraw_Initialize(IDirectDrawImpl*, const GUID*);
73
74 static const ddraw_driver user_driver =
75 {
76     &user_device,
77     10,
78     User_DirectDraw_Create,
79     User_DirectDraw_Initialize
80 };
81
82 BOOL DDRAW_User_Init(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
83 {
84     if (fdwReason == DLL_PROCESS_ATTACH)
85         DDRAW_register_driver(&user_driver);
86
87     return TRUE;
88 }
89
90 static const DDPIXELFORMAT* pixelformat_for_depth(DWORD depth)
91 {
92     switch (depth)
93     {
94     case  8: return pixelformats + 0;
95     case 15: return pixelformats + 1;
96     case 16: return pixelformats + 2;
97     case 24: return pixelformats + 3;
98     case 32: return pixelformats + 4;
99     default: return NULL;
100     }
101 }
102
103 /* Not called from the vtable. */
104 HRESULT User_DirectDraw_Construct(IDirectDrawImpl *This, BOOL ex)
105 {
106     HRESULT hr;
107     DWORD depth;
108     HDC hDC;
109
110     TRACE("(%p,%d)\n",This,ex);
111
112     hr = Main_DirectDraw_Construct(This, ex);
113     if (FAILED(hr)) return hr;
114
115     This->final_release = User_DirectDraw_final_release;
116
117     This->create_primary    = User_DirectDraw_create_primary;
118     This->create_backbuffer = User_DirectDraw_create_backbuffer;
119
120     hDC = CreateDCA("DISPLAY", NULL, NULL, NULL);
121     depth = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);
122     DeleteDC(hDC);
123
124     This->width       = GetSystemMetrics(SM_CXSCREEN);
125     This->height      = GetSystemMetrics(SM_CYSCREEN);
126     This->pitch       = DDRAW_width_bpp_to_pitch(This->width, depth);
127     This->pixelformat = *pixelformat_for_depth(depth);
128
129     This->orig_width       = This->width;
130     This->orig_height      = This->height;
131     This->orig_pitch       = This->pitch;
132     This->orig_pixelformat = This->pixelformat;
133
134     ICOM_INIT_INTERFACE(This, IDirectDraw7, User_DirectDraw_VTable);
135
136     /* capabilities */
137 #define BLIT_CAPS (DDCAPS_BLT | DDCAPS_BLTCOLORFILL | DDCAPS_BLTDEPTHFILL \
138           | DDCAPS_BLTSTRETCH | DDCAPS_CANBLTSYSMEM | DDCAPS_CANCLIP      \
139           | DDCAPS_CANCLIPSTRETCHED | DDCAPS_COLORKEY                     \
140           | DDCAPS_COLORKEYHWASSIST | DDCAPS_OVERLAY | DDCAPS_OVERLAYSTRETCH)
141 #define CKEY_CAPS (DDCKEYCAPS_DESTBLT | DDCKEYCAPS_SRCBLT)
142 #define FX_CAPS (DDFXCAPS_BLTALPHA | DDFXCAPS_BLTMIRRORLEFTRIGHT        \
143                 | DDFXCAPS_BLTMIRRORUPDOWN | DDFXCAPS_BLTROTATION90     \
144                 | DDFXCAPS_BLTSHRINKX | DDFXCAPS_BLTSHRINKXN            \
145                 | DDFXCAPS_BLTSHRINKY | DDFXCAPS_BLTSHRINKXN            \
146                 | DDFXCAPS_BLTSTRETCHX | DDFXCAPS_BLTSTRETCHXN          \
147                 | DDFXCAPS_BLTSTRETCHY | DDFXCAPS_BLTSTRETCHYN)
148     This->caps.dwCaps |= DDCAPS_GDI | DDCAPS_PALETTE | BLIT_CAPS;
149     if( opengl_initialized )
150     {
151         /* Hack for D3D code */
152         This->caps.dwCaps |= DDCAPS_3D;
153     }
154     This->caps.dwCaps2 |= DDCAPS2_CERTIFIED | DDCAPS2_NOPAGELOCKREQUIRED |
155                           DDCAPS2_PRIMARYGAMMA | DDCAPS2_WIDESURFACES;
156     This->caps.dwCKeyCaps |= CKEY_CAPS;
157     This->caps.dwFXCaps |= FX_CAPS;
158     This->caps.dwPalCaps |= DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE;
159     This->caps.dwVidMemTotal = 16*1024*1024;
160     This->caps.dwVidMemFree = 16*1024*1024;
161     This->caps.dwSVBCaps |= BLIT_CAPS;
162     This->caps.dwSVBCKeyCaps |= CKEY_CAPS;
163     This->caps.dwSVBFXCaps |= FX_CAPS;
164     This->caps.dwVSBCaps |= BLIT_CAPS;
165     This->caps.dwVSBCKeyCaps |= CKEY_CAPS;
166     This->caps.dwVSBFXCaps |= FX_CAPS;
167     This->caps.dwSSBCaps |= BLIT_CAPS;
168     This->caps.dwSSBCKeyCaps |= CKEY_CAPS;
169     This->caps.dwSSBFXCaps |= FX_CAPS;
170     This->caps.ddsCaps.dwCaps |= DDSCAPS_ALPHA | DDSCAPS_BACKBUFFER |
171                                  DDSCAPS_FLIP | DDSCAPS_FRONTBUFFER |
172                                  DDSCAPS_OFFSCREENPLAIN | DDSCAPS_PALETTE |
173                                  DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY |
174                                  DDSCAPS_VIDEOMEMORY | DDSCAPS_VISIBLE;
175     if( opengl_initialized )
176     {
177         /* Hacks for D3D code */
178         This->caps.ddsCaps.dwCaps |= DDSCAPS_3DDEVICE | DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_ZBUFFER;
179     }
180     
181     This->caps.ddsOldCaps.dwCaps = This->caps.ddsCaps.dwCaps;
182 #undef BLIT_CAPS
183 #undef CKEY_CAPS
184 #undef FX_CAPS
185
186     return S_OK;
187 }
188
189 /* This function is called from DirectDrawCreate(Ex) on the most-derived
190  * class to start construction.
191  * Not called from the vtable. */
192 HRESULT User_DirectDraw_Create(const GUID* pGUID, LPDIRECTDRAW7* pIface,
193                                IUnknown* pUnkOuter, BOOL ex)
194 {
195     HRESULT hr;
196     IDirectDrawImpl* This;
197
198     assert(pUnkOuter == NULL);
199
200     This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
201                      sizeof(IDirectDrawImpl) + sizeof(User_DirectDrawImpl));
202     if (This == NULL) return E_OUTOFMEMORY;
203
204     /* Note that this relation does *not* hold true if the DD object was
205      * CoCreateInstanced then Initialized. */
206     This->private = (User_DirectDrawImpl *)(This+1);
207
208     /* Initialize the DDCAPS structure */
209     This->caps.dwSize = sizeof(This->caps);
210
211     hr = User_DirectDraw_Construct(This, ex);
212     if (FAILED(hr))
213         HeapFree(GetProcessHeap(), 0, This);
214     else
215         *pIface = ICOM_INTERFACE(This, IDirectDraw7);
216
217     return hr;
218 }
219
220 /* This function is called from Uninit_DirectDraw_Initialize on the
221  * most-derived-class to start initialization.
222  * Not called from the vtable. */
223 HRESULT User_DirectDraw_Initialize(IDirectDrawImpl *This, const GUID* guid)
224 {
225     HRESULT hr;
226     This->private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
227                               sizeof(User_DirectDrawImpl));
228     if (This->private == NULL) return E_OUTOFMEMORY;
229
230     /* Initialize the DDCAPS structure */
231     This->caps.dwSize = sizeof(This->caps);
232
233     hr = User_DirectDraw_Construct(This, TRUE); /* XXX ex? */
234     if (FAILED(hr))
235     {
236         HeapFree(GetProcessHeap(), 0, This->private);
237         return hr;
238     }
239
240     return DD_OK;
241 }
242
243 /* Called from an internal function pointer. */
244 void User_DirectDraw_final_release(IDirectDrawImpl *This)
245 {
246     Main_DirectDraw_final_release(This);
247 }
248
249 /* Compact: generic */
250 /* CreateClipper: generic */
251 /* CreatePalette: generic (with callback) */
252 /* CreateSurface: generic (with callbacks) */
253
254 HRESULT
255 User_DirectDraw_create_primary(IDirectDrawImpl* This,
256                                const DDSURFACEDESC2* pDDSD,
257                                LPDIRECTDRAWSURFACE7* ppSurf,
258                                IUnknown* pUnkOuter)
259 {
260     return User_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
261 }
262
263 HRESULT
264 User_DirectDraw_create_backbuffer(IDirectDrawImpl* This,
265                                   const DDSURFACEDESC2* pDDSD,
266                                   LPDIRECTDRAWSURFACE7* ppSurf,
267                                   IUnknown* pUnkOuter,
268                                   IDirectDrawSurfaceImpl* primary)
269 {
270     return User_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
271 }
272
273 /* DuplicateSurface: generic */
274
275 /* Originally derived from Xlib_IDirectDraw2Impl_EnumDisplayModes.
276  *
277  * The depths are whatever DIBsections support on the client side.
278  * Should they be limited by screen depth?
279  */
280 HRESULT WINAPI
281 User_DirectDraw_EnumDisplayModes(LPDIRECTDRAW7 iface, DWORD dwFlags,
282                                  LPDDSURFACEDESC2 pDDSD, LPVOID context,
283                                  LPDDENUMMODESCALLBACK2 callback)
284 {
285     DDSURFACEDESC2 callback_sd;
286     DEVMODEW DevModeW;
287     const DDPIXELFORMAT* pixelformat;
288
289     int i;
290
291     TRACE("(%p)->(0x%08lx,%p,%p,%p)\n",iface,dwFlags,pDDSD,context,callback);
292
293     if (pDDSD && TRACE_ON(ddraw))
294     {
295         TRACE("Enumerate modes matching:\n");
296         DDRAW_dump_surface_desc(pDDSD);
297     }
298
299     ZeroMemory(&callback_sd, sizeof(callback_sd));
300     callback_sd.dwSize = sizeof(callback_sd);
301
302     callback_sd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_CAPS
303         | DDSD_PITCH;
304
305     if (dwFlags & DDEDM_REFRESHRATES)
306         callback_sd.dwFlags |= DDSD_REFRESHRATE;
307
308     callback_sd.u2.dwRefreshRate = 60.0;
309
310     for (i = 0; EnumDisplaySettingsExW(NULL, i, &DevModeW, 0); i++)
311     {
312         if (pDDSD)
313         {
314             if ((pDDSD->dwFlags & DDSD_WIDTH) && (pDDSD->dwWidth != DevModeW.dmPelsWidth))
315                 continue; 
316             if ((pDDSD->dwFlags & DDSD_HEIGHT) && (pDDSD->dwHeight != DevModeW.dmPelsHeight))
317                 continue; 
318             if ((pDDSD->dwFlags & DDSD_PIXELFORMAT) && (pDDSD->u4.ddpfPixelFormat.dwFlags & DDPF_RGB) &&
319                 (pDDSD->u4.ddpfPixelFormat.u1.dwRGBBitCount != DevModeW.dmBitsPerPel))
320                     continue; 
321         }
322
323         callback_sd.dwHeight = DevModeW.dmPelsHeight;
324         callback_sd.dwWidth = DevModeW.dmPelsWidth;
325         if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
326         {
327             callback_sd.u2.dwRefreshRate = DevModeW.dmDisplayFrequency;
328         }
329
330         TRACE("- mode: %ldx%ld\n", callback_sd.dwWidth, callback_sd.dwHeight);
331         
332         pixelformat = pixelformat_for_depth(DevModeW.dmBitsPerPel);
333         callback_sd.u1.lPitch
334             = DDRAW_width_bpp_to_pitch(DevModeW.dmPelsWidth,
335                                        pixelformat->u1.dwRGBBitCount);
336
337         callback_sd.u4.ddpfPixelFormat = *pixelformat;
338
339         callback_sd.ddsCaps.dwCaps = 0;
340         if (pixelformat->dwFlags & DDPF_PALETTEINDEXED8) /* ick */
341             callback_sd.ddsCaps.dwCaps |= DDSCAPS_PALETTE;
342
343         TRACE(" - %2ld bpp, R=%08lx G=%08lx B=%08lx\n",
344             callback_sd.u4.ddpfPixelFormat.u1.dwRGBBitCount,
345             callback_sd.u4.ddpfPixelFormat.u2.dwRBitMask,
346             callback_sd.u4.ddpfPixelFormat.u3.dwGBitMask,
347             callback_sd.u4.ddpfPixelFormat.u4.dwBBitMask);
348         if (callback(&callback_sd, context) == DDENUMRET_CANCEL)
349             return DD_OK;
350     }
351
352     return DD_OK;
353 }
354
355 /* EnumSurfaces: generic */
356 /* FlipToGDISurface: ??? */
357
358 #if 0
359 HRESULT WINAPI
360 User_DirectDraw_GetCaps(LPDIRECTDRAW7 iface, LPDDCAPS pDriverCaps,
361                         LPDDCAPS pHELCaps)
362 {
363 /* Based on my guesses for what is appropriate with some clues from the
364  * NVidia driver. Not everything is actually implemented yet.
365  * NV has but we don't: Overlays, Video Ports, DDCAPS_READSCANLINE,
366  * DDCAPS2_CERTIFIED (heh), DDSCAPS2_NONLOCALVIDMEM, DDSCAPS2_COPYFOURCC.
367  * It actually has no FX alpha caps.
368  * Oddly, it doesn't list DDPCAPS_PRIMARYSURFACE.
369  * And the HEL caps make little sense.
370  */
371 #define BLIT_CAPS (DDCAPS_BLT | DDCAPS_BLTCOLORFILL | DDCAPS_BLTDEPTHFILL \
372           | DDCAPS_BLTSTRETCH | DDCAPS_CANBLTSYSMEM | DDCAPS_CANCLIP      \
373           | DDCAPS_CANCLIPSTRETCHED | DDCAPS_COLORKEY                     \
374           | DDCAPS_COLORKEYHWASSIST | DDCAPS_OVERLAY | DDCAPS_OVERLAYSTRETCH)
375
376 #define CKEY_CAPS (DDCKEYCAPS_DESTBLT | DDCKEYCAPS_SRCBLT)
377
378 #define FX_CAPS (DDFXCAPS_BLTALPHA | DDFXCAPS_BLTMIRRORLEFTRIGHT        \
379                 | DDFXCAPS_BLTMIRRORUPDOWN | DDFXCAPS_BLTROTATION90     \
380                 | DDFXCAPS_BLTSHRINKX | DDFXCAPS_BLTSHRINKXN            \
381                 | DDFXCAPS_BLTSHRINKY | DDFXCAPS_BLTSHRINKXN            \
382                 | DDFXCAPS_BLTSTRETCHX | DDFXCAPS_BLTSTRETCHXN          \
383                 | DDFXCAPS_BLTSTRETCHY | DDFXCAPS_BLTSTRETCHYN)
384
385 #if 0
386 #define ROPS { SRCCOPY, SRCPAINT, SRCAND, SRCINVERT, SRCERASE, NOTSRCCOPY, \
387         NOTSRCERASE, MERGEPAINT, BLACKNESS, WHITENESS, }
388 #else
389 #define ROPS { 0, }
390 #endif
391
392     static const DDCAPS caps =
393     { sizeof(DDCAPS),
394       DDCAPS_3D | DDCAPS_GDI | DDCAPS_PALETTE | BLIT_CAPS,
395       DDCAPS2_CANMANAGETEXTURE | DDCAPS2_CANRENDERWINDOWED | DDCAPS2_CERTIFIED
396       | DDCAPS2_NOPAGELOCKREQUIRED | DDCAPS2_PRIMARYGAMMA
397       | DDCAPS2_WIDESURFACES,
398       CKEY_CAPS,
399       FX_CAPS,
400       0, /* dwFXAlphaCaps */
401       DDPCAPS_8BIT | DDPCAPS_PRIMARYSURFACE,
402       0, /* dwSVCaps */
403       0, /* ? dwAlphaBitConstBitDepths */
404       0, /* ? dwAlphaBitPixelPitDepths */
405       0, /* ? dwAlphaBltSurfaceBitDepths */
406       0, /* ? dwAlphaOverlayConstBitDepths */
407       0, /* ? dwAlphaOverlayPixelBitDepths */
408       0, /* ? dwAlphaOverlaySurfaceBitDepths */
409       DDBD_16, /* ? dwZBufferBitDepths */
410       16*1024*1024, /* dwVidMemTotal */
411       16*1024*1024, /* dwVidMemFree */
412       0, /* dwMaxVisibleOverlays */
413       0, /* dwCurrVisibleOverlays */
414       0, /* dwNumFourCCCodes */
415       0, /* dwAlignBoundarySrc */
416       0, /* dwAlignSizeSrc */
417       0, /* dwAlignBoundaryDest */
418       0, /* dwAlignSizeDest */
419       0, /* dwAlignStrideAlign */
420       ROPS, /* XXX dwRops[DD_ROP_SPACE] */
421       { 0, }, /* XXX ddsOldCaps */
422       1000, /* dwMinOverlayStretch */
423       1000, /* dwMaxOverlayStretch */
424       1000, /* dwMinLiveVideoStretch */
425       1000, /* dwMaxLiveVideoStretch */
426       1000, /* dwMinHwCodecStretch */
427       1000, /* dwMaxHwCodecStretch */
428       0, 0, 0, /* dwReserved1, 2, 3 */
429       BLIT_CAPS, /* dwSVBCaps */
430       CKEY_CAPS, /* dwSVBCKeyCaps */
431       FX_CAPS, /* dwSVBFXCaps */
432       ROPS, /* dwSVBRops */
433       BLIT_CAPS, /* dwVSBCaps */
434       CKEY_CAPS, /* dwVSBCKeyCaps */
435       FX_CAPS, /* dwVSBFXCaps */
436       ROPS, /* dwVSBRops */
437       BLIT_CAPS, /* dwSSBCaps */
438       CKEY_CAPS, /* dwSSBCKeyCaps */
439       FX_CAPS, /* dwSSBFXCaps */
440       ROPS, /* dwSSBRops */
441       0, /* dwMaxVideoPorts */
442       0, /* dwCurrVideoPorts */
443       0, /* ? dwSVBCaps2 */
444       BLIT_CAPS, /* ? dwNLVBCaps */
445       0, /* ? dwNLVBCaps2 */
446       CKEY_CAPS, /* dwNLVBCKeyCaps */
447       FX_CAPS, /* dwNLVBFXCaps */
448       ROPS, /* dwNLVBRops */
449       { /* ddsCaps */
450           DDSCAPS_3DDEVICE | DDSCAPS_ALPHA | DDSCAPS_BACKBUFFER | DDSCAPS_FLIP
451           | DDSCAPS_FRONTBUFFER | DDSCAPS_MIPMAP | DDSCAPS_OFFSCREENPLAIN
452           | DDSCAPS_PALETTE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY
453           | DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_VISIBLE
454           | DDSCAPS_ZBUFFER,
455           DDSCAPS2_CUBEMAP,
456           0,
457           0
458       }
459     };
460
461 #undef BLIT_CAPS
462 #undef CKEY_CAPS
463 #undef FX_CAPS
464 #undef ROPS
465
466     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
467
468     TRACE("(%p)->(%p,%p)\n",This,pDriverCaps,pHELCaps);
469
470     if (pDriverCaps != NULL)
471         DD_STRUCT_COPY_BYSIZE(pDriverCaps,&caps);
472
473     if (pHELCaps != NULL)
474         DD_STRUCT_COPY_BYSIZE(pHELCaps,&caps);
475
476     return DD_OK;
477 }
478 #endif
479
480 HRESULT WINAPI
481 User_DirectDraw_GetDeviceIdentifier(LPDIRECTDRAW7 iface,
482                                     LPDDDEVICEIDENTIFIER2 pDDDI,
483                                     DWORD dwFlags)
484 {
485     TRACE("(%p)->(%p,%08lx)\n",iface,pDDDI,dwFlags);
486     *pDDDI = user_device;
487     return DD_OK;
488 }
489
490 /* GetDisplayMode: generic */
491 /* GetFourCCCodes: generic */
492 /* GetGDISurface: ??? */
493 /* GetMonitorFrequency: generic */
494 /* GetScanLine: generic */
495 /* GetSurfaceFromDC: generic */
496 /* GetVerticalBlankStatus: generic */
497 /* Initialize: generic */
498 /* RestoreAllSurfaces: generic */
499 /* RestoreDisplayMode: generic */
500 /* SetCooperativeLevel: ??? */
501
502 HRESULT WINAPI
503 User_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface, DWORD dwWidth,
504                                DWORD dwHeight, DWORD dwBPP,
505                                DWORD dwRefreshRate, DWORD dwFlags)
506 {
507     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
508
509     const DDPIXELFORMAT* pixelformat;
510     DEVMODEW devmode;
511     LONG pitch;
512
513     TRACE("(%p)->(%ldx%ldx%ld,%ld Hz,%08lx)\n",This,dwWidth,dwHeight,dwBPP,dwRefreshRate,dwFlags);
514     devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
515     devmode.dmBitsPerPel = dwBPP;
516     devmode.dmPelsWidth  = dwWidth;
517     devmode.dmPelsHeight = dwHeight;
518     /* '0' means default frequency */
519     if (dwRefreshRate != 0) 
520     {
521         devmode.dmFields |= DM_DISPLAYFREQUENCY;
522         devmode.dmDisplayFrequency = dwRefreshRate;
523     }
524     if (ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL)
525         return DDERR_INVALIDMODE;
526
527     pixelformat = pixelformat_for_depth(dwBPP);
528     if (pixelformat == NULL)
529     {
530         assert(0);
531         return DDERR_GENERIC;
532     }
533
534     pitch = DDRAW_width_bpp_to_pitch(dwWidth, dwBPP);
535     return Main_DirectDraw_SetDisplayMode(iface, dwWidth, dwHeight, pitch,
536                                           dwRefreshRate, dwFlags, pixelformat);
537 }
538
539 /* StartModeTest: ??? */
540 /* TestCooperativeLevel: generic? */
541 /* WaitForVerticalBlank: ??? */
542
543 static const IDirectDraw7Vtbl User_DirectDraw_VTable =
544 {
545     Main_DirectDraw_QueryInterface,
546     Main_DirectDraw_AddRef,
547     Main_DirectDraw_Release,
548     Main_DirectDraw_Compact,
549     Main_DirectDraw_CreateClipper,
550     Main_DirectDraw_CreatePalette,
551     Main_DirectDraw_CreateSurface,
552     Main_DirectDraw_DuplicateSurface,
553     User_DirectDraw_EnumDisplayModes,
554     Main_DirectDraw_EnumSurfaces,
555     Main_DirectDraw_FlipToGDISurface,
556     Main_DirectDraw_GetCaps,
557     Main_DirectDraw_GetDisplayMode,
558     Main_DirectDraw_GetFourCCCodes,
559     Main_DirectDraw_GetGDISurface,
560     Main_DirectDraw_GetMonitorFrequency,
561     Main_DirectDraw_GetScanLine,
562     Main_DirectDraw_GetVerticalBlankStatus,
563     Main_DirectDraw_Initialize,
564     Main_DirectDraw_RestoreDisplayMode,
565     Main_DirectDraw_SetCooperativeLevel,
566     User_DirectDraw_SetDisplayMode,
567     Main_DirectDraw_WaitForVerticalBlank,
568     Main_DirectDraw_GetAvailableVidMem,
569     Main_DirectDraw_GetSurfaceFromDC,
570     Main_DirectDraw_RestoreAllSurfaces,
571     Main_DirectDraw_TestCooperativeLevel,
572     User_DirectDraw_GetDeviceIdentifier,
573     Main_DirectDraw_StartModeTest,
574     Main_DirectDraw_EvaluateMode
575 };