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