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"
30 DEFAULT_DEBUG_CHANNEL(ddraw
);
32 static ICOM_VTABLE(IDirectDraw7
) HAL_DirectDraw_VTable
;
34 static DDVERSIONDATA hal_version
;
35 static DD32BITDRIVERDATA hal_driverdata
;
36 static HINSTANCE hal_instance
;
38 static const DDDEVICEIDENTIFIER2 hal_device
=
42 { { 0x00010001, 0x00010001 } },
44 /* 40c1b248-9d7d-4a29-b7d7-4cd8109f3d5d */
45 {0x40c1b248,0x9d7d,0x4a29,{0xd7,0xb7,0x4c,0xd8,0x10,0x9f,0x3d,0x5d}},
49 HRESULT
HAL_DirectDraw_Create(const GUID
* pGUID
, LPDIRECTDRAW7
* pIface
,
50 IUnknown
* pUnkOuter
, BOOL ex
);
51 HRESULT
HAL_DirectDraw_Initialize(IDirectDrawImpl
*, const GUID
*);
53 static const ddraw_driver hal_driver
=
56 100, /* we prefer the HAL */
57 HAL_DirectDraw_Create
,
58 HAL_DirectDraw_Initialize
61 static DDHAL_CALLBACKS dd_cbs
;
62 static DDRAWI_DIRECTDRAW_GBL dd_gbl
;
64 static D3DHAL_GLOBALDRIVERDATA d3d_hal_data
;
65 static D3DHAL_D3DEXTENDEDCAPS d3d_hal_extcaps
;
66 static D3DHAL_CALLBACKS d3d_hal_cbs1
;
67 static D3DHAL_CALLBACKS2 d3d_hal_cbs2
;
69 /* in real windoze, these entry points are 16-bit, but we can work in 32-bit */
70 static BOOL DDAPI
set_hal_info(LPDDHALINFO lpDDHalInfo
, BOOL reset
)
72 dd_cbs
.HALDD
= *lpDDHalInfo
->lpDDCallbacks
;
73 dd_cbs
.HALDDSurface
= *lpDDHalInfo
->lpDDSurfaceCallbacks
;
74 dd_cbs
.HALDDPalette
= *lpDDHalInfo
->lpDDPaletteCallbacks
;
75 if (lpDDHalInfo
->lpDDExeBufCallbacks
)
76 dd_cbs
.HALDDExeBuf
= *lpDDHalInfo
->lpDDExeBufCallbacks
;
78 dd_gbl
.lpDDCBtmp
= &dd_cbs
;
80 dd_gbl
.ddCaps
= lpDDHalInfo
->ddCaps
;
81 dd_gbl
.dwMonitorFrequency
= lpDDHalInfo
->dwMonitorFrequency
;
82 dd_gbl
.vmiData
= lpDDHalInfo
->vmiData
;
83 dd_gbl
.dwModeIndex
= lpDDHalInfo
->dwModeIndex
;
84 /* FIXME: dwNumFourCC */
85 dd_gbl
.lpdwFourCC
= lpDDHalInfo
->lpdwFourCC
;
86 dd_gbl
.dwNumModes
= lpDDHalInfo
->dwNumModes
;
87 dd_gbl
.lpModeInfo
= lpDDHalInfo
->lpModeInfo
;
89 dd_gbl
.dwPDevice
= (DWORD
)lpDDHalInfo
->lpPDevice
;
90 dd_gbl
.hInstance
= lpDDHalInfo
->hInstance
;
92 if (lpDDHalInfo
->lpD3DGlobalDriverData
)
93 memcpy(&d3d_hal_data
, (LPVOID
)lpDDHalInfo
->lpD3DGlobalDriverData
, sizeof(D3DDEVICEDESC_V1
));
95 memset(&d3d_hal_data
, 0, sizeof(D3DDEVICEDESC_V1
));
96 dd_gbl
.lpD3DGlobalDriverData
= (ULONG_PTR
)&d3d_hal_data
;
98 if (lpDDHalInfo
->lpD3DHALCallbacks
)
99 memcpy(&d3d_hal_cbs1
, (LPVOID
)lpDDHalInfo
->lpD3DHALCallbacks
, sizeof(D3DHAL_CALLBACKS
));
101 memset(&d3d_hal_cbs1
, 0, sizeof(D3DDEVICEDESC_V1
));
102 dd_gbl
.lpD3DHALCallbacks
= (ULONG_PTR
)&d3d_hal_cbs1
;
104 if (lpDDHalInfo
->dwFlags
& DDHALINFO_GETDRIVERINFOSET
) {
105 DDHAL_GETDRIVERINFODATA data
;
106 data
.dwSize
= sizeof(DDHAL_GETDRIVERINFODATA
);
107 data
.dwFlags
= 0; /* ? */
108 data
.dwContext
= hal_driverdata
.dwContext
; /* ? */
110 data
.guidInfo
= GUID_D3DExtendedCaps
;
111 data
.dwExpectedSize
= sizeof(D3DHAL_D3DEXTENDEDCAPS
);
112 data
.lpvData
= &d3d_hal_extcaps
;
113 data
.dwActualSize
= 0;
115 lpDDHalInfo
->GetDriverInfo(&data
);
116 d3d_hal_extcaps
.dwSize
= data
.dwActualSize
;
117 dd_gbl
.lpD3DExtendedCaps
= (ULONG_PTR
)&d3d_hal_extcaps
;
119 data
.guidInfo
= GUID_D3DCallbacks2
;
120 data
.dwExpectedSize
= sizeof(D3DHAL_CALLBACKS2
);
121 data
.lpvData
= &d3d_hal_cbs2
;
122 data
.dwActualSize
= 0;
124 lpDDHalInfo
->GetDriverInfo(&data
);
125 d3d_hal_cbs2
.dwSize
= data
.dwActualSize
;
126 dd_gbl
.lpD3DHALCallbacks2
= (ULONG_PTR
)&d3d_hal_cbs2
;
130 if (d3d_hal_data
.hwCaps
.dwFlags
& D3DDD_WINE_OPENGL_DEVICE
) {
131 /*GL_DirectDraw_Init(&dd_gbl);*/
138 static DDHALDDRAWFNS hal_funcs
= {
139 sizeof(DDHALDDRAWFNS
),
141 NULL
, /* VidMemAlloc */
142 NULL
/* VidMemFree */
145 /* Called from DllInit, which is synchronised so there are no threading
147 static BOOL
initialize(void)
150 INT ncmd
= DCICOMMAND
;
152 HDC dc
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
153 INT ver
= Escape(dc
, QUERYESCSUPPORT
, sizeof(ncmd
), (LPVOID
)&ncmd
, NULL
);
154 if (ver
!= DD_HAL_VERSION
) {
156 TRACE("DirectDraw HAL not available\n");
159 cmd
.dwVersion
= DD_VERSION
;
162 /* the DDNEWCALLBACKFNS is supposed to give the 16-bit driver entry points
163 * in ddraw16.dll, but since Wine doesn't have or use 16-bit display drivers,
164 * we'll just work in 32-bit, who'll notice... */
165 cmd
.dwCommand
= DDNEWCALLBACKFNS
;
166 cmd
.dwParam1
= (DWORD
)&hal_funcs
;
167 ExtEscape(dc
, DCICOMMAND
, sizeof(cmd
), (LPVOID
)&cmd
, 0, NULL
);
169 /* next, exchange version information */
170 cmd
.dwCommand
= DDVERSIONINFO
;
171 cmd
.dwParam1
= DD_RUNTIME_VERSION
; /* not sure what should *really* go here */
172 ExtEscape(dc
, DCICOMMAND
, sizeof(cmd
), (LPVOID
)&cmd
, sizeof(hal_version
), (LPVOID
)&hal_version
);
174 /* get 32-bit driver data (dll name and entry point) */
175 cmd
.dwCommand
= DDGET32BITDRIVERNAME
;
176 ExtEscape(dc
, DCICOMMAND
, sizeof(cmd
), (LPVOID
)&cmd
, sizeof(hal_driverdata
), (LPVOID
)&hal_driverdata
);
177 /* we're supposed to load the DLL in hal_driverdata.szName, then GetProcAddress
178 * the hal_driverdata.szEntryPoint, and call it with hal_driverdata.dwContext
179 * as a parameter... but since this is only more remains from the 16-bit world,
182 /* finally, initialize the driver object */
183 cmd
.dwCommand
= DDCREATEDRIVEROBJECT
;
184 ret
= ExtEscape(dc
, DCICOMMAND
, sizeof(cmd
), (LPVOID
)&cmd
, sizeof(hal_instance
), (LPVOID
)&hal_instance
);
186 /* the driver should have called our set_hal_info now */
187 if (!dd_gbl
.lpDDCBtmp
) ret
= FALSE
;
193 TRACE("%s DirectDraw HAL\n", ret
? "enabling" : "disabling");
198 static void cleanup(void)
200 DDHAL_DESTROYDRIVERDATA data
;
203 data
.DestroyDriver
= dd_cbs
.HALDD
.DestroyDriver
;
204 data
.DestroyDriver(&data
);
207 static DWORD
choose_mode(DWORD dwWidth
, DWORD dwHeight
, DWORD dwBPP
,
208 DWORD dwRefreshRate
, DWORD dwFlags
)
213 if (!dd_gbl
.dwNumModes
) return 0;
215 /* let's support HALs that cannot switch depths (XVidMode),
216 * these should return dwBPP == 0 for all their resolutions */
217 #define BPP_MATCH(dd, bpp) ((!(dd)) || ((dd) == bpp))
219 /* FIXME: we should try to match the refresh rate too */
221 /* Choose the smallest mode that is large enough. */
222 for (i
=0; i
< dd_gbl
.dwNumModes
; i
++)
224 if (dd_gbl
.lpModeInfo
[i
].dwWidth
>= dwWidth
&&
225 dd_gbl
.lpModeInfo
[i
].dwHeight
>= dwHeight
&&
226 BPP_MATCH(dd_gbl
.lpModeInfo
[i
].dwBPP
, dwBPP
))
228 if (best
== -1) best
= i
;
231 if (dd_gbl
.lpModeInfo
[i
].dwWidth
< dd_gbl
.lpModeInfo
[best
].dwWidth
||
232 dd_gbl
.lpModeInfo
[i
].dwHeight
< dd_gbl
.lpModeInfo
[best
].dwHeight
)
240 TRACE("all modes too small\n");
241 /* ok, let's use the largest */
243 for (i
=0; i
< dd_gbl
.dwNumModes
; i
++)
245 if (BPP_MATCH(dd_gbl
.lpModeInfo
[i
].dwBPP
, dwBPP
))
247 if (best
== -1) best
= i
;
250 if (dd_gbl
.lpModeInfo
[i
].dwWidth
> dd_gbl
.lpModeInfo
[best
].dwWidth
||
251 dd_gbl
.lpModeInfo
[i
].dwHeight
> dd_gbl
.lpModeInfo
[best
].dwHeight
)
261 ERR("requested color depth (%ld) not available, try reconfiguring X server\n", dwBPP
);
262 return dd_gbl
.dwModeIndex
;
265 TRACE("using mode %d\n", best
);
270 static HRESULT
set_mode(IDirectDrawImpl
*This
, DWORD dwMode
)
274 if (dwMode
!= dd_gbl
.dwModeIndex
)
276 DDHAL_SETMODEDATA data
;
278 data
.dwModeIndex
= dwMode
;
280 data
.SetMode
= dd_cbs
.HALDD
.SetMode
;
282 data
.useRefreshRate
= FALSE
;
287 dd_gbl
.dwModeIndex
= dwMode
;
292 static HRESULT
set_exclusive_mode(IDirectDrawImpl
*This
, DWORD dwEnterExcl
)
294 DDHAL_SETEXCLUSIVEMODEDATA data
;
297 data
.dwEnterExcl
= dwEnterExcl
;
300 data
.SetExclusiveMode
= dd_cbs
.HALDD
.SetExclusiveMode
;
301 if (data
.SetExclusiveMode
)
302 data
.SetExclusiveMode(&data
);
306 BOOL
DDRAW_HAL_Init(HINSTANCE hInstDLL
, DWORD fdwReason
, LPVOID lpv
)
308 if (fdwReason
== DLL_PROCESS_ATTACH
)
311 DDRAW_register_driver(&hal_driver
);
313 else if (fdwReason
== DLL_PROCESS_DETACH
)
321 /* Not called from the vtable. */
322 HRESULT
HAL_DirectDraw_Construct(IDirectDrawImpl
*This
, BOOL ex
)
326 TRACE("(%p)\n", This
);
328 hr
= User_DirectDraw_Construct(This
, ex
);
329 if (FAILED(hr
)) return hr
;
331 This
->local
.lpGbl
= &dd_gbl
;
333 This
->final_release
= HAL_DirectDraw_final_release
;
334 This
->set_exclusive_mode
= set_exclusive_mode
;
336 This
->create_palette
= HAL_DirectDrawPalette_Create
;
338 This
->create_primary
= HAL_DirectDraw_create_primary
;
339 This
->create_backbuffer
= HAL_DirectDraw_create_backbuffer
;
340 This
->create_texture
= HAL_DirectDraw_create_texture
;
342 ICOM_INIT_INTERFACE(This
, IDirectDraw7
, HAL_DirectDraw_VTable
);
345 This
->caps
.dwCaps
|= dd_gbl
.ddCaps
.dwCaps
;
346 This
->caps
.dwCaps2
|= dd_gbl
.ddCaps
.dwCaps2
;
347 This
->caps
.dwCKeyCaps
|= dd_gbl
.ddCaps
.dwCKeyCaps
;
348 This
->caps
.dwFXCaps
|= dd_gbl
.ddCaps
.dwFXCaps
;
349 This
->caps
.dwPalCaps
|= dd_gbl
.ddCaps
.dwPalCaps
;
350 /* FIXME: merge more caps */
351 This
->caps
.ddsCaps
.dwCaps
|= dd_gbl
.ddCaps
.ddsCaps
.dwCaps
;
352 This
->caps
.ddsCaps
.dwCaps2
|= dd_gbl
.ddsCapsMore
.dwCaps2
;
353 This
->caps
.ddsCaps
.dwCaps3
|= dd_gbl
.ddsCapsMore
.dwCaps3
;
354 This
->caps
.ddsCaps
.dwCaps4
|= dd_gbl
.ddsCapsMore
.dwCaps4
;
355 This
->caps
.ddsOldCaps
.dwCaps
= This
->caps
.ddsCaps
.dwCaps
;
360 /* This function is called from DirectDrawCreate(Ex) on the most-derived
361 * class to start construction.
362 * Not called from the vtable. */
363 HRESULT
HAL_DirectDraw_Create(const GUID
* pGUID
, LPDIRECTDRAW7
* pIface
,
364 IUnknown
* pUnkOuter
, BOOL ex
)
367 IDirectDrawImpl
* This
;
371 assert(pUnkOuter
== NULL
);
373 This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
374 sizeof(IDirectDrawImpl
)
375 + sizeof(HAL_DirectDrawImpl
));
376 if (This
== NULL
) return E_OUTOFMEMORY
;
378 /* Note that this relation does *not* hold true if the DD object was
379 * CoCreateInstanced then Initialized. */
380 This
->private = (HAL_DirectDrawImpl
*)(This
+1);
382 hr
= HAL_DirectDraw_Construct(This
, ex
);
384 HeapFree(GetProcessHeap(), 0, This
);
386 *pIface
= ICOM_INTERFACE(This
, IDirectDraw7
);
391 /* This function is called from Uninit_DirectDraw_Initialize on the
392 * most-derived-class to start initialization.
393 * Not called from the vtable. */
394 HRESULT
HAL_DirectDraw_Initialize(IDirectDrawImpl
*This
, const GUID
* guid
)
400 This
->private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
401 sizeof(HAL_DirectDrawImpl
));
402 if (This
->private == NULL
) return E_OUTOFMEMORY
;
404 hr
= HAL_DirectDraw_Construct(This
, TRUE
); /* XXX ex? */
407 HeapFree(GetProcessHeap(), 0, This
->private);
414 /* Called from an internal function pointer. */
415 void HAL_DirectDraw_final_release(IDirectDrawImpl
*This
)
417 if (dd_gbl
.dwFlags
& DDRAWI_MODECHANGED
) set_mode(This
, dd_gbl
.dwModeIndexOrig
);
418 User_DirectDraw_final_release(This
);
421 HRESULT
HAL_DirectDraw_create_primary(IDirectDrawImpl
* This
,
422 const DDSURFACEDESC2
* pDDSD
,
423 LPDIRECTDRAWSURFACE7
* ppSurf
,
426 if (This
->cooperative_level
& DDSCL_EXCLUSIVE
)
427 return HAL_DirectDrawSurface_Create(This
, pDDSD
, ppSurf
, pUnkOuter
);
429 return User_DirectDrawSurface_Create(This
, pDDSD
, ppSurf
, pUnkOuter
);
432 HRESULT
HAL_DirectDraw_create_backbuffer(IDirectDrawImpl
* This
,
433 const DDSURFACEDESC2
* pDDSD
,
434 LPDIRECTDRAWSURFACE7
* ppSurf
,
436 IDirectDrawSurfaceImpl
* primary
)
438 if (This
->cooperative_level
& DDSCL_EXCLUSIVE
)
439 return HAL_DirectDrawSurface_Create(This
, pDDSD
, ppSurf
, pUnkOuter
);
441 return User_DirectDrawSurface_Create(This
, pDDSD
, ppSurf
, pUnkOuter
);
444 HRESULT
HAL_DirectDraw_create_texture(IDirectDrawImpl
* This
,
445 const DDSURFACEDESC2
* pDDSD
,
446 LPDIRECTDRAWSURFACE7
* ppSurf
,
450 return HAL_DirectDrawSurface_Create(This
, pDDSD
, ppSurf
, pOuter
);
454 HAL_DirectDraw_GetDeviceIdentifier(LPDIRECTDRAW7 iface
,
455 LPDDDEVICEIDENTIFIER2 pDDDI
,
463 HAL_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface
)
465 ICOM_THIS(IDirectDrawImpl
, iface
);
468 TRACE("(%p)\n", iface
);
470 if (!(dd_gbl
.dwFlags
& DDRAWI_MODECHANGED
)) return DD_OK
;
472 hr
= Main_DirectDraw_RestoreDisplayMode(iface
);
474 hr
= set_mode(This
, dd_gbl
.dwModeIndexOrig
);
475 if (SUCCEEDED(hr
)) dd_gbl
.dwFlags
&= ~DDRAWI_MODECHANGED
;
482 HAL_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface
, DWORD dwWidth
,
483 DWORD dwHeight
, DWORD dwBPP
,
484 DWORD dwRefreshRate
, DWORD dwFlags
)
486 ICOM_THIS(IDirectDrawImpl
, iface
);
490 TRACE("(%p)->(%ldx%ldx%ld,%ld Hz,%08lx)\n",This
,dwWidth
,dwHeight
,dwBPP
,dwRefreshRate
,dwFlags
);
491 hr
= User_DirectDraw_SetDisplayMode(iface
, dwWidth
, dwHeight
, dwBPP
,
492 dwRefreshRate
, dwFlags
);
495 if (!(dd_gbl
.dwFlags
& DDRAWI_MODECHANGED
)) dd_gbl
.dwModeIndexOrig
= dd_gbl
.dwModeIndex
;
496 hr
= set_mode(This
, choose_mode(dwWidth
, dwHeight
, dwBPP
, dwRefreshRate
, dwFlags
));
497 if (SUCCEEDED(hr
)) dd_gbl
.dwFlags
|= DDRAWI_MODECHANGED
;
503 static ICOM_VTABLE(IDirectDraw7
) HAL_DirectDraw_VTable
=
505 Main_DirectDraw_QueryInterface
,
506 Main_DirectDraw_AddRef
,
507 Main_DirectDraw_Release
,
508 Main_DirectDraw_Compact
,
509 Main_DirectDraw_CreateClipper
,
510 Main_DirectDraw_CreatePalette
,
511 Main_DirectDraw_CreateSurface
,
512 Main_DirectDraw_DuplicateSurface
,
513 User_DirectDraw_EnumDisplayModes
,
514 Main_DirectDraw_EnumSurfaces
,
515 Main_DirectDraw_FlipToGDISurface
,
516 Main_DirectDraw_GetCaps
,
517 Main_DirectDraw_GetDisplayMode
,
518 Main_DirectDraw_GetFourCCCodes
,
519 Main_DirectDraw_GetGDISurface
,
520 Main_DirectDraw_GetMonitorFrequency
,
521 Main_DirectDraw_GetScanLine
,
522 Main_DirectDraw_GetVerticalBlankStatus
,
523 Main_DirectDraw_Initialize
,
524 HAL_DirectDraw_RestoreDisplayMode
,
525 Main_DirectDraw_SetCooperativeLevel
,
526 HAL_DirectDraw_SetDisplayMode
,
527 Main_DirectDraw_WaitForVerticalBlank
,
528 Main_DirectDraw_GetAvailableVidMem
,
529 Main_DirectDraw_GetSurfaceFromDC
,
530 Main_DirectDraw_RestoreAllSurfaces
,
531 Main_DirectDraw_TestCooperativeLevel
,
532 HAL_DirectDraw_GetDeviceIdentifier
,
533 Main_DirectDraw_StartModeTest
,
534 Main_DirectDraw_EvaluateMode