xref: /reactos/dll/directx/d3d9/d3d9_caps.c (revision 9393fc32)
1 #include <d3d9.h>
2 #include <ddraw.h>
3 #include <d3dnthal.h>
4 #include <d3dhal.h>
5 #include <ddrawi.h>
6 #include <ddrawgdi.h>
7 #include <dll/directx/d3d8thk.h>
8 #include <debug.h>
9 #include <limits.h>
10 #include "d3d9_helpers.h"
11 #include "d3d9_caps.h"
12 #include "adapter.h"
13 #include "d3d9_callbacks.h"
14 
15 static INT g_NumDevices = 0;
16 
CreateDisplayModeList(LPCSTR lpszDeviceName,D3DDISPLAYMODE * pDisplayModes,DWORD * pNumDisplayModes,D3DFORMAT Default16BitFormat,D3D9_Unknown6BC * pUnknown6BC)17 void CreateDisplayModeList(LPCSTR lpszDeviceName, D3DDISPLAYMODE* pDisplayModes, DWORD* pNumDisplayModes, D3DFORMAT Default16BitFormat, D3D9_Unknown6BC* pUnknown6BC)
18 {
19     DEVMODEA DevMode;
20     DWORD ModeIndex = 0;
21     DWORD ValidModes = 0;
22 
23     while (TRUE == EnumDisplaySettingsA(lpszDeviceName, ModeIndex, &DevMode))
24     {
25         D3DFORMAT DefaultFormat;
26 
27         if (DevMode.dmBitsPerPel != 15 &&
28             DevMode.dmBitsPerPel != 16 &&
29             DevMode.dmBitsPerPel != 32)
30         {
31             ++ModeIndex;
32             continue;
33         }
34 
35         ++ValidModes;
36 
37         if (DevMode.dmBitsPerPel == 15 || DevMode.dmBitsPerPel == 16)
38         {
39             if (NULL == pUnknown6BC)
40             {
41                 ++ModeIndex;
42                 continue;
43             }
44 
45             DefaultFormat = Default16BitFormat;
46         }
47         else
48         {
49             DefaultFormat = D3DFMT_X8R8G8B8;
50         }
51 
52         if (NULL != pDisplayModes)
53         {
54             if (ValidModes == *pNumDisplayModes)
55                 break;
56 
57             pDisplayModes->Width = DevMode.dmPelsWidth;
58             pDisplayModes->Height = DevMode.dmPelsHeight;
59             pDisplayModes->RefreshRate = DevMode.dmDisplayFrequency;
60             pDisplayModes->Format = DefaultFormat;
61             ++pDisplayModes;
62         }
63 
64         ++ModeIndex;
65     }
66 
67     *pNumDisplayModes = ValidModes;
68 }
69 
CreateInternalDeviceData(HDC hDC,LPCSTR lpszDeviceName,D3D9_Unknown6BC ** ppUnknown,D3DDEVTYPE DeviceType,HMODULE * hD3DRefDll)70 static void CreateInternalDeviceData(HDC hDC, LPCSTR lpszDeviceName, D3D9_Unknown6BC** ppUnknown, D3DDEVTYPE DeviceType, HMODULE* hD3DRefDll)
71 {
72     D3D9_Unknown6BC* pUnknown6BC;
73     DWORD ValueSize;
74 
75     if (ppUnknown) *ppUnknown = NULL;
76     if (hD3DRefDll) *hD3DRefDll = NULL;
77 
78     if (DeviceType != D3DDEVTYPE_HAL)
79     {
80         /* TODO: Implement D3DDEVTYPE_REF and D3DDEVTYPE_SW */
81         UNIMPLEMENTED;
82         return;
83     }
84 
85     pUnknown6BC = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3D9_Unknown6BC));
86     if (NULL == pUnknown6BC)
87     {
88         DPRINT1("Out of memory");
89         return;
90     }
91 
92     pUnknown6BC->hDirectDrawLocal = OsThunkDdCreateDirectDrawObject(hDC);
93     if (0 == pUnknown6BC->hDirectDrawLocal)
94     {
95         HeapFree(GetProcessHeap(), 0, pUnknown6BC);
96         return;
97     }
98 
99 
100     SafeCopyString(pUnknown6BC->szDeviceName, CCHDEVICENAME, lpszDeviceName);
101     //pUnknown6BC->DeviceUniq = DdQueryDisplaySettingsUniqueness();
102     pUnknown6BC->DeviceType = DeviceType;
103 
104 
105     ValueSize = sizeof(DWORD);
106     ReadRegistryValue(REG_DWORD, "ForceDriverFlagsOn", (LPBYTE)&pUnknown6BC->bForceDriverFlagsOn, &ValueSize);
107 
108     ValueSize = sizeof(DWORD);
109     ReadRegistryValue(REG_DWORD, "ForceDriverFlagsOff", (LPBYTE)&pUnknown6BC->bForceDriverFlagsOff, &ValueSize);
110 
111     ++g_NumDevices;
112 
113     *ppUnknown = pUnknown6BC;
114 }
115 
ReleaseInternalDeviceData(LPD3D9_DEVICEDATA pDeviceData)116 static void ReleaseInternalDeviceData(LPD3D9_DEVICEDATA pDeviceData)
117 {
118     OsThunkDdDeleteDirectDrawObject(pDeviceData->pUnknown6BC->hDirectDrawLocal);
119 
120     HeapFree(GetProcessHeap(), 0, pDeviceData->pUnknown6BC);
121     pDeviceData->pUnknown6BC = NULL;
122 
123     --g_NumDevices;
124 }
125 
GetDeviceData(LPD3D9_DEVICEDATA pDeviceData)126 BOOL GetDeviceData(LPD3D9_DEVICEDATA pDeviceData)
127 {
128     BOOL bRet;
129     D3DHAL_GLOBALDRIVERDATA GlobalDriverData;
130     D3DHAL_D3DEXTENDEDCAPS D3dExtendedCaps;
131     LPDDSURFACEDESC puD3dTextureFormats;
132     DDPIXELFORMAT* pD3dZStencilFormatList;
133     D3DDISPLAYMODE* pD3dDisplayModeList;
134     D3DQUERYTYPE* pD3dQueryList;
135     DWORD NumTextureFormats = 0;
136     DWORD NumStencilFormats = 0;
137     DWORD NumExtendedFormats = 0;
138     DWORD NumQueries = 0;
139 
140     if (NULL == pDeviceData->pUnknown6BC)
141     {
142         CreateInternalDeviceData(
143             pDeviceData->hDC,
144             pDeviceData->szDeviceName,
145             &pDeviceData->pUnknown6BC,
146             pDeviceData->DeviceType,
147             &pDeviceData->hD3DRefDll
148             );
149 
150         if (NULL == pDeviceData->pUnknown6BC)
151         {
152             DPRINT1("Failed to create DirectDrawObject for Direct3D9");
153             return FALSE;
154         }
155     }
156     else
157     {
158         D3D9_DRIVERCAPS DriverCaps;
159         D3D9_CALLBACKS D3D9Callbacks;
160 
161         if (FALSE == CanReenableDirectDrawObject(pDeviceData->pUnknown6BC))
162         {
163             DPRINT1("Failed to re-enable DirectDrawObject");
164             return FALSE;
165         }
166 
167         bRet = GetD3D9DriverInfo(
168             pDeviceData->pUnknown6BC,
169             &DriverCaps,
170             &D3D9Callbacks,
171             pDeviceData->szDeviceName,
172             pDeviceData->hD3DRefDll,
173             &GlobalDriverData,
174             &D3dExtendedCaps,
175             NULL,
176             NULL,
177             NULL,
178             NULL,
179             &NumTextureFormats,
180             &NumStencilFormats,
181             &NumExtendedFormats,
182             &NumQueries
183             );
184 
185         if (TRUE == bRet)
186         {
187             pDeviceData->DriverCaps.dwDisplayWidth = DriverCaps.dwDisplayWidth;
188             pDeviceData->DriverCaps.dwDisplayHeight = DriverCaps.dwDisplayHeight;
189             pDeviceData->DriverCaps.RawDisplayFormat = DriverCaps.RawDisplayFormat;
190             pDeviceData->DriverCaps.DisplayFormat = DriverCaps.DisplayFormat;
191             pDeviceData->DriverCaps.dwRefreshRate = DriverCaps.dwRefreshRate;
192         }
193 
194         return bRet;
195     }
196 
197     /* Cleanup of old stuff */
198     if (pDeviceData->DriverCaps.pSupportedFormatOps)
199     {
200         HeapFree(GetProcessHeap(), 0, pDeviceData->DriverCaps.pSupportedFormatOps);
201         pDeviceData->DriverCaps.pSupportedFormatOps = NULL;
202     }
203     if (pDeviceData->DriverCaps.pSupportedExtendedModes)
204     {
205         HeapFree(GetProcessHeap(), 0, pDeviceData->DriverCaps.pSupportedExtendedModes);
206         pDeviceData->DriverCaps.pSupportedExtendedModes = NULL;
207     }
208     if (pDeviceData->DriverCaps.pSupportedQueriesList)
209     {
210         HeapFree(GetProcessHeap(), 0, pDeviceData->DriverCaps.pSupportedQueriesList);
211         pDeviceData->DriverCaps.pSupportedQueriesList = NULL;
212     }
213 
214     if (FALSE == CanReenableDirectDrawObject(pDeviceData->pUnknown6BC))
215     {
216         DPRINT1("Failed to re-enable DirectDrawObject");
217         ReleaseInternalDeviceData(pDeviceData);
218         return FALSE;
219     }
220 
221     bRet = GetD3D9DriverInfo(
222         pDeviceData->pUnknown6BC,
223         &pDeviceData->DriverCaps,
224         &pDeviceData->D3D9Callbacks,
225         pDeviceData->szDeviceName,
226         pDeviceData->hD3DRefDll,
227         &GlobalDriverData,
228         &D3dExtendedCaps,
229         NULL,
230         NULL,
231         NULL,
232         NULL,
233         &NumTextureFormats,
234         &NumStencilFormats,
235         &NumExtendedFormats,
236         &NumQueries
237         );
238 
239     if (FALSE == bRet)
240     {
241         DPRINT1("Could not query DirectDrawObject, aborting");
242         ReleaseInternalDeviceData(pDeviceData);
243         return FALSE;
244     }
245 
246     puD3dTextureFormats = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, max(NumTextureFormats, 1) * sizeof(DDSURFACEDESC));
247     pD3dZStencilFormatList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, max(NumStencilFormats, 1) * sizeof(DDPIXELFORMAT));
248     pD3dDisplayModeList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, max(NumExtendedFormats, 1) * sizeof(D3DDISPLAYMODE));
249     pD3dQueryList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, max(NumQueries, 1) * sizeof(D3DQUERYTYPE));
250 
251     bRet = GetD3D9DriverInfo(
252         pDeviceData->pUnknown6BC,
253         &pDeviceData->DriverCaps,
254         &pDeviceData->D3D9Callbacks,
255         pDeviceData->szDeviceName,
256         pDeviceData->hD3DRefDll,
257         &GlobalDriverData,
258         &D3dExtendedCaps,
259         puD3dTextureFormats,
260         pD3dZStencilFormatList,
261         pD3dDisplayModeList,
262         pD3dQueryList,
263         &NumTextureFormats,
264         &NumStencilFormats,
265         &NumExtendedFormats,
266         &NumQueries
267         );
268 
269     if (FALSE == bRet)
270     {
271         DPRINT1("Could not query DirectDrawObject, aborting");
272         HeapFree(GetProcessHeap(), 0, puD3dTextureFormats);
273         HeapFree(GetProcessHeap(), 0, pD3dZStencilFormatList);
274         HeapFree(GetProcessHeap(), 0, pD3dDisplayModeList);
275         HeapFree(GetProcessHeap(), 0, pD3dQueryList);
276         ReleaseInternalDeviceData(pDeviceData);
277         return FALSE;
278     }
279 
280     pDeviceData->DriverCaps.NumSupportedFormatOps = NumTextureFormats;
281     if (NumTextureFormats > 0)
282         pDeviceData->DriverCaps.pSupportedFormatOps = puD3dTextureFormats;
283 
284     pDeviceData->DriverCaps.NumSupportedExtendedModes = NumExtendedFormats;
285     if (NumExtendedFormats > 0)
286         pDeviceData->DriverCaps.pSupportedExtendedModes = pD3dDisplayModeList;
287 
288     pDeviceData->DriverCaps.NumSupportedQueries = NumQueries;
289     if (NumQueries > 0)
290         pDeviceData->DriverCaps.pSupportedQueriesList = pD3dQueryList;
291 
292     HeapFree(GetProcessHeap(), 0, pD3dZStencilFormatList);
293 
294     return TRUE;
295 }
296 
297 
298 
CanReenableDirectDrawObject(D3D9_Unknown6BC * pUnknown)299 BOOL CanReenableDirectDrawObject(D3D9_Unknown6BC* pUnknown)
300 {
301     BOOL bDisplayModeWasChanged;
302 
303     /* Try the real way first */
304     if (TRUE == OsThunkDdReenableDirectDrawObject(pUnknown->hDirectDrawLocal, &bDisplayModeWasChanged))
305         return TRUE;
306 
307     /* Ref types and software types can always be reenabled after a mode switch */
308     if (pUnknown->DeviceType == D3DDEVTYPE_REF || pUnknown->DeviceType == D3DDEVTYPE_SW)
309         return TRUE;
310 
311     return FALSE;
312 }
313 
314 
315 
PrepareDriverInfoData(DD_GETDRIVERINFODATA * DrvInfo,LPVOID pData,DWORD dwExpectedSize)316 static void PrepareDriverInfoData(DD_GETDRIVERINFODATA* DrvInfo, LPVOID pData, DWORD dwExpectedSize)
317 {
318     memset(DrvInfo, 0, sizeof(DD_GETDRIVERINFODATA));
319     DrvInfo->dwSize = sizeof(DD_GETDRIVERINFODATA);
320     DrvInfo->guidInfo = GUID_GetDriverInfo2;
321     DrvInfo->dwExpectedSize = dwExpectedSize;
322     DrvInfo->lpvData = pData;
323     DrvInfo->ddRVal = E_FAIL;
324 }
325 
ResetGetDriverInfo2Data(DD_GETDRIVERINFO2DATA * DrvInfo2,DWORD dwType,DWORD dwExpectedSize)326 static void ResetGetDriverInfo2Data(DD_GETDRIVERINFO2DATA* DrvInfo2, DWORD dwType, DWORD dwExpectedSize)
327 {
328     memset(DrvInfo2, 0, dwExpectedSize);
329     DrvInfo2->dwMagic = D3DGDI2_MAGIC;
330     DrvInfo2->dwType = dwType;
331     DrvInfo2->dwExpectedSize = dwExpectedSize;
332 }
333 
GetD3D9DriverInfo(D3D9_Unknown6BC * pUnknown6BC,LPD3D9_DRIVERCAPS pDriverCaps,D3D9_CALLBACKS * pD3D9Callbacks,LPCSTR lpszDeviceName,HMODULE hD3dRefDll,D3DHAL_GLOBALDRIVERDATA * pGblDriverData,D3DHAL_D3DEXTENDEDCAPS * pD3dExtendedCaps,LPDDSURFACEDESC puD3dTextureFormats,DDPIXELFORMAT * pD3dZStencilFormatList,D3DDISPLAYMODE * pD3dDisplayModeList,D3DQUERYTYPE * pD3dQueryList,LPDWORD pNumTextureFormats,LPDWORD pNumZStencilFormats,LPDWORD pNumExtendedFormats,LPDWORD pNumQueries)334 BOOL GetD3D9DriverInfo( D3D9_Unknown6BC* pUnknown6BC,
335                         LPD3D9_DRIVERCAPS pDriverCaps,
336                         D3D9_CALLBACKS* pD3D9Callbacks,
337                         LPCSTR lpszDeviceName,
338                         HMODULE hD3dRefDll,
339                         D3DHAL_GLOBALDRIVERDATA* pGblDriverData,
340                         D3DHAL_D3DEXTENDEDCAPS* pD3dExtendedCaps,
341                         LPDDSURFACEDESC puD3dTextureFormats,
342                         DDPIXELFORMAT* pD3dZStencilFormatList,
343                         D3DDISPLAYMODE* pD3dDisplayModeList,
344                         D3DQUERYTYPE* pD3dQueryList,
345                         LPDWORD pNumTextureFormats,
346                         LPDWORD pNumZStencilFormats,
347                         LPDWORD pNumExtendedFormats,
348                         LPDWORD pNumQueries)
349 {
350     BOOL bRet;
351     DWORD ValueSize;
352     DWORD dwDXVersion;
353 
354     DD_HALINFO HalInfo;
355     DWORD CallBackFlags[3];
356     D3DNTHAL_CALLBACKS D3dCallbacks;
357     D3DNTHAL_GLOBALDRIVERDATA D3dDriverData;
358     DD_D3DBUFCALLBACKS D3dBufferCallbacks;
359     DWORD NumHeaps = 0;
360     DWORD NumFourCC = 0;
361 
362     BOOL bDX8Mode = FALSE;
363 
364     DD_GETDRIVERINFODATA DrvInfo;
365     DD_GETDDIVERSIONDATA DdiVersion;
366     DD_GETFORMATCOUNTDATA FormatCountData;
367     DD_GETEXTENDEDMODECOUNTDATA ExModeCountData;
368     DD_GETD3DQUERYCOUNTDATA D3dQueryCountData;
369 
370     /* Init */
371     *pNumTextureFormats = 0;
372     *pNumZStencilFormats = 0;
373     *pNumExtendedFormats = 0;
374     *pNumQueries = 0;
375     memset(pD3dExtendedCaps, 0, sizeof(D3DHAL_D3DEXTENDEDCAPS));
376     memset(pGblDriverData, 0, sizeof(D3DHAL_GLOBALDRIVERDATA));
377     memset(pDriverCaps, 0, sizeof(D3D9_DRIVERCAPS));
378 
379     /* Set runtime version */
380     ValueSize = sizeof(dwDXVersion);
381     if (FALSE == ReadRegistryValue(REG_DWORD, "DD_RUNTIME_VERSION", (LPBYTE)&dwDXVersion, &ValueSize))
382         dwDXVersion = DD_RUNTIME_VERSION;
383 
384 
385     bRet = OsThunkDdQueryDirectDrawObject(
386         pUnknown6BC->hDirectDrawLocal,
387         &HalInfo,
388         CallBackFlags,
389         &D3dCallbacks,
390         &D3dDriverData,
391         &D3dBufferCallbacks,
392         NULL,
393         &NumHeaps,
394         NULL,
395         &NumFourCC,
396         NULL
397         );
398 
399     if (bRet == FALSE)
400     {
401         /* TODO: Handle error */
402         return FALSE;
403     }
404 
405     if ((HalInfo.ddCaps.dwSVBCaps2 & DDCAPS2_AUTOFLIPOVERLAY) == 0 &&
406         puD3dTextureFormats != NULL)
407     {
408         bRet = OsThunkDdQueryDirectDrawObject(
409             pUnknown6BC->hDirectDrawLocal,
410             &HalInfo,
411             CallBackFlags,
412             &D3dCallbacks,
413             &D3dDriverData,
414             &D3dBufferCallbacks,
415             puD3dTextureFormats,
416             &NumHeaps,
417             NULL,
418             &NumFourCC,
419             NULL
420             );
421 
422         if (FALSE == bRet)
423             return FALSE;
424     }
425 
426     if (NULL == pUnknown6BC->swDDICreateDirectDrawObject)
427     {
428         *pNumTextureFormats = D3dDriverData.dwNumTextureFormats;
429     }
430 
431     pDriverCaps->DriverCaps9.Caps = HalInfo.ddCaps.dwCaps;
432     pDriverCaps->DriverCaps9.Caps2 = HalInfo.ddCaps.dwCaps2;
433     pDriverCaps->DriverCaps9.Caps3 = HalInfo.ddCaps.dwSVCaps;
434     pDriverCaps->dwSVBCaps = HalInfo.ddCaps.dwSVBCaps;
435     pDriverCaps->dwVSBCaps = HalInfo.ddCaps.dwVSBCaps;
436     pDriverCaps->dwSVBCaps2 = HalInfo.ddCaps.dwSVBCaps2;
437     pUnknown6BC->lDisplayPitch = HalInfo.vmiData.lDisplayPitch;
438 
439     if (HalInfo.dwFlags & DDHALINFO_GETDRIVERINFO2)
440     {
441         /* GUID_GetDriverInfo2 - Inform driver of DX version */
442         {
443             DD_DXVERSION DxVersion;
444 
445             ResetGetDriverInfo2Data(&DxVersion.gdi2, D3DGDI2_TYPE_DXVERSION, sizeof(DD_DXVERSION));
446             DxVersion.dwDXVersion = dwDXVersion;
447 
448             PrepareDriverInfoData(&DrvInfo, &DxVersion, sizeof(DxVersion));
449             OsThunkDdGetDriverInfo(pUnknown6BC->hDirectDrawLocal, &DrvInfo);
450         }
451 
452 
453         /* GUID_GetDriverInfo2 - Get DDI version */
454         {
455             ResetGetDriverInfo2Data(&DdiVersion.gdi2, D3DGDI2_TYPE_GETDDIVERSION, sizeof(DD_GETDDIVERSIONDATA));
456             PrepareDriverInfoData(&DrvInfo, &DdiVersion, sizeof(DdiVersion));
457             bRet = OsThunkDdGetDriverInfo(pUnknown6BC->hDirectDrawLocal, &DrvInfo);
458 
459             if (DdiVersion.dwDDIVersion != DX9_DDI_VERSION)
460             {
461                 DWORD ForceDDIOn;
462 
463                 ValueSize = sizeof(ForceDDIOn);
464                 if (TRUE == ReadRegistryValue(REG_DWORD, "ForceOldDDIOn", (LPBYTE)&ForceDDIOn, &ValueSize) &&
465                     0 != ForceDDIOn)
466                 {
467                     DdiVersion.dwDDIVersion = DX9_DDI_VERSION;
468                 }
469             }
470         }
471 
472 
473         /* Check for errors to fallback to DX8 mode  */
474         if (DdiVersion.dwDDIVersion < DX9_DDI_VERSION)
475         {
476             bDX8Mode = TRUE;
477 
478             if (DdiVersion.dwDDIVersion == 0)
479             {
480                 DPRINT1("Driver claims to be DX9 driver, but didn't report DX9 DDI version - reverting to DX8 mode");
481             }
482             else
483             {
484                 DPRINT1("Driver claims to be DX9 driver, but was built with an old DDI version - reverting to DX8 mode");
485             }
486 
487             /* GUID_GetDriverInfo2 - Get D3DCAPS8 */
488             {
489                 D3DCAPS8 DriverCaps8;
490 
491                 ResetGetDriverInfo2Data((DD_GETDRIVERINFO2DATA*)&DriverCaps8, D3DGDI2_TYPE_GETD3DCAPS8, sizeof(D3DCAPS8));
492                 PrepareDriverInfoData(&DrvInfo, &DriverCaps8, sizeof(D3DCAPS8));
493 
494                 if (FALSE == OsThunkDdGetDriverInfo(pUnknown6BC->hDirectDrawLocal, &DrvInfo) ||
495                     S_OK != DrvInfo.ddRVal ||
496                     DrvInfo.dwActualSize != sizeof(D3DCAPS8))
497                 {
498                     DPRINT1("Driver returned an invalid D3DCAPS8 structure - aborting");
499                     return FALSE;
500                 }
501 
502                 memcpy(&pDriverCaps->DriverCaps9, &DriverCaps8, sizeof(D3DCAPS8));
503                 pDriverCaps->DriverCaps9.Caps = HalInfo.ddCaps.dwCaps;
504                 pDriverCaps->dwDriverCaps |= D3D9_INT_D3DCAPS8_VALID;
505             }
506         }
507 
508 
509         /* GUID_GetDriverInfo2 - Get D3DCAPS9 */
510         if (FALSE == bDX8Mode)
511         {
512             D3DCAPS9 DriverCaps9;
513 
514             ResetGetDriverInfo2Data((DD_GETDRIVERINFO2DATA*)&DriverCaps9, D3DGDI2_TYPE_GETD3DCAPS9, sizeof(D3DCAPS9));
515             PrepareDriverInfoData(&DrvInfo, &DriverCaps9, sizeof(D3DCAPS9));
516 
517             if (FALSE == OsThunkDdGetDriverInfo(pUnknown6BC->hDirectDrawLocal, &DrvInfo) ||
518                 S_OK != DrvInfo.ddRVal ||
519                 DrvInfo.dwActualSize != sizeof(D3DCAPS9))
520             {
521                 DPRINT1("Driver returned an invalid D3DCAPS9 structure - aborting");
522                 return FALSE;
523             }
524 
525             pDriverCaps->DriverCaps9 = DriverCaps9;
526             pDriverCaps->DriverCaps9.Caps = HalInfo.ddCaps.dwCaps;
527             pDriverCaps->dwDriverCaps |= D3D9_INT_D3DCAPS9_VALID;
528         }
529 
530 
531         /* GUID_GetDriverInfo2 - Get format count data */
532         {
533             ResetGetDriverInfo2Data(&FormatCountData.gdi2, D3DGDI2_TYPE_GETFORMATCOUNT, sizeof(DD_GETFORMATCOUNTDATA));
534             PrepareDriverInfoData(&DrvInfo, &FormatCountData, sizeof(DD_GETFORMATCOUNTDATA));
535             FormatCountData.dwFormatCount = UINT_MAX;
536             FormatCountData.dwReserved = dwDXVersion;
537 
538             if (TRUE == OsThunkDdGetDriverInfo(pUnknown6BC->hDirectDrawLocal, &DrvInfo))
539             {
540                 if (DrvInfo.ddRVal != S_OK)
541                 {
542                     DPRINT1("Driver claimed to be DX9 driver, but didn't support D3DGDI_TYPE_GETFORMATCOUNT in GetDriverInfo call");
543                     return FALSE;
544                 }
545                 else if (DrvInfo.dwActualSize != sizeof(DD_GETFORMATCOUNTDATA))
546                 {
547                     DPRINT1("Driver returned an invalid DD_GETFORMATCOUNTDATA structure - aborting");
548                     return FALSE;
549                 }
550                 else if (FormatCountData.dwFormatCount == UINT_MAX)
551                 {
552                     DPRINT1("Driver didn't set DD_GETFORMATCOUNTDATA.dwFormatCount - aborting");
553                     return FALSE;
554                 }
555 
556                 *pNumTextureFormats = FormatCountData.dwFormatCount;
557             }
558         }
559 
560         /* GUID_GetDriverInfo2 - Get format data */
561         if (puD3dTextureFormats != NULL)
562         {
563             DWORD FormatIndex;
564             DD_GETFORMATDATA FormatData;
565 
566             for (FormatIndex = 0; FormatIndex < FormatCountData.dwFormatCount; FormatIndex++)
567             {
568                 ResetGetDriverInfo2Data(&FormatData.gdi2, D3DGDI2_TYPE_GETFORMAT, sizeof(DD_GETFORMATDATA));
569                 PrepareDriverInfoData(&DrvInfo, &FormatData, sizeof(DD_GETFORMATDATA));
570                 FormatData.dwFormatIndex = FormatIndex;
571 
572                 if (TRUE == OsThunkDdGetDriverInfo(pUnknown6BC->hDirectDrawLocal, &DrvInfo))
573                 {
574                     if (DrvInfo.ddRVal != S_OK)
575                     {
576                         DPRINT1("Driver claimed to be DX9 driver, but didn't support D3DGDI_TYPE_GETFORMAT in GetDriverInfo call");
577                         return FALSE;
578                     }
579                     else if (DrvInfo.dwActualSize != sizeof(DD_GETFORMATDATA))
580                     {
581                         DPRINT1("Driver returned an invalid DD_GETFORMATDATA structure - aborting");
582                         return FALSE;
583                     }
584                     else if (FormatData.format.dwSize != sizeof(DDPIXELFORMAT))
585                     {
586                         DPRINT1("Driver didn't set DD_GETFORMATDATA.format - aborting");
587                         return FALSE;
588                     }
589 
590                     /* Copy format data to puD3dTextureFormats */
591                     memset(puD3dTextureFormats, 0, sizeof(DDSURFACEDESC));
592                     puD3dTextureFormats->dwSize = sizeof(DDSURFACEDESC);
593                     puD3dTextureFormats->dwFlags = DDSD_PIXELFORMAT;
594                     memcpy(&puD3dTextureFormats->ddpfPixelFormat, &FormatData.format, sizeof(DDPIXELFORMAT));
595 
596                     if ((FormatData.format.dwOperations & D3DFORMAT_OP_PIXELSIZE) != 0 &&
597                         FormatData.format.dwPrivateFormatBitCount > 0)
598                     {
599                         /* TODO: Register driver's own pixelformat */
600                     }
601 
602                     ++puD3dTextureFormats;
603                 }
604             }
605         }
606 
607         /* GUID_GetDriverInfo2 - Get extended mode count data */
608         {
609             ResetGetDriverInfo2Data(&ExModeCountData.gdi2, D3DGDI2_TYPE_GETEXTENDEDMODECOUNT, sizeof(DD_GETEXTENDEDMODECOUNTDATA));
610             PrepareDriverInfoData(&DrvInfo, &ExModeCountData, sizeof(DD_GETEXTENDEDMODECOUNTDATA));
611             ExModeCountData.dwModeCount = UINT_MAX;
612             ExModeCountData.dwReserved = dwDXVersion;
613 
614             if (TRUE == OsThunkDdGetDriverInfo(pUnknown6BC->hDirectDrawLocal, &DrvInfo))
615             {
616                 if (DrvInfo.ddRVal == S_OK)
617                 {
618                     if (DrvInfo.dwActualSize != sizeof(DD_GETEXTENDEDMODECOUNTDATA))
619                     {
620                         DPRINT1("Driver returned an invalid DD_GETEXTENDEDFORMATCOUNTDATA structure - aborting");
621                         return FALSE;
622                     }
623                     else if (ExModeCountData.dwModeCount == UINT_MAX)
624                     {
625                         DPRINT1("Driver didn't set DD_GETEXTENDEDMODECOUNTDATA.dwModeCount - aborting");
626                         return FALSE;
627                     }
628 
629                     *pNumExtendedFormats = ExModeCountData.dwModeCount;
630                 }
631                 else
632                 {
633                     ExModeCountData.dwModeCount = 0;
634                 }
635             }
636         }
637 
638         /* GUID_GetDriverInfo2 - Get extended mode data */
639         if (pD3dDisplayModeList != NULL)
640         {
641             DWORD ModeIndex;
642             DD_GETEXTENDEDMODEDATA ExModeData;
643 
644             for (ModeIndex = 0; ModeIndex < ExModeCountData.dwModeCount; ModeIndex++)
645             {
646                 ResetGetDriverInfo2Data(&ExModeData.gdi2, D3DGDI2_TYPE_GETEXTENDEDMODE, sizeof(DD_GETEXTENDEDMODEDATA));
647                 PrepareDriverInfoData(&DrvInfo, &ExModeData, sizeof(DD_GETEXTENDEDMODEDATA));
648                 ExModeData.dwModeIndex = ModeIndex;
649                 ExModeData.mode.Width = UINT_MAX;
650 
651                 if (TRUE == OsThunkDdGetDriverInfo(pUnknown6BC->hDirectDrawLocal, &DrvInfo))
652                 {
653                     if (DrvInfo.ddRVal != S_OK)
654                     {
655                         DPRINT1("Driver claimed to be DX9 driver, but didn't support D3DGDI2_TYPE_GETEXTENDEDMODE in GetDriverInfo call");
656                         return FALSE;
657                     }
658                     else if (DrvInfo.dwActualSize != sizeof(DD_GETEXTENDEDMODEDATA))
659                     {
660                         DPRINT1("Driver returned an invalid DD_GETEXTENDEDMODEDATA structure - aborting");
661                         return FALSE;
662                     }
663                     else if (ExModeData.mode.Width != UINT_MAX)
664                     {
665                         DPRINT1("Driver didn't set DD_GETEXTENDEDMODEDATA.mode - aborting");
666                         return FALSE;
667                     }
668 
669                     memcpy(pD3dDisplayModeList, &ExModeData.mode, sizeof(D3DDISPLAYMODE));
670                     ++pD3dDisplayModeList;
671                 }
672             }
673         }
674 
675         /* GUID_GetDriverInfo2 - Get adapter group */
676         {
677             DD_GETADAPTERGROUPDATA AdapterGroupData;
678             ResetGetDriverInfo2Data(&AdapterGroupData.gdi2, D3DGDI2_TYPE_GETADAPTERGROUP, sizeof(DD_GETADAPTERGROUPDATA));
679             PrepareDriverInfoData(&DrvInfo, &AdapterGroupData, sizeof(DD_GETADAPTERGROUPDATA));
680             AdapterGroupData.ulUniqueAdapterGroupId = UINT_MAX;
681 
682             if (TRUE == OsThunkDdGetDriverInfo(pUnknown6BC->hDirectDrawLocal, &DrvInfo))
683             {
684                 if (DrvInfo.ddRVal != S_OK)
685                 {
686                     DPRINT1("Driver claimed to be DX9 driver, but didn't support D3DGDI2_TYPE_GETADAPTERGROUP in GetDriverInfo call");
687                     return FALSE;
688                 }
689                 else if (DrvInfo.dwActualSize != sizeof(DD_GETADAPTERGROUPDATA))
690                 {
691                     DPRINT1("Driver returned an invalid DD_GETADAPTERGROUPDATA structure - aborting");
692                     return FALSE;
693                 }
694                 else if (AdapterGroupData.ulUniqueAdapterGroupId == UINT_MAX)
695                 {
696                     DPRINT1("Driver didn't set DD_GETADAPTERGROUPDATA.ulUniqueAdapterGroupId - aborting");
697                     return FALSE;
698                 }
699 
700                 pDriverCaps->ulUniqueAdapterGroupId = (ULONG)AdapterGroupData.ulUniqueAdapterGroupId;
701             }
702         }
703 
704         /* GUID_GetDriverInfo2 - Query count data */
705         {
706             ResetGetDriverInfo2Data(&D3dQueryCountData.gdi2, D3DGDI2_TYPE_GETD3DQUERYCOUNT, sizeof(DD_GETD3DQUERYCOUNTDATA));
707             PrepareDriverInfoData(&DrvInfo, &D3dQueryCountData, sizeof(DD_GETD3DQUERYCOUNTDATA));
708             D3dQueryCountData.dwNumQueries = UINT_MAX;
709 
710             if (TRUE == OsThunkDdGetDriverInfo(pUnknown6BC->hDirectDrawLocal, &DrvInfo))
711             {
712                 if (DrvInfo.ddRVal != S_OK)
713                 {
714                     DPRINT1("Driver claimed to be DX9 driver, but didn't support D3DGDI2_TYPE_GETD3DQUERYCOUNT in GetDriverInfo call");
715                     return FALSE;
716                 }
717                 else if (DrvInfo.dwActualSize != sizeof(DD_GETD3DQUERYCOUNTDATA))
718                 {
719                     DPRINT1("Driver returned an invalid DD_GETD3DQUERYCOUNTDATA structure - aborting");
720                     return FALSE;
721                 }
722                 else if (D3dQueryCountData.dwNumQueries == UINT_MAX)
723                 {
724                     DPRINT1("Driver didn't set DD_GETD3DQUERYCOUNTDATA.dwNumQueries - aborting");
725                     return FALSE;
726                 }
727 
728                 *pNumQueries = D3dQueryCountData.dwNumQueries;
729             }
730         }
731 
732         /* GUID_GetDriverInfo2 - Query data */
733         if (pD3dQueryList != NULL)
734         {
735             DWORD QueryIndex;
736             DD_GETD3DQUERYDATA D3dQueryData;
737 
738             for (QueryIndex = 0; QueryIndex < D3dQueryCountData.dwNumQueries; QueryIndex++)
739             {
740                 ResetGetDriverInfo2Data(&D3dQueryData.gdi2, D3DGDI2_TYPE_GETD3DQUERY, sizeof(DD_GETD3DQUERYDATA));
741                 PrepareDriverInfoData(&DrvInfo, &D3dQueryData, sizeof(DD_GETD3DQUERYDATA));
742                 D3dQueryData.dwQueryIndex = QueryIndex;
743 
744                 if (TRUE == OsThunkDdGetDriverInfo(pUnknown6BC->hDirectDrawLocal, &DrvInfo))
745                 {
746                     if (DrvInfo.ddRVal != S_OK)
747                     {
748                         DPRINT1("Driver claimed to be DX9 driver, but didn't support D3DGDI2_TYPE_GETD3DQUERY in GetDriverInfo call");
749                         return FALSE;
750                     }
751                     else if (DrvInfo.dwActualSize != sizeof(DD_GETD3DQUERYDATA))
752                     {
753                         DPRINT1("Driver returned an invalid DD_GETD3DQUERYDATA structure - aborting");
754                         return FALSE;
755                     }
756 
757                     *pD3dQueryList = D3dQueryData.QueryType;
758                     ++pD3dQueryList;
759                 }
760             }
761         }
762     }
763 
764     /* D3dDriverData -> pGblDriverData */
765     memcpy(&pGblDriverData->hwCaps, &D3dDriverData.hwCaps, sizeof(D3DNTHALDEVICEDESC_V1));
766     pGblDriverData->dwNumVertices = D3dDriverData.dwNumVertices;
767     pGblDriverData->dwNumClipVertices = D3dDriverData.dwNumClipVertices;
768 
769     /* GUID_D3DExtendedCaps */
770     {
771         DrvInfo.dwSize = sizeof(DD_GETDRIVERINFODATA);
772         DrvInfo.guidInfo = GUID_D3DExtendedCaps;
773         DrvInfo.dwExpectedSize = sizeof(D3DHAL_D3DEXTENDEDCAPS);
774         DrvInfo.lpvData = pD3dExtendedCaps;
775         bRet = OsThunkDdGetDriverInfo(pUnknown6BC->hDirectDrawLocal, &DrvInfo);
776 
777         if (TRUE != bRet || DrvInfo.ddRVal != S_OK)
778         {
779             DPRINT1("Driver failed call to GetDriverInfo() with: GUID_D3DExtendedCaps");
780             return FALSE;
781         }
782     }
783 
784     /* GUID_ZPixelFormats */
785     {
786         DDPIXELFORMAT *pZPixelFormats = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, FormatCountData.dwFormatCount * sizeof(DDPIXELFORMAT));
787 
788         DrvInfo.dwSize = sizeof(DD_GETDRIVERINFODATA);
789         DrvInfo.guidInfo = GUID_ZPixelFormats;
790         DrvInfo.dwExpectedSize = FormatCountData.dwFormatCount * sizeof(DDPIXELFORMAT);
791         DrvInfo.lpvData = pZPixelFormats;
792         bRet = OsThunkDdGetDriverInfo(pUnknown6BC->hDirectDrawLocal, &DrvInfo);
793 
794         if (TRUE != bRet || DrvInfo.ddRVal != S_OK)
795         {
796             DPRINT1("Driver failed call to GetDriverInfo() with: GUID_ZPixelFormats");
797             HeapFree(GetProcessHeap(), 0, pZPixelFormats);
798             return FALSE;
799         }
800 
801         *pNumZStencilFormats = FormatCountData.dwFormatCount;
802 
803         if (pD3dZStencilFormatList != NULL)
804             memcpy(pD3dZStencilFormatList, pZPixelFormats, FormatCountData.dwFormatCount * sizeof(DDPIXELFORMAT));
805 
806         HeapFree(GetProcessHeap(), 0, pZPixelFormats);
807     }
808 
809     /* Get current display format */
810     {
811         D3DDISPLAYMODE CurrentDisplayMode;
812         GetAdapterMode(lpszDeviceName, &CurrentDisplayMode);
813         pUnknown6BC->RawDisplayFormat = CurrentDisplayMode.Format;
814         pUnknown6BC->DisplayFormat = CurrentDisplayMode.Format;
815 
816         if ((HalInfo.vmiData.ddpfDisplay.dwFlags & DDPF_ALPHAPIXELS) != 0)
817         {
818             if (CurrentDisplayMode.Format == D3DFMT_X8R8G8B8)
819             {
820                 pUnknown6BC->DisplayFormat = D3DFMT_A8R8G8B8;
821             }
822             else if (CurrentDisplayMode.Format == D3DFMT_X1R5G5B5)
823             {
824                 pUnknown6BC->DisplayFormat = D3DFMT_A1R5G5B5;
825             }
826         }
827 
828         pDriverCaps->dwDisplayWidth = CurrentDisplayMode.Width;
829         pDriverCaps->dwDisplayHeight = CurrentDisplayMode.Height;
830         pDriverCaps->RawDisplayFormat = CurrentDisplayMode.Format;
831         pDriverCaps->DisplayFormat = pUnknown6BC->DisplayFormat;
832         pDriverCaps->dwRefreshRate = CurrentDisplayMode.RefreshRate;
833     }
834 
835     /* TODO: Set all internal function pointers to create surface, etc. */
836     pD3D9Callbacks->DdGetAvailDriverMemory = &D3d9GetAvailDriverMemory;
837 
838     /* Set device rect */
839     {
840         HMONITOR hMonitor;
841         MONITORINFO MonitorInfo;
842 
843         memset(&MonitorInfo, 0, sizeof(MONITORINFO));
844         MonitorInfo.cbSize = sizeof(MONITORINFO);
845 
846         hMonitor = GetAdapterMonitor(lpszDeviceName);
847         if (TRUE == GetMonitorInfoA(hMonitor, &MonitorInfo))
848         {
849             pUnknown6BC->DeviceRect = MonitorInfo.rcMonitor;
850         }
851         else
852         {
853             DPRINT1("Could not get monitor information");
854         }
855     }
856 
857     pUnknown6BC->dwCaps = pDriverCaps->DriverCaps9.Caps;
858     pUnknown6BC->dwSVBCaps = pDriverCaps->dwSVBCaps;
859 
860     if (FALSE == bDX8Mode)
861     {
862         pUnknown6BC->MajorDxVersion = 9;
863 
864         if (0 != (pDriverCaps->DriverCaps9.VertexProcessingCaps & D3DVTXPCAPS_NO_VSDT_UBYTE4))
865         {
866             DPRINT1("Driver claimed to be DX9 driver, but used depricated D3DCAPS9.VertexProcessingCaps: D3DVTXPCAPS_NO_VSDT_UBYTE4 instead of not setting D3DCAPS9.DeclTypes: D3DDTCAPS_UBYTE4.");
867             return FALSE;
868         }
869     }
870     else
871     {
872         pUnknown6BC->MajorDxVersion = 8;
873 
874         if (0 == (pDriverCaps->DriverCaps9.VertexProcessingCaps & D3DVTXPCAPS_NO_VSDT_UBYTE4))
875         {
876             pDriverCaps->DriverCaps9.DeclTypes |= D3DDTCAPS_UBYTE4;
877             pDriverCaps->DriverCaps9.VertexProcessingCaps &= ~D3DVTXPCAPS_NO_VSDT_UBYTE4;
878         }
879     }
880 
881     return TRUE;
882 }
883