Don't leak a list of visuals (with advice of Jacek Caban).
[wine] / dlls / ddraw / ddraw_hal.c
1 /*      DirectDraw HAL driver
2  *
3  * Copyright 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 <stdlib.h>
25
26 #include "wine/debug.h"
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wingdi.h"
30 #include "ddraw.h"
31 #include "ddrawi.h"
32 #include "d3dhal.h"
33
34 #include "ddraw_private.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
37
38 static const IDirectDraw7Vtbl HAL_DirectDraw_VTable;
39
40 static DDVERSIONDATA hal_version;
41 static DD32BITDRIVERDATA hal_driverdata;
42 static HINSTANCE hal_instance;
43
44 static const DDDEVICEIDENTIFIER2 hal_device =
45 {
46     "display",
47     "DirectDraw HAL",
48     { { 0x00010001, 0x00010001 } },
49     0, 0, 0, 0,
50     /* 40c1b248-9d7d-4a29-b7d7-4cd8109f3d5d */
51     {0x40c1b248,0x9d7d,0x4a29,{0xd7,0xb7,0x4c,0xd8,0x10,0x9f,0x3d,0x5d}},
52     0
53 };
54
55 HRESULT HAL_DirectDraw_Create(const GUID* pGUID, LPDIRECTDRAW7* pIface,
56                               IUnknown* pUnkOuter, BOOL ex);
57 HRESULT HAL_DirectDraw_Initialize(IDirectDrawImpl*, const GUID*);
58
59 static const ddraw_driver hal_driver =
60 {
61     &hal_device,
62     100, /* we prefer the HAL */
63     HAL_DirectDraw_Create,
64     HAL_DirectDraw_Initialize
65 };
66
67 static DDHAL_CALLBACKS dd_cbs;
68 static DDRAWI_DIRECTDRAW_GBL dd_gbl;
69
70 static D3DHAL_GLOBALDRIVERDATA d3d_hal_data;
71 static D3DHAL_D3DEXTENDEDCAPS d3d_hal_extcaps;
72 static D3DHAL_CALLBACKS d3d_hal_cbs1;
73 static D3DHAL_CALLBACKS2 d3d_hal_cbs2;
74
75 /* in real windoze, these entry points are 16-bit, but we can work in 32-bit */
76 static BOOL WINAPI set_hal_info(LPDDHALINFO lpDDHalInfo, BOOL reset)
77 {
78     dd_cbs.HALDD        = *lpDDHalInfo->lpDDCallbacks;
79     dd_cbs.HALDDSurface = *lpDDHalInfo->lpDDSurfaceCallbacks;
80     dd_cbs.HALDDPalette = *lpDDHalInfo->lpDDPaletteCallbacks;
81     if (lpDDHalInfo->lpDDExeBufCallbacks)
82         dd_cbs.HALDDExeBuf      = *lpDDHalInfo->lpDDExeBufCallbacks;
83
84     dd_gbl.lpDDCBtmp = &dd_cbs;
85
86     dd_gbl.ddCaps                = lpDDHalInfo->ddCaps;
87     dd_gbl.dwMonitorFrequency    = lpDDHalInfo->dwMonitorFrequency;
88     dd_gbl.vmiData               = lpDDHalInfo->vmiData;
89     dd_gbl.dwModeIndex           = lpDDHalInfo->dwModeIndex;
90     dd_gbl.dwNumFourCC           = lpDDHalInfo->ddCaps.dwNumFourCCCodes;
91     dd_gbl.lpdwFourCC            = lpDDHalInfo->lpdwFourCC;
92     dd_gbl.dwNumModes            = lpDDHalInfo->dwNumModes;
93     dd_gbl.lpModeInfo            = lpDDHalInfo->lpModeInfo;
94     /* FIXME: dwFlags */
95     dd_gbl.dwPDevice             = (DWORD)lpDDHalInfo->lpPDevice;
96     dd_gbl.hInstance             = lpDDHalInfo->hInstance;
97     /* DirectX 2 */
98     if (lpDDHalInfo->lpD3DGlobalDriverData)
99         memcpy(&d3d_hal_data, (LPVOID)lpDDHalInfo->lpD3DGlobalDriverData, sizeof(D3DDEVICEDESC_V1));
100     else
101         memset(&d3d_hal_data, 0, sizeof(D3DDEVICEDESC_V1));
102     dd_gbl.lpD3DGlobalDriverData = (ULONG_PTR)&d3d_hal_data;
103
104     if (lpDDHalInfo->lpD3DHALCallbacks)
105         memcpy(&d3d_hal_cbs1, (LPVOID)lpDDHalInfo->lpD3DHALCallbacks, sizeof(D3DHAL_CALLBACKS));
106     else
107         memset(&d3d_hal_cbs1, 0, sizeof(D3DHAL_CALLBACKS));
108     dd_gbl.lpD3DHALCallbacks     = (ULONG_PTR)&d3d_hal_cbs1;
109
110     if (lpDDHalInfo->dwFlags & DDHALINFO_GETDRIVERINFOSET) {
111         DDHAL_GETDRIVERINFODATA data;
112         data.dwSize = sizeof(DDHAL_GETDRIVERINFODATA);
113         data.dwFlags = 0; /* ? */
114         data.dwContext = hal_driverdata.dwContext; /* ? */
115
116         data.guidInfo = GUID_D3DExtendedCaps;
117         data.dwExpectedSize = sizeof(D3DHAL_D3DEXTENDEDCAPS);
118         data.lpvData = &d3d_hal_extcaps;
119         data.dwActualSize = 0;
120         data.ddRVal = 0;
121         lpDDHalInfo->GetDriverInfo(&data);
122         d3d_hal_extcaps.dwSize = data.dwActualSize;
123         dd_gbl.lpD3DExtendedCaps = (ULONG_PTR)&d3d_hal_extcaps;
124
125         data.guidInfo = GUID_D3DCallbacks2;
126         data.dwExpectedSize = sizeof(D3DHAL_CALLBACKS2);
127         data.lpvData = &d3d_hal_cbs2;
128         data.dwActualSize = 0;
129         data.ddRVal = 0;
130         lpDDHalInfo->GetDriverInfo(&data);
131         d3d_hal_cbs2.dwSize = data.dwActualSize;
132         dd_gbl.lpD3DHALCallbacks2 = (ULONG_PTR)&d3d_hal_cbs2;
133     }
134
135     if( opengl_initialized && 
136            (d3d_hal_data.hwCaps.dwFlags & D3DDD_WINE_OPENGL_DEVICE) ) {
137         /*GL_DirectDraw_Init(&dd_gbl);*/
138     }
139
140     return FALSE;
141 }
142
143 static DDHALDDRAWFNS hal_funcs = {
144     sizeof(DDHALDDRAWFNS),
145     set_hal_info,
146     NULL, /* VidMemAlloc */
147     NULL  /* VidMemFree */
148 };
149
150 /* Called from DllInit, which is synchronised so there are no threading
151  * concerns. */
152 static BOOL initialize(void)
153 {
154     DCICMD cmd;
155     INT ncmd = DCICOMMAND;
156     BOOL ret;
157     HDC dc = CreateDCA("DISPLAY", NULL, NULL, NULL);
158     INT ver = Escape(dc, QUERYESCSUPPORT, sizeof(ncmd), (LPVOID)&ncmd, NULL);
159     if (ver != DD_HAL_VERSION) {
160         DeleteDC(dc);
161         TRACE("DirectDraw HAL not available\n");
162         return FALSE;
163     }
164     cmd.dwVersion = DD_VERSION;
165     cmd.dwReserved = 0;
166
167     /* the DDNEWCALLBACKFNS is supposed to give the 16-bit driver entry points
168      * in ddraw16.dll, but since Wine doesn't have or use 16-bit display drivers,
169      * we'll just work in 32-bit, who'll notice... */
170     cmd.dwCommand = DDNEWCALLBACKFNS;
171     cmd.dwParam1 = (DWORD)&hal_funcs;
172     ExtEscape(dc, DCICOMMAND, sizeof(cmd), (LPVOID)&cmd, 0, NULL);
173
174     /* next, exchange version information */
175     cmd.dwCommand = DDVERSIONINFO;
176     cmd.dwParam1 = DD_RUNTIME_VERSION; /* not sure what should *really* go here */
177     ExtEscape(dc, DCICOMMAND, sizeof(cmd), (LPVOID)&cmd, sizeof(hal_version), (LPVOID)&hal_version);
178
179     /* get 32-bit driver data (dll name and entry point) */
180     cmd.dwCommand = DDGET32BITDRIVERNAME;
181     ExtEscape(dc, DCICOMMAND, sizeof(cmd), (LPVOID)&cmd, sizeof(hal_driverdata), (LPVOID)&hal_driverdata);
182     /* we're supposed to load the DLL in hal_driverdata.szName, then GetProcAddress
183      * the hal_driverdata.szEntryPoint, and call it with hal_driverdata.dwContext
184      * as a parameter... but since this is only more remains from the 16-bit world,
185      * we'll ignore it */
186
187     /* finally, initialize the driver object */
188     cmd.dwCommand = DDCREATEDRIVEROBJECT;
189     ret = ExtEscape(dc, DCICOMMAND, sizeof(cmd), (LPVOID)&cmd, sizeof(hal_instance), (LPVOID)&hal_instance);
190     if (ret) {
191         /* the driver should have called our set_hal_info now */
192         if (!dd_gbl.lpDDCBtmp) ret = FALSE;
193     }
194
195     /* init done */
196     DeleteDC(dc);
197
198     TRACE("%s DirectDraw HAL\n", ret ? "enabling" : "disabling");
199
200     return ret;
201 }
202
203 static void cleanup(void)
204 {
205     DDHAL_DESTROYDRIVERDATA data;
206
207     if (!dd_cbs.HALDD.DestroyDriver) return;
208
209     data.lpDD = NULL;
210     data.ddRVal = 0;
211     data.DestroyDriver = dd_cbs.HALDD.DestroyDriver;
212     data.DestroyDriver(&data);
213 }
214
215 static DWORD choose_mode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP,
216                          DWORD dwRefreshRate, DWORD dwFlags)
217 {
218     int best = -1;
219     unsigned int i;
220
221     if (!dd_gbl.dwNumModes) return 0;
222
223 /* let's support HALs that cannot switch depths (XVidMode),
224  * these should return dwBPP == 0 for all their resolutions */
225 #define BPP_MATCH(dd, bpp) ((!(dd)) || ((dd) == bpp))
226
227 /* FIXME: we should try to match the refresh rate too */
228
229     /* Choose the smallest mode that is large enough. */
230     for (i=0; i < dd_gbl.dwNumModes; i++)
231     {
232         if (dd_gbl.lpModeInfo[i].dwWidth >= dwWidth &&
233             dd_gbl.lpModeInfo[i].dwHeight >= dwHeight &&
234             BPP_MATCH(dd_gbl.lpModeInfo[i].dwBPP, dwBPP))
235         {
236             if (best == -1) best = i;
237             else
238             {
239                 if (dd_gbl.lpModeInfo[i].dwWidth < dd_gbl.lpModeInfo[best].dwWidth ||
240                     dd_gbl.lpModeInfo[i].dwHeight < dd_gbl.lpModeInfo[best].dwHeight)
241                     best = i;
242             }
243         }
244     }
245
246     if (best == -1)
247     {
248         TRACE("all modes too small\n");
249         /* ok, let's use the largest */
250
251         for (i=0; i < dd_gbl.dwNumModes; i++)
252         {
253             if (BPP_MATCH(dd_gbl.lpModeInfo[i].dwBPP, dwBPP))
254             {
255                 if (best == -1) best = i;
256                 else
257                 {
258                     if (dd_gbl.lpModeInfo[i].dwWidth > dd_gbl.lpModeInfo[best].dwWidth ||
259                         dd_gbl.lpModeInfo[i].dwHeight > dd_gbl.lpModeInfo[best].dwHeight)
260                         best = i;
261                 }
262             }
263         }
264     }
265 #undef BPP_MATCH
266
267     if (best == -1)
268     {
269         ERR("requested color depth (%ld) not available, try reconfiguring X server\n", dwBPP);
270         return dd_gbl.dwModeIndex;
271     }
272
273     TRACE("using mode %d\n", best);
274
275     return best;
276 }
277
278 static HRESULT set_mode(IDirectDrawImpl *This, DWORD dwMode)
279 {
280     HRESULT hr = DD_OK;
281
282     if (dwMode != dd_gbl.dwModeIndex)
283     {
284         DDHAL_SETMODEDATA data;
285         data.lpDD = &dd_gbl;
286         data.dwModeIndex = dwMode;
287         data.ddRVal = 0;
288         data.SetMode = dd_cbs.HALDD.SetMode;
289         data.inexcl = 0;
290         data.useRefreshRate = FALSE;
291         if (data.SetMode)
292             data.SetMode(&data);
293         hr = data.ddRVal;
294         if (SUCCEEDED(hr))
295             dd_gbl.dwModeIndex = dwMode;
296     }
297     return hr;
298 }
299
300 static HRESULT set_exclusive_mode(IDirectDrawImpl *This, DWORD dwEnterExcl)
301 {
302     DDHAL_SETEXCLUSIVEMODEDATA data;
303
304     data.lpDD = &dd_gbl;
305     data.dwEnterExcl = dwEnterExcl;
306     data.dwReserved = 0;
307     data.ddRVal = 0;
308     data.SetExclusiveMode = dd_cbs.HALDD.SetExclusiveMode;
309     if (data.SetExclusiveMode)
310         data.SetExclusiveMode(&data);
311     return data.ddRVal;
312 }
313
314 BOOL DDRAW_HAL_Init(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
315 {
316     if (fdwReason == DLL_PROCESS_ATTACH)
317     {
318         if (initialize())
319             DDRAW_register_driver(&hal_driver);
320     }
321     else if (fdwReason == DLL_PROCESS_DETACH)
322     {
323         cleanup();
324     }
325
326     return TRUE;
327 }
328
329 /* Not called from the vtable. */
330 HRESULT HAL_DirectDraw_Construct(IDirectDrawImpl *This, BOOL ex)
331 {
332     HRESULT hr;
333
334     TRACE("(%p,%d)\n", This, ex);
335
336     hr = User_DirectDraw_Construct(This, ex);
337     if (FAILED(hr)) return hr;
338
339     This->local.lpGbl = &dd_gbl;
340
341     This->final_release = HAL_DirectDraw_final_release;
342     This->set_exclusive_mode = set_exclusive_mode;
343
344     This->create_palette = HAL_DirectDrawPalette_Create;
345
346     This->create_primary    = HAL_DirectDraw_create_primary;
347     This->create_backbuffer = HAL_DirectDraw_create_backbuffer;
348     This->create_texture    = HAL_DirectDraw_create_texture;
349
350     ICOM_INIT_INTERFACE(This, IDirectDraw7, HAL_DirectDraw_VTable);
351
352     /* merge HAL caps */
353     This->caps.dwCaps |= dd_gbl.ddCaps.dwCaps;
354     This->caps.dwCaps2 |= dd_gbl.ddCaps.dwCaps2;
355     This->caps.dwCKeyCaps |= dd_gbl.ddCaps.dwCKeyCaps;
356     This->caps.dwFXCaps |= dd_gbl.ddCaps.dwFXCaps;
357     This->caps.dwPalCaps |= dd_gbl.ddCaps.dwPalCaps;
358     /* FIXME: merge more caps */
359     This->caps.ddsCaps.dwCaps |= dd_gbl.ddCaps.ddsCaps.dwCaps;
360     This->caps.ddsCaps.dwCaps2 |= dd_gbl.ddsCapsMore.dwCaps2;
361     This->caps.ddsCaps.dwCaps3 |= dd_gbl.ddsCapsMore.dwCaps3;
362     This->caps.ddsCaps.dwCaps4 |= dd_gbl.ddsCapsMore.dwCaps4;
363     This->caps.ddsOldCaps.dwCaps = This->caps.ddsCaps.dwCaps;
364
365     return S_OK;
366 }
367
368 /* This function is called from DirectDrawCreate(Ex) on the most-derived
369  * class to start construction.
370  * Not called from the vtable. */
371 HRESULT HAL_DirectDraw_Create(const GUID* pGUID, LPDIRECTDRAW7* pIface,
372                               IUnknown* pUnkOuter, BOOL ex)
373 {
374     HRESULT hr;
375     IDirectDrawImpl* This;
376
377     TRACE("\n");
378
379     assert(pUnkOuter == NULL);
380
381     This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
382                      sizeof(IDirectDrawImpl)
383                      + sizeof(HAL_DirectDrawImpl));
384     if (This == NULL) return E_OUTOFMEMORY;
385
386     /* Note that this relation does *not* hold true if the DD object was
387      * CoCreateInstanced then Initialized. */
388     This->private = (HAL_DirectDrawImpl *)(This+1);
389
390     /* Initialize the DDCAPS structure */
391     This->caps.dwSize = sizeof(This->caps);
392
393     hr = HAL_DirectDraw_Construct(This, ex);
394     if (FAILED(hr))
395         HeapFree(GetProcessHeap(), 0, This);
396     else
397         *pIface = ICOM_INTERFACE(This, IDirectDraw7);
398
399     return hr;
400 }
401
402 /* This function is called from Uninit_DirectDraw_Initialize on the
403  * most-derived-class to start initialization.
404  * Not called from the vtable. */
405 HRESULT HAL_DirectDraw_Initialize(IDirectDrawImpl *This, const GUID* guid)
406 {
407     HRESULT hr;
408
409     TRACE("\n");
410
411     This->private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
412                               sizeof(HAL_DirectDrawImpl));
413     if (This->private == NULL) return E_OUTOFMEMORY;
414
415     /* Initialize the DDCAPS structure */
416     This->caps.dwSize = sizeof(This->caps);
417
418     hr = HAL_DirectDraw_Construct(This, TRUE); /* XXX ex? */
419     if (FAILED(hr))
420     {
421         HeapFree(GetProcessHeap(), 0, This->private);
422         return hr;
423     }
424
425     return DD_OK;
426 }
427
428 /* Called from an internal function pointer. */
429 void HAL_DirectDraw_final_release(IDirectDrawImpl *This)
430 {
431     if (dd_gbl.dwFlags & DDRAWI_MODECHANGED) set_mode(This, dd_gbl.dwModeIndexOrig);
432     User_DirectDraw_final_release(This);
433 }
434
435 HRESULT HAL_DirectDraw_create_primary(IDirectDrawImpl* This,
436                                       const DDSURFACEDESC2* pDDSD,
437                                       LPDIRECTDRAWSURFACE7* ppSurf,
438                                       IUnknown* pUnkOuter)
439 {
440     if (This->cooperative_level & DDSCL_EXCLUSIVE)
441         return HAL_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
442     else
443         return User_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
444 }
445
446 HRESULT HAL_DirectDraw_create_backbuffer(IDirectDrawImpl* This,
447                                          const DDSURFACEDESC2* pDDSD,
448                                          LPDIRECTDRAWSURFACE7* ppSurf,
449                                          IUnknown* pUnkOuter,
450                                          IDirectDrawSurfaceImpl* primary)
451 {
452     if (This->cooperative_level & DDSCL_EXCLUSIVE)
453         return HAL_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
454     else
455         return User_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
456 }
457
458 HRESULT HAL_DirectDraw_create_texture(IDirectDrawImpl* This,
459                                       const DDSURFACEDESC2* pDDSD,
460                                       LPDIRECTDRAWSURFACE7* ppSurf,
461                                       LPUNKNOWN pOuter,
462                                       DWORD dwMipMapLevel)
463 {
464     return HAL_DirectDrawSurface_Create(This, pDDSD, ppSurf, pOuter);
465 }
466
467 HRESULT WINAPI
468 HAL_DirectDraw_GetDeviceIdentifier(LPDIRECTDRAW7 iface,
469                                    LPDDDEVICEIDENTIFIER2 pDDDI,
470                                    DWORD dwFlags)
471 {
472     *pDDDI = hal_device;
473     return DD_OK;
474 }
475
476 HRESULT WINAPI
477 HAL_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface)
478 {
479     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
480     HRESULT hr;
481
482     TRACE("(%p)\n", iface);
483
484     if (!(dd_gbl.dwFlags & DDRAWI_MODECHANGED)) return DD_OK;
485
486     hr = Main_DirectDraw_RestoreDisplayMode(iface);
487     if (SUCCEEDED(hr)) {
488         hr = set_mode(This, dd_gbl.dwModeIndexOrig);
489         if (SUCCEEDED(hr)) dd_gbl.dwFlags &= ~DDRAWI_MODECHANGED;
490     }
491
492     return hr;
493 }
494
495 HRESULT WINAPI
496 HAL_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface, DWORD dwWidth,
497                               DWORD dwHeight, DWORD dwBPP,
498                               DWORD dwRefreshRate, DWORD dwFlags)
499 {
500     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
501
502     HRESULT hr;
503
504     TRACE("(%p)->(%ldx%ldx%ld,%ld Hz,%08lx)\n",This,dwWidth,dwHeight,dwBPP,dwRefreshRate,dwFlags);
505     hr = User_DirectDraw_SetDisplayMode(iface, dwWidth, dwHeight, dwBPP,
506                                         dwRefreshRate, dwFlags);
507
508     if (SUCCEEDED(hr)) {
509         if (!(dd_gbl.dwFlags & DDRAWI_MODECHANGED)) dd_gbl.dwModeIndexOrig = dd_gbl.dwModeIndex;
510         hr = set_mode(This, choose_mode(dwWidth, dwHeight, dwBPP, dwRefreshRate, dwFlags));
511         if (SUCCEEDED(hr)) dd_gbl.dwFlags |= DDRAWI_MODECHANGED;
512     }
513
514     return hr;
515 }
516
517 HRESULT WINAPI
518 HAL_DirectDraw_GetFourCCCodes(LPDIRECTDRAW7 iface, LPDWORD pNumCodes,
519                                LPDWORD pCodes)
520 {
521     unsigned int i;
522     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
523     if (*pNumCodes)
524         *pNumCodes=dd_gbl.dwNumFourCC;
525     if (pCodes && dd_gbl.dwNumFourCC)
526         memcpy(pCodes,dd_gbl.lpdwFourCC,sizeof(pCodes[0])*dd_gbl.dwNumFourCC);
527     FIXME("(%p,%p,%p)\n",This,pNumCodes,pCodes);
528     if (dd_gbl.dwNumFourCC) {
529         if (pCodes && FIXME_ON(ddraw)) {
530             FIXME("returning: ");
531             for (i=0;i<dd_gbl.dwNumFourCC;i++) {
532                 MESSAGE("%c%c%c%c,",
533                         ((LPBYTE)(pCodes+i))[0],
534                         ((LPBYTE)(pCodes+i))[1],
535                         ((LPBYTE)(pCodes+i))[2],
536                         ((LPBYTE)(pCodes+i))[3]
537                 );
538             }
539             MESSAGE("\n");
540         }
541     }
542     return DD_OK;
543 }
544
545
546 static const IDirectDraw7Vtbl HAL_DirectDraw_VTable =
547 {
548     Main_DirectDraw_QueryInterface,
549     Main_DirectDraw_AddRef,
550     Main_DirectDraw_Release,
551     Main_DirectDraw_Compact,
552     Main_DirectDraw_CreateClipper,
553     Main_DirectDraw_CreatePalette,
554     Main_DirectDraw_CreateSurface,
555     Main_DirectDraw_DuplicateSurface,
556     User_DirectDraw_EnumDisplayModes,
557     Main_DirectDraw_EnumSurfaces,
558     Main_DirectDraw_FlipToGDISurface,
559     Main_DirectDraw_GetCaps,
560     Main_DirectDraw_GetDisplayMode,
561     HAL_DirectDraw_GetFourCCCodes,
562     Main_DirectDraw_GetGDISurface,
563     Main_DirectDraw_GetMonitorFrequency,
564     Main_DirectDraw_GetScanLine,
565     Main_DirectDraw_GetVerticalBlankStatus,
566     Main_DirectDraw_Initialize,
567     HAL_DirectDraw_RestoreDisplayMode,
568     Main_DirectDraw_SetCooperativeLevel,
569     HAL_DirectDraw_SetDisplayMode,
570     Main_DirectDraw_WaitForVerticalBlank,
571     Main_DirectDraw_GetAvailableVidMem,
572     Main_DirectDraw_GetSurfaceFromDC,
573     Main_DirectDraw_RestoreAllSurfaces,
574     Main_DirectDraw_TestCooperativeLevel,
575     HAL_DirectDraw_GetDeviceIdentifier,
576     Main_DirectDraw_StartModeTest,
577     Main_DirectDraw_EvaluateMode
578 };