2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS ReactX
4 * FILE: dll/directx/d3d9/adapter.c
5 * PURPOSE: d3d9.dll adapter info functions
6 * PROGRAMERS: Gregor Brunmar <gregor (dot) brunmar (at) home (dot) se>
9 //#define _WIN32_WINNT 0x0502
10 #include "d3d9_common.h"
15 #include "d3d9_private.h"
16 #include "d3d9_helpers.h"
19 #define D3D9_CAPS1 (D3DCAPS_READ_SCANLINE)
20 #define D3D9_PRE_XP_CAPS2 (D3DCAPS2_CANAUTOGENMIPMAP | D3DCAPS2_DYNAMICTEXTURES | D3DCAPS2_RESERVED | D3DCAPS2_FULLSCREENGAMMA)
21 #define D3D9_XP_OR_LATER_CAPS2 (D3D9_PRE_XP_CAPS2 | D3DCAPS2_CANMANAGERESOURCE)
22 #define D3D9_CAPS3 (D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD | D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION | D3DCAPS3_COPY_TO_VIDMEM | D3DCAPS3_COPY_TO_SYSTEMMEM)
23 #define D3D9_DEVCAPS (D3DDEVCAPS_EXECUTESYSTEMMEMORY | D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY \
24 | D3DDEVCAPS_TLVERTEXVIDEOMEMORY | D3DDEVCAPS_TEXTURESYSTEMMEMORY | D3DDEVCAPS_TEXTUREVIDEOMEMORY \
25 | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_TEXTURENONLOCALVIDMEM \
26 | D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_SEPARATETEXTUREMEMORIES | D3DDEVCAPS_DRAWPRIMITIVES2EX \
27 | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_CANBLTSYSTONONLOCAL | D3DDEVCAPS_HWRASTERIZATION \
28 | D3DDEVCAPS_PUREDEVICE | D3DDEVCAPS_QUINTICRTPATCHES | D3DDEVCAPS_RTPATCHES | D3DDEVCAPS_RTPATCHHANDLEZERO \
29 | D3DDEVCAPS_NPATCHES)
31 #define D3DCAPS2_PRESENT_INTERVAL_SEVERAL 0x00200000
32 #define D3DCAPS2_PRESENT_INTERVAL_IMMEDIATE 0x00400000
34 #define D3DVTXPCAPS_FOGVERTEX 0x00000004
36 typedef BOOL (WINAPI
*LPFN_ISWOW64PROCESS
) (HANDLE
, PBOOL
);
37 typedef BOOL (WINAPI
*LPFN_DISABLEWOW64FSREDIRECTION
) (PVOID
*);
38 typedef BOOL (WINAPI
*LPFN_REVERTWOW64FSREDIRECTION
) (PVOID
);
41 typedef struct _ADAPTERMONITOR
43 LPCSTR lpszDeviceName
;
45 } ADAPTERMONITOR
, *LPADAPTERMONITOR
;
48 static BOOL
GetDriverName(LPDISPLAY_DEVICEA pDisplayDevice
, D3DADAPTER_IDENTIFIER9
* pIdentifier
)
53 if (ERROR_SUCCESS
== RegOpenKeyExA(HKEY_LOCAL_MACHINE
, pDisplayDevice
->DeviceKey
+ strlen("\\Registry\\Machine\\"), 0, KEY_QUERY_VALUE
, &hKey
))
55 DWORD DriverNameLength
= MAX_DEVICE_IDENTIFIER_STRING
- (DWORD
)strlen(".dll");
58 if (ERROR_SUCCESS
== RegQueryValueExA(hKey
, "InstalledDisplayDrivers", 0, &Type
, (LPBYTE
)pIdentifier
->Driver
, &DriverNameLength
))
60 pIdentifier
->Driver
[DriverNameLength
] = '\0';
61 SafeAppendString(pIdentifier
->Driver
, MAX_DEVICE_IDENTIFIER_STRING
, ".dll");
71 static void GetDriverVersion(LPDISPLAY_DEVICEA pDisplayDevice
, D3DADAPTER_IDENTIFIER9
* pIdentifier
)
74 LPFN_ISWOW64PROCESS fnIsWow64Process
;
75 BOOL bIsWow64
= FALSE
;
76 PVOID OldWow64RedirectValue
;
79 hModule
= GetModuleHandleA("KERNEL32");
80 fnIsWow64Process
= (LPFN_ISWOW64PROCESS
)GetProcAddress(hModule
, "IsWow64Process");
83 fnIsWow64Process(GetCurrentProcess(), &bIsWow64
);
86 LPFN_DISABLEWOW64FSREDIRECTION fnDisableWow64FsRedirection
;
87 fnDisableWow64FsRedirection
= (LPFN_DISABLEWOW64FSREDIRECTION
)GetProcAddress(hModule
, "Wow64DisableWow64FsRedirection");
88 fnDisableWow64FsRedirection(&OldWow64RedirectValue
);
92 DriverFileSize
= GetFileVersionInfoSizeA(pIdentifier
->Driver
, NULL
);
93 if (DriverFileSize
> 0)
95 VS_FIXEDFILEINFO
* FixedFileInfo
= NULL
;
96 LPVOID pBlock
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, DriverFileSize
);
98 if (TRUE
== GetFileVersionInfoA(pIdentifier
->Driver
, 0, DriverFileSize
, pBlock
))
100 if (TRUE
== VerQueryValueA(pBlock
, "\\", (LPVOID
*)&FixedFileInfo
, &DriverFileSize
))
102 pIdentifier
->DriverVersion
.HighPart
= FixedFileInfo
->dwFileVersionMS
;
103 pIdentifier
->DriverVersion
.LowPart
= FixedFileInfo
->dwFileVersionLS
;
107 HeapFree(GetProcessHeap(), 0, pBlock
);
112 LPFN_REVERTWOW64FSREDIRECTION fnRevertWow64FsRedirection
;
113 fnRevertWow64FsRedirection
= (LPFN_REVERTWOW64FSREDIRECTION
)GetProcAddress(hModule
, "Wow64RevertWow64FsRedirection");
114 fnRevertWow64FsRedirection(&OldWow64RedirectValue
);
119 static void ParseField(LPCSTR lpszDeviceKey
, LPDWORD pField
, LPCSTR lpszSubString
)
121 const char* ResultStr
;
122 ResultStr
= strstr(lpszDeviceKey
, lpszSubString
);
123 if (ResultStr
!= NULL
)
125 *pField
= strtol(ResultStr
+ strlen(lpszSubString
), NULL
, 16);
129 static void GetDeviceId(LPCSTR lpszDeviceKey
, D3DADAPTER_IDENTIFIER9
* pIdentifier
)
131 ParseField(lpszDeviceKey
, &pIdentifier
->VendorId
, "VEN_");
132 ParseField(lpszDeviceKey
, &pIdentifier
->DeviceId
, "DEV_");
133 ParseField(lpszDeviceKey
, &pIdentifier
->SubSysId
, "SUBSYS_");
134 ParseField(lpszDeviceKey
, &pIdentifier
->Revision
, "REV_");
137 static void GenerateDeviceIdentifier(D3DADAPTER_IDENTIFIER9
* pIdentifier
)
139 DWORD
* dwIdentifier
= (DWORD
*)&pIdentifier
->DeviceIdentifier
;
141 pIdentifier
->DeviceIdentifier
= CLSID_DirectDraw
;
143 dwIdentifier
[0] ^= pIdentifier
->VendorId
;
144 dwIdentifier
[1] ^= pIdentifier
->DeviceId
;
145 dwIdentifier
[2] ^= pIdentifier
->SubSysId
;
146 dwIdentifier
[3] ^= pIdentifier
->Revision
;
147 dwIdentifier
[2] ^= pIdentifier
->DriverVersion
.LowPart
;
148 dwIdentifier
[3] ^= pIdentifier
->DriverVersion
.HighPart
;
151 BOOL
GetAdapterInfo(LPCSTR lpszDeviceName
, D3DADAPTER_IDENTIFIER9
* pIdentifier
)
153 DISPLAY_DEVICEA DisplayDevice
;
155 BOOL FoundDisplayDevice
;
157 memset(&DisplayDevice
, 0, sizeof(DISPLAY_DEVICEA
));
158 DisplayDevice
.cb
= sizeof(DISPLAY_DEVICEA
);
161 FoundDisplayDevice
= FALSE
;
162 while (EnumDisplayDevicesA(NULL
, AdapterIndex
, &DisplayDevice
, 0) == TRUE
)
164 if (_stricmp(lpszDeviceName
, DisplayDevice
.DeviceName
) == 0)
166 FoundDisplayDevice
= TRUE
;
173 /* No matching display device found? */
174 if (FALSE
== FoundDisplayDevice
)
177 lstrcpynA(pIdentifier
->Description
, DisplayDevice
.DeviceString
, MAX_DEVICE_IDENTIFIER_STRING
);
178 lstrcpynA(pIdentifier
->DeviceName
, DisplayDevice
.DeviceName
, CCHDEVICENAME
);
180 if (GetDriverName(&DisplayDevice
, pIdentifier
) == TRUE
)
181 GetDriverVersion(&DisplayDevice
, pIdentifier
);
183 GetDeviceId(DisplayDevice
.DeviceID
, pIdentifier
);
185 GenerateDeviceIdentifier(pIdentifier
);
192 static BOOL
IsWindowsXPorLaterCompatible()
196 ZeroMemory(&osvi
, sizeof(OSVERSIONINFOA
));
197 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
199 if (GetVersionExA(&osvi
) != 0)
201 return ( (osvi
.dwMajorVersion
> 5) ||
202 ( (osvi
.dwMajorVersion
== 5) && (osvi
.dwMinorVersion
>= 1) ));
208 static void CopyDriverCaps(const D3DCAPS9
* pSrcCaps
, D3DCAPS9
* pDstCaps
)
210 *pDstCaps
= *pSrcCaps
;
212 pDstCaps
->Caps
= pSrcCaps
->Caps
& D3D9_CAPS1
;
214 /* TODO: Fit in D3DCAPS2_CANCALIBRATEGAMMA somewhere here */
215 if (IsWindowsXPorLaterCompatible())
216 pDstCaps
->Caps2
= pSrcCaps
->Caps2
& D3D9_XP_OR_LATER_CAPS2
;
218 pDstCaps
->Caps2
= pSrcCaps
->Caps2
& D3D9_PRE_XP_CAPS2
;
220 pDstCaps
->Caps3
= pSrcCaps
->Caps3
& D3D9_CAPS3
;
221 pDstCaps
->DevCaps
= pSrcCaps
->DevCaps
& D3D9_DEVCAPS
;
223 pDstCaps
->PresentationIntervals
= D3DPRESENT_INTERVAL_ONE
;
224 if (pSrcCaps
->Caps2
& D3DCAPS2_PRESENT_INTERVAL_SEVERAL
)
225 pDstCaps
->PresentationIntervals
|= (D3DPRESENT_INTERVAL_TWO
| D3DPRESENT_INTERVAL_THREE
| D3DPRESENT_INTERVAL_FOUR
);
226 if (pSrcCaps
->Caps2
& D3DCAPS2_PRESENT_INTERVAL_IMMEDIATE
)
227 pDstCaps
->PresentationIntervals
|= D3DPRESENT_INTERVAL_IMMEDIATE
;
229 pDstCaps
->PrimitiveMiscCaps
= pSrcCaps
->PrimitiveMiscCaps
& ~D3DPMISCCAPS_FOGINFVF
;
231 if (pSrcCaps
->VertexProcessingCaps
& D3DVTXPCAPS_FOGVERTEX
)
233 pDstCaps
->RasterCaps
|= D3DPRASTERCAPS_FOGVERTEX
;
234 pDstCaps
->VertexProcessingCaps
&= ~D3DVTXPCAPS_FOGVERTEX
;
237 if (pSrcCaps
->MaxPointSize
< 0.0f
)
238 pDstCaps
->MaxPointSize
= 1.0f
;
241 HRESULT
GetAdapterCaps(const LPDIRECT3D9_DISPLAYADAPTER pDisplayAdapter
, D3DDEVTYPE DeviceType
, D3DCAPS9
* pDstCaps
)
243 HRESULT hResult
= D3DERR_INVALIDDEVICE
;
244 D3DCAPS9
* pDriverCaps
= NULL
;
246 ZeroMemory(pDstCaps
, sizeof(D3DCAPS9
));
251 pDriverCaps
= &pDisplayAdapter
->DriverCaps
.DriverCaps9
;
257 case D3DDEVTYPE_NULLREF
:
263 DPRINT1("Unknown DeviceType argument");
267 if (pDriverCaps
!= NULL
)
269 CopyDriverCaps(pDriverCaps
, pDstCaps
);
272 if (SUCCEEDED(hResult
))
274 pDstCaps
->DeviceType
= DeviceType
;
275 pDstCaps
->MasterAdapterOrdinal
= pDisplayAdapter
->MasterAdapterIndex
;
276 pDstCaps
->AdapterOrdinalInGroup
= pDisplayAdapter
->AdapterIndexInGroup
;
277 pDstCaps
->NumberOfAdaptersInGroup
= pDisplayAdapter
->NumAdaptersInGroup
;
285 static D3DFORMAT
Get16BitD3DFormat(LPCSTR lpszDeviceName
)
289 LPBITMAPINFO pBitmapInfo
;
290 D3DFORMAT Format
= D3DFMT_R5G6B5
;
292 if (NULL
== (hDC
= CreateDCA(NULL
, lpszDeviceName
, NULL
, NULL
)))
297 if (NULL
== (hBitmap
= CreateCompatibleBitmap(hDC
, 1, 1)))
303 pBitmapInfo
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(BITMAPINFOHEADER
) + 4 * sizeof(RGBQUAD
));
304 if (NULL
== pBitmapInfo
)
306 DeleteObject(hBitmap
);
311 pBitmapInfo
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
312 if (GetDIBits(hDC
, hBitmap
, 0, 0, NULL
, pBitmapInfo
, DIB_RGB_COLORS
) > 0)
314 if (pBitmapInfo
->bmiHeader
.biCompression
== BI_BITFIELDS
)
316 if (GetDIBits(hDC
, hBitmap
, 0, pBitmapInfo
->bmiHeader
.biHeight
, NULL
, pBitmapInfo
, DIB_RGB_COLORS
) > 0)
318 /* Check if the green field is 6 bits long */
319 if (*(DWORD
*)(&pBitmapInfo
->bmiColors
[1]) == 0x000003E0)
321 Format
= D3DFMT_X1R5G5B5
;
327 HeapFree(GetProcessHeap(), 0, pBitmapInfo
);
328 DeleteObject(hBitmap
);
334 BOOL
GetAdapterMode(LPCSTR lpszDeviceName
, D3DDISPLAYMODE
* pMode
)
338 memset(&DevMode
, 0, sizeof(DEVMODEA
));
339 DevMode
.dmSize
= sizeof(DEVMODEA
);
340 if (FALSE
== EnumDisplaySettingsA(lpszDeviceName
, ENUM_CURRENT_SETTINGS
, &DevMode
))
343 pMode
->Width
= DevMode
.dmPelsWidth
;
344 pMode
->Height
= DevMode
.dmPelsHeight
;
345 pMode
->RefreshRate
= DevMode
.dmDisplayFrequency
;
347 switch (DevMode
.dmBitsPerPel
)
350 pMode
->Format
= D3DFMT_P8
;
354 pMode
->Format
= Get16BitD3DFormat(lpszDeviceName
);
358 pMode
->Format
= D3DFMT_R8G8B8
;
362 pMode
->Format
= D3DFMT_X8R8G8B8
;
366 pMode
->Format
= D3DFMT_UNKNOWN
;
375 static BOOL CALLBACK
AdapterMonitorEnumProc(HMONITOR hMonitor
, HDC hdcMonitor
, LPRECT lprcMonitor
, LPARAM dwData
)
377 MONITORINFOEXA MonitorInfoEx
;
378 LPADAPTERMONITOR lpAdapterMonitor
= (LPADAPTERMONITOR
)dwData
;
380 memset(&MonitorInfoEx
, 0, sizeof(MONITORINFOEXA
));
381 MonitorInfoEx
.cbSize
= sizeof(MONITORINFOEXA
);
383 GetMonitorInfoA(hMonitor
, (LPMONITORINFO
)&MonitorInfoEx
);
385 if (_stricmp(lpAdapterMonitor
->lpszDeviceName
, MonitorInfoEx
.szDevice
) == 0)
387 lpAdapterMonitor
->hMonitor
= hMonitor
;
394 HMONITOR
GetAdapterMonitor(LPCSTR lpszDeviceName
)
396 ADAPTERMONITOR AdapterMonitor
;
397 AdapterMonitor
.lpszDeviceName
= lpszDeviceName
;
398 AdapterMonitor
.hMonitor
= NULL
;
400 EnumDisplayMonitors(NULL
, NULL
, AdapterMonitorEnumProc
, (LPARAM
)&AdapterMonitor
);
402 return AdapterMonitor
.hMonitor
;
407 UINT
GetDisplayFormatCount(D3DFORMAT Format
, const D3DDISPLAYMODE
* pSupportedDisplayModes
, UINT NumDisplayModes
)
409 UINT DisplayModeIndex
;
410 UINT FormatIndex
= 0;
412 for (DisplayModeIndex
= 0; DisplayModeIndex
< NumDisplayModes
; DisplayModeIndex
++)
414 if (pSupportedDisplayModes
[DisplayModeIndex
].Format
== Format
)
423 const D3DDISPLAYMODE
* FindDisplayFormat(D3DFORMAT Format
, UINT ModeIndex
, const D3DDISPLAYMODE
* pSupportedDisplayModes
, UINT NumDisplayModes
)
425 UINT DisplayModeIndex
;
426 UINT FormatIndex
= 0;
428 for (DisplayModeIndex
= 0; DisplayModeIndex
< NumDisplayModes
; DisplayModeIndex
++)
430 if (pSupportedDisplayModes
[DisplayModeIndex
].Format
== Format
)
432 if (ModeIndex
== FormatIndex
)
433 return &pSupportedDisplayModes
[DisplayModeIndex
];
439 if (FormatIndex
== 0)
441 DPRINT1("No modes with the specified format found");
443 else if (FormatIndex
< ModeIndex
)
445 DPRINT1("Invalid mode index");