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