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.

1049 lines
33 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: d3di.h
  6. * Content: Direct3D HAL include file
  7. *@@BEGIN_MSINTERNAL
  8. *
  9. * History:
  10. * Date By Reason
  11. * ==== == ======
  12. * 09/11/95 stevela Initial rev with this header.
  13. * 07/12/95 stevela Merged Colin's changes.
  14. * 10/12/95 stevela Removed AGGREGATE_D3D.
  15. * Validate args.
  16. * 17/04/96 colinmc Bug 17008: DirectDraw/Direct3D deadlock
  17. * 29/04/96 colinmc Bug 19954: Must query for Direct3D before texture
  18. * or device
  19. * 27/08/96 stevela Ifdefed out definition of ghEvent as we're using
  20. * DirectDraw's critical section.
  21. *@@END_MSINTERNAL
  22. *
  23. ***************************************************************************/
  24. #include "pch.cpp"
  25. #pragma hdrstop
  26. /*
  27. * Create an api for the Direct3D object
  28. */
  29. // Remove DDraw's type unsafe definition and replace with our C++ friendly def
  30. #ifdef VALIDEX_CODE_PTR
  31. #undef VALIDEX_CODE_PTR
  32. #endif
  33. #define VALIDEX_CODE_PTR( ptr ) \
  34. (!IsBadCodePtr( (FARPROC) ptr ) )
  35. LPCRITICAL_SECTION lpD3DCSect;
  36. #if DBG
  37. int iD3DCSCnt;
  38. #endif
  39. HRESULT D3DAPI DIRECT3DI::Initialize(REFCLSID riid)
  40. {
  41. return DDERR_ALREADYINITIALIZED;
  42. }
  43. //---------------------------------------------------------------------
  44. // for use by fns that take a GUID param before device is created
  45. BOOL IsValidD3DDeviceGuid(REFCLSID riid) {
  46. if (IsBadReadPtr(&riid, sizeof(CLSID))) {
  47. return FALSE;
  48. }
  49. if( IsEqualIID(riid, IID_IDirect3DRampDevice) ||
  50. IsEqualIID(riid, IID_IDirect3DRGBDevice) ||
  51. IsEqualIID(riid, IID_IDirect3DMMXDevice) ||
  52. IsEqualIID(riid, IID_IDirect3DHALDevice) ||
  53. IsEqualIID(riid, IID_IDirect3DRefDevice) ||
  54. IsEqualIID(riid, IID_IDirect3DNullDevice) ||
  55. IsEqualIID(riid, IID_IDirect3DNewRGBDevice)) {
  56. return TRUE;
  57. } else {
  58. return FALSE;
  59. }
  60. }
  61. //---------------------------------------------------------------------
  62. #undef DPF_MODNAME
  63. #define DPF_MODNAME "Direct3DCreate"
  64. DIRECT3DI::DIRECT3DI(IUnknown* pUnkOuter, LPDDRAWI_DIRECTDRAW_INT pDDrawInt)
  65. {
  66. // HACK. D3D needs a DD1 DDRAWI interface because it uses CreateSurface1 internally
  67. // for exebufs, among other things. Because pDDrawInt could be any DDRAWI type,
  68. // we need to QI to find a DD1 interface. But the D3DI object cannot keep a reference
  69. // to its parent DD object because it is aggegrated with the DD obj, so that would constitute
  70. // a circular reference that would prevent deletion. So we QI for DD1 interface, copy it into D3DI
  71. // and release it, then point lpDD at the copy. (disgusting)
  72. // another HACK alert: dont know which DDRAWI type pDDrawInt is, but a cast to LPDIRECTDRAW should
  73. // work because QI is in the same place in all the DDRAWI vtables and is the same fn for all
  74. HRESULT ret;
  75. ret = ((LPDIRECTDRAW)pDDrawInt)->QueryInterface(IID_IDirectDraw, (LPVOID*)&lpDD);
  76. if(FAILED(ret)) {
  77. lpDD=NULL; //signal failure
  78. D3D_ERR( "QueryInterface for IDDraw failed" );
  79. return;
  80. }
  81. memcpy(&DDInt_DD1,lpDD,sizeof(DDInt_DD1));
  82. lpDD->Release();
  83. lpDD=(LPDIRECTDRAW)&DDInt_DD1;
  84. ret = ((LPDIRECTDRAW)pDDrawInt)->QueryInterface(IID_IDirectDraw4, (LPVOID*)&lpDD4);
  85. if(FAILED(ret))
  86. {
  87. lpDD4=NULL; //signal failure
  88. D3D_WARN(1,"QueryInterface for IDDraw4 failed" );
  89. }
  90. else
  91. {
  92. memcpy(&DDInt_DD4,lpDD4,sizeof(DDInt_DD4));
  93. lpDD4->Release();
  94. lpDD4=(LPDIRECTDRAW4)&DDInt_DD4;
  95. D3D_INFO(4,"QueryInterface for IDDraw4 succeeded" );
  96. }
  97. numDevs =
  98. numViewports =
  99. numLights =
  100. numMaterials = 0;
  101. mD3DUnk.pD3DI = this;
  102. mD3DUnk.refCnt = 1;
  103. LIST_INITIALIZE(&devices);
  104. LIST_INITIALIZE(&viewports);
  105. LIST_INITIALIZE(&lights);
  106. LIST_INITIALIZE(&materials);
  107. v_next = 1;
  108. lpFreeList=NULL; /* nothing is allocated initially */
  109. lpBufferList=NULL;
  110. lpTextureManager=new TextureCacheManager(this);
  111. /*
  112. * Are we really being aggregated?
  113. */
  114. if (pUnkOuter != NULL)
  115. {
  116. /*
  117. * Yup - we are being aggregated. Store the supplied
  118. * IUnknown so we can punt to that.
  119. * NOTE: We explicitly DO NOT AddRef here.
  120. */
  121. this->lpOwningIUnknown = pUnkOuter;
  122. /*
  123. * Store away the interface pointer
  124. */
  125. }
  126. else
  127. {
  128. /*
  129. * Nope - but we pretend we are anyway by storing our
  130. * own IUnknown as the parent IUnknown. This makes the
  131. * code much neater.
  132. */
  133. this->lpOwningIUnknown = static_cast<LPUNKNOWN>(&this->mD3DUnk);
  134. }
  135. }
  136. extern "C" HRESULT WINAPI Direct3DCreate(LPCRITICAL_SECTION lpDDCSect,
  137. LPUNKNOWN* lplpDirect3D,
  138. IUnknown* pUnkOuter)
  139. {
  140. LPDIRECT3DI pd3d;
  141. DPFINIT();
  142. /*
  143. * No need to validate params as DirectDraw is giving them to us.
  144. */
  145. /*
  146. * Is another thread coming in and is this the first time?
  147. */
  148. /*
  149. * We can let every invocation of this function assign
  150. * the critical section as we know its always going to
  151. * be the same value (for a D3D session).
  152. */
  153. lpD3DCSect = lpDDCSect;
  154. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  155. // Release in the destructor
  156. *lplpDirect3D = NULL;
  157. // We do not support non aggregated Direct3D object yet
  158. if (!pUnkOuter)
  159. return DDERR_INVALIDPARAMS;
  160. if (!(pd3d = static_cast<LPDIRECT3DI>(new DIRECT3DI(pUnkOuter, (LPDDRAWI_DIRECTDRAW_INT)pUnkOuter))))
  161. {
  162. return (DDERR_OUTOFMEMORY);
  163. }
  164. if(pd3d->lpDD==NULL) { //QI failed
  165. delete pd3d;
  166. return E_NOINTERFACE;
  167. }
  168. /*
  169. * NOTE: The special IUnknown is returned and not the actual
  170. * Direct3D interface so you can't use this to drive Direct3D.
  171. * You must query off this interface for the Direct3D interface.
  172. */
  173. *lplpDirect3D = static_cast<LPUNKNOWN>(&(pd3d->mD3DUnk));
  174. return (D3D_OK);
  175. }
  176. #undef DPF_MODNAME
  177. #define DPF_MODNAME "Direct3D::EnumDevices"
  178. extern BOOL isMMXprocessor(void);
  179. typedef struct _D3DI_DeviceType {
  180. CONST GUID *pGuid;
  181. char name[256];
  182. char description[512];
  183. } D3DI_DeviceType;
  184. // Static definitions for various enumerable devices
  185. static D3DI_DeviceType RampDevice =
  186. {
  187. &IID_IDirect3DRampDevice, "Ramp Emulation",
  188. "Microsoft Direct3D Mono(Ramp) Software Emulation"
  189. };
  190. static D3DI_DeviceType RGBDevice =
  191. {
  192. &IID_IDirect3DRGBDevice, "RGB Emulation",
  193. "Microsoft Direct3D RGB Software Emulation"
  194. };
  195. static D3DI_DeviceType HALDevice =
  196. {
  197. &IID_IDirect3DHALDevice, "Direct3D HAL",
  198. "Microsoft Direct3D Hardware acceleration through Direct3D HAL"
  199. };
  200. static D3DI_DeviceType MMXDevice =
  201. {
  202. &IID_IDirect3DMMXDevice, "MMX Emulation",
  203. "Microsoft Direct3D MMX Software Emulation"
  204. };
  205. static D3DI_DeviceType RefDevice =
  206. {
  207. &IID_IDirect3DRefDevice, "Reference Rasterizer",
  208. "Microsoft Reference Rasterizer"
  209. };
  210. static D3DI_DeviceType NullDevice =
  211. {
  212. &IID_IDirect3DNullDevice, "Null device",
  213. "Microsoft Null Device"
  214. };
  215. static D3DI_DeviceType *AllDevices[] =
  216. {
  217. &RampDevice, &RGBDevice, &HALDevice, &MMXDevice, &RefDevice, &NullDevice, NULL
  218. };
  219. HRESULT
  220. DIRECT3DI::EnumDevices(LPD3DENUMDEVICESCALLBACK lpEnumCallback,
  221. LPVOID lpContext, DWORD dwSize, DWORD dwVer)
  222. {
  223. HRESULT err, userRet;
  224. HKEY hKey;
  225. LONG result;
  226. int i;
  227. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  228. // Release in the destructor
  229. /*
  230. * validate parms
  231. */
  232. TRY
  233. {
  234. if (!VALIDEX_CODE_PTR((FARPROC)lpEnumCallback)) {
  235. D3D_ERR( "Invalid callback pointer" );
  236. return DDERR_INVALIDPARAMS;
  237. }
  238. }
  239. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  240. {
  241. D3D_ERR( "Exception encountered validating parameters" );
  242. return DDERR_INVALIDPARAMS;
  243. }
  244. BOOL bSoftwareOnly = FALSE;
  245. DWORD dwEnumReference = 0;
  246. BOOL bEnumNullDevice = FALSE;
  247. BOOL bEnumSeparateMMX = FALSE;
  248. result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, RESPATH, 0, KEY_READ, &hKey);
  249. if (result == ERROR_SUCCESS)
  250. {
  251. DWORD dwData, dwType;
  252. DWORD dwDataSize;
  253. // Enumerate software rasterizers only ?
  254. dwDataSize = sizeof(dwData);
  255. result = RegQueryValueEx(hKey, "SoftwareOnly", NULL,
  256. &dwType, (BYTE *) &dwData, &dwDataSize);
  257. if ( result == ERROR_SUCCESS && dwType == REG_DWORD )
  258. {
  259. bSoftwareOnly = ( dwData != 0 );
  260. }
  261. // Enumerate Reference Rasterizer ?
  262. dwDataSize = sizeof(dwData);
  263. result = RegQueryValueEx(hKey, "EnumReference", NULL,
  264. &dwType, (BYTE *)&dwData, &dwDataSize);
  265. if (result == ERROR_SUCCESS &&
  266. dwType == REG_DWORD &&
  267. dwDataSize == sizeof(dwData))
  268. {
  269. dwEnumReference = dwData;
  270. }
  271. if (dwVer >= 3)
  272. {
  273. // Enumerate MMX Rasterizer separately for DX6?
  274. dwDataSize = sizeof(dwData);
  275. result = RegQueryValueEx(hKey, "EnumSeparateMMX", NULL,
  276. &dwType, (BYTE *)&dwData, &dwDataSize);
  277. if (result == ERROR_SUCCESS &&
  278. dwType == REG_DWORD &&
  279. dwDataSize == sizeof(dwData))
  280. {
  281. bEnumSeparateMMX = (BOOL)dwData;
  282. }
  283. }
  284. else
  285. {
  286. // Enumerate MMX Rasterizer separately for DX5
  287. // MMX is not enumerated for DX3 and older later
  288. bEnumSeparateMMX = TRUE;
  289. }
  290. // Enumerate Null Device ?
  291. dwDataSize = sizeof(dwData);
  292. result = RegQueryValueEx(hKey, "EnumNullDevice", NULL,
  293. &dwType, (BYTE *)&dwData, &dwDataSize);
  294. if (result == ERROR_SUCCESS &&
  295. dwType == REG_DWORD &&
  296. dwDataSize == sizeof(dwData))
  297. {
  298. bEnumNullDevice = (BOOL)dwData;
  299. }
  300. RegCloseKey( hKey );
  301. }
  302. D3DI_DeviceType **lpDevices = AllDevices;
  303. userRet = D3DENUMRET_OK;
  304. for (i = 0; lpDevices[i] && userRet == D3DENUMRET_OK; i++)
  305. {
  306. LPSTR drvName = lpDevices[i]->name;
  307. LPSTR drvDesc = lpDevices[i]->description;
  308. REFCLSID riid = *lpDevices[i]->pGuid;
  309. D3DDEVICEDESC HWDesc;
  310. D3DDEVICEDESC HELDesc;
  311. LPDDRAWI_DIRECTDRAW_GBL lpDDGbl;
  312. IHalProvider *pHalProv;
  313. HINSTANCE hDll;
  314. if ( (dwVer < 2 || !isMMXprocessor()) &&
  315. IsEqualIID(riid, IID_IDirect3DMMXDevice ) )
  316. {
  317. // Not Device2, not on MMX machine, or DisableMMX is set.
  318. // Don't enumerate the MMX device.
  319. continue;
  320. }
  321. if ( !bEnumSeparateMMX &&
  322. IsEqualIID(riid, IID_IDirect3DMMXDevice ) )
  323. {
  324. // Not enumerating MMX separate from RGB.
  325. continue;
  326. }
  327. if ( IsEqualIID(riid, IID_IDirect3DRefDevice) &&
  328. !(dwEnumReference == 1) && // enumerate for all devices if value == 1
  329. !( (dwVer >= 3) && (dwEnumReference == 2) ) ) // enumerate for Device3+ if value == 2
  330. {
  331. // Not enumerating the reference.
  332. continue;
  333. }
  334. if (!bEnumNullDevice &&
  335. IsEqualIID(riid, IID_IDirect3DNullDevice))
  336. {
  337. // Not enumerating the Null device.
  338. continue;
  339. }
  340. #ifndef _X86_
  341. if (IsEqualIID(riid, IID_IDirect3DRampDevice))
  342. {
  343. // Not enumerating ramp for non-x86 (alpha) platforms.
  344. continue;
  345. }
  346. #endif
  347. if((dwVer>=3) && IsEqualIID(riid, IID_IDirect3DRampDevice)) {
  348. // Ramp not available in Device3. No more old-style texture handles.
  349. continue;
  350. }
  351. // By COM definition, our owning IUnknown is a pointer to the
  352. // DirectDraw object that was used to create us.
  353. // Check this for the existence of a Direct3D HAL.
  354. lpDDGbl = ((LPDDRAWI_DIRECTDRAW_INT)this->lpDD)->lpLcl->lpGbl;
  355. // See if this is a software driver.
  356. err = GetSwHalProvider(riid, &pHalProv, &hDll);
  357. if (err == S_OK)
  358. {
  359. // Successfully got a software driver.
  360. }
  361. else if (err == E_NOINTERFACE &&
  362. ! bSoftwareOnly &&
  363. GetHwHalProvider(riid, &pHalProv, &hDll, lpDDGbl) == S_OK)
  364. {
  365. // Successfully got a hardware driver.
  366. }
  367. else
  368. {
  369. // Unrecognized driver.
  370. continue;
  371. }
  372. err = pHalProv->GetCaps(lpDDGbl, &HWDesc, &HELDesc, dwVer);
  373. pHalProv->Release();
  374. if (hDll != NULL)
  375. {
  376. FreeLibrary(hDll);
  377. }
  378. if (err != S_OK)
  379. {
  380. continue;
  381. }
  382. HWDesc.dwSize = dwSize;
  383. HELDesc.dwSize = dwSize;
  384. userRet = (*lpEnumCallback)((GUID *) lpDevices[i]->pGuid, drvDesc, drvName,
  385. &HWDesc, &HELDesc, lpContext);
  386. }
  387. return D3D_OK;
  388. }
  389. HRESULT D3DAPI CDirect3D::EnumDevices(LPD3DENUMDEVICESCALLBACK lpEnumCallback,
  390. LPVOID lpContext)
  391. {
  392. return EnumDevices(lpEnumCallback, lpContext, D3DDEVICEDESCSIZE_V1, 1);
  393. }
  394. HRESULT D3DAPI CDirect3D2::EnumDevices(LPD3DENUMDEVICESCALLBACK lpEnumCallback,
  395. LPVOID lpContext)
  396. {
  397. return EnumDevices(lpEnumCallback, lpContext, D3DDEVICEDESCSIZE_V2, 2);
  398. }
  399. HRESULT D3DAPI CDirect3D3::EnumDevices(LPD3DENUMDEVICESCALLBACK lpEnumCallback,
  400. LPVOID lpContext)
  401. {
  402. return EnumDevices(lpEnumCallback, lpContext, D3DDEVICEDESCSIZE, 3);
  403. }
  404. #define MATCH(cap) ((matchCaps->cap & primCaps->cap) == matchCaps->cap)
  405. static BOOL MatchCaps(DWORD dwFlags,
  406. LPD3DPRIMCAPS matchCaps,
  407. LPD3DPRIMCAPS primCaps)
  408. {
  409. if (dwFlags & D3DFDS_MISCCAPS) {
  410. if (!MATCH(dwMiscCaps))
  411. return FALSE;
  412. }
  413. if (dwFlags & D3DFDS_RASTERCAPS) {
  414. if (!MATCH(dwRasterCaps))
  415. return FALSE;
  416. }
  417. if (dwFlags & D3DFDS_ZCMPCAPS) {
  418. if (!MATCH(dwZCmpCaps))
  419. return FALSE;
  420. }
  421. if (dwFlags & D3DFDS_ALPHACMPCAPS) {
  422. if (!MATCH(dwAlphaCmpCaps))
  423. return FALSE;
  424. }
  425. if (dwFlags & D3DFDS_SRCBLENDCAPS) {
  426. if (!MATCH(dwSrcBlendCaps))
  427. return FALSE;
  428. }
  429. if (dwFlags & D3DFDS_DSTBLENDCAPS) {
  430. if (!MATCH(dwDestBlendCaps))
  431. return FALSE;
  432. }
  433. if (dwFlags & D3DFDS_SHADECAPS) {
  434. if (!MATCH(dwShadeCaps))
  435. return FALSE;
  436. }
  437. if (dwFlags & D3DFDS_TEXTURECAPS) {
  438. if (!MATCH(dwTextureCaps))
  439. return FALSE;
  440. }
  441. if (dwFlags & D3DFDS_TEXTUREFILTERCAPS) {
  442. if (!MATCH(dwTextureFilterCaps))
  443. return FALSE;
  444. }
  445. if (dwFlags & D3DFDS_TEXTUREBLENDCAPS) {
  446. if (!MATCH(dwTextureBlendCaps))
  447. return FALSE;
  448. }
  449. if (dwFlags & D3DFDS_TEXTUREADDRESSCAPS) {
  450. if (!MATCH(dwTextureAddressCaps))
  451. return FALSE;
  452. }
  453. return TRUE;
  454. }
  455. #undef MATCH
  456. typedef struct _enumArgs {
  457. D3DFINDDEVICESEARCH search;
  458. int foundHardware;
  459. int foundSoftware;
  460. D3DFINDDEVICERESULT result;
  461. } enumArgs;
  462. HRESULT WINAPI enumFunc(LPGUID lpGuid,
  463. LPSTR lpDeviceDescription,
  464. LPSTR lpDeviceName,
  465. LPD3DDEVICEDESC lpHWDesc,
  466. LPD3DDEVICEDESC lpHELDesc,
  467. LPVOID lpContext)
  468. {
  469. enumArgs* lpArgs = (enumArgs*)lpContext;
  470. BOOL bHardware = (lpHWDesc->dcmColorModel != 0);
  471. if (lpArgs->search.dwFlags & D3DFDS_GUID) {
  472. if (!IsEqualGUID(lpArgs->search.guid, *lpGuid))
  473. return D3DENUMRET_OK;
  474. }
  475. if (lpArgs->search.dwFlags & D3DFDS_HARDWARE) {
  476. if (lpArgs->search.bHardware != bHardware)
  477. return D3DENUMRET_OK;
  478. }
  479. if (lpArgs->search.dwFlags & D3DFDS_COLORMODEL) {
  480. if ((lpHWDesc->dcmColorModel & lpArgs->search.dcmColorModel) == 0
  481. && (lpHELDesc->dcmColorModel & lpArgs->search.dcmColorModel) == 0) {
  482. return D3DENUMRET_OK;
  483. }
  484. }
  485. if (lpArgs->search.dwFlags & D3DFDS_TRIANGLES) {
  486. if (!MatchCaps(lpArgs->search.dwFlags,
  487. &lpArgs->search.dpcPrimCaps, &lpHWDesc->dpcTriCaps)
  488. && !MatchCaps(lpArgs->search.dwFlags,
  489. &lpArgs->search.dpcPrimCaps, &lpHELDesc->dpcTriCaps))
  490. return D3DENUMRET_OK;
  491. }
  492. if (lpArgs->search.dwFlags & D3DFDS_LINES) {
  493. if (!MatchCaps(lpArgs->search.dwFlags,
  494. &lpArgs->search.dpcPrimCaps, &lpHWDesc->dpcLineCaps)
  495. && !MatchCaps(lpArgs->search.dwFlags,
  496. &lpArgs->search.dpcPrimCaps, &lpHELDesc->dpcLineCaps))
  497. return D3DENUMRET_OK;
  498. }
  499. if (lpArgs->foundHardware && !bHardware)
  500. return D3DENUMRET_OK;
  501. if (bHardware)
  502. lpArgs->foundHardware = TRUE;
  503. else
  504. lpArgs->foundSoftware = TRUE;
  505. lpArgs->result.guid = *lpGuid;
  506. lpArgs->result.ddHwDesc = *lpHWDesc;
  507. lpArgs->result.ddSwDesc = *lpHELDesc;
  508. return D3DENUMRET_OK;
  509. }
  510. #undef DPF_MODNAME
  511. #define DPF_MODNAME "Direct3D::FindDevice"
  512. HRESULT D3DAPI CDirect3D::FindDevice(LPD3DFINDDEVICESEARCH lpSearch, LPD3DFINDDEVICERESULT lpResult)
  513. {
  514. return FindDevice(lpSearch,lpResult,1);
  515. }
  516. HRESULT D3DAPI CDirect3D2::FindDevice(LPD3DFINDDEVICESEARCH lpSearch, LPD3DFINDDEVICERESULT lpResult)
  517. {
  518. return FindDevice(lpSearch,lpResult,2);
  519. }
  520. HRESULT D3DAPI CDirect3D3::FindDevice(LPD3DFINDDEVICESEARCH lpSearch, LPD3DFINDDEVICERESULT lpResult)
  521. {
  522. return FindDevice(lpSearch,lpResult,3);
  523. }
  524. HRESULT
  525. DIRECT3DI::FindDevice(LPD3DFINDDEVICESEARCH lpSearch,
  526. LPD3DFINDDEVICERESULT lpResult, DWORD dwVer)
  527. {
  528. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  529. // Release in the destructor
  530. TRY
  531. {
  532. if (!VALID_D3DFINDDEVICESEARCH_PTR(lpSearch)) {
  533. D3D_ERR( "Invalid search pointer" );
  534. return DDERR_INVALIDPARAMS;
  535. }
  536. if (!VALID_D3DFINDDEVICERESULT_PTR(lpResult)) {
  537. D3D_ERR( "Invalid result pointer" );
  538. return DDERR_INVALIDPARAMS;
  539. }
  540. }
  541. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  542. {
  543. D3D_ERR( "Exception encountered validating parameters" );
  544. return DDERR_INVALIDPARAMS;
  545. }
  546. enumArgs args;
  547. memset(&args, 0, sizeof args);
  548. args.result.dwSize = sizeof(args.result);
  549. args.search = *lpSearch;
  550. switch(dwVer) {
  551. case 1: CDirect3D::EnumDevices(enumFunc, &args); break;
  552. case 2: CDirect3D2::EnumDevices(enumFunc, &args); break;
  553. case 3: CDirect3D3::EnumDevices(enumFunc, &args); break;
  554. }
  555. if (args.foundHardware || args.foundSoftware) {
  556. DWORD dwSize = lpResult->dwSize;
  557. if (dwSize == sizeof( D3DFINDDEVICERESULT ) )
  558. {
  559. // The app is using DX6
  560. D3D_INFO(4, "New D3DFINDDEVICERESULT size");
  561. memcpy(lpResult, &args.result, lpResult->dwSize);
  562. }
  563. else
  564. {
  565. // The app is pre DX6
  566. DWORD dwSize = lpResult->dwSize;
  567. DWORD dDescSize = (dwSize - (sizeof(DWORD) + sizeof(GUID)))/2;
  568. D3D_INFO(4, "Old D3DFINDDEVICERESULT size");
  569. // Copy the header
  570. memcpy(lpResult, &args.result, sizeof(DWORD)+sizeof(GUID));
  571. //restore the size
  572. lpResult->dwSize = dwSize;
  573. // Copy and convert the embedded D3DDEVICEDESC's
  574. // DDescSize = (lpResult->dwSize - (sizeof(DWORD) + sizeof(GUID)))/2
  575. // This calculation assumes that the structure of
  576. // LPD3DFINDDEVICERESULT is the same as in DX6, DX5, if it is changed
  577. // This computation needs to be updated
  578. memcpy((LPVOID) (&lpResult->ddHwDesc),
  579. &args.result.ddHwDesc,
  580. dDescSize);
  581. memcpy((LPVOID) ((ULONG_PTR)&lpResult->ddHwDesc + dDescSize),
  582. &args.result.ddSwDesc,
  583. dDescSize);
  584. }
  585. return D3D_OK;
  586. }
  587. else
  588. {
  589. return DDERR_NOTFOUND;
  590. }
  591. }
  592. #undef DPF_MODNAME
  593. #define DPF_MODNAME "Direct3DI::EnumZBufferFormats"
  594. HRESULT D3DAPI DIRECT3DI::EnumZBufferFormats(REFCLSID riid,
  595. LPD3DENUMPIXELFORMATSCALLBACK lpEnumCallback,
  596. LPVOID lpContext)
  597. {
  598. HRESULT ret, userRet;
  599. LPDDPIXELFORMAT lpTmpPixFmts;
  600. DWORD i,cPixFmts;
  601. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  602. ret = D3D_OK;
  603. /*
  604. * validate parms
  605. */
  606. TRY
  607. {
  608. if (!VALID_DIRECT3D3_PTR(this)) {
  609. D3D_ERR( "Invalid Direct3D3 pointer" );
  610. return DDERR_INVALIDOBJECT;
  611. }
  612. if (!VALIDEX_CODE_PTR(lpEnumCallback)) {
  613. D3D_ERR( "Invalid callback pointer" );
  614. return DDERR_INVALIDPARAMS;
  615. }
  616. if(!IsValidD3DDeviceGuid(riid)) {
  617. D3D_ERR( "Invalid D3D Device GUID" );
  618. return DDERR_INVALIDPARAMS;
  619. }
  620. }
  621. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  622. {
  623. D3D_ERR( "Exception encountered validating parameters" );
  624. return DDERR_INVALIDPARAMS;
  625. }
  626. if(IsEqualIID(riid, IID_IDirect3DHALDevice)) {
  627. LPDDRAWI_DIRECTDRAW_GBL pDdGbl=((LPDDRAWI_DIRECTDRAW_INT)this->lpDD)->lpLcl->lpGbl;
  628. LPD3DHAL_GLOBALDRIVERDATA lpD3DHALGlobalDriverData=pDdGbl->lpD3DGlobalDriverData;
  629. DWORD dwHW_ZBitDepthFlags;
  630. if (NULL == lpD3DHALGlobalDriverData)
  631. {
  632. D3D_ERR("No HAL Support ZBufferBitDepths!");
  633. return (DDERR_NOZBUFFERHW);
  634. }
  635. cPixFmts=pDdGbl->dwNumZPixelFormats;
  636. if (cPixFmts==0) {
  637. // driver is pre-dx6, so it doesn't support stencil buffer pix fmts or this callback.
  638. // we can fake support using DD_BD bits in dwZBufferBitDepth in D3DDEVICEDESC
  639. D3D_WARN(6,"EnumZBufferFormats not supported directly by driver, faking it using dwDeviceZBufferBitDepth DD_BD bits");
  640. dwHW_ZBitDepthFlags=lpD3DHALGlobalDriverData->hwCaps.dwDeviceZBufferBitDepth;
  641. if(!(dwHW_ZBitDepthFlags & (DDBD_8|DDBD_16|DDBD_24|DDBD_32))) {
  642. D3D_ERR("No Supported ZBufferBitDepths!");
  643. return (DDERR_NOZBUFFERHW);
  644. }
  645. // malloc space for 4 DDPIXELFORMATs, since that the most there could be (DDBD_8,16,24,32)
  646. if (D3DMalloc((void**)&lpTmpPixFmts, 4*sizeof(DDPIXELFORMAT)) != D3D_OK) {
  647. D3D_ERR("failed to alloc space for return descriptions");
  648. return (DDERR_OUTOFMEMORY);
  649. }
  650. DWORD zdepthflags[4]= {DDBD_8,DDBD_16,DDBD_24,DDBD_32};
  651. DWORD zbitdepths[4]= {8,16,24,32};
  652. DWORD zbitmasks[4]= {0xff,0xffff,0xffffff,0xffffffff};
  653. memset(lpTmpPixFmts,0,sizeof(4*sizeof(DDPIXELFORMAT)));
  654. // create some DDPIXELFORMATs the app can look at
  655. for(i=0;i<4;i++) {
  656. if(dwHW_ZBitDepthFlags & zdepthflags[i]) {
  657. lpTmpPixFmts[cPixFmts].dwSize=sizeof(DDPIXELFORMAT);
  658. lpTmpPixFmts[cPixFmts].dwFlags=DDPF_ZBUFFER;
  659. lpTmpPixFmts[cPixFmts].dwZBufferBitDepth=zbitdepths[i];
  660. lpTmpPixFmts[cPixFmts].dwZBitMask= zbitmasks[i];
  661. cPixFmts++;
  662. }
  663. }
  664. } else {
  665. // only show the app a temp copy of DDraw's real records
  666. if (D3DMalloc((void**)&lpTmpPixFmts, cPixFmts*sizeof(DDPIXELFORMAT)) != D3D_OK) {
  667. D3D_ERR("Out of memory allocating space for return descriptions");
  668. return (DDERR_OUTOFMEMORY);
  669. }
  670. memcpy(lpTmpPixFmts, pDdGbl->lpZPixelFormats, cPixFmts*sizeof(DDPIXELFORMAT));
  671. }
  672. } else {
  673. // Handle SW rasterizers
  674. DDPIXELFORMAT *pDDPF;
  675. // malloc space for 10 DDPIXELFORMAT's, which is currently more than enough for the SW rasterizers
  676. if (D3DMalloc((void**)&lpTmpPixFmts, 10*sizeof(DDPIXELFORMAT)) != D3D_OK) {
  677. D3D_ERR("Out of memory allocating space for return descriptions");
  678. return (DDERR_OUTOFMEMORY);
  679. }
  680. cPixFmts=GetSwZBufferFormats(riid,&pDDPF);
  681. memcpy(lpTmpPixFmts, pDDPF, cPixFmts*sizeof(DDPIXELFORMAT));
  682. }
  683. userRet = D3DENUMRET_OK;
  684. for (i = 0; (i < cPixFmts) && (userRet == D3DENUMRET_OK); i++) {
  685. userRet = (*lpEnumCallback)(&lpTmpPixFmts[i], lpContext);
  686. }
  687. D3DFree(lpTmpPixFmts);
  688. return (D3D_OK);
  689. }
  690. #undef DPF_MODNAME
  691. #define DPF_MODNAME "Direct3D::EnumOptTextureFormats"
  692. HRESULT D3DAPI DIRECT3DI::EnumOptTextureFormats(REFCLSID riid, LPD3DENUMOPTTEXTUREFORMATSCALLBACK lpEnumCallback, LPVOID lpContext)
  693. {
  694. HRESULT ret, userRet;
  695. LPDDSURFACEDESC lpDescs;
  696. LPDDSURFACEDESC2 lpRetDescs;
  697. LPDDOPTSURFACEDESC lpRetOptDescs;
  698. LPD3DHAL_GLOBALDRIVERDATA lpD3DHALGlobalDriverData;
  699. DWORD num_descs;
  700. DWORD i;
  701. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  702. ret = D3D_OK;
  703. //
  704. // Validation
  705. //
  706. TRY
  707. {
  708. if (!VALID_DIRECT3D3_PTR(this)) {
  709. D3D_ERR( "Invalid Direct3D pointer" );
  710. return DDERR_INVALIDOBJECT;
  711. }
  712. if (!VALIDEX_CODE_PTR(lpEnumCallback)) {
  713. D3D_ERR( "Invalid callback pointer" );
  714. return DDERR_INVALIDPARAMS;
  715. }
  716. if(!IsValidD3DDeviceGuid(riid)) {
  717. D3D_ERR( "Invalid D3D Device GUID" );
  718. return DDERR_INVALIDPARAMS;
  719. }
  720. }
  721. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  722. {
  723. D3D_ERR( "Exception encountered validating parameters" );
  724. return DDERR_INVALIDPARAMS;
  725. }
  726. if(IsEqualIID(riid, IID_IDirect3DHALDevice)) {
  727. lpD3DHALGlobalDriverData=((LPDDRAWI_DIRECTDRAW_INT)this->lpDD)->lpLcl->lpGbl->lpD3DGlobalDriverData;
  728. num_descs = lpD3DHALGlobalDriverData->dwNumTextureFormats;
  729. lpDescs = lpD3DHALGlobalDriverData->lpTextureFormats;
  730. } else {
  731. num_descs = GetSwTextureFormats(riid,&lpDescs,3/*enum for Device3*/);
  732. }
  733. if (!num_descs)
  734. {
  735. D3D_ERR("no texture formats supported");
  736. return (D3DERR_TEXTURE_NO_SUPPORT);
  737. }
  738. //
  739. // Make a local copy of these formats
  740. //
  741. if (D3DMalloc((void**)&lpRetDescs, sizeof(DDSURFACEDESC2) * num_descs)
  742. != D3D_OK)
  743. {
  744. D3D_ERR("Out of memory allocating space for return descriptions");
  745. return (DDERR_OUTOFMEMORY);
  746. }
  747. for (i=0; i<num_descs; i++)
  748. {
  749. // We can copy only the subset of the data
  750. memcpy(&lpRetDescs[i], &lpDescs[i], sizeof(DDSURFACEDESC));
  751. }
  752. userRet = D3DENUMRET_OK;
  753. //
  754. // First return the unoptimized formats......
  755. //
  756. for (i = 0; i < num_descs && userRet == D3DENUMRET_OK; i++)
  757. {
  758. userRet = (*lpEnumCallback)(&lpRetDescs[i], NULL, lpContext);
  759. }
  760. //
  761. // ......Now return the formats capable of being optimized
  762. //
  763. for (i = 0; i < num_descs && userRet == D3DENUMRET_OK; i++)
  764. {
  765. userRet = (*lpEnumCallback)(&lpRetDescs[i], NULL, lpContext);
  766. }
  767. D3DFree(lpRetDescs);
  768. return (D3D_OK);
  769. }
  770. #undef DPF_MODNAME
  771. #define DPF_MODNAME "DIRECT3D::EvictManagedTextures"
  772. HRESULT D3DAPI
  773. DIRECT3DI::EvictManagedTextures()
  774. {
  775. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  776. if (!VALID_DIRECT3D_PTR(this))
  777. {
  778. D3D_ERR( "Invalid Direct3D3 pointer" );
  779. return DDERR_INVALIDOBJECT;
  780. }
  781. lpTextureManager->EvictTextures();
  782. return D3D_OK;
  783. }
  784. #undef DPF_MODNAME
  785. #define DPF_MODNAME "DIRECT3D::FlushDevicesExcept"
  786. HRESULT DIRECT3DI::FlushDevicesExcept(LPDIRECT3DDEVICEI pDev)
  787. {
  788. LPDIRECT3DDEVICEI lpDevI = LIST_FIRST(&this->devices);
  789. while (lpDevI)
  790. {
  791. if(lpDevI != pDev)
  792. {
  793. HRESULT hr = lpDevI->FlushStates();
  794. if(hr != D3D_OK)
  795. {
  796. DPF_ERR("Error flushing device in FlushDevicesExcept");
  797. return hr;
  798. }
  799. }
  800. lpDevI = LIST_NEXT(lpDevI,list);
  801. }
  802. return D3D_OK;
  803. }
  804. extern "C" void WINAPI PaletteUpdateNotify(
  805. LPVOID pD3DIUnknown,
  806. DWORD dwPaletteHandle,
  807. DWORD dwStartIndex,
  808. DWORD dwNumberOfIndices,
  809. LPPALETTEENTRY pFirstIndex)
  810. {
  811. LPDIRECT3DI lpD3D = static_cast<CDirect3DUnk*>(pD3DIUnknown)->pD3DI;
  812. DDASSERT(lpD3D);
  813. LPDIRECT3DDEVICEI lpDevI = LIST_FIRST(&lpD3D->devices);
  814. while (lpDevI)
  815. {
  816. D3D_INFO(4,"PaletteUpdateNotify lpDevI(%x) %08lx %08lx %08lx %08lx",
  817. lpDevI,dwPaletteHandle,dwStartIndex,dwNumberOfIndices,*(DWORD*)&pFirstIndex[10]);
  818. if (IS_DX7HAL_DEVICE(lpDevI))
  819. {
  820. if(lpD3D->numDevs > 1)
  821. lpD3D->FlushDevicesExcept(lpDevI);
  822. static_cast<CDirect3DDeviceIDP2*>(lpDevI)->UpdatePalette(dwPaletteHandle,dwStartIndex,dwNumberOfIndices,pFirstIndex);
  823. if(lpD3D->numDevs > 1)
  824. lpDevI->FlushStates();
  825. break;
  826. }
  827. lpDevI = LIST_NEXT(lpDevI,list);
  828. }
  829. }
  830. extern "C" void WINAPI PaletteAssociateNotify(
  831. LPVOID pD3DIUnknown,
  832. DWORD dwPaletteHandle,
  833. DWORD dwPaletteFlags,
  834. DWORD dwSurfaceHandle )
  835. {
  836. LPDIRECT3DI lpD3D = static_cast<CDirect3DUnk*>(pD3DIUnknown)->pD3DI;
  837. DDASSERT(lpD3D);
  838. LPDIRECT3DDEVICEI lpDevI = LIST_FIRST(&lpD3D->devices);
  839. while (lpDevI)
  840. {
  841. D3D_INFO(4,"PaletteAssociateNotify lpDevI(%x) %08lx %08lx",
  842. lpDevI,dwPaletteHandle, dwSurfaceHandle);
  843. if (IS_DX7HAL_DEVICE(lpDevI))
  844. {
  845. if(lpD3D->numDevs > 1)
  846. lpD3D->FlushDevicesExcept(lpDevI);
  847. static_cast<CDirect3DDeviceIDP2*>(lpDevI)->SetPalette(dwPaletteHandle,dwPaletteFlags,dwSurfaceHandle);
  848. if(lpD3D->numDevs > 1)
  849. lpDevI->FlushStates();
  850. break;
  851. }
  852. lpDevI = LIST_NEXT(lpDevI,list);
  853. }
  854. }
  855. extern "C" void WINAPI SurfaceFlipNotify(LPVOID pD3DIUnknown)
  856. {
  857. LPDIRECT3DI lpD3D = static_cast<CDirect3DUnk*>(pD3DIUnknown)->pD3DI;
  858. DDASSERT(lpD3D);
  859. LPDIRECT3DDEVICEI lpDevI = LIST_FIRST(&lpD3D->devices);
  860. D3D_INFO(4,"SurfaceFlipNotify");
  861. while (lpDevI)
  862. {
  863. if (IS_DX7HAL_DEVICE(lpDevI))
  864. {
  865. #ifndef WIN95
  866. if(lpDevI->hSurfaceTarget != ((LPDDRAWI_DDRAWSURFACE_INT)lpDevI->lpDDSTarget)->lpLcl->hDDSurface)
  867. {
  868. static_cast<CDirect3DDeviceIDP2*>(lpDevI)->SetRenderTargetI(lpDevI->lpDDSTarget,lpDevI->lpDDSZBuffer);
  869. lpDevI->hSurfaceTarget=((LPDDRAWI_DDRAWSURFACE_INT)lpDevI->lpDDSTarget)->lpLcl->hDDSurface;
  870. }
  871. #else
  872. if(lpDevI->hSurfaceTarget != ((LPDDRAWI_DDRAWSURFACE_INT)lpDevI->lpDDSTarget)->lpLcl->lpSurfMore->dwSurfaceHandle)
  873. {
  874. static_cast<CDirect3DDeviceIDP2*>(lpDevI)->SetRenderTargetI(lpDevI->lpDDSTarget,lpDevI->lpDDSZBuffer);
  875. lpDevI->hSurfaceTarget=((LPDDRAWI_DDRAWSURFACE_INT)lpDevI->lpDDSTarget)->lpLcl->lpSurfMore->dwSurfaceHandle;
  876. }
  877. #endif
  878. }
  879. lpDevI = LIST_NEXT(lpDevI,list);
  880. }
  881. }
  882. #undef DPF_MODNAME
  883. #define DPF_MODNAME "FlushD3DDevices"
  884. extern "C" HRESULT WINAPI FlushD3DDevices(LPDDRAWI_DDRAWSURFACE_LCL surf_lcl)
  885. {
  886. LPD3DBUCKET list = reinterpret_cast<LPD3DBUCKET>(surf_lcl->lpSurfMore->lpD3DDevIList);
  887. while(list)
  888. {
  889. LPD3DBUCKET temp = list->next;
  890. reinterpret_cast<LPDIRECT3DDEVICEI>(list->lpD3DDevI)->FlushStates();
  891. list = temp;
  892. }
  893. return DD_OK;
  894. }
  895. #undef DPF_MODNAME
  896. #define DPF_MODNAME "FlushD3DDevices2"
  897. extern "C" HRESULT WINAPI FlushD3DDevices2(LPDDRAWI_DDRAWSURFACE_LCL surf_lcl)
  898. {
  899. LPD3DBUCKET list = reinterpret_cast<LPD3DBUCKET>(surf_lcl->lpSurfMore->lpD3DDevIList);
  900. while(list)
  901. {
  902. LPD3DBUCKET temp = list->next;
  903. if (list->lplpDDSZBuffer)
  904. *list->lplpDDSZBuffer = 0; // detached
  905. reinterpret_cast<LPDIRECT3DDEVICEI>(list->lpD3DDevI)->FlushStates();
  906. list = temp;
  907. }
  908. return DD_OK;
  909. }