1 /* DirectDraw HAL driver
3 * Copyright 2001 TransGaming Technologies Inc.
8 #include "debugtools.h"
16 #include "ddraw_private.h"
17 #include "ddraw/main.h"
18 #include "ddraw/user.h"
19 #include "ddraw/hal.h"
20 #include "dclipper/main.h"
21 #include "dpalette/main.h"
22 #include "dpalette/hal.h"
23 #include "dsurface/main.h"
24 #include "dsurface/dib.h"
25 #include "dsurface/user.h"
26 #include "dsurface/hal.h"
28 DEFAULT_DEBUG_CHANNEL(ddraw);
30 static ICOM_VTABLE(IDirectDraw7) HAL_DirectDraw_VTable;
32 static DDVERSIONDATA hal_version;
33 static DD32BITDRIVERDATA hal_driverdata;
34 static HINSTANCE hal_instance;
36 static const DDDEVICEIDENTIFIER2 hal_device =
40 { { 0x00010001, 0x00010001 } },
42 /* 40c1b248-9d7d-4a29-b7d7-4cd8109f3d5d */
43 {0x40c1b248,0x9d7d,0x4a29,{0xd7,0xb7,0x4c,0xd8,0x10,0x9f,0x3d,0x5d}},
47 HRESULT HAL_DirectDraw_Create(const GUID* pGUID, LPDIRECTDRAW7* pIface,
48 IUnknown* pUnkOuter, BOOL ex);
49 HRESULT HAL_DirectDraw_Initialize(IDirectDrawImpl*, const GUID*);
51 static const ddraw_driver hal_driver =
54 100, /* we prefer the HAL */
55 HAL_DirectDraw_Create,
56 HAL_DirectDraw_Initialize
59 static DDHAL_CALLBACKS dd_cbs;
60 static DDRAWI_DIRECTDRAW_GBL dd_gbl;
62 static D3DHAL_GLOBALDRIVERDATA d3d_hal_data;
63 static D3DHAL_D3DEXTENDEDCAPS d3d_hal_extcaps;
64 static D3DHAL_CALLBACKS d3d_hal_cbs1;
65 static D3DHAL_CALLBACKS2 d3d_hal_cbs2;
67 /* in real windoze, these entry points are 16-bit, but we can work in 32-bit */
68 static BOOL WINAPI set_hal_info(LPDDHALINFO lpDDHalInfo, BOOL reset)
70 dd_cbs.HALDD = *lpDDHalInfo->lpDDCallbacks;
71 dd_cbs.HALDDSurface = *lpDDHalInfo->lpDDSurfaceCallbacks;
72 dd_cbs.HALDDPalette = *lpDDHalInfo->lpDDPaletteCallbacks;
73 if (lpDDHalInfo->lpDDExeBufCallbacks)
74 dd_cbs.HALDDExeBuf = *lpDDHalInfo->lpDDExeBufCallbacks;
76 dd_gbl.lpDDCBtmp = &dd_cbs;
78 dd_gbl.ddCaps = lpDDHalInfo->ddCaps;
79 dd_gbl.dwMonitorFrequency = lpDDHalInfo->dwMonitorFrequency;
80 dd_gbl.vmiData = lpDDHalInfo->vmiData;
81 dd_gbl.dwModeIndex = lpDDHalInfo->dwModeIndex;
82 /* FIXME: dwNumFourCC */
83 dd_gbl.lpdwFourCC = lpDDHalInfo->lpdwFourCC;
84 dd_gbl.dwNumModes = lpDDHalInfo->dwNumModes;
85 dd_gbl.lpModeInfo = lpDDHalInfo->lpModeInfo;
87 dd_gbl.dwPDevice = (DWORD)lpDDHalInfo->lpPDevice;
88 dd_gbl.hInstance = lpDDHalInfo->hInstance;
90 if (lpDDHalInfo->lpD3DGlobalDriverData)
91 memcpy(&d3d_hal_data, (LPVOID)lpDDHalInfo->lpD3DGlobalDriverData, sizeof(D3DDEVICEDESC_V1));
93 memset(&d3d_hal_data, 0, sizeof(D3DDEVICEDESC_V1));
94 dd_gbl.lpD3DGlobalDriverData = (ULONG_PTR)&d3d_hal_data;
96 if (lpDDHalInfo->lpD3DHALCallbacks)
97 memcpy(&d3d_hal_cbs1, (LPVOID)lpDDHalInfo->lpD3DHALCallbacks, sizeof(D3DHAL_CALLBACKS));
99 memset(&d3d_hal_cbs1, 0, sizeof(D3DDEVICEDESC_V1));
100 dd_gbl.lpD3DHALCallbacks = (ULONG_PTR)&d3d_hal_cbs1;
102 if (lpDDHalInfo->dwFlags & DDHALINFO_GETDRIVERINFOSET) {
103 DDHAL_GETDRIVERINFODATA data;
104 data.dwSize = sizeof(DDHAL_GETDRIVERINFODATA);
105 data.dwFlags = 0; /* ? */
106 data.dwContext = hal_driverdata.dwContext; /* ? */
108 data.guidInfo = GUID_D3DExtendedCaps;
109 data.dwExpectedSize = sizeof(D3DHAL_D3DEXTENDEDCAPS);
110 data.lpvData = &d3d_hal_extcaps;
111 data.dwActualSize = 0;
113 lpDDHalInfo->GetDriverInfo(&data);
114 d3d_hal_extcaps.dwSize = data.dwActualSize;
115 dd_gbl.lpD3DExtendedCaps = (ULONG_PTR)&d3d_hal_extcaps;
117 data.guidInfo = GUID_D3DCallbacks2;
118 data.dwExpectedSize = sizeof(D3DHAL_CALLBACKS2);
119 data.lpvData = &d3d_hal_cbs2;
120 data.dwActualSize = 0;
122 lpDDHalInfo->GetDriverInfo(&data);
123 d3d_hal_cbs2.dwSize = data.dwActualSize;
124 dd_gbl.lpD3DHALCallbacks2 = (ULONG_PTR)&d3d_hal_cbs2;
128 if (d3d_hal_data.hwCaps.dwFlags & D3DDD_WINE_OPENGL_DEVICE) {
129 /*GL_DirectDraw_Init(&dd_gbl);*/
136 static DDHALDDRAWFNS hal_funcs = {
137 sizeof(DDHALDDRAWFNS),
139 NULL, /* VidMemAlloc */
140 NULL /* VidMemFree */
143 /* Called from DllInit, which is synchronised so there are no threading
145 static BOOL initialize(void)
148 INT ncmd = DCICOMMAND;
150 HDC dc = CreateDCA("DISPLAY", NULL, NULL, NULL);
151 INT ver = Escape(dc, QUERYESCSUPPORT, sizeof(ncmd), (LPVOID)&ncmd, NULL);
152 if (ver != DD_HAL_VERSION) {
154 TRACE("DirectDraw HAL not available\n");
157 cmd.dwVersion = DD_VERSION;
160 /* the DDNEWCALLBACKFNS is supposed to give the 16-bit driver entry points
161 * in ddraw16.dll, but since Wine doesn't have or use 16-bit display drivers,
162 * we'll just work in 32-bit, who'll notice... */
163 cmd.dwCommand = DDNEWCALLBACKFNS;
164 cmd.dwParam1 = (DWORD)&hal_funcs;
165 ExtEscape(dc, DCICOMMAND, sizeof(cmd), (LPVOID)&cmd, 0, NULL);
167 /* next, exchange version information */
168 cmd.dwCommand = DDVERSIONINFO;
169 cmd.dwParam1 = DD_RUNTIME_VERSION; /* not sure what should *really* go here */
170 ExtEscape(dc, DCICOMMAND, sizeof(cmd), (LPVOID)&cmd, sizeof(hal_version), (LPVOID)&hal_version);
172 /* get 32-bit driver data (dll name and entry point) */
173 cmd.dwCommand = DDGET32BITDRIVERNAME;
174 ExtEscape(dc, DCICOMMAND, sizeof(cmd), (LPVOID)&cmd, sizeof(hal_driverdata), (LPVOID)&hal_driverdata);
175 /* we're supposed to load the DLL in hal_driverdata.szName, then GetProcAddress
176 * the hal_driverdata.szEntryPoint, and call it with hal_driverdata.dwContext
177 * as a parameter... but since this is only more remains from the 16-bit world,
180 /* finally, initialize the driver object */
181 cmd.dwCommand = DDCREATEDRIVEROBJECT;
182 ret = ExtEscape(dc, DCICOMMAND, sizeof(cmd), (LPVOID)&cmd, sizeof(hal_instance), (LPVOID)&hal_instance);
184 /* the driver should have called our set_hal_info now */
185 if (!dd_gbl.lpDDCBtmp) ret = FALSE;
191 TRACE("%s DirectDraw HAL\n", ret ? "enabling" : "disabling");
196 static void cleanup(void)
198 DDHAL_DESTROYDRIVERDATA data;
201 data.DestroyDriver = dd_cbs.HALDD.DestroyDriver;
202 data.DestroyDriver(&data);
205 static DWORD choose_mode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP,
206 DWORD dwRefreshRate, DWORD dwFlags)
211 if (!dd_gbl.dwNumModes) return 0;
213 /* let's support HALs that cannot switch depths (XVidMode),
214 * these should return dwBPP == 0 for all their resolutions */
215 #define BPP_MATCH(dd, bpp) ((!(dd)) || ((dd) == bpp))
217 /* FIXME: we should try to match the refresh rate too */
219 /* Choose the smallest mode that is large enough. */
220 for (i=0; i < dd_gbl.dwNumModes; i++)
222 if (dd_gbl.lpModeInfo[i].dwWidth >= dwWidth &&
223 dd_gbl.lpModeInfo[i].dwHeight >= dwHeight &&
224 BPP_MATCH(dd_gbl.lpModeInfo[i].dwBPP, dwBPP))
226 if (best == -1) best = i;
229 if (dd_gbl.lpModeInfo[i].dwWidth < dd_gbl.lpModeInfo[best].dwWidth ||
230 dd_gbl.lpModeInfo[i].dwHeight < dd_gbl.lpModeInfo[best].dwHeight)
238 TRACE("all modes too small\n");
239 /* ok, let's use the largest */
241 for (i=0; i < dd_gbl.dwNumModes; i++)
243 if (BPP_MATCH(dd_gbl.lpModeInfo[i].dwBPP, dwBPP))
245 if (best == -1) best = i;
248 if (dd_gbl.lpModeInfo[i].dwWidth > dd_gbl.lpModeInfo[best].dwWidth ||
249 dd_gbl.lpModeInfo[i].dwHeight > dd_gbl.lpModeInfo[best].dwHeight)
259 ERR("requested color depth (%ld) not available, try reconfiguring X server\n", dwBPP);
260 return dd_gbl.dwModeIndex;
263 TRACE("using mode %d\n", best);
268 static HRESULT set_mode(IDirectDrawImpl *This, DWORD dwMode)
272 if (dwMode != dd_gbl.dwModeIndex)
274 DDHAL_SETMODEDATA data;
276 data.dwModeIndex = dwMode;
278 data.SetMode = dd_cbs.HALDD.SetMode;
280 data.useRefreshRate = FALSE;
285 dd_gbl.dwModeIndex = dwMode;
290 static HRESULT set_exclusive_mode(IDirectDrawImpl *This, DWORD dwEnterExcl)
292 DDHAL_SETEXCLUSIVEMODEDATA data;
295 data.dwEnterExcl = dwEnterExcl;
298 data.SetExclusiveMode = dd_cbs.HALDD.SetExclusiveMode;
299 if (data.SetExclusiveMode)
300 data.SetExclusiveMode(&data);
304 BOOL DDRAW_HAL_Init(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
306 if (fdwReason == DLL_PROCESS_ATTACH)
309 DDRAW_register_driver(&hal_driver);
311 else if (fdwReason == DLL_PROCESS_DETACH)
319 /* Not called from the vtable. */
320 HRESULT HAL_DirectDraw_Construct(IDirectDrawImpl *This, BOOL ex)
324 TRACE("(%p)\n", This);
326 hr = User_DirectDraw_Construct(This, ex);
327 if (FAILED(hr)) return hr;
329 This->local.lpGbl = &dd_gbl;
331 This->final_release = HAL_DirectDraw_final_release;
332 This->set_exclusive_mode = set_exclusive_mode;
334 This->create_palette = HAL_DirectDrawPalette_Create;
336 This->create_primary = HAL_DirectDraw_create_primary;
337 This->create_backbuffer = HAL_DirectDraw_create_backbuffer;
338 This->create_texture = HAL_DirectDraw_create_texture;
340 ICOM_INIT_INTERFACE(This, IDirectDraw7, HAL_DirectDraw_VTable);
343 This->caps.dwCaps |= dd_gbl.ddCaps.dwCaps;
344 This->caps.dwCaps2 |= dd_gbl.ddCaps.dwCaps2;
345 This->caps.dwCKeyCaps |= dd_gbl.ddCaps.dwCKeyCaps;
346 This->caps.dwFXCaps |= dd_gbl.ddCaps.dwFXCaps;
347 This->caps.dwPalCaps |= dd_gbl.ddCaps.dwPalCaps;
348 /* FIXME: merge more caps */
349 This->caps.ddsCaps.dwCaps |= dd_gbl.ddCaps.ddsCaps.dwCaps;
350 This->caps.ddsCaps.dwCaps2 |= dd_gbl.ddsCapsMore.dwCaps2;
351 This->caps.ddsCaps.dwCaps3 |= dd_gbl.ddsCapsMore.dwCaps3;
352 This->caps.ddsCaps.dwCaps4 |= dd_gbl.ddsCapsMore.dwCaps4;
353 This->caps.ddsOldCaps.dwCaps = This->caps.ddsCaps.dwCaps;
358 /* This function is called from DirectDrawCreate(Ex) on the most-derived
359 * class to start construction.
360 * Not called from the vtable. */
361 HRESULT HAL_DirectDraw_Create(const GUID* pGUID, LPDIRECTDRAW7* pIface,
362 IUnknown* pUnkOuter, BOOL ex)
365 IDirectDrawImpl* This;
369 assert(pUnkOuter == NULL);
371 This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
372 sizeof(IDirectDrawImpl)
373 + sizeof(HAL_DirectDrawImpl));
374 if (This == NULL) return E_OUTOFMEMORY;
376 /* Note that this relation does *not* hold true if the DD object was
377 * CoCreateInstanced then Initialized. */
378 This->private = (HAL_DirectDrawImpl *)(This+1);
380 hr = HAL_DirectDraw_Construct(This, ex);
382 HeapFree(GetProcessHeap(), 0, This);
384 *pIface = ICOM_INTERFACE(This, IDirectDraw7);
389 /* This function is called from Uninit_DirectDraw_Initialize on the
390 * most-derived-class to start initialization.
391 * Not called from the vtable. */
392 HRESULT HAL_DirectDraw_Initialize(IDirectDrawImpl *This, const GUID* guid)
398 This->private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
399 sizeof(HAL_DirectDrawImpl));
400 if (This->private == NULL) return E_OUTOFMEMORY;
402 hr = HAL_DirectDraw_Construct(This, TRUE); /* XXX ex? */
405 HeapFree(GetProcessHeap(), 0, This->private);
412 /* Called from an internal function pointer. */
413 void HAL_DirectDraw_final_release(IDirectDrawImpl *This)
415 if (dd_gbl.dwFlags & DDRAWI_MODECHANGED) set_mode(This, dd_gbl.dwModeIndexOrig);
416 User_DirectDraw_final_release(This);
419 HRESULT HAL_DirectDraw_create_primary(IDirectDrawImpl* This,
420 const DDSURFACEDESC2* pDDSD,
421 LPDIRECTDRAWSURFACE7* ppSurf,
424 if (This->cooperative_level & DDSCL_EXCLUSIVE)
425 return HAL_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
427 return User_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
430 HRESULT HAL_DirectDraw_create_backbuffer(IDirectDrawImpl* This,
431 const DDSURFACEDESC2* pDDSD,
432 LPDIRECTDRAWSURFACE7* ppSurf,
434 IDirectDrawSurfaceImpl* primary)
436 if (This->cooperative_level & DDSCL_EXCLUSIVE)
437 return HAL_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
439 return User_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
442 HRESULT HAL_DirectDraw_create_texture(IDirectDrawImpl* This,
443 const DDSURFACEDESC2* pDDSD,
444 LPDIRECTDRAWSURFACE7* ppSurf,
448 return HAL_DirectDrawSurface_Create(This, pDDSD, ppSurf, pOuter);
452 HAL_DirectDraw_GetDeviceIdentifier(LPDIRECTDRAW7 iface,
453 LPDDDEVICEIDENTIFIER2 pDDDI,
461 HAL_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface)
463 ICOM_THIS(IDirectDrawImpl, iface);
466 TRACE("(%p)\n", iface);
468 if (!(dd_gbl.dwFlags & DDRAWI_MODECHANGED)) return DD_OK;
470 hr = Main_DirectDraw_RestoreDisplayMode(iface);
472 hr = set_mode(This, dd_gbl.dwModeIndexOrig);
473 if (SUCCEEDED(hr)) dd_gbl.dwFlags &= ~DDRAWI_MODECHANGED;
480 HAL_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface, DWORD dwWidth,
481 DWORD dwHeight, DWORD dwBPP,
482 DWORD dwRefreshRate, DWORD dwFlags)
484 ICOM_THIS(IDirectDrawImpl, iface);
488 TRACE("(%p)->(%ldx%ldx%ld,%ld Hz,%08lx)\n",This,dwWidth,dwHeight,dwBPP,dwRefreshRate,dwFlags);
489 hr = User_DirectDraw_SetDisplayMode(iface, dwWidth, dwHeight, dwBPP,
490 dwRefreshRate, dwFlags);
493 if (!(dd_gbl.dwFlags & DDRAWI_MODECHANGED)) dd_gbl.dwModeIndexOrig = dd_gbl.dwModeIndex;
494 hr = set_mode(This, choose_mode(dwWidth, dwHeight, dwBPP, dwRefreshRate, dwFlags));
495 if (SUCCEEDED(hr)) dd_gbl.dwFlags |= DDRAWI_MODECHANGED;
501 static ICOM_VTABLE(IDirectDraw7) HAL_DirectDraw_VTable =
503 Main_DirectDraw_QueryInterface,
504 Main_DirectDraw_AddRef,
505 Main_DirectDraw_Release,
506 Main_DirectDraw_Compact,
507 Main_DirectDraw_CreateClipper,
508 Main_DirectDraw_CreatePalette,
509 Main_DirectDraw_CreateSurface,
510 Main_DirectDraw_DuplicateSurface,
511 User_DirectDraw_EnumDisplayModes,
512 Main_DirectDraw_EnumSurfaces,
513 Main_DirectDraw_FlipToGDISurface,
514 Main_DirectDraw_GetCaps,
515 Main_DirectDraw_GetDisplayMode,
516 Main_DirectDraw_GetFourCCCodes,
517 Main_DirectDraw_GetGDISurface,
518 Main_DirectDraw_GetMonitorFrequency,
519 Main_DirectDraw_GetScanLine,
520 Main_DirectDraw_GetVerticalBlankStatus,
521 Main_DirectDraw_Initialize,
522 HAL_DirectDraw_RestoreDisplayMode,
523 Main_DirectDraw_SetCooperativeLevel,
524 HAL_DirectDraw_SetDisplayMode,
525 Main_DirectDraw_WaitForVerticalBlank,
526 Main_DirectDraw_GetAvailableVidMem,
527 Main_DirectDraw_GetSurfaceFromDC,
528 Main_DirectDraw_RestoreAllSurfaces,
529 Main_DirectDraw_TestCooperativeLevel,
530 HAL_DirectDraw_GetDeviceIdentifier,
531 Main_DirectDraw_StartModeTest,
532 Main_DirectDraw_EvaluateMode