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