Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2970 lines
92 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1995-1999 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: enum.cpp
  6. * Content Handles all of the enum functions for determing what device
  7. * you want before you go there.
  8. *
  9. *
  10. ***************************************************************************/
  11. #include "ddrawpr.h"
  12. #include <stdio.h>
  13. #include "d3dobj.hpp"
  14. #include "pixel.hpp"
  15. #include "enum.hpp"
  16. #include "d3di.hpp"
  17. #include "fcache.hpp"
  18. #include "swapchan.hpp"
  19. #define D3DPMISCCAPS_DX7VALID \
  20. (D3DPMISCCAPS_MASKZ | \
  21. D3DPMISCCAPS_LINEPATTERNREP | \
  22. D3DPMISCCAPS_CULLNONE | \
  23. D3DPMISCCAPS_CULLCW | \
  24. D3DPMISCCAPS_CULLCCW)
  25. // Maps D3DMULTISAMPLE_TYPE into the bit to use for the flags.
  26. // Maps each of the multisampling values (2 to 16) to the bits[1] to bits[15]
  27. // of wBltMSTypes and wFlipMSTypes
  28. #define DDI_MULTISAMPLE_TYPE(x) (1 << ((x)-1))
  29. #ifdef WINNT
  30. extern "C" BOOL IsWhistler();
  31. #endif
  32. void DXReleaseExclusiveModeMutex(void)
  33. {
  34. if (hExclusiveModeMutex)
  35. {
  36. BOOL bSucceed = ReleaseMutex(hExclusiveModeMutex);
  37. if (!bSucceed)
  38. {
  39. DWORD dwErr = GetLastError();
  40. DPF_ERR("Release Exclusive Mode Mutex Failed.");
  41. DPF_ERR("Application attempts to leave exclusive mode on different thread than the device was created on. Dangerous!!");
  42. DPF(0, "Mutex 0x%p could not be released. Extended Error = %d",
  43. hExclusiveModeMutex, dwErr);
  44. DXGASSERT(FALSE);
  45. }
  46. }
  47. } // DXReleaseExclusiveModeMutex
  48. // DLL exposed Creation function
  49. IDirect3D8 * WINAPI Direct3DCreate8(UINT SDKVersion)
  50. {
  51. // Turn off D3D8 interfaces on WOW64.
  52. #ifndef _IA64_
  53. #if _WIN32_WINNT >= 0x0501
  54. typedef BOOL (WINAPI *PFN_ISWOW64PROC)( HANDLE hProcess,
  55. PBOOL Wow64Process );
  56. HINSTANCE hInst = NULL;
  57. hInst = LoadLibrary( "kernel32.dll" );
  58. if( hInst )
  59. {
  60. PFN_ISWOW64PROC pfnIsWow64 = NULL;
  61. pfnIsWow64 = (PFN_ISWOW64PROC)GetProcAddress( (HMODULE)hInst, "IsWow64Process" );
  62. // We assume that if this function is not available, then it is some OS where
  63. // WOW64 does not exist (this means that pre-Release versions of XP are busted)
  64. if( pfnIsWow64 )
  65. {
  66. BOOL wow64Process;
  67. if (pfnIsWow64(GetCurrentProcess(), &wow64Process) && wow64Process)
  68. {
  69. DPF_ERR("DX8 D3D interfaces are not supported on WOW64");
  70. return NULL;
  71. }
  72. }
  73. FreeLibrary( hInst );
  74. }
  75. else
  76. {
  77. DPF_ERR("LoadLibrary failed. Quitting.");
  78. return NULL;
  79. }
  80. #endif // _WIN32_WINNT >= 0x0501
  81. #endif // _IA64_
  82. #ifndef DEBUG
  83. // Check for debug-please registry key. If debug is required, then
  84. // we delegate this call to the debug version, if it exists,,
  85. HKEY hKey;
  86. if (!RegOpenKey(HKEY_LOCAL_MACHINE, RESPATH_D3D, &hKey))
  87. {
  88. DWORD type;
  89. DWORD value;
  90. DWORD cb = sizeof(value);
  91. if (!RegQueryValueEx(hKey, "LoadDebugRuntime", NULL, &type, (CONST LPBYTE)&value, &cb))
  92. {
  93. if (value)
  94. {
  95. HINSTANCE hDebugDLL = LoadLibrary("d3d8d.dll");
  96. if (hDebugDLL)
  97. {
  98. typedef IDirect3D8* (WINAPI * PDIRECT3DCREATE8)(UINT);
  99. PDIRECT3DCREATE8 pDirect3DCreate8 =
  100. (PDIRECT3DCREATE8) GetProcAddress(hDebugDLL, "Direct3DCreate8");
  101. if (pDirect3DCreate8)
  102. {
  103. return pDirect3DCreate8(SDKVersion);
  104. }
  105. }
  106. }
  107. }
  108. RegCloseKey(hKey);
  109. }
  110. #else
  111. //If we are debug, then spew a string at level 2
  112. DPF(2,"Direct3D8 Debug Runtime selected.");
  113. #endif
  114. #ifndef DX_FINAL_RELEASE
  115. // Time-bomb check.
  116. {
  117. #pragma message("BETA EXPIRATION TIME BOMB! Remove for final build!")
  118. SYSTEMTIME st;
  119. GetSystemTime(&st);
  120. if (st.wYear > DX_EXPIRE_YEAR ||
  121. ((st.wYear == DX_EXPIRE_YEAR) && (MAKELONG(st.wDay, st.wMonth) > MAKELONG(DX_EXPIRE_DAY, DX_EXPIRE_MONTH)))
  122. )
  123. {
  124. MessageBox(0, DX_EXPIRE_TEXT,
  125. TEXT("Microsoft Direct3D"), MB_OK | MB_TASKMODAL);
  126. }
  127. }
  128. #endif //DX_FINAL_RELEASE
  129. #ifdef DEBUG
  130. HKEY hKey;
  131. if (!RegOpenKey(HKEY_LOCAL_MACHINE, RESPATH_D3D, &hKey))
  132. {
  133. DWORD type;
  134. DWORD value;
  135. DWORD cb = sizeof(value);
  136. if (!RegQueryValueEx(hKey, "SDKVersion", NULL, &type, (CONST LPBYTE)&value, &cb))
  137. {
  138. if (value)
  139. {
  140. SDKVersion = value;
  141. }
  142. }
  143. RegCloseKey(hKey);
  144. }
  145. #endif
  146. if ((SDKVersion != D3D_SDK_VERSION_DX8) &&
  147. ((SDKVersion < (D3D_SDK_VERSION)) || (SDKVersion >= (D3D_SDK_VERSION+100))) )
  148. {
  149. #ifdef DEBUG
  150. char pbuf[256];
  151. _snprintf(pbuf, 256,
  152. "\n"
  153. "D3D ERROR: This application compiled against improper D3D headers.\n"
  154. "The application is compiled with SDK version (%d) but the currently installed\n"
  155. "runtime supports versions from (%d).\n"
  156. "Please recompile with an up-to-date SDK.\n\n",
  157. SDKVersion, D3D_SDK_VERSION);
  158. OutputDebugString(pbuf);
  159. #endif
  160. return NULL;
  161. }
  162. IDirect3D8 *pEnum = new CEnum(SDKVersion);
  163. if (pEnum == NULL)
  164. {
  165. DPF_ERR("Creating D3D enumeration object failed; out of memory. Direct3DCreate fails and returns NULL.");
  166. }
  167. return pEnum;
  168. } // Direct3DCreate
  169. //---------------------------------------------------------------------------
  170. // CEnum methods
  171. //---------------------------------------------------------------------------
  172. #undef DPF_MODNAME
  173. #define DPF_MODNAME "CEnum::AddRef"
  174. STDMETHODIMP_(ULONG) CEnum::AddRef(void)
  175. {
  176. API_ENTER_NO_LOCK(this);
  177. // InterlockedIncrement requires the memory
  178. // to be aligned on DWORD boundary
  179. DXGASSERT(((ULONG_PTR)(&m_cRef) & 3) == 0);
  180. InterlockedIncrement((LONG *)&m_cRef);
  181. return m_cRef;
  182. } // AddRef
  183. #undef DPF_MODNAME
  184. #define DPF_MODNAME "CEnum::Release"
  185. STDMETHODIMP_(ULONG) CEnum::Release(void)
  186. {
  187. API_ENTER_NO_LOCK(this);
  188. // InterlockedDecrement requires the memory
  189. // to be aligned on DWORD boundary
  190. DXGASSERT(((ULONG_PTR)(&m_cRef) & 3) == 0);
  191. InterlockedDecrement((LONG *)&m_cRef);
  192. if (m_cRef != 0)
  193. return m_cRef;
  194. for (UINT i = 0; i < m_cAdapter; i++)
  195. {
  196. if (m_REFCaps[i].pGDD8SupportedFormatOps)
  197. MemFree(m_REFCaps[i].pGDD8SupportedFormatOps);
  198. if (m_SwCaps[i].pGDD8SupportedFormatOps)
  199. MemFree(m_SwCaps[i].pGDD8SupportedFormatOps);
  200. if (m_AdapterInfo[i].HALCaps.pGDD8SupportedFormatOps)
  201. MemFree(m_AdapterInfo[i].HALCaps.pGDD8SupportedFormatOps);
  202. if (m_AdapterInfo[i].pModeTable)
  203. MemFree(m_AdapterInfo[i].pModeTable);
  204. }
  205. if (m_hGammaCalibrator)
  206. {
  207. FreeLibrary((HMODULE) m_hGammaCalibrator);
  208. }
  209. delete this;
  210. return 0;
  211. } // Release
  212. #undef DPF_MODNAME
  213. #define DPF_MODNAME "CEnum::QueryInterface"
  214. STDMETHODIMP CEnum::QueryInterface(REFIID riid, LPVOID FAR *ppv)
  215. {
  216. API_ENTER(this);
  217. if (!VALID_PTR_PTR(ppv))
  218. {
  219. DPF_ERR("Invalid pointer passed to QueryInterface for IDirect3D8 interface");
  220. return D3DERR_INVALIDCALL;
  221. }
  222. if (!VALID_PTR(&riid, sizeof(GUID)))
  223. {
  224. DPF_ERR("Invalid guid memory address to QueryInterface for IDirect3D8 interface");
  225. return D3DERR_INVALIDCALL;
  226. }
  227. if (riid == IID_IUnknown || riid == IID_IDirect3D8)
  228. {
  229. *ppv = static_cast<void*>(static_cast<IDirect3D8*>(this));
  230. AddRef();
  231. }
  232. else
  233. {
  234. DPF_ERR("Unsupported Interface identifier passed to QueryInterface for IDirect3D8 interface");
  235. *ppv = NULL;
  236. return E_NOINTERFACE;
  237. }
  238. return S_OK;
  239. } // QueryInterface
  240. // DisplayGUID - GUID used to enumerate secondary displays.
  241. //
  242. // {67685559-3106-11d0-B971-00AA00342F9F}
  243. //
  244. // we use this GUID and the next 32 for enumerating devices
  245. // returned via EnumDisplayDevices
  246. //
  247. GUID DisplayGUID =
  248. {0x67685559,0x3106,0x11d0,{0xb9,0x71,0x0,0xaa,0x0,0x34,0x2f,0x9f}};
  249. #undef DPF_MODNAME
  250. #define DPF_MODNAME "::strToGUID"
  251. /*
  252. * strToGUID
  253. *
  254. * converts a string in the form xxxxxxxx-xxxx-xxxx-xx-xx-xx-xx-xx-xx-xx-xx
  255. * into a guid
  256. */
  257. static BOOL strToGUID(LPSTR str, GUID * pguid)
  258. {
  259. int idx;
  260. LPSTR ptr;
  261. LPSTR next;
  262. DWORD data;
  263. DWORD mul;
  264. BYTE ch;
  265. BOOL done;
  266. idx = 0;
  267. done = FALSE;
  268. while (!done)
  269. {
  270. /*
  271. * find the end of the current run of digits
  272. */
  273. ptr = str;
  274. while ((*str) != '-' && (*str) != 0)
  275. {
  276. str++;
  277. }
  278. if (*str == 0)
  279. {
  280. done = TRUE;
  281. }
  282. else
  283. {
  284. next = str+1;
  285. }
  286. /*
  287. * scan backwards from the end of the string to the beginning,
  288. * converting characters from hex chars to numbers as we go
  289. */
  290. str--;
  291. mul = 1;
  292. data = 0;
  293. while (str >= ptr)
  294. {
  295. ch = *str;
  296. if (ch >= 'A' && ch <= 'F')
  297. {
  298. data += mul * (DWORD) (ch-'A'+10);
  299. }
  300. else if (ch >= 'a' && ch <= 'f')
  301. {
  302. data += mul * (DWORD) (ch-'a'+10);
  303. }
  304. else if (ch >= '0' && ch <= '9')
  305. {
  306. data += mul * (DWORD) (ch-'0');
  307. }
  308. else
  309. {
  310. return FALSE;
  311. }
  312. mul *= 16;
  313. str--;
  314. }
  315. /*
  316. * stuff the current number into the guid
  317. */
  318. switch(idx)
  319. {
  320. case 0:
  321. pguid->Data1 = data;
  322. break;
  323. case 1:
  324. pguid->Data2 = (WORD) data;
  325. break;
  326. case 2:
  327. pguid->Data3 = (WORD) data;
  328. break;
  329. default:
  330. pguid->Data4[ idx-3 ] = (BYTE) data;
  331. break;
  332. }
  333. /*
  334. * did we find all 11 numbers?
  335. */
  336. idx++;
  337. if (idx == 11)
  338. {
  339. if (done)
  340. {
  341. return TRUE;
  342. }
  343. else
  344. {
  345. return FALSE;
  346. }
  347. }
  348. str = next;
  349. }
  350. return FALSE;
  351. } /* strToGUID */
  352. // REF, HAL
  353. typedef struct _DEVICEREGISTRYDATA
  354. {
  355. UINT Size;
  356. UINT Cookie;
  357. FILETIME FileDate;
  358. GUID DriverGuid;
  359. D3D8_DRIVERCAPS DeviceCaps;
  360. UINT OffsetFormatOps;
  361. D3DFORMAT Unknown16;
  362. DWORD HALFlags;
  363. } DEVICEREGISTRYDATA;
  364. inline UINT EXPECTED_CACHE_SIZE(UINT nFormatOps)
  365. {
  366. return sizeof(DEVICEREGISTRYDATA) + sizeof(DDSURFACEDESC) * nFormatOps;
  367. }
  368. #define DDRAW_REGCAPS_KEY "Software\\Microsoft\\DirectDraw\\MostRecentDrivers"
  369. #define VERSION_COOKIE 0x0083
  370. #undef DPF_MODNAME
  371. #define DPF_MODNAME "ReadCapsFromCache"
  372. BOOL GetFileDate (char* Driver, FILETIME* pFileDate)
  373. {
  374. WIN32_FILE_ATTRIBUTE_DATA FA;
  375. char Name[MAX_PATH];
  376. HMODULE h = GetModuleHandle("KERNEL32");
  377. BOOL (WINAPI *pfnGetFileAttributesEx)(LPCSTR, GET_FILEEX_INFO_LEVELS, LPVOID);
  378. pFileDate->dwLowDateTime = 0;
  379. pFileDate->dwHighDateTime = 0;
  380. *((void **)&pfnGetFileAttributesEx) = GetProcAddress(h,"GetFileAttributesExA");
  381. if (pfnGetFileAttributesEx != NULL)
  382. {
  383. GetSystemDirectory(Name, sizeof(Name) - (strlen(Driver) + 3));
  384. lstrcat(Name,"\\");
  385. lstrcat(Name, Driver);
  386. if ((*pfnGetFileAttributesEx)(Name, GetFileExInfoStandard, &FA) != 0)
  387. {
  388. *pFileDate = FA.ftCreationTime;
  389. return TRUE;
  390. }
  391. }
  392. return FALSE;
  393. }
  394. //If pCaps is NULL, then those data will not be returned.
  395. BOOL ReadCapsFromCache(UINT iAdapter,
  396. D3D8_DRIVERCAPS *pCaps,
  397. UINT* pHALFlags,
  398. D3DFORMAT* pUnknown16,
  399. char* pDeviceName,
  400. BOOL bDisplayDriver)
  401. {
  402. D3DADAPTER_IDENTIFIER8 DI;
  403. DEVICEREGISTRYDATA* pData = NULL;
  404. UINT Size;
  405. FILETIME FileDate;
  406. // Read the data from the registry
  407. // Don't need WHQL level or driver name
  408. GetAdapterInfo(pDeviceName, &DI, bDisplayDriver, TRUE, FALSE);
  409. ReadFromCache(&DI, &Size, (BYTE**)&pData);
  410. if (pData == NULL)
  411. {
  412. return FALSE;
  413. }
  414. // We have the data, now do a sanity check to make sure that it
  415. // it makes sense
  416. if (pData->Size != Size)
  417. {
  418. MemFree(pData);
  419. return FALSE;
  420. }
  421. if (Size != EXPECTED_CACHE_SIZE(pData->DeviceCaps.GDD8NumSupportedFormatOps))
  422. {
  423. MemFree(pData);
  424. return FALSE;
  425. }
  426. if (pData->DriverGuid != DI.DeviceIdentifier)
  427. {
  428. MemFree(pData);
  429. return FALSE;
  430. }
  431. if (pData->Cookie != VERSION_COOKIE)
  432. {
  433. MemFree(pData);
  434. return FALSE;
  435. }
  436. // Check the driver date to see if it changed
  437. if (GetFileDate(DI.Driver, &FileDate))
  438. {
  439. if ((FileDate.dwLowDateTime != pData->FileDate.dwLowDateTime) ||
  440. (FileDate.dwHighDateTime != pData->FileDate.dwHighDateTime))
  441. {
  442. MemFree(pData);
  443. return FALSE;
  444. }
  445. }
  446. *pUnknown16 = pData->Unknown16;
  447. *pHALFlags = pData->HALFlags;
  448. //Sometime we may not be asked to get the whole caps
  449. if (!pCaps)
  450. {
  451. MemFree(pData);
  452. return TRUE;
  453. }
  454. // Now that we have the data, we need to load it into a form that we
  455. // can use.
  456. memcpy(pCaps, &pData->DeviceCaps, sizeof(*pCaps));
  457. //reuse size to calculate size of support format ops
  458. Size = pData->DeviceCaps.GDD8NumSupportedFormatOps
  459. * sizeof(*(pData->DeviceCaps.pGDD8SupportedFormatOps));
  460. pCaps->pGDD8SupportedFormatOps = (DDSURFACEDESC*) MemAlloc(Size);
  461. if (pCaps->pGDD8SupportedFormatOps != NULL)
  462. {
  463. memcpy(pCaps->pGDD8SupportedFormatOps,
  464. ((BYTE*)pData) + pData->OffsetFormatOps,
  465. Size);
  466. }
  467. else
  468. {
  469. pCaps->GDD8NumSupportedFormatOps = 0;
  470. }
  471. MemFree(pData);
  472. return TRUE;
  473. }
  474. #undef DPF_MODNAME
  475. #define DPF_MODNAME "WriteCapsToCache"
  476. void WriteCapsToCache(UINT iAdapter,
  477. D3D8_DRIVERCAPS *pCaps,
  478. UINT HALFlags,
  479. D3DFORMAT Unknown16,
  480. char* pDeviceName,
  481. BOOL bDisplayDriver)
  482. {
  483. DEVICEREGISTRYDATA* pData;
  484. D3DADAPTER_IDENTIFIER8 DI;
  485. UINT Size;
  486. UINT Offset;
  487. FILETIME FileDate;
  488. // Allocate the buffer and fill in all of the memory
  489. Size = EXPECTED_CACHE_SIZE(pCaps->GDD8NumSupportedFormatOps);
  490. pData = (DEVICEREGISTRYDATA*) MemAlloc(Size);
  491. if (pData == NULL)
  492. {
  493. return;
  494. }
  495. // Don't need WHQL level or driver name
  496. GetAdapterInfo(pDeviceName, &DI, bDisplayDriver, TRUE, FALSE);
  497. pData->DriverGuid = DI.DeviceIdentifier;
  498. pData->Size = Size;
  499. pData->Cookie = VERSION_COOKIE;
  500. memcpy(&pData->DeviceCaps, pCaps, sizeof(*pCaps));
  501. pData->Unknown16 = Unknown16;
  502. pData->HALFlags = HALFlags;
  503. if (GetFileDate(DI.Driver, &FileDate))
  504. {
  505. pData->FileDate = FileDate;
  506. }
  507. Offset = sizeof(DEVICEREGISTRYDATA);
  508. pData->OffsetFormatOps = Offset;
  509. memcpy(((BYTE*)pData) + Offset,
  510. pCaps->pGDD8SupportedFormatOps,
  511. pCaps->GDD8NumSupportedFormatOps *
  512. sizeof(*(pCaps->pGDD8SupportedFormatOps)));
  513. // Now save it
  514. WriteToCache(&DI, Size, (BYTE*) pData);
  515. MemFree(pData);
  516. }
  517. HRESULT CopyDriverCaps(D3D8_DRIVERCAPS* pDriverCaps, D3D8_DEVICEDATA* pDeviceData, BOOL bForce)
  518. {
  519. HRESULT hr = D3DERR_INVALIDCALL;
  520. // Do they report any D3D caps in this mode?
  521. DWORD Size;
  522. // If it's not at least a DX6 driver, we don't want to fill
  523. // in any caps at all. Also, if it can't texture, then
  524. // we don't to support it either.
  525. BOOL bCanTexture = TRUE;
  526. BOOL bCanHandleFVF = TRUE;
  527. BOOL bHasGoodCaps = TRUE;
  528. if (!bForce)
  529. {
  530. if (pDeviceData->DriverData.D3DCaps.TextureCaps)
  531. {
  532. bCanTexture = TRUE;
  533. }
  534. else
  535. {
  536. DPF(0, "HAL Disabled: Device doesn't support texturing");
  537. bCanTexture = FALSE;
  538. }
  539. // Some DX6 drivers are not FVF aware; and we need to
  540. // disable HAL for them.
  541. if (pDeviceData->DriverData.D3DCaps.FVFCaps != 0)
  542. {
  543. bCanHandleFVF = TRUE;
  544. }
  545. else
  546. {
  547. DPF(0, "HAL Disabled: Device doesn't support FVF");
  548. bCanHandleFVF = FALSE;
  549. }
  550. if (pDeviceData->Callbacks.DrawPrimitives2 == NULL)
  551. {
  552. DPF(0, "HAL Disabled: Device doesn't support DX6 or higher");
  553. }
  554. // We dont want drivers that report bogus caps:
  555. // pre-DX8 drivers that can do DX8 features.
  556. if (pDeviceData->DriverData.D3DCaps.MaxStreams == 0)
  557. {
  558. D3DCAPS8& Caps = pDeviceData->DriverData.D3DCaps;
  559. // Should have none of the following:
  560. // 1) PointSprites.
  561. // 2) VertexShaders.
  562. // 3) PixelShaders.
  563. // 4) Volume textures.
  564. // 5) Indexed Vertex Blending.
  565. // 6) Higher order primitives.
  566. // 7) PureDevice
  567. // 8) Perspective Color.
  568. // 9) Color Write.
  569. // 10) Newer texture caps.
  570. if ((Caps.MaxPointSize != 0) ||
  571. (Caps.VertexShaderVersion != D3DVS_VERSION(0,0)) ||
  572. (Caps.PixelShaderVersion != D3DPS_VERSION(0,0)) ||
  573. (Caps.MaxVolumeExtent != 0) ||
  574. (Caps.MaxVertexBlendMatrixIndex != 0) ||
  575. (Caps.MaxVertexIndex != 0xffff) ||
  576. ((Caps.DevCaps & ~(D3DDEVCAPS_DX7VALID | D3DDEVCAPS_HWVERTEXBUFFER)) != 0) ||
  577. ((Caps.RasterCaps & ~(D3DPRASTERCAPS_DX7VALID)) != 0) ||
  578. ((Caps.PrimitiveMiscCaps & ~(D3DPMISCCAPS_DX7VALID)) != 0) ||
  579. ((Caps.TextureCaps & ~(D3DPTEXTURECAPS_DX7VALID)) != 0)
  580. )
  581. {
  582. DPF(0, "HAL Disabled: DX7 Device should not support DX8 features");
  583. bHasGoodCaps = FALSE;
  584. }
  585. }
  586. else
  587. // We dont want drivers that report bogus caps:
  588. // DX8 drivers should do DX8 features.
  589. {
  590. D3DCAPS8& Caps = pDeviceData->DriverData.D3DCaps;
  591. }
  592. }
  593. // We require drivers to support DP2 (i.e. DX6+),
  594. // texturing and proper FVF support in order to use a HAL
  595. if ((pDeviceData->Callbacks.DrawPrimitives2 != NULL &&
  596. bCanTexture &&
  597. bCanHandleFVF &&
  598. bHasGoodCaps) ||
  599. bForce)
  600. {
  601. MemFree(pDriverCaps->pGDD8SupportedFormatOps);
  602. memcpy(pDriverCaps,
  603. &pDeviceData->DriverData, sizeof(pDeviceData->DriverData));
  604. Size = sizeof(DDSURFACEDESC) *
  605. pDriverCaps->GDD8NumSupportedFormatOps;
  606. pDriverCaps->pGDD8SupportedFormatOps =
  607. (DDSURFACEDESC*) MemAlloc(Size);
  608. if (pDriverCaps->pGDD8SupportedFormatOps != NULL)
  609. {
  610. memcpy(pDriverCaps->pGDD8SupportedFormatOps,
  611. pDeviceData->DriverData.pGDD8SupportedFormatOps,
  612. Size);
  613. }
  614. else
  615. {
  616. pDriverCaps->GDD8NumSupportedFormatOps = 0;
  617. }
  618. hr = D3D_OK;
  619. }
  620. return hr;
  621. }
  622. #undef DPF_MODNAME
  623. #define DPF_MODNAME "AddSoftwareDevice"
  624. HRESULT AddSoftwareDevice(D3DDEVTYPE DeviceType,
  625. D3D8_DRIVERCAPS* pSoftCaps,
  626. ADAPTERINFO* pAdapterInfo,
  627. VOID* pInitFunction)
  628. {
  629. HRESULT hr;
  630. PD3D8_DEVICEDATA pDeviceData;
  631. hr = InternalDirectDrawCreate(&pDeviceData,
  632. pAdapterInfo,
  633. DeviceType,
  634. pInitFunction,
  635. pAdapterInfo->Unknown16,
  636. pAdapterInfo->HALCaps.pGDD8SupportedFormatOps,
  637. pAdapterInfo->HALCaps.GDD8NumSupportedFormatOps);
  638. if (SUCCEEDED(hr))
  639. {
  640. hr = CopyDriverCaps(pSoftCaps, pDeviceData, FALSE);
  641. InternalDirectDrawRelease(pDeviceData);
  642. }
  643. return hr;
  644. }
  645. #undef DPF_MODNAME
  646. #define DPF_MODNAME "CreateCoverWindow"
  647. HWND CreateCoverWindow()
  648. {
  649. #define COVERWINDOWNAME "DxCoverWindow"
  650. WNDCLASS windowClass =
  651. {
  652. 0,
  653. DefWindowProc,
  654. 0,
  655. 0,
  656. g_hModule,
  657. LoadIcon(NULL, IDI_APPLICATION),
  658. LoadCursor(NULL, IDC_ARROW),
  659. (HBRUSH)(BLACK_BRUSH),
  660. NULL,
  661. COVERWINDOWNAME
  662. };
  663. RegisterClass(&windowClass);
  664. HWND hWindow = CreateWindowEx(
  665. WS_EX_TOPMOST,
  666. COVERWINDOWNAME,
  667. COVERWINDOWNAME,
  668. WS_POPUP,
  669. 0,
  670. 0,
  671. 100,
  672. 100,
  673. NULL,
  674. NULL,
  675. g_hModule,
  676. NULL);
  677. return hWindow;
  678. }
  679. HRESULT GetHALCapsInCurrentMode (PD3D8_DEVICEDATA pHalData, PADAPTERINFO pAdapterInfo, BOOL bForce, BOOL bFetchNewCaps)
  680. {
  681. HRESULT hr;
  682. DWORD i;
  683. // Free the old stuff if we no longer care
  684. if (bFetchNewCaps)
  685. {
  686. MemFree(pHalData->DriverData.pGDD8SupportedFormatOps);
  687. pHalData->DriverData.pGDD8SupportedFormatOps = NULL;
  688. pHalData->DriverData.GDD8NumSupportedFormatOps = 0;
  689. MemFree(pAdapterInfo->HALCaps.pGDD8SupportedFormatOps);
  690. pAdapterInfo->HALCaps.pGDD8SupportedFormatOps = NULL;
  691. pAdapterInfo->HALCaps.GDD8NumSupportedFormatOps = 0;
  692. // Set this to ensure that we actually get the caps
  693. pHalData->DriverData.D3DCaps.DevCaps = 0;
  694. pHalData->DriverData.dwFlags &= ~DDIFLAG_D3DCAPS8;
  695. FetchDirectDrawData(pHalData,
  696. NULL,
  697. pAdapterInfo->Unknown16,
  698. NULL,
  699. 0);
  700. }
  701. // Do they report any D3D caps in this mode?
  702. hr = CopyDriverCaps(&pAdapterInfo->HALCaps, pHalData, bForce);
  703. return hr;
  704. }
  705. #undef DPF_MODNAME
  706. #define DPF_MODNAME "ProfileAdapter"
  707. void ProfileAdapter(
  708. PADAPTERINFO pAdapterInfo,
  709. PD3D8_DEVICEDATA pHalData)
  710. {
  711. UINT i;
  712. IDirect3DDevice8* pDevice;
  713. D3DDISPLAYMODE OrigMode;
  714. UINT OrigBpp;
  715. HRESULT hr;
  716. // We will be changing display modes, so first we want to save the current
  717. // mode so we can return to it later.
  718. D3D8GetMode (pHalData->hDD, pAdapterInfo->DeviceName, &OrigMode, D3DFMT_UNKNOWN);
  719. MemFree(pAdapterInfo->HALCaps.pGDD8SupportedFormatOps);
  720. memset(&pAdapterInfo->HALCaps, 0, sizeof(D3D8_DRIVERCAPS));
  721. OrigBpp = CPixel::ComputePixelStride(OrigMode.Format)*8;
  722. //First gather what we need from 16bpp: Unknown16 format
  723. if (16 != OrigBpp)
  724. {
  725. D3D8SetMode (pHalData->hDD,
  726. pAdapterInfo->DeviceName,
  727. 640,
  728. 480,
  729. 16,
  730. 0,
  731. FALSE);
  732. }
  733. D3DDISPLAYMODE Mode;
  734. D3D8GetMode (pHalData->hDD, pAdapterInfo->DeviceName, &Mode, D3DFMT_UNKNOWN);
  735. pAdapterInfo->Unknown16 = Mode.Format;
  736. // We need to change to 32bpp, because the above code guarenteed we are now in 16bpp
  737. hr = D3D8SetMode (pHalData->hDD,
  738. pAdapterInfo->DeviceName,
  739. 640,
  740. 480,
  741. 32,
  742. 0,
  743. FALSE);
  744. if (SUCCEEDED(hr))
  745. {
  746. hr = GetHALCapsInCurrentMode(pHalData, pAdapterInfo, FALSE, TRUE);
  747. }
  748. if (FAILED(hr))
  749. {
  750. // If they don't report caps in 32bpp mode (ala Voodoo 3), then go
  751. // back to 16bpp mode and get the caps. If the device supports
  752. // caps in any mode, we want to exit this function with the caps.
  753. D3D8SetMode (pHalData->hDD,
  754. pAdapterInfo->DeviceName,
  755. 640,
  756. 480,
  757. 16,
  758. 0,
  759. FALSE);
  760. hr = GetHALCapsInCurrentMode(pHalData, pAdapterInfo, FALSE, TRUE);
  761. // If they don't report good D3D caps in any mode at all, we still need
  762. // to return some caps, if only so we can support a SW driver.
  763. if (FAILED(hr))
  764. {
  765. GetHALCapsInCurrentMode(pHalData, pAdapterInfo, TRUE, TRUE);
  766. for (i = 0; i < pAdapterInfo->HALCaps.GDD8NumSupportedFormatOps; i++)
  767. {
  768. pAdapterInfo->HALCaps.pGDD8SupportedFormatOps[i].ddpfPixelFormat.dwOperations &= D3DFORMAT_OP_DISPLAYMODE;
  769. }
  770. }
  771. }
  772. //And now set back to original mode...
  773. D3D8SetMode (pHalData->hDD,
  774. pAdapterInfo->DeviceName,
  775. OrigMode.Width,
  776. OrigMode.Height,
  777. OrigBpp,
  778. 0,
  779. TRUE);
  780. }
  781. #undef DPF_MODNAME
  782. #define DPF_MODNAME "GetRefCaps"
  783. void CEnum::GetRefCaps(UINT iAdapter)
  784. {
  785. // If we've already got the caps once, there's ne need to get
  786. // them again
  787. if (m_REFCaps[iAdapter].GDD8NumSupportedFormatOps == 0)
  788. {
  789. AddSoftwareDevice(D3DDEVTYPE_REF,
  790. &m_REFCaps[iAdapter],
  791. &m_AdapterInfo[iAdapter],
  792. NULL);
  793. }
  794. }
  795. void CEnum::GetSwCaps(UINT iAdapter)
  796. {
  797. // If we've already got the caps once, there's ne need to get
  798. // them again
  799. if (m_SwCaps[iAdapter].GDD8NumSupportedFormatOps == 0)
  800. {
  801. AddSoftwareDevice(D3DDEVTYPE_SW,
  802. &m_SwCaps[iAdapter],
  803. &m_AdapterInfo[iAdapter],
  804. m_pSwInitFunction);
  805. }
  806. }
  807. // IsSupportedOp
  808. // Runs the pixel format operation list looking to see if the
  809. // selected format can support at least the requested operations.
  810. #undef DPF_MODNAME
  811. #define DPF_MODNAME "IsSupportedOp"
  812. BOOL IsSupportedOp (D3DFORMAT Format,
  813. DDSURFACEDESC* pList,
  814. UINT NumElements,
  815. DWORD dwRequestedOps)
  816. {
  817. UINT i;
  818. for (i = 0; i < NumElements; i++)
  819. {
  820. DDASSERT(pList[i].ddpfPixelFormat.dwFlags == DDPF_D3DFORMAT);
  821. if (pList[i].ddpfPixelFormat.dwFourCC == (DWORD) Format &&
  822. (pList[i].ddpfPixelFormat.dwOperations & dwRequestedOps) == dwRequestedOps)
  823. {
  824. return TRUE;
  825. }
  826. }
  827. return FALSE;
  828. }
  829. #undef DPF_MODNAME
  830. #define DPF_MODNAME "IsInList"
  831. BOOL IsInList (D3DFORMAT Format,
  832. D3DFORMAT* pList,
  833. UINT NumElements)
  834. {
  835. UINT i;
  836. for (i = 0; i < NumElements; i++)
  837. {
  838. if (pList[i] == Format)
  839. {
  840. return TRUE;
  841. }
  842. }
  843. return FALSE;
  844. }
  845. #undef DPF_MODNAME
  846. #define DPF_MODNAME "CEnum::MapDepthStencilFormat"
  847. D3DFORMAT CEnum::MapDepthStencilFormat(UINT iAdapter,
  848. D3DDEVTYPE Type,
  849. D3DFORMAT Format) const
  850. {
  851. DXGASSERT(CPixel::IsMappedDepthFormat(D3DFMT_D24X8));
  852. DXGASSERT(CPixel::IsMappedDepthFormat(D3DFMT_D15S1));
  853. DXGASSERT(CPixel::IsMappedDepthFormat(D3DFMT_D24S8));
  854. DXGASSERT(CPixel::IsMappedDepthFormat(D3DFMT_D16));
  855. DXGASSERT(CPixel::IsMappedDepthFormat(D3DFMT_D24X4S4));
  856. if (CPixel::IsMappedDepthFormat(Format))
  857. {
  858. DDSURFACEDESC *pTextureList;
  859. UINT NumTextures;
  860. switch (Type)
  861. {
  862. case D3DDEVTYPE_SW:
  863. pTextureList = m_SwCaps[iAdapter].pGDD8SupportedFormatOps;
  864. NumTextures = m_SwCaps[iAdapter].GDD8NumSupportedFormatOps;
  865. break;
  866. case D3DDEVTYPE_HAL:
  867. NumTextures = m_AdapterInfo[iAdapter].HALCaps.GDD8NumSupportedFormatOps;
  868. pTextureList = m_AdapterInfo[iAdapter].HALCaps.pGDD8SupportedFormatOps;
  869. break;
  870. case D3DDEVTYPE_REF:
  871. NumTextures = m_REFCaps[iAdapter].GDD8NumSupportedFormatOps;
  872. pTextureList = m_REFCaps[iAdapter].pGDD8SupportedFormatOps;
  873. break;
  874. }
  875. // No operations are required; we just want to know
  876. // if this format is listed in the table for any purpose
  877. // at all
  878. DWORD dwRequiredOperations = 0;
  879. switch (Format)
  880. {
  881. case D3DFMT_D24X4S4:
  882. if (IsSupportedOp(D3DFMT_X4S4D24, pTextureList, NumTextures, dwRequiredOperations))
  883. {
  884. return D3DFMT_X4S4D24;
  885. }
  886. break;
  887. case D3DFMT_D24X8:
  888. if (IsSupportedOp(D3DFMT_X8D24, pTextureList, NumTextures, dwRequiredOperations))
  889. {
  890. return D3DFMT_X8D24;
  891. }
  892. break;
  893. case D3DFMT_D24S8:
  894. if (IsSupportedOp(D3DFMT_S8D24, pTextureList, NumTextures, dwRequiredOperations))
  895. {
  896. return D3DFMT_S8D24;
  897. }
  898. break;
  899. case D3DFMT_D16:
  900. if (IsSupportedOp(D3DFMT_D16, pTextureList, NumTextures, dwRequiredOperations))
  901. {
  902. return D3DFMT_D16;
  903. }
  904. return D3DFMT_D16_LOCKABLE;
  905. case D3DFMT_D15S1:
  906. if (IsSupportedOp(D3DFMT_S1D15, pTextureList, NumTextures, dwRequiredOperations))
  907. {
  908. return D3DFMT_S1D15;
  909. }
  910. break;
  911. default:
  912. // Unexpected format?
  913. DXGASSERT(FALSE);
  914. break;
  915. }
  916. }
  917. return Format;
  918. }
  919. #undef DPF_MODNAME
  920. #define DPF_MODNAME "CEnum::GetAdapterCaps"
  921. HRESULT CEnum::GetAdapterCaps(UINT iAdapter,
  922. D3DDEVTYPE Type,
  923. D3D8_DRIVERCAPS** ppCaps)
  924. {
  925. *ppCaps = NULL;
  926. if (Type == D3DDEVTYPE_REF)
  927. {
  928. GetRefCaps (iAdapter);
  929. *ppCaps = &m_REFCaps[iAdapter];
  930. if (m_REFCaps[iAdapter].GDD8NumSupportedFormatOps == 0)
  931. {
  932. DPF_ERR("The reference driver cannot be found. GetAdapterCaps fails.");
  933. return D3DERR_NOTAVAILABLE;
  934. }
  935. return D3D_OK;
  936. }
  937. else if (Type == D3DDEVTYPE_SW)
  938. {
  939. if (m_pSwInitFunction == NULL)
  940. {
  941. DPF_ERR("No SW device has been registered.. GetAdapterCaps fails.");
  942. return D3DERR_INVALIDCALL;
  943. }
  944. else
  945. {
  946. GetSwCaps(iAdapter);
  947. *ppCaps = &m_SwCaps[iAdapter];
  948. if (m_SwCaps[iAdapter].GDD8NumSupportedFormatOps == 0)
  949. {
  950. DPF_ERR("The software driver cannot be loaded. GetAdapterCaps fails.");
  951. return D3DERR_NOTAVAILABLE;
  952. }
  953. return D3D_OK;
  954. }
  955. }
  956. else if (Type == D3DDEVTYPE_HAL)
  957. {
  958. DWORD i;
  959. if (m_bDisableHAL)
  960. {
  961. DPF_ERR("HW device not available. GetAdapterCaps fails.");
  962. return D3DERR_NOTAVAILABLE;
  963. }
  964. *ppCaps = &m_AdapterInfo[iAdapter].HALCaps;
  965. return D3D_OK;
  966. }
  967. return D3DERR_INVALIDDEVICE;
  968. }
  969. void GetDX8HALCaps(UINT iAdapter, PD3D8_DEVICEDATA pHalData, ADAPTERINFO * pAdapterInfo)
  970. {
  971. //DX7 or older drivers may need to be profiled to determine
  972. //their 555/565 format and whether they support an alpha
  973. //channel in 32bpp
  974. D3DFORMAT CachedUnknown16 = D3DFMT_UNKNOWN;
  975. UINT CachedHALFlags = 0;
  976. D3DDISPLAYMODE Mode;
  977. BOOL bProfiled = FALSE;
  978. UINT i;
  979. HRESULT hr;
  980. // If it's a DX8 driver, we hopefully don't need to profile at all.
  981. pAdapterInfo->Unknown16 = D3DFMT_UNKNOWN;
  982. hr = GetHALCapsInCurrentMode(pHalData, pAdapterInfo, FALSE, FALSE);
  983. if (SUCCEEDED(hr))
  984. {
  985. for (i = 0; i < pAdapterInfo->HALCaps.GDD8NumSupportedFormatOps; i++)
  986. {
  987. if (pAdapterInfo->HALCaps.pGDD8SupportedFormatOps[i].ddpfPixelFormat.dwOperations & D3DFORMAT_OP_DISPLAYMODE)
  988. {
  989. switch (pAdapterInfo->HALCaps.pGDD8SupportedFormatOps[i].ddpfPixelFormat.dwFourCC)
  990. {
  991. case D3DFMT_X1R5G5B5:
  992. case D3DFMT_R5G6B5:
  993. pAdapterInfo->Unknown16 = (D3DFORMAT) pAdapterInfo->HALCaps.pGDD8SupportedFormatOps[i].ddpfPixelFormat.dwFourCC;
  994. break;
  995. }
  996. }
  997. }
  998. if (pAdapterInfo->Unknown16 != D3DFMT_UNKNOWN)
  999. {
  1000. // That wasn't hard
  1001. return;
  1002. }
  1003. }
  1004. // We are definately need to read stuff from the caps at some point,
  1005. // so why not now?
  1006. if (!ReadCapsFromCache(iAdapter,
  1007. NULL,
  1008. &CachedHALFlags,
  1009. &CachedUnknown16,
  1010. pAdapterInfo->DeviceName,
  1011. pAdapterInfo->bIsDisplay))
  1012. {
  1013. // There's nothing to read, so we need to re-profile
  1014. ProfileAdapter(
  1015. pAdapterInfo,
  1016. pHalData);
  1017. bProfiled = TRUE;
  1018. }
  1019. // If we profiled, then we already have everything that we need;
  1020. // otherwise, we have to go get it.
  1021. if (!bProfiled)
  1022. {
  1023. D3D8GetMode (pHalData->hDD, pAdapterInfo->DeviceName, &Mode, D3DFMT_UNKNOWN);
  1024. if ((Mode.Format == D3DFMT_X1R5G5B5) ||
  1025. (Mode.Format == D3DFMT_R5G6B5))
  1026. {
  1027. pAdapterInfo->Unknown16 = Mode.Format;
  1028. }
  1029. else
  1030. {
  1031. pAdapterInfo->Unknown16 = CachedUnknown16;
  1032. }
  1033. HRESULT hCurrentModeIsSupported = GetHALCapsInCurrentMode(pHalData, pAdapterInfo, FALSE, TRUE);
  1034. if (FAILED(hCurrentModeIsSupported))
  1035. {
  1036. // We assume that this will succeed because the call above already has
  1037. ReadCapsFromCache(iAdapter,
  1038. &pAdapterInfo->HALCaps,
  1039. &CachedHALFlags,
  1040. &CachedUnknown16,
  1041. pAdapterInfo->DeviceName,
  1042. pAdapterInfo->bIsDisplay);
  1043. DPF(0,"D3D not supported in current mode - reading caps from file");
  1044. }
  1045. }
  1046. //We now have good caps. Write them out to the cache.
  1047. WriteCapsToCache(iAdapter,
  1048. &pAdapterInfo->HALCaps,
  1049. pAdapterInfo->HALFlags,
  1050. pAdapterInfo->Unknown16,
  1051. pAdapterInfo->DeviceName,
  1052. pAdapterInfo->bIsDisplay);
  1053. }
  1054. #ifdef WINNT
  1055. void FakeDirectDrawCreate (ADAPTERINFO * pAdapterInfo, int iAdapter)
  1056. {
  1057. HDC hdc;
  1058. DDSURFACEDESC* pTextureList = NULL;
  1059. BOOL bProfiled = FALSE;
  1060. BOOL b32Supported;
  1061. BOOL b16Supported;
  1062. int NumOps;
  1063. DWORD j;
  1064. pTextureList = (DDSURFACEDESC *) MemAlloc (2 * sizeof (*pTextureList));
  1065. if (pTextureList != NULL)
  1066. {
  1067. hdc = DD_CreateDC(pAdapterInfo->DeviceName);
  1068. if (hdc != NULL)
  1069. {
  1070. HANDLE hDD;
  1071. HINSTANCE hLib;
  1072. D3D8CreateDirectDrawObject(hdc,
  1073. pAdapterInfo->DeviceName,
  1074. &hDD,
  1075. D3DDEVTYPE_HAL,
  1076. &hLib,
  1077. NULL);
  1078. if (hDD != NULL)
  1079. {
  1080. pAdapterInfo->bNoDDrawSupport = TRUE;
  1081. // Figure out the unknown 16 value
  1082. if (!ReadCapsFromCache(iAdapter,
  1083. NULL,
  1084. &(pAdapterInfo->HALFlags),
  1085. &(pAdapterInfo->Unknown16),
  1086. pAdapterInfo->DeviceName,
  1087. pAdapterInfo->bIsDisplay))
  1088. {
  1089. D3DDISPLAYMODE OrigMode;
  1090. D3DDISPLAYMODE NewMode;
  1091. D3D8GetMode (hDD,
  1092. pAdapterInfo->DeviceName,
  1093. &OrigMode,
  1094. D3DFMT_UNKNOWN);
  1095. if ((OrigMode.Format == D3DFMT_R5G6B5) ||
  1096. (OrigMode.Format == D3DFMT_X1R5G5B5))
  1097. {
  1098. pAdapterInfo->Unknown16 = OrigMode.Format;
  1099. }
  1100. else
  1101. {
  1102. D3D8SetMode (hDD,
  1103. pAdapterInfo->DeviceName,
  1104. 640,
  1105. 480,
  1106. 16,
  1107. 0,
  1108. FALSE);
  1109. D3D8GetMode (hDD,
  1110. pAdapterInfo->DeviceName,
  1111. &NewMode,
  1112. D3DFMT_UNKNOWN);
  1113. D3D8SetMode (hDD,
  1114. pAdapterInfo->DeviceName,
  1115. OrigMode.Width,
  1116. OrigMode.Height,
  1117. 0,
  1118. 0,
  1119. TRUE);
  1120. pAdapterInfo->Unknown16 = NewMode.Format;
  1121. }
  1122. bProfiled = TRUE;
  1123. }
  1124. // Build the mode table
  1125. while (1)
  1126. {
  1127. D3D8BuildModeTable(
  1128. pAdapterInfo->DeviceName,
  1129. NULL,
  1130. &(pAdapterInfo->NumModes),
  1131. pAdapterInfo->Unknown16,
  1132. hDD,
  1133. TRUE,
  1134. TRUE);
  1135. if (pAdapterInfo->NumModes)
  1136. {
  1137. pAdapterInfo->pModeTable = (D3DDISPLAYMODE*)
  1138. MemAlloc (sizeof(D3DDISPLAYMODE) * pAdapterInfo->NumModes);
  1139. if (pAdapterInfo->pModeTable != NULL)
  1140. {
  1141. D3D8BuildModeTable(
  1142. pAdapterInfo->DeviceName,
  1143. pAdapterInfo->pModeTable,
  1144. &(pAdapterInfo->NumModes),
  1145. pAdapterInfo->Unknown16,
  1146. hDD,
  1147. TRUE,
  1148. TRUE);
  1149. //If D3D8BuildModeTable finds it needs more space for its table,
  1150. //it will return 0 to indicate we should try again.
  1151. if (0 == pAdapterInfo->NumModes)
  1152. {
  1153. MemFree(pAdapterInfo->pModeTable);
  1154. pAdapterInfo->pModeTable = NULL;
  1155. continue;
  1156. }
  1157. }
  1158. else
  1159. {
  1160. pAdapterInfo->NumModes = 0;
  1161. }
  1162. }
  1163. break;
  1164. }//while(1)
  1165. // Now build a rudimentary op list based on what modes we support
  1166. b32Supported = b16Supported = FALSE;
  1167. for (j = 0; j < pAdapterInfo->NumModes; j++)
  1168. {
  1169. if (pAdapterInfo->pModeTable[j].Format == D3DFMT_X8R8G8B8)
  1170. {
  1171. b32Supported = TRUE;
  1172. }
  1173. if (pAdapterInfo->pModeTable[j].Format == pAdapterInfo->Unknown16)
  1174. {
  1175. b16Supported = TRUE;
  1176. }
  1177. }
  1178. NumOps = 0;
  1179. if (b16Supported)
  1180. {
  1181. pTextureList[NumOps].ddpfPixelFormat.dwFlags = DDPF_D3DFORMAT;
  1182. pTextureList[NumOps].ddpfPixelFormat.dwFourCC = (DWORD) pAdapterInfo->Unknown16;
  1183. pTextureList[NumOps].ddpfPixelFormat.dwOperations = D3DFORMAT_OP_DISPLAYMODE;
  1184. pTextureList[NumOps].ddpfPixelFormat.dwPrivateFormatBitCount = 0;
  1185. pTextureList[NumOps].ddpfPixelFormat.MultiSampleCaps.wFlipMSTypes = 0;
  1186. pTextureList[NumOps].ddpfPixelFormat.MultiSampleCaps.wBltMSTypes = 0;
  1187. NumOps++;
  1188. }
  1189. if (b32Supported)
  1190. {
  1191. pTextureList[NumOps].ddpfPixelFormat.dwFlags = DDPF_D3DFORMAT;
  1192. pTextureList[NumOps].ddpfPixelFormat.dwFourCC = (DWORD) D3DFMT_X8R8G8B8;
  1193. pTextureList[NumOps].ddpfPixelFormat.dwOperations = D3DFORMAT_OP_DISPLAYMODE;
  1194. pTextureList[NumOps].ddpfPixelFormat.dwPrivateFormatBitCount = 0;
  1195. pTextureList[NumOps].ddpfPixelFormat.MultiSampleCaps.wFlipMSTypes = 0;
  1196. pTextureList[NumOps].ddpfPixelFormat.MultiSampleCaps.wBltMSTypes = 0;
  1197. NumOps++;
  1198. }
  1199. pAdapterInfo->HALCaps.pGDD8SupportedFormatOps = pTextureList;
  1200. pAdapterInfo->HALCaps.GDD8NumSupportedFormatOps = NumOps;
  1201. if (bProfiled)
  1202. {
  1203. WriteCapsToCache(iAdapter,
  1204. &(pAdapterInfo->HALCaps),
  1205. pAdapterInfo->HALFlags,
  1206. pAdapterInfo->Unknown16,
  1207. pAdapterInfo->DeviceName,
  1208. pAdapterInfo->bIsDisplay);
  1209. }
  1210. D3D8DeleteDirectDrawObject(hDD);
  1211. }
  1212. DD_DoneDC(hdc);
  1213. }
  1214. if (pAdapterInfo->HALCaps.pGDD8SupportedFormatOps == NULL)
  1215. {
  1216. MemFree(pTextureList);
  1217. }
  1218. }
  1219. }
  1220. #endif
  1221. #undef DPF_MODNAME
  1222. #define DPF_MODNAME "CEnum::CEnum"
  1223. CEnum::CEnum(UINT AppSdkVersion)
  1224. :
  1225. m_cRef(1),
  1226. m_cAdapter(0),
  1227. m_bHasExclusive(FALSE),
  1228. m_AppSdkVersion(AppSdkVersion)
  1229. {
  1230. DWORD rc;
  1231. DWORD keyidx;
  1232. HKEY hkey;
  1233. HKEY hsubkey;
  1234. char keyname[256];
  1235. char desc[256];
  1236. char drvname[MAX_PATH];
  1237. DWORD cb;
  1238. DWORD i;
  1239. DWORD type;
  1240. GUID guid;
  1241. HDC hdc;
  1242. DISPLAY_DEVICEA dd;
  1243. // Give our base class a pointer to ourselves
  1244. SetOwner(this);
  1245. // Initialize our critical section
  1246. EnableCriticalSection();
  1247. // Disable DPFs that occur during this phase
  1248. DPF_MUTE();
  1249. // WARNING: Must call DPF_UNMUTE before returning from
  1250. // this function.
  1251. for (i = 0; i < MAX_DX8_ADAPTERS; i++)
  1252. m_pFullScreenDevice[i] = NULL;
  1253. ZeroMemory(m_AdapterInfo, sizeof(m_AdapterInfo));
  1254. // Always make the first entry reflect the primary device
  1255. ZeroMemory(&dd, sizeof(dd));
  1256. dd.cb = sizeof(dd);
  1257. for (i = 0; xxxEnumDisplayDevicesA(NULL, i, &dd, 0); i++)
  1258. {
  1259. //
  1260. // skip drivers that are not hardware devices
  1261. //
  1262. if (dd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)
  1263. continue;
  1264. //
  1265. // don't enumerate devices that are not attached
  1266. //
  1267. if (!(dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
  1268. continue;
  1269. if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
  1270. {
  1271. m_AdapterInfo[m_cAdapter].Guid = DisplayGUID;
  1272. m_AdapterInfo[m_cAdapter].Guid.Data1 += i;
  1273. lstrcpyn(m_AdapterInfo[m_cAdapter].DeviceName, dd.DeviceName, MAX_PATH);
  1274. m_AdapterInfo[m_cAdapter].bIsPrimary = TRUE;
  1275. m_AdapterInfo[m_cAdapter++].bIsDisplay = TRUE;
  1276. }
  1277. }
  1278. // Now get the info for the attached secondary devices
  1279. for (i = 0; xxxEnumDisplayDevicesA(NULL, i, &dd, 0); i++)
  1280. {
  1281. //
  1282. // skip drivers that are not hardware devices
  1283. //
  1284. if (dd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)
  1285. continue;
  1286. //
  1287. // don't enumerate devices that are not attached
  1288. //
  1289. if (!(dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
  1290. continue;
  1291. if (!(dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) &&
  1292. (m_cAdapter < MAX_DX8_ADAPTERS))
  1293. {
  1294. m_AdapterInfo[m_cAdapter].Guid = DisplayGUID;
  1295. m_AdapterInfo[m_cAdapter].Guid.Data1 += i;
  1296. lstrcpyn(m_AdapterInfo[m_cAdapter].DeviceName, dd.DeviceName, MAX_PATH);
  1297. m_AdapterInfo[m_cAdapter].bIsPrimary = FALSE;
  1298. m_AdapterInfo[m_cAdapter++].bIsDisplay = TRUE;
  1299. }
  1300. }
  1301. // Now get info for the passthrough devices listed under
  1302. // HKEY_LOCALMACHINE\Hardware\DirectDrawDrivers
  1303. if (RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_DDHW, &hkey) == 0)
  1304. {
  1305. keyidx = 0;
  1306. while (!RegEnumKey(hkey, keyidx, keyname, sizeof(keyname)))
  1307. {
  1308. if (strToGUID(keyname, &guid))
  1309. {
  1310. if (!RegOpenKey(hkey, keyname, &hsubkey))
  1311. {
  1312. cb = sizeof(desc) - 1;
  1313. if (!RegQueryValueEx(hsubkey, REGSTR_KEY_DDHW_DESCRIPTION, NULL, &type,
  1314. (CONST LPBYTE)desc, &cb))
  1315. {
  1316. if (type == REG_SZ)
  1317. {
  1318. desc[cb] = 0;
  1319. cb = sizeof(drvname) - 1;
  1320. if (!RegQueryValueEx(hsubkey, REGSTR_KEY_DDHW_DRIVERNAME, NULL, &type,
  1321. (CONST LPBYTE)drvname, &cb))
  1322. {
  1323. // It is possible that the registry is out
  1324. // of date, so we will try to create a DC.
  1325. // The problem is that the Voodoo 1 driver
  1326. // will suceed on a Voodoo 2, Banshee, or
  1327. // Voodoo 3 (and hang later), so we need to
  1328. // hack around it.
  1329. drvname[cb] = 0;
  1330. if (Voodoo1GoodToGo(&guid))
  1331. {
  1332. hdc = DD_CreateDC(drvname);
  1333. }
  1334. else
  1335. {
  1336. hdc = NULL;
  1337. }
  1338. if ((type == REG_SZ) &&
  1339. (hdc != NULL))
  1340. {
  1341. if (m_cAdapter < MAX_DX8_ADAPTERS)
  1342. {
  1343. drvname[cb] = 0;
  1344. m_AdapterInfo[m_cAdapter].Guid = guid;
  1345. lstrcpyn(m_AdapterInfo[m_cAdapter].DeviceName, drvname, MAX_PATH);
  1346. m_AdapterInfo[m_cAdapter].bIsPrimary = FALSE;
  1347. m_AdapterInfo[m_cAdapter++].bIsDisplay = FALSE;
  1348. }
  1349. }
  1350. if (hdc != NULL)
  1351. {
  1352. DD_DoneDC(hdc);
  1353. }
  1354. }
  1355. }
  1356. }
  1357. RegCloseKey(hsubkey);
  1358. }
  1359. }
  1360. keyidx++;
  1361. }
  1362. RegCloseKey(hkey);
  1363. }
  1364. DPF_UNMUTE();
  1365. // Now that we know about all of the devices, we need to build a mode
  1366. // table for each one
  1367. for (i = 0; i < m_cAdapter; i++)
  1368. {
  1369. HRESULT hr;
  1370. D3DDISPLAYMODE Mode;
  1371. DWORD j;
  1372. BOOL b16bppSupported;
  1373. BOOL b32bppSupported;
  1374. PD3D8_DEVICEDATA pHalData;
  1375. hr = InternalDirectDrawCreate(&pHalData,
  1376. &m_AdapterInfo[i],
  1377. D3DDEVTYPE_HAL,
  1378. NULL,
  1379. D3DFMT_UNKNOWN,
  1380. NULL,
  1381. 0);
  1382. if (FAILED(hr))
  1383. {
  1384. memset(&m_AdapterInfo[i].HALCaps, 0, sizeof(m_AdapterInfo[i].HALCaps));
  1385. // On Win2K, we want to enable sufficient functionality so that this
  1386. // adapter can at least run a sw driver. If it truly failed due to
  1387. // no ddraw support, we need to special case this and then build a
  1388. // rudimentary op list indicting that it works in the current mode.
  1389. #ifdef WINNT
  1390. FakeDirectDrawCreate(&m_AdapterInfo[i], i);
  1391. #endif
  1392. }
  1393. else
  1394. {
  1395. GetDX8HALCaps(i, pHalData, &m_AdapterInfo[i]);
  1396. b16bppSupported = b32bppSupported = FALSE;
  1397. for (j = 0; j < m_AdapterInfo[i].HALCaps.GDD8NumSupportedFormatOps; j++)
  1398. {
  1399. if (m_AdapterInfo[i].HALCaps.pGDD8SupportedFormatOps[j].ddpfPixelFormat.dwOperations & D3DFORMAT_OP_DISPLAYMODE)
  1400. {
  1401. switch(m_AdapterInfo[i].HALCaps.pGDD8SupportedFormatOps[j].ddpfPixelFormat.dwFourCC)
  1402. {
  1403. case D3DFMT_X1R5G5B5:
  1404. case D3DFMT_R5G6B5:
  1405. b16bppSupported = TRUE;
  1406. break;
  1407. case D3DFMT_X8R8G8B8:
  1408. b32bppSupported = TRUE;
  1409. break;
  1410. }
  1411. }
  1412. }
  1413. while (1)
  1414. {
  1415. D3D8BuildModeTable(
  1416. m_AdapterInfo[i].DeviceName,
  1417. NULL,
  1418. &m_AdapterInfo[i].NumModes,
  1419. m_AdapterInfo[i].Unknown16,
  1420. pHalData->hDD,
  1421. b16bppSupported,
  1422. b32bppSupported);
  1423. if (m_AdapterInfo[i].NumModes)
  1424. {
  1425. m_AdapterInfo[i].pModeTable = (D3DDISPLAYMODE*)
  1426. MemAlloc (sizeof(D3DDISPLAYMODE) * m_AdapterInfo[i].NumModes);
  1427. if (m_AdapterInfo[i].pModeTable != NULL)
  1428. {
  1429. D3D8BuildModeTable(
  1430. m_AdapterInfo[i].DeviceName,
  1431. m_AdapterInfo[i].pModeTable,
  1432. &m_AdapterInfo[i].NumModes,
  1433. m_AdapterInfo[i].Unknown16,
  1434. pHalData->hDD,
  1435. b16bppSupported,
  1436. b32bppSupported);
  1437. //If D3D8BuildModeTable finds it needs more space for its table,
  1438. //it will return 0 to indicate we should try again.
  1439. if (0 == m_AdapterInfo[i].NumModes)
  1440. {
  1441. MemFree(m_AdapterInfo[i].pModeTable);
  1442. m_AdapterInfo[i].pModeTable = NULL;
  1443. continue;
  1444. }
  1445. }
  1446. else
  1447. {
  1448. m_AdapterInfo[i].NumModes = 0;
  1449. }
  1450. }
  1451. break;
  1452. }//while(1)
  1453. // If this doesn't have a ddraw HAL, but guessed that it might
  1454. // support a 32bpp mode, go see if we were right.
  1455. if (b32bppSupported &&
  1456. (m_AdapterInfo[i].HALCaps.D3DCaps.DevCaps == 0) &&
  1457. (m_AdapterInfo[i].HALCaps.DisplayFormatWithoutAlpha != D3DFMT_X8R8G8B8))
  1458. {
  1459. for (j = 0; j < m_AdapterInfo[i].NumModes; j++)
  1460. {
  1461. if (m_AdapterInfo[i].pModeTable[j].Format == D3DFMT_X8R8G8B8)
  1462. {
  1463. break;
  1464. }
  1465. }
  1466. if (j >= m_AdapterInfo[i].NumModes)
  1467. {
  1468. // This card apparently does NOT support 32bpp so remove it
  1469. for (j = 0; j < m_AdapterInfo[i].HALCaps.GDD8NumSupportedFormatOps; j++)
  1470. {
  1471. if ((m_AdapterInfo[i].HALCaps.pGDD8SupportedFormatOps[j].ddpfPixelFormat.dwOperations & D3DFORMAT_OP_DISPLAYMODE) &&
  1472. (m_AdapterInfo[i].HALCaps.pGDD8SupportedFormatOps[j].ddpfPixelFormat.dwFourCC == D3DFMT_X8R8G8B8))
  1473. {
  1474. m_AdapterInfo[i].HALCaps.pGDD8SupportedFormatOps[j].ddpfPixelFormat.dwOperations &= ~D3DFORMAT_OP_DISPLAYMODE;
  1475. }
  1476. }
  1477. }
  1478. }
  1479. InternalDirectDrawRelease(pHalData);
  1480. }
  1481. }
  1482. m_hGammaCalibrator = NULL;
  1483. m_pGammaCalibratorProc = NULL;
  1484. m_bAttemptedGammaCalibrator= FALSE;
  1485. m_bGammaCalibratorExists = FALSE;
  1486. // The first time through, we will also check to see if a gamma
  1487. // calibrator is registered. All we'll do here is read the registry
  1488. // key and if it's non-NULL, we'll assume that one exists.
  1489. {
  1490. HKEY hkey;
  1491. if (!RegOpenKey(HKEY_LOCAL_MACHINE,
  1492. REGSTR_PATH_DDRAW "\\" REGSTR_KEY_GAMMA_CALIBRATOR, &hkey))
  1493. {
  1494. DWORD type;
  1495. DWORD cb;
  1496. cb = sizeof(m_szGammaCalibrator);
  1497. if (!RegQueryValueEx(hkey, REGSTR_VAL_GAMMA_CALIBRATOR,
  1498. NULL, &type, m_szGammaCalibrator, &cb))
  1499. {
  1500. if ((type == REG_SZ) &&
  1501. (m_szGammaCalibrator[0] != '\0'))
  1502. {
  1503. m_bGammaCalibratorExists = TRUE;
  1504. }
  1505. }
  1506. RegCloseKey(hkey);
  1507. }
  1508. }
  1509. // Check to see if they disabled the D3DHAL in the registry
  1510. {
  1511. HKEY hKey;
  1512. if (!RegOpenKey(HKEY_LOCAL_MACHINE, RESPATH_D3D "\\Drivers", &hKey))
  1513. {
  1514. DWORD type;
  1515. DWORD value;
  1516. DWORD cb = sizeof(value);
  1517. if (!RegQueryValueEx(hKey, "SoftwareOnly", NULL, &type, (CONST LPBYTE)&value, &cb))
  1518. {
  1519. if (value)
  1520. {
  1521. m_bDisableHAL = TRUE;
  1522. }
  1523. else
  1524. {
  1525. m_bDisableHAL = FALSE;
  1526. }
  1527. }
  1528. RegCloseKey(hKey);
  1529. }
  1530. }
  1531. DXGASSERT(IsValid());
  1532. } // CEnum::CEnum
  1533. #undef DPF_MODNAME
  1534. #define DPF_MODNAME "CEnum::GetAdapterCount"
  1535. STDMETHODIMP_(UINT) CEnum::GetAdapterCount()
  1536. {
  1537. API_ENTER_RET(this, UINT);
  1538. return m_cAdapter;
  1539. } // GetAdapterCount
  1540. #undef DPF_MODNAME
  1541. #define DPF_MODNAME "CEnum::GetAdapterIdentifier"
  1542. STDMETHODIMP CEnum::GetAdapterIdentifier(
  1543. UINT iAdapter,
  1544. DWORD dwFlags,
  1545. D3DADAPTER_IDENTIFIER8 *pIdentifier)
  1546. {
  1547. API_ENTER(this);
  1548. if (!VALID_WRITEPTR(pIdentifier, sizeof(D3DADAPTER_IDENTIFIER8)))
  1549. {
  1550. DPF_ERR("Invalid pIdentifier parameter specified for GetAdapterIdentifier");
  1551. return D3DERR_INVALIDCALL;
  1552. }
  1553. memset(pIdentifier, 0, sizeof(*pIdentifier));
  1554. if (dwFlags & ~VALID_D3DENUM_FLAGS)
  1555. {
  1556. DPF_ERR("Invalid flags specified. GetAdapterIdentifier fails.");
  1557. return D3DERR_INVALIDCALL;
  1558. }
  1559. if (iAdapter >= m_cAdapter)
  1560. {
  1561. DPF_ERR("Invalid Adapter number specified. GetAdapterIdentifier fails.");
  1562. return D3DERR_INVALIDCALL;
  1563. }
  1564. // Need driver name
  1565. GetAdapterInfo (m_AdapterInfo[iAdapter].DeviceName,
  1566. pIdentifier,
  1567. m_AdapterInfo[iAdapter].bIsDisplay,
  1568. (dwFlags & D3DENUM_NO_WHQL_LEVEL) ? TRUE : FALSE,
  1569. TRUE);
  1570. return D3D_OK;
  1571. } // GetAdapterIdentifier
  1572. #undef DPF_MODNAME
  1573. #define DPF_MODNAME "CEnum::GetAdapterModeCount"
  1574. STDMETHODIMP_(UINT) CEnum::GetAdapterModeCount(
  1575. UINT iAdapter)
  1576. {
  1577. API_ENTER_RET(this, UINT);
  1578. if (iAdapter >= m_cAdapter)
  1579. {
  1580. DPF_ERR("Invalid adapter specified. GetAdapterModeCount returns zero.");
  1581. return 0;
  1582. }
  1583. return m_AdapterInfo[iAdapter].NumModes;
  1584. } // GetAdapterModeCount
  1585. #undef DPF_MODNAME
  1586. #define DPF_MODNAME "CEnum::EnumAdapterModes"
  1587. STDMETHODIMP CEnum::EnumAdapterModes(
  1588. UINT iAdapter,
  1589. UINT iMode,
  1590. D3DDISPLAYMODE* pMode)
  1591. {
  1592. API_ENTER(this);
  1593. if (iAdapter >= m_cAdapter)
  1594. {
  1595. DPF_ERR("Invalid adapter specified. EnumAdapterModes fails.");
  1596. return D3DERR_INVALIDCALL;
  1597. }
  1598. if (iMode >= m_AdapterInfo[iAdapter].NumModes)
  1599. {
  1600. DPF_ERR("Invalid mode number specified. EnumAdapterModes fails.");
  1601. return D3DERR_INVALIDCALL;
  1602. }
  1603. if (!VALID_WRITEPTR(pMode, sizeof(D3DDISPLAYMODE)))
  1604. {
  1605. DPF_ERR("Invalid pMode parameter specified for EnumAdapterModes");
  1606. return D3DERR_INVALIDCALL;
  1607. }
  1608. *pMode = m_AdapterInfo[iAdapter].pModeTable[iMode];
  1609. return D3D_OK;
  1610. } // EnumAdapterModes
  1611. #undef DPF_MODNAME
  1612. #define DPF_MODNAME "CEnum::GetAdapterMonitor"
  1613. HMONITOR CEnum::GetAdapterMonitor(UINT iAdapter)
  1614. {
  1615. API_ENTER_RET(this, HMONITOR);
  1616. if (iAdapter >= m_cAdapter)
  1617. {
  1618. DPF_ERR("Invalid adapter specified. GetAdapterMonitor returns NULL");
  1619. return NULL;
  1620. }
  1621. return GetMonitorFromDeviceName((LPSTR)m_AdapterInfo[iAdapter].DeviceName);
  1622. } // GetAdapterMonitor
  1623. #undef DPF_MODNAME
  1624. #define DPF_MODNAME "CEnum::CheckDeviceFormat"
  1625. STDMETHODIMP CEnum::CheckDeviceFormat(
  1626. UINT iAdapter,
  1627. D3DDEVTYPE DevType,
  1628. D3DFORMAT DisplayFormat,
  1629. DWORD Usage,
  1630. D3DRESOURCETYPE RType,
  1631. D3DFORMAT CheckFormat)
  1632. {
  1633. API_ENTER(this);
  1634. D3D8_DRIVERCAPS* pAdapterCaps;
  1635. HRESULT hr;
  1636. // Check parameters
  1637. if (iAdapter >= m_cAdapter)
  1638. {
  1639. DPF_ERR("Invalid adapter specified. CheckDeviceFormat fails");
  1640. return D3DERR_INVALIDCALL;
  1641. }
  1642. // Check Device Type
  1643. if (DevType != D3DDEVTYPE_REF &&
  1644. DevType != D3DDEVTYPE_HAL &&
  1645. DevType != D3DDEVTYPE_SW)
  1646. {
  1647. DPF_ERR("Invalid device specified to CheckDeviceFormat");
  1648. return D3DERR_INVALIDCALL;
  1649. }
  1650. if ((DisplayFormat == D3DFMT_UNKNOWN) ||
  1651. (CheckFormat == D3DFMT_UNKNOWN))
  1652. {
  1653. DPF(0, "D3DFMT_UNKNOWN is not a valid format.");
  1654. return D3DERR_INVALIDCALL;
  1655. }
  1656. // Sanity check the input format
  1657. if ((DisplayFormat != D3DFMT_X8R8G8B8) &&
  1658. (DisplayFormat != D3DFMT_R5G6B5) &&
  1659. (DisplayFormat != D3DFMT_X1R5G5B5) &&
  1660. (DisplayFormat != D3DFMT_R8G8B8))
  1661. {
  1662. DPF(1, "D3D Unsupported for the adapter format passed to CheckDeviceFormat");
  1663. return D3DERR_NOTAVAILABLE;
  1664. }
  1665. //We infer the texture usage from type...
  1666. if (RType == D3DRTYPE_TEXTURE ||
  1667. RType == D3DRTYPE_CUBETEXTURE ||
  1668. RType == D3DRTYPE_VOLUMETEXTURE)
  1669. {
  1670. Usage |= D3DUSAGE_TEXTURE;
  1671. }
  1672. // Surface should be either render targets or Z/Stencil
  1673. else if (RType == D3DRTYPE_SURFACE)
  1674. {
  1675. if (!(Usage & D3DUSAGE_DEPTHSTENCIL) &&
  1676. !(Usage & D3DUSAGE_RENDERTARGET))
  1677. {
  1678. DPF_ERR("Must specify either D3DUSAGE_DEPTHSTENCIL or D3DUSAGE_RENDERTARGET for D3DRTYPE_SURFACE. CheckDeviceFormat fails.");
  1679. return D3DERR_INVALIDCALL;
  1680. }
  1681. }
  1682. // Any attempt to query anything but an unknown Z/stencil
  1683. // or D16 value must fail (because we explicitly don't allow apps to
  1684. // know what the z/stencil format really is, except for D16).
  1685. if (Usage & D3DUSAGE_DEPTHSTENCIL)
  1686. {
  1687. if (!CPixel::IsEnumeratableZ(CheckFormat))
  1688. {
  1689. DPF_ERR("Format is not in approved list for Z buffer formats. CheckDeviceFormats fails.");
  1690. return D3DERR_INVALIDCALL;
  1691. }
  1692. }
  1693. // Parameter check for invalid usages and resource types
  1694. if ((RType != D3DRTYPE_SURFACE) &&
  1695. (RType != D3DRTYPE_VOLUME) &&
  1696. (RType != D3DRTYPE_TEXTURE) &&
  1697. (RType != D3DRTYPE_VOLUMETEXTURE) &&
  1698. (RType != D3DRTYPE_CUBETEXTURE))
  1699. {
  1700. DPF_ERR("Invalid resource type specified. CheckDeviceFormat fails.");
  1701. return D3DERR_INVALIDCALL;
  1702. }
  1703. if (Usage & ~(D3DUSAGE_EXTERNAL |
  1704. D3DUSAGE_LOCK |
  1705. D3DUSAGE_TEXTURE |
  1706. D3DUSAGE_BACKBUFFER |
  1707. D3DUSAGE_INTERNALBUFFER |
  1708. D3DUSAGE_OFFSCREENPLAIN |
  1709. D3DUSAGE_PRIMARYSURFACE))
  1710. {
  1711. DPF_ERR("Invalid usage flag specified. CheckDeviceFormat fails.");
  1712. return D3DERR_INVALIDCALL;
  1713. }
  1714. hr = GetAdapterCaps(iAdapter,
  1715. DevType,
  1716. &pAdapterCaps);
  1717. if (FAILED(hr))
  1718. {
  1719. return hr;
  1720. }
  1721. // Check if USAGE_DYNAMIC is allowed
  1722. if ((Usage & D3DUSAGE_DYNAMIC) && (Usage & D3DUSAGE_TEXTURE))
  1723. {
  1724. if (!(pAdapterCaps->D3DCaps.Caps2 & D3DCAPS2_DYNAMICTEXTURES))
  1725. {
  1726. DPF_ERR("Driver does not support dynamic textures.");
  1727. return D3DERR_INVALIDCALL;
  1728. }
  1729. if (Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL))
  1730. {
  1731. DPF_ERR("Dynamic textures cannot be rendertargets or depth/stencils.");
  1732. return D3DERR_INVALIDCALL;
  1733. }
  1734. }
  1735. // Make sure that the specified display format is supported
  1736. if (!IsSupportedOp (DisplayFormat,
  1737. pAdapterCaps->pGDD8SupportedFormatOps,
  1738. pAdapterCaps->GDD8NumSupportedFormatOps,
  1739. D3DFORMAT_OP_DISPLAYMODE |D3DFORMAT_OP_3DACCELERATION))
  1740. {
  1741. return D3DERR_NOTAVAILABLE;
  1742. }
  1743. //We now need to map the API desires to the set of capabilities that we
  1744. //allow drivers to express in their DX8 pixel format operation list.
  1745. DWORD dwRequiredOperations=0;
  1746. //We have three different texturing methodologies that the driver may
  1747. //support independently
  1748. switch(RType)
  1749. {
  1750. case D3DRTYPE_TEXTURE:
  1751. dwRequiredOperations |= D3DFORMAT_OP_TEXTURE;
  1752. break;
  1753. case D3DRTYPE_VOLUMETEXTURE:
  1754. dwRequiredOperations |= D3DFORMAT_OP_VOLUMETEXTURE;
  1755. break;
  1756. case D3DRTYPE_CUBETEXTURE:
  1757. dwRequiredOperations |= D3DFORMAT_OP_CUBETEXTURE;
  1758. break;
  1759. }
  1760. // If it's a depth/stencil, make sure it's a format that the driver understands
  1761. CheckFormat = MapDepthStencilFormat(iAdapter,
  1762. DevType,
  1763. CheckFormat);
  1764. //Render targets may be the same format as the display, or they may
  1765. //be different
  1766. if (Usage & D3DUSAGE_RENDERTARGET)
  1767. {
  1768. if (DisplayFormat == CheckFormat)
  1769. {
  1770. // We have a special cap for the case when the offscreen is the
  1771. // same format as the display
  1772. dwRequiredOperations |= D3DFORMAT_OP_SAME_FORMAT_RENDERTARGET;
  1773. }
  1774. else if ((CPixel::SuppressAlphaChannel(CheckFormat) != CheckFormat) && //offscreen has alpha
  1775. (CPixel::SuppressAlphaChannel(CheckFormat) == DisplayFormat)) //offscreen is same as display mod alpha
  1776. {
  1777. //We have a special cap for the case when the offscreen is the same
  1778. //format as the display modulo the alpha channel
  1779. //(such as X8R8G8B8 for the primary and A8R8G8B8 for the offscreen).
  1780. dwRequiredOperations |= D3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET;
  1781. }
  1782. else
  1783. {
  1784. dwRequiredOperations |= D3DFORMAT_OP_OFFSCREEN_RENDERTARGET;
  1785. }
  1786. }
  1787. //Some hardware doesn't support Z and color buffers of differing pixel depths.
  1788. //We only do this check on known z/stencil formats, since drivers are free
  1789. //to spoof unknown formats (they can't be locked).
  1790. // Now we know what we're being asked to do on this format...
  1791. // let's run through the driver's list and see if it can do it.
  1792. for(UINT i=0;i< pAdapterCaps->GDD8NumSupportedFormatOps; i++)
  1793. {
  1794. // We need a match for format, plus all the requested operation flags
  1795. if ((CheckFormat ==
  1796. (D3DFORMAT) pAdapterCaps->pGDD8SupportedFormatOps[i].ddpfPixelFormat.dwFourCC) &&
  1797. (dwRequiredOperations == (dwRequiredOperations &
  1798. pAdapterCaps->pGDD8SupportedFormatOps[i].ddpfPixelFormat.dwOperations)))
  1799. {
  1800. return D3D_OK;
  1801. }
  1802. }
  1803. // We don't spew info here; because NotAvailable is a reasonable
  1804. // usage of the API; this doesn't reflect an app bug or an
  1805. // anomalous circumstance where a message would be useful
  1806. return D3DERR_NOTAVAILABLE;
  1807. }
  1808. #undef DPF_MODNAME
  1809. #define DPF_MODNAME "CEnum::CheckDeviceType"
  1810. STDMETHODIMP CEnum::CheckDeviceType(
  1811. UINT iAdapter,
  1812. D3DDEVTYPE DevType,
  1813. D3DFORMAT DisplayFormat,
  1814. D3DFORMAT BackBufferFormat,
  1815. BOOL bWindowed)
  1816. {
  1817. API_ENTER(this);
  1818. D3D8_DRIVERCAPS* pAdapterCaps;
  1819. HRESULT hr;
  1820. if (iAdapter >= m_cAdapter)
  1821. {
  1822. DPF_ERR("Invalid adapter specified. CheckDeviceType fails.");
  1823. return D3DERR_INVALIDCALL;
  1824. }
  1825. if (DevType != D3DDEVTYPE_REF &&
  1826. DevType != D3DDEVTYPE_HAL &&
  1827. DevType != D3DDEVTYPE_SW)
  1828. {
  1829. DPF_ERR("Invalid device specified to CheckDeviceType");
  1830. return D3DERR_INVALIDCALL;
  1831. }
  1832. if ((DisplayFormat == D3DFMT_UNKNOWN) ||
  1833. (BackBufferFormat == D3DFMT_UNKNOWN))
  1834. {
  1835. DPF(0, "D3DFMT_UNKNOWN is not a valid format.");
  1836. return D3DERR_INVALIDCALL;
  1837. }
  1838. // Force the backbuffer format to be one of the 16 or 32bpp formats (not
  1839. // 24bpp). We do this because DX8 shipped with a similar check in Reset,
  1840. // and we want to be consistent.
  1841. if ((BackBufferFormat != D3DFMT_X1R5G5B5) &&
  1842. (BackBufferFormat != D3DFMT_A1R5G5B5) &&
  1843. (BackBufferFormat != D3DFMT_R5G6B5) &&
  1844. (BackBufferFormat != D3DFMT_X8R8G8B8) &&
  1845. (BackBufferFormat != D3DFMT_A8R8G8B8))
  1846. {
  1847. // We should return D3DDERR_INVALIDCALL, but we didn't ship that way for
  1848. // DX8 and we don't want to cause regressions, so NOTAVAILABLE is safer.
  1849. DPF(1, "Invalid backbuffer format specified");
  1850. return D3DERR_NOTAVAILABLE;
  1851. }
  1852. // Sanity check the input format
  1853. if ((DisplayFormat != D3DFMT_X8R8G8B8) &&
  1854. (DisplayFormat != D3DFMT_R5G6B5) &&
  1855. (DisplayFormat != D3DFMT_X1R5G5B5) &&
  1856. (DisplayFormat != D3DFMT_R8G8B8))
  1857. {
  1858. DPF(1, "D3D Unsupported for the adapter format passed to CheckDeviceType");
  1859. return D3DERR_NOTAVAILABLE;
  1860. }
  1861. hr = GetAdapterCaps(iAdapter,
  1862. DevType,
  1863. &pAdapterCaps);
  1864. if (FAILED(hr))
  1865. {
  1866. return hr;
  1867. }
  1868. // Is the display mode supported?
  1869. if (!IsSupportedOp (DisplayFormat,
  1870. pAdapterCaps->pGDD8SupportedFormatOps,
  1871. pAdapterCaps->GDD8NumSupportedFormatOps,
  1872. D3DFORMAT_OP_DISPLAYMODE |D3DFORMAT_OP_3DACCELERATION))
  1873. {
  1874. return D3DERR_NOTAVAILABLE;
  1875. }
  1876. if (DisplayFormat != BackBufferFormat)
  1877. {
  1878. D3DFORMAT AlphaFormat = D3DFMT_UNKNOWN;
  1879. UINT i;
  1880. // This is allowed only if the only difference is alpha.
  1881. switch (DisplayFormat)
  1882. {
  1883. case D3DFMT_X1R5G5B5:
  1884. AlphaFormat = D3DFMT_A1R5G5B5;
  1885. break;
  1886. case D3DFMT_X8R8G8B8:
  1887. AlphaFormat = D3DFMT_A8R8G8B8;
  1888. break;
  1889. }
  1890. hr = D3DERR_NOTAVAILABLE;
  1891. if (AlphaFormat == BackBufferFormat)
  1892. {
  1893. if (IsSupportedOp (AlphaFormat,
  1894. pAdapterCaps->pGDD8SupportedFormatOps,
  1895. pAdapterCaps->GDD8NumSupportedFormatOps,
  1896. D3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET))
  1897. {
  1898. hr = D3D_OK;
  1899. }
  1900. }
  1901. }
  1902. else
  1903. {
  1904. // For DX8, we force the backbuffer and display formats to match
  1905. // (minus alpha). This means that they should support a render target
  1906. // of the same format.
  1907. if (!IsSupportedOp (DisplayFormat,
  1908. pAdapterCaps->pGDD8SupportedFormatOps,
  1909. pAdapterCaps->GDD8NumSupportedFormatOps,
  1910. D3DFORMAT_OP_SAME_FORMAT_RENDERTARGET))
  1911. {
  1912. return D3DERR_NOTAVAILABLE;
  1913. }
  1914. }
  1915. if (SUCCEEDED(hr))
  1916. {
  1917. if (bWindowed &&
  1918. !(pAdapterCaps->D3DCaps.Caps2 & DDCAPS2_CANRENDERWINDOWED))
  1919. {
  1920. hr = D3DERR_NOTAVAILABLE;
  1921. }
  1922. }
  1923. return hr;
  1924. }
  1925. #undef DPF_MODNAME
  1926. #define DPF_MODNAME "CEnum::GetAdapterDisplayMode"
  1927. STDMETHODIMP CEnum::GetAdapterDisplayMode(UINT iAdapter, D3DDISPLAYMODE* pMode)
  1928. {
  1929. API_ENTER(this);
  1930. HANDLE h;
  1931. HRESULT hr = D3D_OK;
  1932. if (iAdapter >= m_cAdapter)
  1933. {
  1934. DPF_ERR("Invalid adapter specified. GetAdapterDisplayMode fails");
  1935. return D3DERR_INVALIDCALL;
  1936. }
  1937. if (!VALID_WRITEPTR(pMode, sizeof(D3DDISPLAYMODE)))
  1938. {
  1939. DPF_ERR("Invalid pMode parameter specified for GetAdapterDisplayMode");
  1940. return D3DERR_INVALIDCALL;
  1941. }
  1942. if (m_AdapterInfo[iAdapter].bIsDisplay)
  1943. {
  1944. D3D8GetMode (NULL, m_AdapterInfo[iAdapter].DeviceName, pMode, m_AdapterInfo[iAdapter].Unknown16);
  1945. }
  1946. else
  1947. {
  1948. PD3D8_DEVICEDATA pDeviceData;
  1949. hr = InternalDirectDrawCreate(&pDeviceData,
  1950. &m_AdapterInfo[iAdapter],
  1951. D3DDEVTYPE_HAL,
  1952. NULL,
  1953. m_AdapterInfo[iAdapter].Unknown16,
  1954. m_AdapterInfo[iAdapter].HALCaps.pGDD8SupportedFormatOps,
  1955. m_AdapterInfo[iAdapter].HALCaps.GDD8NumSupportedFormatOps);
  1956. if (SUCCEEDED(hr))
  1957. {
  1958. D3D8GetMode (pDeviceData->hDD, m_AdapterInfo[iAdapter].DeviceName, pMode, D3DFMT_UNKNOWN);
  1959. InternalDirectDrawRelease(pDeviceData);
  1960. }
  1961. }
  1962. return hr;
  1963. }
  1964. #undef DPF_MODNAME
  1965. #define DPF_MODNAME "CEnum::EnumDeviceMultiSampleType"
  1966. STDMETHODIMP CEnum::CheckDeviceMultiSampleType(
  1967. UINT iAdapter,
  1968. D3DDEVTYPE DevType,
  1969. D3DFORMAT RTFormat,
  1970. BOOL Windowed,
  1971. D3DMULTISAMPLE_TYPE SampleType)
  1972. {
  1973. API_ENTER(this);
  1974. // Check parameters
  1975. if (iAdapter >= m_cAdapter)
  1976. {
  1977. DPF_ERR("Invalid adapter specified. CheckDeviceMultiSampleType fails.");
  1978. return D3DERR_INVALIDCALL;
  1979. }
  1980. // Check Device Type
  1981. if (DevType != D3DDEVTYPE_REF &&
  1982. DevType != D3DDEVTYPE_HAL &&
  1983. DevType != D3DDEVTYPE_SW)
  1984. {
  1985. DPF_ERR("Invalid device specified to CheckDeviceMultiSampleType");
  1986. return D3DERR_INVALIDCALL;
  1987. }
  1988. if (RTFormat == D3DFMT_UNKNOWN)
  1989. {
  1990. DPF_ERR("D3DFMT_UNKNOWN is not a valid format. CheckDeviceMultiSampleType fails.");
  1991. return D3DERR_INVALIDCALL;
  1992. }
  1993. D3D8_DRIVERCAPS* pAdapterCaps;
  1994. HRESULT hr;
  1995. hr = GetAdapterCaps(iAdapter,
  1996. DevType,
  1997. &pAdapterCaps);
  1998. if (FAILED(hr))
  1999. {
  2000. return hr;
  2001. }
  2002. if (SampleType == D3DMULTISAMPLE_NONE)
  2003. {
  2004. return D3D_OK;
  2005. }
  2006. else if (SampleType == 1)
  2007. {
  2008. DPF_ERR("Invalid sample type specified. Only enumerated values are supported. CheckDeviceMultiSampleType fails.");
  2009. return D3DERR_INVALIDCALL;
  2010. }
  2011. else if (SampleType > D3DMULTISAMPLE_16_SAMPLES)
  2012. {
  2013. DPF_ERR("Invalid sample type specified. CheckDeviceMultiSampleType fails.");
  2014. return D3DERR_INVALIDCALL;
  2015. }
  2016. // Treat Ref/SW Fullscreen the same as Windowed.
  2017. if (DevType == D3DDEVTYPE_REF ||
  2018. DevType == D3DDEVTYPE_SW)
  2019. {
  2020. Windowed = TRUE;
  2021. }
  2022. // If it's a depth/stencil, make sure it's a format that the driver understands
  2023. RTFormat = MapDepthStencilFormat(iAdapter,
  2024. DevType,
  2025. RTFormat);
  2026. DDSURFACEDESC * pDX8SupportedFormatOperations =
  2027. pAdapterCaps->pGDD8SupportedFormatOps;
  2028. // let's run through the driver's list and see if it can do it.
  2029. for (UINT i = 0; i < pAdapterCaps->GDD8NumSupportedFormatOps; i++)
  2030. {
  2031. //We need a match for format, plus all either blt or flip caps
  2032. if (RTFormat == (D3DFORMAT) pDX8SupportedFormatOperations[i].ddpfPixelFormat.dwFourCC)
  2033. {
  2034. // Found the format in question... do we have the MS caps?
  2035. WORD wMSOps = Windowed ?
  2036. pDX8SupportedFormatOperations[i].ddpfPixelFormat.MultiSampleCaps.wBltMSTypes :
  2037. pDX8SupportedFormatOperations[i].ddpfPixelFormat.MultiSampleCaps.wFlipMSTypes;
  2038. // To determine the bit to use, we map the set of sample-types [2-16] to
  2039. // a particular (bit 1 to bit 15) of the WORD.
  2040. DXGASSERT(SampleType > 1);
  2041. DXGASSERT(SampleType <= 16);
  2042. if (wMSOps & DDI_MULTISAMPLE_TYPE(SampleType))
  2043. {
  2044. return D3D_OK;
  2045. }
  2046. }
  2047. }
  2048. return D3DERR_NOTAVAILABLE;
  2049. } // CheckDeviceMultiSampleType
  2050. #undef DPF_MODNAME
  2051. #define DPF_MODNAME "CEnum::CheckDepthStencilMatch"
  2052. STDMETHODIMP CEnum::CheckDepthStencilMatch(UINT iAdapter,
  2053. D3DDEVTYPE DevType,
  2054. D3DFORMAT AdapterFormat,
  2055. D3DFORMAT RTFormat,
  2056. D3DFORMAT DSFormat)
  2057. {
  2058. API_ENTER(this);
  2059. HRESULT hr;
  2060. // Check parameters
  2061. if (iAdapter >= m_cAdapter)
  2062. {
  2063. DPF_ERR("Invalid adapter specified. CheckDepthStencilMatch fails.");
  2064. return D3DERR_INVALIDCALL;
  2065. }
  2066. // Check Device Type
  2067. if (DevType != D3DDEVTYPE_REF &&
  2068. DevType != D3DDEVTYPE_HAL &&
  2069. DevType != D3DDEVTYPE_SW)
  2070. {
  2071. DPF_ERR("Invalid device specified to CheckDepthStencilMatch");
  2072. return D3DERR_INVALIDCALL;
  2073. }
  2074. if ((AdapterFormat == D3DFMT_UNKNOWN) ||
  2075. (RTFormat == D3DFMT_UNKNOWN) ||
  2076. (DSFormat == D3DFMT_UNKNOWN))
  2077. {
  2078. DPF_ERR("D3DFMT_UNKNOWN is not a valid format. CheckDepthStencilMatch fails.");
  2079. return D3DERR_INVALIDCALL;
  2080. }
  2081. D3D8_DRIVERCAPS *pAdapterCaps = NULL;
  2082. hr = GetAdapterCaps(iAdapter,
  2083. DevType,
  2084. &pAdapterCaps);
  2085. if (FAILED(hr))
  2086. {
  2087. return hr;
  2088. }
  2089. // Is the display mode supported?
  2090. if (!IsSupportedOp (AdapterFormat,
  2091. pAdapterCaps->pGDD8SupportedFormatOps,
  2092. pAdapterCaps->GDD8NumSupportedFormatOps,
  2093. D3DFORMAT_OP_DISPLAYMODE |D3DFORMAT_OP_3DACCELERATION))
  2094. {
  2095. return D3DERR_NOTAVAILABLE;
  2096. }
  2097. DDSURFACEDESC * pDX8SupportedFormatOperations =
  2098. pAdapterCaps->pGDD8SupportedFormatOps;
  2099. // Decide what we need to check
  2100. BOOL bCanDoRT = FALSE;
  2101. BOOL bCanDoDS = FALSE;
  2102. BOOL bMatchNeededForDS = FALSE;
  2103. // We only need to check for matching if the user is trying
  2104. // to use D3DFMT_D16 or has Stencil
  2105. if (DSFormat == D3DFMT_D16_LOCKABLE ||
  2106. CPixel::HasStencilBits(DSFormat))
  2107. {
  2108. bMatchNeededForDS = TRUE;
  2109. }
  2110. //In DX8.1 and beyond, we also make this function check D24X8 and D32, since all known parts that have restrictions
  2111. //also have this restriction
  2112. if (GetAppSdkVersion() > D3D_SDK_VERSION_DX8)
  2113. {
  2114. switch (DSFormat)
  2115. {
  2116. case D3DFMT_D24X8:
  2117. case D3DFMT_D32:
  2118. bMatchNeededForDS = TRUE;
  2119. }
  2120. }
  2121. DWORD dwRequiredZOps = D3DFORMAT_OP_ZSTENCIL;
  2122. // If it's a depth/stencil, make sure it's a format that the driver understands
  2123. DSFormat = MapDepthStencilFormat(iAdapter,
  2124. DevType,
  2125. DSFormat);
  2126. // let's run through the driver's list and see if this all
  2127. // works
  2128. for (UINT i = 0; i < pAdapterCaps->GDD8NumSupportedFormatOps; i++)
  2129. {
  2130. // See if it matches the RT format
  2131. if (RTFormat == (D3DFORMAT) pDX8SupportedFormatOperations[i].ddpfPixelFormat.dwFourCC)
  2132. {
  2133. // Found the RT Format, can we use as a render-target?
  2134. // we check the format that has the least constraints so that
  2135. // we are truly checking "For all possible RTs that I can make
  2136. // with this device, does the Z match it?" We'd like to say
  2137. // "No." if you couldn't make the RT at all in any circumstance.
  2138. if (D3DFORMAT_OP_SAME_FORMAT_RENDERTARGET &
  2139. pAdapterCaps->pGDD8SupportedFormatOps[i].ddpfPixelFormat.dwOperations)
  2140. {
  2141. bCanDoRT = TRUE;
  2142. }
  2143. }
  2144. // See if it matches the DS Format
  2145. if (DSFormat == (D3DFORMAT) pDX8SupportedFormatOperations[i].ddpfPixelFormat.dwFourCC)
  2146. {
  2147. // Found the DS format, can we use it as DS (and potentially lockable)?
  2148. // i.e. if ALL required bits are on in this FOL entry.
  2149. // Again, we check the formats that have the least constraints.
  2150. if (dwRequiredZOps ==
  2151. (dwRequiredZOps & pAdapterCaps->pGDD8SupportedFormatOps[i].ddpfPixelFormat.dwOperations) )
  2152. {
  2153. bCanDoDS = TRUE;
  2154. if (D3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH &
  2155. pAdapterCaps->pGDD8SupportedFormatOps[i].ddpfPixelFormat.dwOperations)
  2156. {
  2157. bMatchNeededForDS = FALSE;
  2158. }
  2159. }
  2160. }
  2161. }
  2162. if (!bCanDoRT)
  2163. {
  2164. DPF_ERR("RenderTarget Format is not supported for this "
  2165. "Adapter/DevType/AdapterFormat. This error can happen if the "
  2166. "application has not successfully called CheckDeviceFormats on the "
  2167. "specified Format prior to calling CheckDepthStencilMatch. The application "
  2168. "is advised to call CheckDeviceFormats on this format first, because a "
  2169. "success return from CheckDepthStencilMatch does not guarantee "
  2170. "that the format is valid as a RenderTarget for all possible cases "
  2171. "i.e. D3DRTYPE_TEXTURE or D3DRTYPE_SURFACE or D3DRTYPE_CUBETEXTURE.");
  2172. return D3DERR_INVALIDCALL;
  2173. }
  2174. if (!bCanDoDS)
  2175. {
  2176. DPF_ERR("DepthStencil Format is not supported for this "
  2177. "Adapter/DevType/AdapterFormat. This error can happen if the "
  2178. "application has not successfully called CheckDeviceFormats on the "
  2179. "specified Format prior to calling CheckDepthStencilMatch. The application "
  2180. "is advised to call CheckDeviceFormats on this format first, because a "
  2181. "success return from CheckDepthStencilMatch does not guarantee "
  2182. "that the format is valid as a DepthStencil buffer for all possible cases "
  2183. "i.e. D3DRTYPE_TEXTURE or D3DRTYPE_SURFACE or D3DRTYPE_CUBETEXTURE.");
  2184. return D3DERR_INVALIDCALL;
  2185. }
  2186. if (bMatchNeededForDS)
  2187. {
  2188. // Check if the DS depth matches the RT depth
  2189. if (CPixel::ComputePixelStride(RTFormat) !=
  2190. CPixel::ComputePixelStride(DSFormat))
  2191. {
  2192. DPF(1, "Specified DepthStencil Format can not be used with RenderTarget Format");
  2193. return D3DERR_NOTAVAILABLE;
  2194. }
  2195. }
  2196. // Otherwise, we now know that the both the RT and DS formats
  2197. // are valid and that they match if they need to.
  2198. DXGASSERT(bCanDoRT && bCanDoDS);
  2199. return S_OK;
  2200. } // CheckDepthStencilMatch
  2201. #undef DPF_MODNAME
  2202. #define DPF_MODNAME "CEnum::FillInCaps"
  2203. void CEnum::FillInCaps (D3DCAPS8 *pCaps,
  2204. const D3D8_DRIVERCAPS *pDriverCaps,
  2205. D3DDEVTYPE Type,
  2206. UINT AdapterOrdinal) const
  2207. {
  2208. memset(pCaps, 0, sizeof(D3DCAPS8));
  2209. //
  2210. // do 3D caps first so we can copy the struct and clear the (few) non-3D fields
  2211. //
  2212. if (pDriverCaps->dwFlags & DDIFLAG_D3DCAPS8)
  2213. {
  2214. // set 3D fields from caps8 struct from driver
  2215. *pCaps = pDriverCaps->D3DCaps;
  2216. if (Type == D3DDEVTYPE_HAL)
  2217. {
  2218. pCaps->DevCaps |= D3DDEVCAPS_HWRASTERIZATION;
  2219. }
  2220. }
  2221. else
  2222. {
  2223. // ASSERT here
  2224. DDASSERT(FALSE);
  2225. }
  2226. //
  2227. // non-3D caps
  2228. //
  2229. pCaps->DeviceType = Type;
  2230. pCaps->AdapterOrdinal = AdapterOrdinal;
  2231. pCaps->Caps = pDriverCaps->D3DCaps.Caps &
  2232. (DDCAPS_READSCANLINE |
  2233. DDCAPS_NOHARDWARE);
  2234. pCaps->Caps2 = pDriverCaps->D3DCaps.Caps2 &
  2235. (DDCAPS2_NO2DDURING3DSCENE |
  2236. DDCAPS2_PRIMARYGAMMA |
  2237. DDCAPS2_CANRENDERWINDOWED |
  2238. DDCAPS2_STEREO |
  2239. DDCAPS2_DYNAMICTEXTURES |
  2240. #ifdef WINNT
  2241. (IsWhistler() ? DDCAPS2_CANMANAGERESOURCE : 0));
  2242. #else
  2243. DDCAPS2_CANMANAGERESOURCE);
  2244. #endif
  2245. // Special case: gamma calibrator is loaded by the enumerator...
  2246. if (m_bGammaCalibratorExists)
  2247. pCaps->Caps2 |= DDCAPS2_CANCALIBRATEGAMMA;
  2248. pCaps->Caps3 = pDriverCaps->D3DCaps.Caps3 & ~D3DCAPS3_RESERVED; //mask off the old stereo flags.
  2249. pCaps->PresentationIntervals = D3DPRESENT_INTERVAL_ONE;
  2250. if (pDriverCaps->D3DCaps.Caps2 & DDCAPS2_FLIPINTERVAL)
  2251. {
  2252. pCaps->PresentationIntervals |=
  2253. (D3DPRESENT_INTERVAL_TWO |
  2254. D3DPRESENT_INTERVAL_THREE |
  2255. D3DPRESENT_INTERVAL_FOUR);
  2256. }
  2257. if (pDriverCaps->D3DCaps.Caps2 & DDCAPS2_FLIPNOVSYNC)
  2258. {
  2259. pCaps->PresentationIntervals |=
  2260. (D3DPRESENT_INTERVAL_IMMEDIATE);
  2261. }
  2262. // Mask out the HW VB and IB caps
  2263. pCaps->DevCaps &= ~(D3DDEVCAPS_HWVERTEXBUFFER | D3DDEVCAPS_HWINDEXBUFFER);
  2264. // Clear internal caps
  2265. pCaps->PrimitiveMiscCaps &= ~D3DPMISCCAPS_FOGINFVF;
  2266. // Fix up the vertex fog cap.
  2267. if (pCaps->VertexProcessingCaps & D3DVTXPCAPS_RESERVED)
  2268. {
  2269. pCaps->RasterCaps |= D3DPRASTERCAPS_FOGVERTEX;
  2270. pCaps->VertexProcessingCaps &= ~D3DVTXPCAPS_RESERVED;
  2271. }
  2272. } // FillInCaps
  2273. #undef DPF_MODNAME
  2274. #define DPF_MODNAME "CEnum::GetDeviceCaps"
  2275. STDMETHODIMP CEnum::GetDeviceCaps(
  2276. UINT iAdapter,
  2277. D3DDEVTYPE Type,
  2278. D3DCAPS8 *pCaps)
  2279. {
  2280. API_ENTER(this);
  2281. BOOL bValidRTFormat;
  2282. D3DFORMAT Format;
  2283. D3D8_DRIVERCAPS* pAdapterCaps;
  2284. HRESULT hr;
  2285. DWORD i;
  2286. if (iAdapter >= m_cAdapter)
  2287. {
  2288. DPF_ERR("Invalid adapter specified. GetDeviceCaps fails.");
  2289. return D3DERR_INVALIDCALL;
  2290. }
  2291. if (!VALID_WRITEPTR(pCaps, sizeof(D3DCAPS8)))
  2292. {
  2293. DPF_ERR("Invalid pointer to D3DCAPS8 specified. GetDeviceCaps fails.");
  2294. return D3DERR_INVALIDCALL;
  2295. }
  2296. hr = GetAdapterCaps(iAdapter,
  2297. Type,
  2298. &pAdapterCaps);
  2299. if (FAILED(hr))
  2300. {
  2301. // No caps for this type of device
  2302. memset(pCaps, 0, sizeof(D3DCAPS8));
  2303. return hr;
  2304. }
  2305. // Fail this call if the driver dosn't support any accelerated modes
  2306. for (i = 0; i < pAdapterCaps->GDD8NumSupportedFormatOps; i++)
  2307. {
  2308. if (pAdapterCaps->pGDD8SupportedFormatOps[i].ddpfPixelFormat.dwOperations & D3DFORMAT_OP_3DACCELERATION)
  2309. {
  2310. break;
  2311. }
  2312. }
  2313. if (i == pAdapterCaps->GDD8NumSupportedFormatOps)
  2314. {
  2315. // No caps for this type of device
  2316. memset(pCaps, 0, sizeof(D3DCAPS8));
  2317. return D3DERR_NOTAVAILABLE;
  2318. }
  2319. FillInCaps (pCaps,
  2320. pAdapterCaps,
  2321. Type,
  2322. iAdapter);
  2323. if (pCaps->MaxPointSize == 0)
  2324. {
  2325. pCaps->MaxPointSize = 1.0f;
  2326. }
  2327. return D3D_OK;
  2328. } // GetDeviceCaps
  2329. #undef DPF_MODNAME
  2330. #define DPF_MODNAME "CEnum::LoadAndCallGammaCalibrator"
  2331. void CEnum::LoadAndCallGammaCalibrator(
  2332. D3DGAMMARAMP *pRamp,
  2333. UCHAR * pDeviceName)
  2334. {
  2335. API_ENTER_VOID(this);
  2336. if (!m_bAttemptedGammaCalibrator)
  2337. {
  2338. m_bAttemptedGammaCalibrator = TRUE;
  2339. m_hGammaCalibrator = LoadLibrary((char*) m_szGammaCalibrator);
  2340. if (m_hGammaCalibrator)
  2341. {
  2342. m_pGammaCalibratorProc = (LPDDGAMMACALIBRATORPROC)
  2343. GetProcAddress(m_hGammaCalibrator, "CalibrateGammaRamp");
  2344. if (m_pGammaCalibratorProc == NULL)
  2345. {
  2346. FreeLibrary((HMODULE) m_hGammaCalibrator);
  2347. m_hGammaCalibrator = NULL;
  2348. }
  2349. }
  2350. }
  2351. if (m_pGammaCalibratorProc)
  2352. {
  2353. m_pGammaCalibratorProc((LPDDGAMMARAMP) pRamp, pDeviceName);
  2354. }
  2355. } // LoadAndCallGammaCalibrator
  2356. #undef DPF_MODNAME
  2357. #define DPF_MODNAME "CEnum::RegisterSoftwareDevice"
  2358. STDMETHODIMP CEnum::RegisterSoftwareDevice(
  2359. void* pInitFunction)
  2360. {
  2361. HRESULT hr;
  2362. API_ENTER(this);
  2363. if (pInitFunction == NULL)
  2364. {
  2365. DPF_ERR("Invalid initialization function specified. RegisterSoftwareDevice fails.");
  2366. return D3DERR_INVALIDCALL;
  2367. }
  2368. if (m_pSwInitFunction != NULL)
  2369. {
  2370. DPF_ERR("A software device is already registered.");
  2371. return D3DERR_INVALIDCALL;
  2372. }
  2373. if (m_cAdapter == 0)
  2374. {
  2375. DPF_ERR("No display devices are available.");
  2376. return D3DERR_NOTAVAILABLE;
  2377. }
  2378. hr = AddSoftwareDevice(D3DDEVTYPE_SW, &m_SwCaps[0], &m_AdapterInfo[0], pInitFunction);
  2379. if (SUCCEEDED(hr))
  2380. {
  2381. m_pSwInitFunction = pInitFunction;
  2382. }
  2383. if (FAILED(hr))
  2384. {
  2385. DPF_ERR("RegisterSoftwareDevice fails");
  2386. }
  2387. return hr;
  2388. } // RegisterSoftwareDevice
  2389. #ifdef WINNT
  2390. #undef DPF_MODNAME
  2391. #define DPF_MODNAME "CEnum::FocusWindow"
  2392. HWND CEnum::ExclusiveOwnerWindow()
  2393. {
  2394. API_ENTER_RET(this, HWND);
  2395. for (UINT iAdapter = 0; iAdapter < m_cAdapter; iAdapter++)
  2396. {
  2397. CBaseDevice *pDevice = m_pFullScreenDevice[iAdapter];
  2398. if (pDevice)
  2399. {
  2400. return pDevice->FocusWindow();
  2401. }
  2402. }
  2403. return NULL;
  2404. } // FocusWindow
  2405. #undef DPF_MODNAME
  2406. #define DPF_MODNAME "CEnum::SetFullScreenDevice"
  2407. void CEnum::SetFullScreenDevice(UINT iAdapter,
  2408. CBaseDevice *pDevice)
  2409. {
  2410. API_ENTER_VOID(this);
  2411. if (m_pFullScreenDevice[iAdapter] != pDevice)
  2412. {
  2413. DDASSERT(NULL == m_pFullScreenDevice[iAdapter] || NULL == pDevice);
  2414. m_pFullScreenDevice[iAdapter] = pDevice;
  2415. if (NULL == pDevice && NULL == ExclusiveOwnerWindow() && m_bHasExclusive)
  2416. {
  2417. m_bHasExclusive = FALSE;
  2418. DXReleaseExclusiveModeMutex();
  2419. }
  2420. }
  2421. } // SetFullScreenDevice
  2422. #undef DPF_MODNAME
  2423. #define DPF_MODNAME "CEnum::CheckExclusiveMode"
  2424. BOOL CEnum::CheckExclusiveMode(
  2425. CBaseDevice* pDevice,
  2426. LPBOOL pbThisDeviceOwnsExclusive,
  2427. BOOL bKeepMutex)
  2428. {
  2429. DWORD dwWaitResult;
  2430. BOOL bExclusiveExists=FALSE;
  2431. WaitForSingleObject(hCheckExclusiveModeMutex, INFINITE);
  2432. dwWaitResult = WaitForSingleObject(hExclusiveModeMutex, 0);
  2433. if (dwWaitResult == WAIT_OBJECT_0)
  2434. {
  2435. /*
  2436. * OK, so this process now owns the exclusive mode object,
  2437. * Have we taken the Mutex already ?
  2438. */
  2439. if (m_bHasExclusive)
  2440. {
  2441. bExclusiveExists = TRUE;
  2442. bKeepMutex = FALSE;
  2443. }
  2444. else
  2445. {
  2446. bExclusiveExists = FALSE;
  2447. }
  2448. if (pbThisDeviceOwnsExclusive && pDevice)
  2449. {
  2450. if (bExclusiveExists &&
  2451. (pDevice == m_pFullScreenDevice[pDevice->AdapterIndex()]
  2452. || NULL == m_pFullScreenDevice[pDevice->AdapterIndex()]) &&
  2453. pDevice->FocusWindow() == ExclusiveOwnerWindow()
  2454. )
  2455. {
  2456. *pbThisDeviceOwnsExclusive = TRUE;
  2457. }
  2458. else
  2459. {
  2460. *pbThisDeviceOwnsExclusive = FALSE;
  2461. }
  2462. }
  2463. /*
  2464. * Undo the temporary ref we just took on the mutex to check its state, if we're not actually
  2465. * taking ownership. We are not taking ownership if we already have ownership. This means this routine
  2466. * doesn't allow more than one ref on the exclusive mode mutex.
  2467. */
  2468. if (!bKeepMutex)
  2469. {
  2470. ReleaseMutex(hExclusiveModeMutex);
  2471. }
  2472. else
  2473. {
  2474. m_bHasExclusive = TRUE;
  2475. }
  2476. }
  2477. else if (dwWaitResult == WAIT_TIMEOUT)
  2478. {
  2479. bExclusiveExists = TRUE;
  2480. if (pbThisDeviceOwnsExclusive)
  2481. *pbThisDeviceOwnsExclusive = FALSE;
  2482. }
  2483. else if (dwWaitResult == WAIT_ABANDONED)
  2484. {
  2485. /*
  2486. * Some other thread lost exclusive mode. We have now picked it up.
  2487. */
  2488. bExclusiveExists = FALSE;
  2489. if (pbThisDeviceOwnsExclusive)
  2490. *pbThisDeviceOwnsExclusive = FALSE;
  2491. /*
  2492. * Undo the temporary ref we just took on the mutex to check its state, if we're not actually
  2493. * taking ownership.
  2494. */
  2495. if (!bKeepMutex)
  2496. {
  2497. ReleaseMutex(hExclusiveModeMutex);
  2498. }
  2499. else
  2500. {
  2501. m_bHasExclusive = TRUE;
  2502. }
  2503. }
  2504. ReleaseMutex(hCheckExclusiveModeMutex);
  2505. return bExclusiveExists;
  2506. } // CheckExclusiveMode
  2507. #undef DPF_MODNAME
  2508. #define DPF_MODNAME "CEnum::DoneExclusiveMode"
  2509. /*
  2510. * DoneExclusiveMode
  2511. */
  2512. void
  2513. CEnum::DoneExclusiveMode()
  2514. {
  2515. UINT iAdapter;
  2516. for (iAdapter=0;iAdapter < m_cAdapter;iAdapter++)
  2517. {
  2518. CBaseDevice* pDevice = m_pFullScreenDevice[iAdapter];
  2519. if (pDevice)
  2520. {
  2521. pDevice->SwapChain()->DoneExclusiveMode(TRUE);
  2522. }
  2523. }
  2524. m_bHasExclusive = FALSE;
  2525. DXReleaseExclusiveModeMutex();
  2526. } /* DoneExclusiveMode */
  2527. #undef DPF_MODNAME
  2528. #define DPF_MODNAME "CEnum::StartExclusiveMode"
  2529. /*
  2530. * StartExclusiveMode
  2531. */
  2532. void
  2533. CEnum::StartExclusiveMode()
  2534. {
  2535. UINT iAdapter;
  2536. for (iAdapter=0;iAdapter<m_cAdapter;iAdapter++)
  2537. {
  2538. CBaseDevice* pDevice = m_pFullScreenDevice[iAdapter];
  2539. if (pDevice)
  2540. {
  2541. pDevice->SwapChain()->StartExclusiveMode(TRUE);
  2542. }
  2543. }
  2544. } /* StartExclusiveMode */
  2545. #endif // WINNT
  2546. // End of file : enum.cpp