1 /* DirectDraw HAL driver
3 * Copyright 2001 TransGaming Technologies Inc.
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.
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.
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
28 #include "wine/debug.h"
36 #include "ddraw_private.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
40 static const IDirectDraw7Vtbl HAL_DirectDraw_VTable;
42 static DDVERSIONDATA hal_version;
43 static DD32BITDRIVERDATA hal_driverdata;
44 static HINSTANCE hal_instance;
46 static const DDDEVICEIDENTIFIER2 hal_device =
50 { { 0x00010001, 0x00010001 } },
52 /* 40c1b248-9d7d-4a29-b7d7-4cd8109f3d5d */
53 {0x40c1b248,0x9d7d,0x4a29,{0xd7,0xb7,0x4c,0xd8,0x10,0x9f,0x3d,0x5d}},
57 HRESULT HAL_DirectDraw_Create(const GUID* pGUID, LPDIRECTDRAW7* pIface,
58 IUnknown* pUnkOuter, BOOL ex);
59 HRESULT HAL_DirectDraw_Initialize(IDirectDrawImpl*, const GUID*);
61 static const ddraw_driver hal_driver =
64 100, /* we prefer the HAL */
65 HAL_DirectDraw_Create,
66 HAL_DirectDraw_Initialize
69 static DDHAL_CALLBACKS dd_cbs;
70 static DDRAWI_DIRECTDRAW_GBL dd_gbl;
72 static D3DHAL_GLOBALDRIVERDATA d3d_hal_data;
73 static D3DHAL_D3DEXTENDEDCAPS d3d_hal_extcaps;
74 static D3DHAL_CALLBACKS d3d_hal_cbs1;
75 static D3DHAL_CALLBACKS2 d3d_hal_cbs2;
77 /* in real windoze, these entry points are 16-bit, but we can work in 32-bit */
78 static BOOL WINAPI set_hal_info(LPDDHALINFO lpDDHalInfo, BOOL reset)
80 dd_cbs.HALDD = *lpDDHalInfo->lpDDCallbacks;
81 dd_cbs.HALDDSurface = *lpDDHalInfo->lpDDSurfaceCallbacks;
82 dd_cbs.HALDDPalette = *lpDDHalInfo->lpDDPaletteCallbacks;
83 if (lpDDHalInfo->lpDDExeBufCallbacks)
84 dd_cbs.HALDDExeBuf = *lpDDHalInfo->lpDDExeBufCallbacks;
86 dd_gbl.lpDDCBtmp = &dd_cbs;
88 dd_gbl.ddCaps = lpDDHalInfo->ddCaps;
89 dd_gbl.dwMonitorFrequency = lpDDHalInfo->dwMonitorFrequency;
90 dd_gbl.vmiData = lpDDHalInfo->vmiData;
91 dd_gbl.dwModeIndex = lpDDHalInfo->dwModeIndex;
92 dd_gbl.dwNumFourCC = lpDDHalInfo->ddCaps.dwNumFourCCCodes;
93 dd_gbl.lpdwFourCC = lpDDHalInfo->lpdwFourCC;
94 dd_gbl.dwNumModes = lpDDHalInfo->dwNumModes;
95 dd_gbl.lpModeInfo = lpDDHalInfo->lpModeInfo;
97 dd_gbl.dwPDevice = (DWORD)lpDDHalInfo->lpPDevice;
98 dd_gbl.hInstance = lpDDHalInfo->hInstance;
100 if (lpDDHalInfo->lpD3DGlobalDriverData)
101 memcpy(&d3d_hal_data, (LPVOID)lpDDHalInfo->lpD3DGlobalDriverData, sizeof(D3DDEVICEDESC_V1));
103 memset(&d3d_hal_data, 0, sizeof(D3DDEVICEDESC_V1));
104 dd_gbl.lpD3DGlobalDriverData = (ULONG_PTR)&d3d_hal_data;
106 if (lpDDHalInfo->lpD3DHALCallbacks)
107 memcpy(&d3d_hal_cbs1, (LPVOID)lpDDHalInfo->lpD3DHALCallbacks, sizeof(D3DHAL_CALLBACKS));
109 memset(&d3d_hal_cbs1, 0, sizeof(D3DHAL_CALLBACKS));
110 dd_gbl.lpD3DHALCallbacks = (ULONG_PTR)&d3d_hal_cbs1;
112 if (lpDDHalInfo->dwFlags & DDHALINFO_GETDRIVERINFOSET) {
113 DDHAL_GETDRIVERINFODATA data;
114 data.dwSize = sizeof(DDHAL_GETDRIVERINFODATA);
115 data.dwFlags = 0; /* ? */
116 data.dwContext = hal_driverdata.dwContext; /* ? */
118 data.guidInfo = GUID_D3DExtendedCaps;
119 data.dwExpectedSize = sizeof(D3DHAL_D3DEXTENDEDCAPS);
120 data.lpvData = &d3d_hal_extcaps;
121 data.dwActualSize = 0;
123 lpDDHalInfo->GetDriverInfo(&data);
124 d3d_hal_extcaps.dwSize = data.dwActualSize;
125 dd_gbl.lpD3DExtendedCaps = (ULONG_PTR)&d3d_hal_extcaps;
127 data.guidInfo = GUID_D3DCallbacks2;
128 data.dwExpectedSize = sizeof(D3DHAL_CALLBACKS2);
129 data.lpvData = &d3d_hal_cbs2;
130 data.dwActualSize = 0;
132 lpDDHalInfo->GetDriverInfo(&data);
133 d3d_hal_cbs2.dwSize = data.dwActualSize;
134 dd_gbl.lpD3DHALCallbacks2 = (ULONG_PTR)&d3d_hal_cbs2;
137 if( opengl_initialized &&
138 (d3d_hal_data.hwCaps.dwFlags & D3DDD_WINE_OPENGL_DEVICE) ) {
139 /*GL_DirectDraw_Init(&dd_gbl);*/
145 static DDHALDDRAWFNS hal_funcs = {
146 sizeof(DDHALDDRAWFNS),
148 NULL, /* VidMemAlloc */
149 NULL /* VidMemFree */
152 /* Called from DllInit, which is synchronised so there are no threading
154 static BOOL initialize(void)
157 INT ncmd = DCICOMMAND;
159 HDC dc = CreateDCA("DISPLAY", NULL, NULL, NULL);
160 INT ver = Escape(dc, QUERYESCSUPPORT, sizeof(ncmd), (LPVOID)&ncmd, NULL);
161 if (ver != DD_HAL_VERSION) {
163 TRACE("DirectDraw HAL not available\n");
166 cmd.dwVersion = DD_VERSION;
169 /* the DDNEWCALLBACKFNS is supposed to give the 16-bit driver entry points
170 * in ddraw16.dll, but since Wine doesn't have or use 16-bit display drivers,
171 * we'll just work in 32-bit, who'll notice... */
172 cmd.dwCommand = DDNEWCALLBACKFNS;
173 cmd.dwParam1 = (DWORD)&hal_funcs;
174 ExtEscape(dc, DCICOMMAND, sizeof(cmd), (LPVOID)&cmd, 0, NULL);
176 /* next, exchange version information */
177 cmd.dwCommand = DDVERSIONINFO;
178 cmd.dwParam1 = DD_RUNTIME_VERSION; /* not sure what should *really* go here */
179 ExtEscape(dc, DCICOMMAND, sizeof(cmd), (LPVOID)&cmd, sizeof(hal_version), (LPVOID)&hal_version);
181 /* get 32-bit driver data (dll name and entry point) */
182 cmd.dwCommand = DDGET32BITDRIVERNAME;
183 ExtEscape(dc, DCICOMMAND, sizeof(cmd), (LPVOID)&cmd, sizeof(hal_driverdata), (LPVOID)&hal_driverdata);
184 /* we're supposed to load the DLL in hal_driverdata.szName, then GetProcAddress
185 * the hal_driverdata.szEntryPoint, and call it with hal_driverdata.dwContext
186 * as a parameter... but since this is only more remains from the 16-bit world,
189 /* finally, initialize the driver object */
190 cmd.dwCommand = DDCREATEDRIVEROBJECT;
191 ret = ExtEscape(dc, DCICOMMAND, sizeof(cmd), (LPVOID)&cmd, sizeof(hal_instance), (LPVOID)&hal_instance);
193 /* the driver should have called our set_hal_info now */
194 if (!dd_gbl.lpDDCBtmp) ret = FALSE;
200 TRACE("%s DirectDraw HAL\n", ret ? "enabling" : "disabling");
205 static void cleanup(void)
207 DDHAL_DESTROYDRIVERDATA data;
209 if (!dd_cbs.HALDD.DestroyDriver) return;
213 data.DestroyDriver = dd_cbs.HALDD.DestroyDriver;
214 data.DestroyDriver(&data);
217 static DWORD choose_mode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP,
218 DWORD dwRefreshRate, DWORD dwFlags)
223 if (!dd_gbl.dwNumModes) return 0;
225 /* let's support HALs that cannot switch depths (XVidMode),
226 * these should return dwBPP == 0 for all their resolutions */
227 #define BPP_MATCH(dd, bpp) ((!(dd)) || ((dd) == bpp))
229 /* FIXME: we should try to match the refresh rate too */
231 /* Choose the smallest mode that is large enough. */
232 for (i=0; i < dd_gbl.dwNumModes; i++)
234 if (dd_gbl.lpModeInfo[i].dwWidth >= dwWidth &&
235 dd_gbl.lpModeInfo[i].dwHeight >= dwHeight &&
236 BPP_MATCH(dd_gbl.lpModeInfo[i].dwBPP, dwBPP))
238 if (best == -1) best = i;
241 if (dd_gbl.lpModeInfo[i].dwWidth < dd_gbl.lpModeInfo[best].dwWidth ||
242 dd_gbl.lpModeInfo[i].dwHeight < dd_gbl.lpModeInfo[best].dwHeight)
250 TRACE("all modes too small\n");
251 /* ok, let's use the largest */
253 for (i=0; i < dd_gbl.dwNumModes; i++)
255 if (BPP_MATCH(dd_gbl.lpModeInfo[i].dwBPP, dwBPP))
257 if (best == -1) best = i;
260 if (dd_gbl.lpModeInfo[i].dwWidth > dd_gbl.lpModeInfo[best].dwWidth ||
261 dd_gbl.lpModeInfo[i].dwHeight > dd_gbl.lpModeInfo[best].dwHeight)
271 ERR("requested color depth (%ld) not available, try reconfiguring X server\n", dwBPP);
272 return dd_gbl.dwModeIndex;
275 TRACE("using mode %d\n", best);
280 static HRESULT set_mode(IDirectDrawImpl *This, DWORD dwMode)
284 if (dwMode != dd_gbl.dwModeIndex)
286 DDHAL_SETMODEDATA data;
288 data.dwModeIndex = dwMode;
290 data.SetMode = dd_cbs.HALDD.SetMode;
292 data.useRefreshRate = FALSE;
297 dd_gbl.dwModeIndex = dwMode;
302 static HRESULT set_exclusive_mode(IDirectDrawImpl *This, DWORD dwEnterExcl)
304 DDHAL_SETEXCLUSIVEMODEDATA data;
307 data.dwEnterExcl = dwEnterExcl;
310 data.SetExclusiveMode = dd_cbs.HALDD.SetExclusiveMode;
311 if (data.SetExclusiveMode)
312 data.SetExclusiveMode(&data);
316 BOOL DDRAW_HAL_Init(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
318 if (fdwReason == DLL_PROCESS_ATTACH)
321 DDRAW_register_driver(&hal_driver);
323 else if (fdwReason == DLL_PROCESS_DETACH)
331 /* Not called from the vtable. */
332 HRESULT HAL_DirectDraw_Construct(IDirectDrawImpl *This, BOOL ex)
336 TRACE("(%p,%d)\n", This, ex);
338 hr = User_DirectDraw_Construct(This, ex);
339 if (FAILED(hr)) return hr;
341 This->local.lpGbl = &dd_gbl;
343 This->final_release = HAL_DirectDraw_final_release;
344 This->set_exclusive_mode = set_exclusive_mode;
346 This->create_palette = HAL_DirectDrawPalette_Create;
348 This->create_primary = HAL_DirectDraw_create_primary;
349 This->create_backbuffer = HAL_DirectDraw_create_backbuffer;
350 This->create_texture = HAL_DirectDraw_create_texture;
352 ICOM_INIT_INTERFACE(This, IDirectDraw7, HAL_DirectDraw_VTable);
355 This->caps.dwCaps |= dd_gbl.ddCaps.dwCaps;
356 This->caps.dwCaps2 |= dd_gbl.ddCaps.dwCaps2;
357 This->caps.dwCKeyCaps |= dd_gbl.ddCaps.dwCKeyCaps;
358 This->caps.dwFXCaps |= dd_gbl.ddCaps.dwFXCaps;
359 This->caps.dwPalCaps |= dd_gbl.ddCaps.dwPalCaps;
360 /* FIXME: merge more caps */
361 This->caps.ddsCaps.dwCaps |= dd_gbl.ddCaps.ddsCaps.dwCaps;
362 This->caps.ddsCaps.dwCaps2 |= dd_gbl.ddsCapsMore.dwCaps2;
363 This->caps.ddsCaps.dwCaps3 |= dd_gbl.ddsCapsMore.dwCaps3;
364 This->caps.ddsCaps.dwCaps4 |= dd_gbl.ddsCapsMore.dwCaps4;
365 This->caps.ddsOldCaps.dwCaps = This->caps.ddsCaps.dwCaps;
370 /* This function is called from DirectDrawCreate(Ex) on the most-derived
371 * class to start construction.
372 * Not called from the vtable. */
373 HRESULT HAL_DirectDraw_Create(const GUID* pGUID, LPDIRECTDRAW7* pIface,
374 IUnknown* pUnkOuter, BOOL ex)
377 IDirectDrawImpl* This;
381 assert(pUnkOuter == NULL);
383 This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
384 sizeof(IDirectDrawImpl)
385 + sizeof(HAL_DirectDrawImpl));
386 if (This == NULL) return E_OUTOFMEMORY;
388 /* Note that this relation does *not* hold true if the DD object was
389 * CoCreateInstanced then Initialized. */
390 This->private = (HAL_DirectDrawImpl *)(This+1);
392 /* Initialize the DDCAPS structure */
393 This->caps.dwSize = sizeof(This->caps);
395 hr = HAL_DirectDraw_Construct(This, ex);
397 HeapFree(GetProcessHeap(), 0, This);
399 *pIface = ICOM_INTERFACE(This, IDirectDraw7);
404 /* This function is called from Uninit_DirectDraw_Initialize on the
405 * most-derived-class to start initialization.
406 * Not called from the vtable. */
407 HRESULT HAL_DirectDraw_Initialize(IDirectDrawImpl *This, const GUID* guid)
413 This->private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
414 sizeof(HAL_DirectDrawImpl));
415 if (This->private == NULL) return E_OUTOFMEMORY;
417 /* Initialize the DDCAPS structure */
418 This->caps.dwSize = sizeof(This->caps);
420 hr = HAL_DirectDraw_Construct(This, TRUE); /* XXX ex? */
423 HeapFree(GetProcessHeap(), 0, This->private);
430 /* Called from an internal function pointer. */
431 void HAL_DirectDraw_final_release(IDirectDrawImpl *This)
433 if (dd_gbl.dwFlags & DDRAWI_MODECHANGED) set_mode(This, dd_gbl.dwModeIndexOrig);
434 User_DirectDraw_final_release(This);
437 HRESULT HAL_DirectDraw_create_primary(IDirectDrawImpl* This,
438 const DDSURFACEDESC2* pDDSD,
439 LPDIRECTDRAWSURFACE7* ppSurf,
442 if (This->cooperative_level & DDSCL_EXCLUSIVE)
443 return HAL_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
445 return User_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
448 HRESULT HAL_DirectDraw_create_backbuffer(IDirectDrawImpl* This,
449 const DDSURFACEDESC2* pDDSD,
450 LPDIRECTDRAWSURFACE7* ppSurf,
452 IDirectDrawSurfaceImpl* primary)
454 if (This->cooperative_level & DDSCL_EXCLUSIVE)
455 return HAL_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
457 return User_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
460 HRESULT HAL_DirectDraw_create_texture(IDirectDrawImpl* This,
461 const DDSURFACEDESC2* pDDSD,
462 LPDIRECTDRAWSURFACE7* ppSurf,
466 return HAL_DirectDrawSurface_Create(This, pDDSD, ppSurf, pOuter);
470 HAL_DirectDraw_GetDeviceIdentifier(LPDIRECTDRAW7 iface,
471 LPDDDEVICEIDENTIFIER2 pDDDI,
479 HAL_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface)
481 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
484 TRACE("(%p)\n", iface);
486 if (!(dd_gbl.dwFlags & DDRAWI_MODECHANGED)) return DD_OK;
488 hr = Main_DirectDraw_RestoreDisplayMode(iface);
490 hr = set_mode(This, dd_gbl.dwModeIndexOrig);
491 if (SUCCEEDED(hr)) dd_gbl.dwFlags &= ~DDRAWI_MODECHANGED;
498 HAL_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface, DWORD dwWidth,
499 DWORD dwHeight, DWORD dwBPP,
500 DWORD dwRefreshRate, DWORD dwFlags)
502 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
506 TRACE("(%p)->(%ldx%ldx%ld,%ld Hz,%08lx)\n",This,dwWidth,dwHeight,dwBPP,dwRefreshRate,dwFlags);
507 hr = User_DirectDraw_SetDisplayMode(iface, dwWidth, dwHeight, dwBPP,
508 dwRefreshRate, dwFlags);
511 if (!(dd_gbl.dwFlags & DDRAWI_MODECHANGED)) dd_gbl.dwModeIndexOrig = dd_gbl.dwModeIndex;
512 hr = set_mode(This, choose_mode(dwWidth, dwHeight, dwBPP, dwRefreshRate, dwFlags));
513 if (SUCCEEDED(hr)) dd_gbl.dwFlags |= DDRAWI_MODECHANGED;
520 HAL_DirectDraw_GetFourCCCodes(LPDIRECTDRAW7 iface, LPDWORD pNumCodes,
524 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
526 *pNumCodes=dd_gbl.dwNumFourCC;
527 if (pCodes && dd_gbl.dwNumFourCC)
528 memcpy(pCodes,dd_gbl.lpdwFourCC,sizeof(pCodes[0])*dd_gbl.dwNumFourCC);
529 FIXME("(%p,%p,%p)\n",This,pNumCodes,pCodes);
530 if (dd_gbl.dwNumFourCC) {
531 if (pCodes && FIXME_ON(ddraw)) {
532 FIXME("returning: ");
533 for (i=0;i<dd_gbl.dwNumFourCC;i++) {
535 ((LPBYTE)(pCodes+i))[0],
536 ((LPBYTE)(pCodes+i))[1],
537 ((LPBYTE)(pCodes+i))[2],
538 ((LPBYTE)(pCodes+i))[3]
548 static const IDirectDraw7Vtbl HAL_DirectDraw_VTable =
550 Main_DirectDraw_QueryInterface,
551 Main_DirectDraw_AddRef,
552 Main_DirectDraw_Release,
553 Main_DirectDraw_Compact,
554 Main_DirectDraw_CreateClipper,
555 Main_DirectDraw_CreatePalette,
556 Main_DirectDraw_CreateSurface,
557 Main_DirectDraw_DuplicateSurface,
558 User_DirectDraw_EnumDisplayModes,
559 Main_DirectDraw_EnumSurfaces,
560 Main_DirectDraw_FlipToGDISurface,
561 Main_DirectDraw_GetCaps,
562 Main_DirectDraw_GetDisplayMode,
563 HAL_DirectDraw_GetFourCCCodes,
564 Main_DirectDraw_GetGDISurface,
565 Main_DirectDraw_GetMonitorFrequency,
566 Main_DirectDraw_GetScanLine,
567 Main_DirectDraw_GetVerticalBlankStatus,
568 Main_DirectDraw_Initialize,
569 HAL_DirectDraw_RestoreDisplayMode,
570 Main_DirectDraw_SetCooperativeLevel,
571 HAL_DirectDraw_SetDisplayMode,
572 Main_DirectDraw_WaitForVerticalBlank,
573 Main_DirectDraw_GetAvailableVidMem,
574 Main_DirectDraw_GetSurfaceFromDC,
575 Main_DirectDraw_RestoreAllSurfaces,
576 Main_DirectDraw_TestCooperativeLevel,
577 HAL_DirectDraw_GetDeviceIdentifier,
578 Main_DirectDraw_StartModeTest,
579 Main_DirectDraw_EvaluateMode