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.

2298 lines
75 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1997 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: devstate.c
  6. * Content: device state management
  7. *
  8. ***************************************************************************/
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. #include "drawprim.hpp"
  12. #include "pvvid.h"
  13. #include "d3dfei.h"
  14. extern HRESULT checkDeviceSurface(LPDIRECT3DDEVICEI lpD3DDev,
  15. LPDIRECTDRAWSURFACE lpDDS);
  16. extern HRESULT CalcDDSurfInfo(LPDIRECT3DDEVICEI lpDevI, BOOL bUpdateZBufferFields);
  17. //---------------------------------------------------------------------
  18. inline void UpdateFogFactor(LPDIRECT3DDEVICEI lpDevI)
  19. {
  20. if (lpDevI->lighting.fog_end == lpDevI->lighting.fog_start)
  21. lpDevI->lighting.fog_factor = D3DVAL(0.0);
  22. else
  23. lpDevI->lighting.fog_factor = D3DVAL(255) /
  24. (lpDevI->lighting.fog_end - lpDevI->lighting.fog_start);
  25. }
  26. //---------------------------------------------------------------------
  27. #undef DPF_MODNAME
  28. #define DPF_MODNAME "Direct3DDevice::SetRenderState"
  29. HRESULT D3DAPI
  30. DIRECT3DDEVICEI::SetRenderState(D3DRENDERSTATETYPE dwState, DWORD value)
  31. {
  32. #if DBG
  33. if (dwState >= D3D_MAXRENDERSTATES || dwState == 0 )
  34. {
  35. D3D_ERR( "Invalid render state type" );
  36. return DDERR_INVALIDPARAMS;
  37. }
  38. #endif
  39. // Takes D3D lock (MT only).
  40. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND(""));
  41. try
  42. {
  43. if (this->dwFEFlags & D3DFE_RECORDSTATEMODE)
  44. {
  45. if(this->CheckForRetiredRenderState(dwState))
  46. {
  47. m_pStateSets->InsertRenderState(dwState, value, CanHandleRenderState(dwState));
  48. }
  49. else
  50. {
  51. D3D_ERR("invalid renderstate %d", dwState);
  52. return DDERR_INVALIDPARAMS;
  53. }
  54. }
  55. else
  56. this->SetRenderStateFast(dwState, value);
  57. return D3D_OK;
  58. }
  59. catch(HRESULT ret)
  60. {
  61. return ret;
  62. }
  63. }
  64. //---------------------------------------------------------------------
  65. #undef DPF_MODNAME
  66. #define DPF_MODNAME "DIRECT3DDEVICEI::SetRenderStateFast"
  67. HRESULT D3DAPI
  68. DIRECT3DDEVICEI::SetRenderStateFast(D3DRENDERSTATETYPE dwState, DWORD value)
  69. {
  70. #if DBG
  71. if (dwState >= D3D_MAXRENDERSTATES || dwState == 0 )
  72. {
  73. D3D_ERR( "Invalid render state type" );
  74. return DDERR_INVALIDPARAMS;
  75. }
  76. #endif
  77. if (!(rsVec[dwState >> D3D_RSVEC_SHIFT] & (1ul << (dwState & D3D_RSVEC_MASK))))
  78. { // Fast path. We do not need any processing done in UpdateInternalState other than updating rstates array
  79. if (this->rstates[dwState] == value)
  80. {
  81. D3D_WARN(4,"Ignoring redundant SetRenderState");
  82. return D3D_OK;
  83. }
  84. this->rstates[dwState] = value;
  85. // Output state to the device driver
  86. return SetRenderStateI(dwState, value);
  87. }
  88. else
  89. {
  90. try
  91. {
  92. // Wrap modes could be re-programmed. We need to restore them before
  93. // filtering redundant values
  94. if (this->dwDeviceFlags & D3DDEV_REMAPTEXTUREINDICES)
  95. {
  96. RestoreTextureStages(this);
  97. ForceFVFRecompute();
  98. }
  99. if (this->rstates[dwState] == value)
  100. {
  101. D3D_WARN(4,"Ignoring redundant SetRenderState");
  102. return D3D_OK;
  103. }
  104. this->UpdateInternalState(dwState, value);
  105. if (CanHandleRenderState(dwState))
  106. {
  107. if(CheckForRetiredRenderState(dwState))
  108. return SetRenderStateI(dwState, value);
  109. D3D_ERR("invalid renderstate %d", dwState);
  110. return DDERR_INVALIDPARAMS;
  111. }
  112. }
  113. catch(HRESULT ret)
  114. {
  115. return ret;
  116. }
  117. }
  118. return D3D_OK;
  119. }
  120. //---------------------------------------------------------------------
  121. #undef DPF_MODNAME
  122. #define DPF_MODNAME "Direct3DDevice::SetRenderStateInternal"
  123. HRESULT
  124. DIRECT3DDEVICEI::SetRenderStateInternal(D3DRENDERSTATETYPE dwState, DWORD dwValue)
  125. {
  126. if (this->rstates[dwState] == dwValue)
  127. {
  128. D3D_WARN(4,"Ignoring redundant SetRenderState");
  129. return D3D_OK;
  130. }
  131. try
  132. {
  133. this->UpdateInternalState(dwState, dwValue);
  134. if (CanHandleRenderState(dwState))
  135. return SetRenderStateI(dwState, dwValue);
  136. return D3D_OK;
  137. }
  138. catch(HRESULT ret)
  139. {
  140. return ret;
  141. }
  142. }
  143. #undef DPF_MODNAME
  144. #define DPF_MODNAME "Direct3DDevice::GetRenderState"
  145. HRESULT D3DAPI
  146. DIRECT3DDEVICEI::GetRenderState(D3DRENDERSTATETYPE dwState, LPDWORD lpdwValue)
  147. {
  148. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock (MT only).
  149. #if DBG
  150. if (dwState >= D3D_MAXRENDERSTATES || dwState == 0)
  151. {
  152. D3D_ERR( "Invalid render state value" );
  153. return DDERR_INVALIDPARAMS;
  154. }
  155. #endif
  156. if (!VALID_DIRECT3DDEVICE_PTR(this))
  157. {
  158. D3D_ERR( "Invalid Direct3DDevice pointer" );
  159. return DDERR_INVALIDOBJECT;
  160. }
  161. if (!VALID_PTR(lpdwValue, sizeof(DWORD)))
  162. {
  163. D3D_ERR( "Invalid DWORD pointer" );
  164. return DDERR_INVALIDPARAMS;
  165. }
  166. if(!CheckForRetiredRenderState(dwState))
  167. {
  168. D3D_ERR("invalid renderstate %d", dwState);
  169. return DDERR_INVALIDPARAMS;
  170. }
  171. // WRAP render states could be re-mapped so we have to return the original
  172. // value
  173. if (dwState >= D3DRENDERSTATE_WRAP0 && dwState <= D3DRENDERSTATE_WRAP7)
  174. {
  175. if (this->dwDeviceFlags & D3DDEV_REMAPTEXTUREINDICES)
  176. {
  177. DWORD dwTexCoordIndex = dwState - D3DRENDERSTATE_WRAP0;
  178. for (DWORD i=0; i < this->dwNumTextureStages; i++)
  179. {
  180. LPD3DFE_TEXTURESTAGE pStage = &this->textureStage[i];
  181. if (pStage->dwInpCoordIndex == dwTexCoordIndex)
  182. {
  183. if (pStage->dwInpCoordIndex != pStage->dwOutCoordIndex)
  184. {
  185. *lpdwValue = pStage->dwOrgWrapMode;
  186. return D3D_OK;
  187. }
  188. }
  189. }
  190. }
  191. }
  192. *lpdwValue = this->rstates[dwState];
  193. return D3D_OK;
  194. }
  195. #undef DPF_MODNAME
  196. #define DPF_MODNAME "Direct3DDevice::GetTexture"
  197. HRESULT D3DAPI
  198. DIRECT3DDEVICEI::GetTexture(DWORD dwStage, LPDIRECTDRAWSURFACE7 *lplpTex)
  199. {
  200. // Takes D3D lock (MT only).
  201. // Lock released in the destructor.
  202. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND(""));
  203. #if DBG
  204. if (dwStage >= D3DHAL_TSS_MAXSTAGES)
  205. {
  206. D3D_ERR( "Invalid texture stage or state index" );
  207. return DDERR_INVALIDPARAMS;
  208. }
  209. #endif
  210. if (!VALID_DIRECT3DDEVICE_PTR(this))
  211. {
  212. D3D_ERR( "Invalid Direct3DDevice pointer" );
  213. return DDERR_INVALIDOBJECT;
  214. }
  215. if (!VALID_PTR(lplpTex, sizeof(LPVOID)))
  216. {
  217. D3D_ERR( "Invalid pointer to LPDIRECTDRAWSURFACE7" );
  218. return DDERR_INVALIDPARAMS;
  219. }
  220. if (this->lpD3DMappedTexI[dwStage])
  221. {
  222. if(this->lpD3DMappedTexI[dwStage]->D3DManaged())
  223. *lplpTex = this->lpD3DMappedTexI[dwStage]->lpDDSSys;
  224. else
  225. *lplpTex = this->lpD3DMappedTexI[dwStage]->lpDDS;
  226. (*lplpTex)->AddRef();
  227. }
  228. else
  229. {
  230. *lplpTex = NULL;
  231. }
  232. return D3D_OK;
  233. }
  234. #undef DPF_MODNAME
  235. #define DPF_MODNAME "Direct3DDevice::VerifyTexture"
  236. HRESULT DIRECT3DDEVICEI::VerifyTexture(DWORD dwStage, LPDIRECTDRAWSURFACE7 lpTex)
  237. {
  238. if (dwStage >= D3DHAL_TSS_MAXSTAGES)
  239. {
  240. D3D_ERR( "Invalid texture stage or state index" );
  241. return DDERR_INVALIDPARAMS;
  242. }
  243. if (!VALID_DIRECT3DDEVICE_PTR(this))
  244. {
  245. D3D_ERR( "Invalid Direct3DDevice pointer" );
  246. return DDERR_INVALIDOBJECT;
  247. }
  248. if (lpTex)
  249. {
  250. if (!VALID_DDSURF_PTR(lpTex))
  251. {
  252. D3D_ERR( "Invalid surface pointer" );
  253. return DDERR_INVALIDOBJECT;
  254. }
  255. if((((LPDDRAWI_DDRAWSURFACE_INT)lpTex)->lpLcl->lpSurfMore->ddsCapsEx.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE)) &&
  256. !(this->dwFEFlags & D3DFE_REALHAL))
  257. {
  258. D3D_ERR( "Managed textures cannot be used with a software device" );
  259. return DDERR_INVALIDPARAMS;
  260. }
  261. if(!IsToplevel(((LPDDRAWI_DDRAWSURFACE_INT)lpTex)->lpLcl))
  262. {
  263. D3D_ERR( "Cannot set a mipmap sublevel or a cubemap subface" );
  264. return DDERR_INVALIDPARAMS;
  265. }
  266. LPDIRECT3DTEXTUREI lpTexI = reinterpret_cast<LPDIRECT3DTEXTUREI>(((LPDDRAWI_DDRAWSURFACE_INT)lpTex)->lpLcl->lpSurfMore->lpTex);
  267. if(lpTexI == NULL)
  268. {
  269. D3D_ERR( "Surface must have DDSCAPS_TEXTURE set to use in SetTexture" );
  270. return DDERR_INVALIDPARAMS;
  271. }
  272. if (!lpTexI->D3DManaged())
  273. {
  274. if((((LPDDRAWI_DDRAWSURFACE_INT)(lpTexI->lpDDS))->lpLcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
  275. (!(lpD3DHALGlobalDriverData->hwCaps.dwDevCaps & D3DDEVCAPS_TEXTURESYSTEMMEMORY)))
  276. {
  277. D3D_ERR( "Device cannot render using texture surface from system memory" );
  278. return DDERR_INVALIDPARAMS;
  279. }
  280. }
  281. CLockD3DST lockObject(this, DPF_MODNAME, REMIND("")); // we access DDraw gbl in VerifyTextureCaps
  282. return VerifyTextureCaps(lpTexI);
  283. }
  284. return D3D_OK;
  285. }
  286. #undef DPF_MODNAME
  287. #define DPF_MODNAME "Direct3DDevice::SetTexture"
  288. HRESULT D3DAPI
  289. DIRECT3DDEVICEI::SetTexture(DWORD dwStage, LPDIRECTDRAWSURFACE7 lpTex)
  290. {
  291. try
  292. {
  293. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND(""));
  294. #if DBG
  295. HRESULT ret = VerifyTexture(dwStage, lpTex);
  296. if(ret != D3D_OK)
  297. return ret;
  298. #endif
  299. if (this->dwFEFlags & D3DFE_RECORDSTATEMODE)
  300. {
  301. m_pStateSets->InsertTexture(dwStage, lpTex);
  302. return D3D_OK;
  303. }
  304. return SetTextureInternal(dwStage, lpTex);
  305. }
  306. catch(HRESULT ret)
  307. {
  308. return ret;
  309. }
  310. }
  311. #undef DPF_MODNAME
  312. #define DPF_MODNAME "Direct3DDevice::SetTextureInternal"
  313. HRESULT D3DAPI
  314. DIRECT3DDEVICEI::SetTextureInternal(DWORD dwStage, LPDIRECTDRAWSURFACE7 lpTex)
  315. {
  316. #if DBG
  317. HRESULT ret = VerifyTexture(dwStage, lpTex);
  318. if(ret != D3D_OK)
  319. return ret;
  320. #endif
  321. #if COLLECTSTATS
  322. this->IncNumTexturesSet();
  323. #endif
  324. LPDIRECT3DTEXTUREI lpTexI = lpTex ? reinterpret_cast<LPDIRECT3DTEXTUREI>(((LPDDRAWI_DDRAWSURFACE_INT)lpTex)->lpLcl->lpSurfMore->lpTex) : NULL;
  325. if (lpD3DMappedTexI[dwStage] == lpTexI)
  326. {
  327. return D3D_OK;
  328. }
  329. if (lpD3DMappedTexI[dwStage])
  330. {
  331. lpD3DMappedTexI[dwStage]->Release();
  332. }
  333. lpD3DMappedTexI[dwStage] = lpTexI;
  334. if (lpTexI)
  335. {
  336. lpTexI->AddRef();
  337. #if COLLECTSTATS
  338. if(lpTexI->D3DManaged())
  339. {
  340. this->lpDirect3DI->lpTextureManager->IncNumTexturesSet();
  341. if(lpTexI->InVidmem())
  342. this->lpDirect3DI->lpTextureManager->IncNumSetTexInVid();
  343. }
  344. #endif
  345. }
  346. m_dwStageDirty |= (1 << dwStage);
  347. // Need to call UpdateTextures()
  348. this->dwFEFlags |= D3DFE_NEED_TEXTURE_UPDATE;
  349. return D3D_OK;
  350. }
  351. //---------------------------------------------------------------------
  352. #undef DPF_MODNAME
  353. #define DPF_MODNAME "DIRECT3DDEVICEI::SetTextureStageState"
  354. HRESULT D3DAPI
  355. DIRECT3DDEVICEI::SetTextureStageState(DWORD dwStage,
  356. D3DTEXTURESTAGESTATETYPE dwState,
  357. DWORD dwValue)
  358. {
  359. #if DBG
  360. if (dwStage >= D3DHAL_TSS_MAXSTAGES ||
  361. dwState == 0 || dwState >= D3DTSS_MAX)
  362. {
  363. D3D_ERR( "Invalid texture stage or state index" );
  364. return DDERR_INVALIDPARAMS;
  365. }
  366. #endif //DBG
  367. try
  368. {
  369. // Holds D3D lock until exit.
  370. CLockD3DMT ldmLock(this, DPF_MODNAME, REMIND(""));
  371. if (this->dwFEFlags & D3DFE_RECORDSTATEMODE)
  372. {
  373. m_pStateSets->InsertTextureStageState(dwStage, dwState, dwValue);
  374. return D3D_OK;
  375. }
  376. return this->SetTextureStageStateFast(dwStage, dwState, dwValue);
  377. }
  378. catch(HRESULT ret)
  379. {
  380. return ret;
  381. }
  382. }
  383. //---------------------------------------------------------------------
  384. #undef DPF_MODNAME
  385. #define DPF_MODNAME "DIRECT3DDEVICEI::SetTextureStageStateFast"
  386. HRESULT D3DAPI
  387. DIRECT3DDEVICEI::SetTextureStageStateFast(DWORD dwStage,
  388. D3DTEXTURESTAGESTATETYPE dwState,
  389. DWORD dwValue)
  390. {
  391. #if DBG
  392. if (dwStage >= D3DHAL_TSS_MAXSTAGES ||
  393. dwState == 0 || dwState >= D3DTSS_MAX)
  394. {
  395. D3D_ERR( "Invalid texture stage or state index" );
  396. return DDERR_INVALIDPARAMS;
  397. }
  398. #endif //DBG
  399. // Fast path. We do not need any processing done in UpdateInternalTSS other than updating tsstates array
  400. if (NeedInternalTSSUpdate(dwState))
  401. {
  402. // Texture stages could be re-programmed. We need to restore them before
  403. // filtering redundant values
  404. if (this->dwDeviceFlags & D3DDEV_REMAPTEXTUREINDICES)
  405. {
  406. RestoreTextureStages(this);
  407. ForceFVFRecompute();
  408. }
  409. if (this->tsstates[dwStage][dwState] == dwValue)
  410. {
  411. D3D_WARN(4,"Ignoring redundant SetTextureStageState");
  412. return D3D_OK;
  413. }
  414. if(this->UpdateInternalTextureStageState(dwStage, dwState, dwValue))
  415. return D3D_OK;
  416. }
  417. else
  418. {
  419. if (this->tsstates[dwStage][dwState] == dwValue)
  420. {
  421. D3D_WARN(4,"Ignoring redundant SetTextureStageState");
  422. return D3D_OK;
  423. }
  424. tsstates[dwStage][dwState] = dwValue;
  425. }
  426. if (dwStage >= this->dwMaxTextureBlendStages)
  427. return D3D_OK;
  428. return SetTSSI(dwStage, dwState, dwValue);
  429. }
  430. //---------------------------------------------------------------------
  431. #undef DPF_MODNAME
  432. #define DPF_MODNAME "Direct3DDevice::GetTextureStageState"
  433. HRESULT D3DAPI
  434. DIRECT3DDEVICEI::GetTextureStageState(DWORD dwStage,
  435. D3DTEXTURESTAGESTATETYPE dwState,
  436. LPDWORD pdwValue)
  437. {
  438. // Takes D3D lock (MT only).
  439. // Lock released in the destructor.
  440. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND(""));
  441. #if DBG
  442. if (dwStage >= D3DHAL_TSS_MAXSTAGES ||
  443. dwState == 0 || dwState >= D3DTSS_MAX)
  444. {
  445. D3D_ERR( "Invalid texture stage or state index" );
  446. return DDERR_INVALIDPARAMS;
  447. }
  448. #endif //DBG
  449. if (!VALID_DIRECT3DDEVICE_PTR(this))
  450. {
  451. D3D_ERR( "Invalid Direct3DDevice pointer" );
  452. return DDERR_INVALIDOBJECT;
  453. }
  454. if (!VALID_PTR(pdwValue, sizeof(DWORD)))
  455. {
  456. D3D_ERR( "Invalid DWORD pointer" );
  457. return DDERR_INVALIDPARAMS;
  458. }
  459. // If texture indices were re-mapped we have to find and return the original value
  460. if (dwState == D3DTSS_TEXCOORDINDEX && this->dwDeviceFlags & D3DDEV_REMAPTEXTUREINDICES)
  461. {
  462. RestoreTextureStages(this);
  463. ForceFVFRecompute();
  464. }
  465. // Don't bother to check for DX6 support, just return the
  466. // cached value.
  467. *pdwValue = tsstates[dwStage][dwState];
  468. return D3D_OK;
  469. }
  470. #undef DPF_MODNAME
  471. #define DPF_MODNAME "Direct3D::CreateDevice"
  472. extern HRESULT WINAPI Direct3DCreateDevice(REFCLSID riid,
  473. LPUNKNOWN lpDirect3D,
  474. LPDIRECTDRAWSURFACE lpDDSTarget,
  475. LPUNKNOWN* lplpD3DDevice,
  476. IUnknown* pUnkOuter);
  477. HRESULT D3DAPI DIRECT3DI::CreateDevice(REFCLSID devType,
  478. LPDIRECTDRAWSURFACE7 lpDDS7,
  479. LPDIRECT3DDEVICE7 *lplpDirect3DDevice)
  480. {
  481. HRESULT ret;
  482. LPUNKNOWN lpUnkDevice;
  483. LPDIRECTDRAWSURFACE lpDDS;
  484. try
  485. {
  486. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  487. // Release in the destructor
  488. if (!VALID_DIRECT3D_PTR(this)) {
  489. D3D_ERR( "Invalid Direct3D pointer" );
  490. return DDERR_INVALIDOBJECT;
  491. }
  492. if (!VALID_OUTPTR(lplpDirect3DDevice))
  493. {
  494. D3D_ERR( "Invalid pointer to Device object pointer" );
  495. return DDERR_INVALIDPARAMS;
  496. }
  497. if (!VALID_D3D_DIRECTDRAWSURFACE7_PTR(((LPDDRAWI_DDRAWSURFACE_INT)lpDDS7)))
  498. {
  499. D3D_ERR( "Invalid DirectDrawSurface7 pointer" );
  500. return DDERR_INVALIDOBJECT;
  501. }
  502. *lplpDirect3DDevice = NULL;
  503. // QI lpDDS7 for lpDDS interface
  504. ret = lpDDS7->QueryInterface(IID_IDirectDrawSurface, (LPVOID*)&lpDDS);
  505. if (FAILED(ret))
  506. return ret;
  507. lpDDS->Release();
  508. ret = Direct3DCreateDevice(devType, &this->mD3DUnk, lpDDS, (LPUNKNOWN *) &lpUnkDevice, NULL);
  509. if(FAILED(ret) || (lpUnkDevice==NULL))
  510. return ret;
  511. // QI device1 for a device7 interface
  512. ret = lpUnkDevice->QueryInterface(IID_IDirect3DDevice7, (LPVOID*)lplpDirect3DDevice);
  513. lpUnkDevice->Release(); // release unneeded interface
  514. return ret;
  515. }
  516. catch (HRESULT ret)
  517. {
  518. return ret;
  519. }
  520. }
  521. //----------------------------------------------------------------------
  522. #undef DPF_MODNAME
  523. #define DPF_MODNAME "DIRECT3DDEVICEI::SetTransformI"
  524. void DIRECT3DDEVICEI::SetTransformI(D3DTRANSFORMSTATETYPE state, LPD3DMATRIX lpMat)
  525. {
  526. switch (state)
  527. {
  528. case D3DTRANSFORMSTATE_WORLD :
  529. *(D3DMATRIX*)&this->transform.world[0] = *lpMat;
  530. this->dwFEFlags |= D3DFE_WORLDMATRIX_DIRTY | D3DFE_FRONTEND_DIRTY;
  531. break;
  532. case D3DTRANSFORMSTATE_WORLD1 :
  533. *(D3DMATRIX*)&this->transform.world[1] = *lpMat;
  534. this->dwFEFlags |= D3DFE_WORLDMATRIX1_DIRTY | D3DFE_FRONTEND_DIRTY;
  535. break;
  536. case D3DTRANSFORMSTATE_WORLD2 :
  537. *(D3DMATRIX*)&this->transform.world[2] = *lpMat;
  538. this->dwFEFlags |= D3DFE_WORLDMATRIX2_DIRTY | D3DFE_FRONTEND_DIRTY;
  539. break;
  540. case D3DTRANSFORMSTATE_WORLD3 :
  541. *(D3DMATRIX*)&this->transform.world[3] = *lpMat;
  542. this->dwFEFlags |= D3DFE_WORLDMATRIX3_DIRTY | D3DFE_FRONTEND_DIRTY;
  543. break;
  544. case D3DTRANSFORMSTATE_VIEW :
  545. *(D3DMATRIX*)&this->transform.view = *lpMat;
  546. this->dwFEFlags |= D3DFE_VIEWMATRIX_DIRTY | D3DFE_FRONTEND_DIRTY;
  547. break;
  548. case D3DTRANSFORMSTATE_PROJECTION :
  549. *(D3DMATRIX*)&this->transform.proj = *lpMat;
  550. this->dwFEFlags |= D3DFE_PROJMATRIX_DIRTY | D3DFE_FRONTEND_DIRTY;
  551. if (!(this->dwFEFlags & D3DFE_EXECUTESTATEMODE))
  552. {
  553. this->UpdateDrvWInfo();
  554. }
  555. break;
  556. case D3DTRANSFORMSTATE_TEXTURE0:
  557. case D3DTRANSFORMSTATE_TEXTURE1:
  558. case D3DTRANSFORMSTATE_TEXTURE2:
  559. case D3DTRANSFORMSTATE_TEXTURE3:
  560. case D3DTRANSFORMSTATE_TEXTURE4:
  561. case D3DTRANSFORMSTATE_TEXTURE5:
  562. case D3DTRANSFORMSTATE_TEXTURE6:
  563. case D3DTRANSFORMSTATE_TEXTURE7:
  564. {
  565. this->dwDeviceFlags |= D3DDEV_TEXTRANSFORMDIRTY;
  566. DWORD dwIndex = state - D3DTRANSFORMSTATE_TEXTURE0;
  567. *(D3DMATRIX*)&this->mTexture[dwIndex] = *lpMat;
  568. break;
  569. }
  570. }
  571. }
  572. //----------------------------------------------------------------------
  573. #undef DPF_MODNAME
  574. #define DPF_MODNAME "DIRECT3DDEVICEI::SetTransform"
  575. HRESULT D3DAPI
  576. DIRECT3DDEVICEI::SetTransform(D3DTRANSFORMSTATETYPE state, LPD3DMATRIX lpMat)
  577. {
  578. #if DBG
  579. if (!VALID_PTR(lpMat, sizeof(D3DMATRIX)))
  580. {
  581. D3D_ERR( "Invalid matrix pointer" );
  582. return DDERR_INVALIDPARAMS;
  583. }
  584. switch (state)
  585. {
  586. case D3DTRANSFORMSTATE_WORLD:
  587. case D3DTRANSFORMSTATE_WORLD1:
  588. case D3DTRANSFORMSTATE_WORLD2:
  589. case D3DTRANSFORMSTATE_WORLD3:
  590. case D3DTRANSFORMSTATE_VIEW :
  591. case D3DTRANSFORMSTATE_PROJECTION :
  592. case D3DTRANSFORMSTATE_TEXTURE0:
  593. case D3DTRANSFORMSTATE_TEXTURE1:
  594. case D3DTRANSFORMSTATE_TEXTURE2:
  595. case D3DTRANSFORMSTATE_TEXTURE3:
  596. case D3DTRANSFORMSTATE_TEXTURE4:
  597. case D3DTRANSFORMSTATE_TEXTURE5:
  598. case D3DTRANSFORMSTATE_TEXTURE6:
  599. case D3DTRANSFORMSTATE_TEXTURE7:
  600. break;
  601. default :
  602. D3D_ERR( "Invalid state value passed to SetTransform" );
  603. return DDERR_INVALIDPARAMS; /* Work Item: Generate new meaningful return code */
  604. }
  605. #endif
  606. try
  607. {
  608. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock (MT only).
  609. if (this->dwFEFlags & D3DFE_RECORDSTATEMODE)
  610. m_pStateSets->InsertTransform(state, lpMat);
  611. else
  612. this->SetTransformI(state, lpMat);
  613. return D3D_OK;
  614. }
  615. catch(HRESULT ret)
  616. {
  617. return ret;
  618. }
  619. }
  620. //---------------------------------------------------------------------
  621. #undef DPF_MODNAME
  622. #define DPF_MODNAME "DIRECT3DDEVICEI::GetTransform"
  623. HRESULT D3DAPI
  624. DIRECT3DDEVICEI::GetTransform(D3DTRANSFORMSTATETYPE dtsTransformState, LPD3DMATRIX lpMat)
  625. {
  626. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock (MT only).
  627. HRESULT ret = D3D_OK;
  628. #if DBG
  629. if (!lpMat) {
  630. D3D_ERR( "NULL matrix pointer" );
  631. return DDERR_INVALIDPARAMS;
  632. }
  633. #endif
  634. switch (dtsTransformState) {
  635. case D3DTRANSFORMSTATE_WORLD :
  636. *lpMat = *(LPD3DMATRIX)&this->transform.world[0]._11;
  637. break;
  638. case D3DTRANSFORMSTATE_WORLD1 :
  639. *lpMat = *(LPD3DMATRIX)&this->transform.world[1]._11;
  640. break;
  641. case D3DTRANSFORMSTATE_WORLD2 :
  642. *lpMat = *(LPD3DMATRIX)&this->transform.world[2]._11;
  643. break;
  644. case D3DTRANSFORMSTATE_WORLD3 :
  645. *lpMat = *(LPD3DMATRIX)&this->transform.world[3]._11;
  646. break;
  647. case D3DTRANSFORMSTATE_VIEW :
  648. *lpMat = *(LPD3DMATRIX)&this->transform.view._11;
  649. break;
  650. case D3DTRANSFORMSTATE_PROJECTION :
  651. *lpMat = *(LPD3DMATRIX)&this->transform.proj._11;
  652. break;
  653. case D3DTRANSFORMSTATE_TEXTURE0:
  654. case D3DTRANSFORMSTATE_TEXTURE1:
  655. case D3DTRANSFORMSTATE_TEXTURE2:
  656. case D3DTRANSFORMSTATE_TEXTURE3:
  657. case D3DTRANSFORMSTATE_TEXTURE4:
  658. case D3DTRANSFORMSTATE_TEXTURE5:
  659. case D3DTRANSFORMSTATE_TEXTURE6:
  660. case D3DTRANSFORMSTATE_TEXTURE7:
  661. *lpMat = *(LPD3DMATRIX)&this->mTexture[dtsTransformState-D3DTRANSFORMSTATE_TEXTURE0]._11;
  662. break;
  663. default :
  664. D3D_ERR( "Invalid state value passed to GetTransform" );
  665. ret = DDERR_INVALIDPARAMS; /* Work Item: Generate new meaningful return code */
  666. break;
  667. }
  668. return ret;
  669. } // end of D3DDev2_GetTransform()
  670. void InvalidateHandles(LPDIRECT3DDEVICEI lpDevI)
  671. {
  672. /* free up all textures created by this object */
  673. LPD3DI_TEXTUREBLOCK tBlock=LIST_FIRST(&lpDevI->texBlocks);
  674. while (tBlock)
  675. {
  676. D3DI_RemoveTextureHandle(tBlock);
  677. tBlock=LIST_NEXT(tBlock,devList);
  678. }
  679. }
  680. //---------------------------------------------------------------------
  681. #undef DPF_MODNAME
  682. #define DPF_MODNAME "DIRECT3DDEVICEI::UpdateDriverStates"
  683. HRESULT
  684. DIRECT3DDEVICEI::UpdateDriverStates()
  685. {
  686. // note we can't do a loop from 1 to D3DHAL_MAX_RSTATES(256) as some of rstates are not
  687. // valid states, passin them down to drivers(like voodoo2 DX6 driver) will crash.
  688. for (DWORD i = D3DRENDERSTATE_ANTIALIAS ; i < D3DRENDERSTATE_WRAPBIAS+8; ++i)
  689. {
  690. HRESULT ret = this->SetRenderStateI((D3DRENDERSTATETYPE)i, this->rstates[i]);
  691. if (ret != D3D_OK)
  692. return ret;
  693. }
  694. return D3D_OK;
  695. }
  696. void DIRECT3DDEVICEI::SetRenderTargetI(LPDIRECTDRAWSURFACE lpDDS, LPDIRECTDRAWSURFACE lpZ)
  697. {
  698. HRESULT ret;
  699. // Flush before switching RenderTarget..
  700. ret = FlushStates();
  701. if (ret != D3D_OK)
  702. {
  703. D3D_ERR("Error trying to FlushStates in SetRenderTarget");
  704. throw ret;
  705. }
  706. if (this->lpD3DHALCallbacks2->SetRenderTarget)
  707. {
  708. D3DHAL_SETRENDERTARGETDATA rtData;
  709. rtData.dwhContext = this->dwhContext;
  710. #ifndef WIN95
  711. if (dwFEFlags & D3DFE_REALHAL)
  712. {
  713. if (lpDDS)
  714. rtData.lpDDSLcl = ((LPDDRAWI_DDRAWSURFACE_INT)lpDDS)->lpLcl;
  715. else
  716. rtData.lpDDSLcl = NULL;
  717. if (lpZ)
  718. rtData.lpDDSZLcl = ((LPDDRAWI_DDRAWSURFACE_INT)lpZ)->lpLcl;
  719. else
  720. rtData.lpDDSZLcl = NULL;
  721. }
  722. else
  723. #endif //WIN95
  724. {
  725. rtData.lpDDS = lpDDS;
  726. rtData.lpDDSZ = lpZ;
  727. }
  728. rtData.ddrval = 0;
  729. CALL_HAL2ONLY(ret, this, SetRenderTarget, &rtData);
  730. if ((ret != DDHAL_DRIVER_HANDLED) || (rtData.ddrval != DD_OK))
  731. {
  732. D3D_ERR( "Driver call failed in SetRenderTarget" );
  733. // Need sensible return value in this case,
  734. // currently we return whatever the driver stuck in here.
  735. ret = rtData.ddrval;
  736. throw ret;
  737. }
  738. }
  739. else
  740. {
  741. D3DHAL_CONTEXTCREATEDATA cdata;
  742. D3DHAL_CONTEXTDESTROYDATA ddata;
  743. /* Destroy old context */
  744. memset(&ddata, 0, sizeof(D3DHAL_CONTEXTDESTROYDATA));
  745. ddata.dwhContext = this->dwhContext;
  746. CALL_HALONLY(ret, this, ContextDestroy, &ddata);
  747. if (ret != DDHAL_DRIVER_HANDLED || ddata.ddrval != DD_OK)
  748. {
  749. DPF(0, "(ERROR) ContextDestroy. Failed. dwhContext = %d", ddata.dwhContext);
  750. // Need sensible return value in this case,
  751. // currently we return whatever the driver stuck in here.
  752. ret = ddata.ddrval;
  753. throw ret;
  754. }
  755. /* Create new context */
  756. memset(&cdata, 0, sizeof(D3DHAL_CONTEXTCREATEDATA));
  757. cdata.lpDDGbl = this->lpDDGbl;
  758. cdata.lpDDS = lpDDS;
  759. cdata.lpDDSZ = lpZ;
  760. // Hack Alert!! dwhContext is used to inform the driver which version
  761. // of the D3D interface is calling it.
  762. cdata.dwhContext = 3;
  763. cdata.dwPID = GetCurrentProcessId();
  764. // Hack Alert!! ddrval is used to inform the driver which driver type
  765. // the runtime thinks it is (DriverStyle registry setting)
  766. cdata.ddrval = this->deviceType;
  767. CALL_HALONLY(ret, this, ContextCreate, &cdata);
  768. if (ret != DDHAL_DRIVER_HANDLED || cdata.ddrval != DD_OK)
  769. {
  770. D3D_ERR("HAL call to ContextCreate failed in SetRenderTarget");
  771. // Need sensible return value in this case,
  772. // currently we return whatever the driver stuck in here.
  773. throw cdata.ddrval;
  774. }
  775. this->dwhContext = (DWORD)cdata.dwhContext;
  776. D3D_INFO(9, "in halCreateContext. Succeeded. dwhContext = %d", cdata.dwhContext);
  777. ret = this->UpdateDriverStates();
  778. if (ret != D3D_OK)
  779. throw ret;
  780. }
  781. InvalidateHandles(this);
  782. }
  783. //---------------------------------------------------------------------
  784. #undef DPF_MODNAME
  785. #define DPF_MODNAME "DIRECT3DDEVICEI::SetRenderTarget"
  786. HRESULT D3DAPI
  787. DIRECT3DDEVICEI::SetRenderTarget(LPDIRECTDRAWSURFACE7 lpDDS7, DWORD dwFlags)
  788. {
  789. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  790. // Release in the destructor
  791. LPDIRECTDRAWSURFACE lpZ=NULL,lpDDS=NULL;
  792. LPDIRECTDRAWSURFACE7 lpZ_DDS7=NULL;
  793. LPDIRECTDRAWPALETTE lpPal=NULL;
  794. try
  795. {
  796. DDSCAPS2 ddscaps;
  797. memset(&ddscaps, 0, sizeof(ddscaps));
  798. DDSURFACEDESC2 ddsd;
  799. HRESULT ret, ddrval;
  800. DWORD i, j;
  801. if (!VALID_DIRECT3DDEVICE_PTR(this))
  802. {
  803. D3D_ERR( "Invalid Direct3DDevice7 pointer" );
  804. return DDERR_INVALIDOBJECT;
  805. }
  806. if (!VALID_D3D_DIRECTDRAWSURFACE7_PTR(((LPDDRAWI_DDRAWSURFACE_INT)lpDDS7)))
  807. {
  808. D3D_ERR( "Invalid DirectDrawSurface7 pointer" );
  809. return DDERR_INVALIDOBJECT;
  810. }
  811. /*
  812. * Check if the 3D cap is set on the surface.
  813. */
  814. memset(&ddsd, 0, sizeof ddsd);
  815. ddsd.dwSize = sizeof ddsd;
  816. ddrval = lpDDS7->GetSurfaceDesc(&ddsd);
  817. if (ddrval != DD_OK)
  818. {
  819. D3D_ERR("Failed to get surface description of device's surface.");
  820. return (ddrval);
  821. }
  822. if (!(ddsd.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
  823. {
  824. D3D_ERR("**** The DDSCAPS_3DDEVICE is not set on this surface.");
  825. D3D_ERR("**** You need to add DDSCAPS_3DDEVICE to ddsCaps.dwCaps");
  826. D3D_ERR("**** when creating the surface.");
  827. return (DDERR_INVALIDCAPS);
  828. }
  829. if (!(this->lpD3DHALGlobalDriverData->hwCaps.dwDeviceRenderBitDepth & BitDepthToDDBD(ddsd.ddpfPixelFormat.dwRGBBitCount))) {
  830. D3D_ERR("Rendering surface's RGB bit count not supported by hardware device");
  831. return (DDERR_INVALIDCAPS);
  832. }
  833. if (ddsd.dwWidth > 2048 || ddsd.dwHeight > 2048)
  834. {
  835. D3D_ERR("Surface dimension > 2048");
  836. return DDERR_INVALIDPARAMS;
  837. }
  838. /* The z-buffer... */
  839. ddscaps.dwCaps = DDSCAPS_ZBUFFER;
  840. ret = lpDDS7->GetAttachedSurface(&ddscaps, &lpZ_DDS7);
  841. if ((ret != DD_OK) && (ret != DDERR_NOTFOUND))
  842. {
  843. /*
  844. * NOTE: Not an error if the z-buffer is not found. We will let the
  845. * dirver handle that (it might fail or create its own z-buffer).
  846. */
  847. D3D_ERR("Supplied DirectDraw Z-Buffer is invalid - can't set render target");
  848. throw DDERR_INVALIDPARAMS;
  849. }
  850. if (lpZ_DDS7)
  851. lpZ_DDS7->Release(); // We do not need to addref this one;
  852. // QI lpDDS7 for lpDDS interface, which will be used internally by D3D
  853. ret = lpDDS7->QueryInterface(IID_IDirectDrawSurface, (LPVOID*)&lpDDS);
  854. if(FAILED(ret))
  855. throw ret;
  856. /* The palette... */
  857. ret = lpDDS->GetPalette(&lpPal);
  858. if ((ret != DD_OK) && (ret != DDERR_NOPALETTEATTACHED))
  859. {
  860. /*
  861. * NOTE: Again, not an error (yet) if there is no palette attached.
  862. * But if there is palette and we can't get at it for some reason
  863. * - fail.
  864. */
  865. D3D_ERR("Supplied DirectDraw Palette is invalid - can't create device");
  866. throw DDERR_INVALIDPARAMS;
  867. }
  868. /*
  869. * We're going to check now whether we should have got a palette.
  870. */
  871. if (ret == DDERR_NOPALETTEATTACHED)
  872. {
  873. if (ddsd.ddpfPixelFormat.dwRGBBitCount < 16)
  874. {
  875. D3D_ERR("No palette supplied for palettized surface");
  876. throw DDERR_NOPALETTEATTACHED;
  877. }
  878. }
  879. /* Verify Z buffer */
  880. if (lpZ_DDS7!=NULL)
  881. {
  882. memset(&ddsd, 0, sizeof(ddsd));
  883. ddsd.dwSize = sizeof(ddsd);
  884. if ((ret=lpZ_DDS7->GetSurfaceDesc(&ddsd)) != DD_OK)
  885. {
  886. D3D_ERR("Failed to getsurfacedesc on Z");
  887. throw ret;
  888. }
  889. // QI lpDDS7 for lpDDS interface, which will be used internally by D3D
  890. ret = lpZ_DDS7->QueryInterface(IID_IDirectDrawSurface, (LPVOID*)&lpZ);
  891. if(FAILED(ret))
  892. throw ret;
  893. }
  894. SetRenderTargetI(lpDDS, lpZ);
  895. // this indicates that the device need no longer be flushed when Locking, Blting
  896. // or GetDC'ing from the previous rendertarget
  897. if (this->lpDDSTarget)
  898. ((LPDDRAWI_DDRAWSURFACE_INT)this->lpDDSTarget)->lpLcl->lpSurfMore->qwBatch.QuadPart = 0;
  899. // this indicates that the device need no longer be flushed when Locking, Blting
  900. // or GetDC'ing from the previous zbuffer
  901. if (this->lpDDSZBuffer)
  902. ((LPDDRAWI_DDRAWSURFACE_INT)this->lpDDSZBuffer)->lpLcl->lpSurfMore->qwBatch.QuadPart = 0;
  903. // this indicates that the device should always be flushed when Locking, Blting
  904. // or GetDC'ing a rendertarget
  905. ((LPDDRAWI_DDRAWSURFACE_INT)lpDDS7)->lpLcl->lpSurfMore->qwBatch.QuadPart = _UI64_MAX;
  906. // this indicates that the device should always be flushed when Locking, Blting
  907. // or GetDC'ing a zbuffer
  908. if(lpZ_DDS7)
  909. ((LPDDRAWI_DDRAWSURFACE_INT)lpZ_DDS7)->lpLcl->lpSurfMore->qwBatch.QuadPart = _UI64_MAX;
  910. // release old device DDS/DDS7 interfaces and replace with the new ones,
  911. // which are mostly already AddRef'd (except for lpDDS7)
  912. /// DDSZBuffer ///
  913. if(this->lpDDSZBuffer)
  914. this->lpDDSZBuffer->Release();
  915. // lpZ AddRef'd by QI
  916. this->lpDDSZBuffer = lpZ;
  917. /// DDSZBuffer DDS7 ///
  918. this->lpDDSZBuffer_DDS7=lpZ_DDS7; // This needs no AddRef or Release
  919. /// DDSTarget ///
  920. this->lpDDSTarget = lpDDS;
  921. #ifndef WIN95
  922. hSurfaceTarget = (unsigned long)((LPDDRAWI_DDRAWSURFACE_INT)lpDDS)->lpLcl->hDDSurface;
  923. #else
  924. hSurfaceTarget = (unsigned long)((LPDDRAWI_DDRAWSURFACE_INT)lpDDS)->lpLcl->lpSurfMore->dwSurfaceHandle;
  925. #endif
  926. // lpDDS AddRef'd by QI so release it
  927. this->lpDDSTarget->Release();
  928. /// DDSTarget DDS7 ///
  929. this->lpDDSTarget_DDS7->Release();
  930. lpDDS7->AddRef(); // ensure lpDDS7 (which was an argument) doesnt disappear
  931. this->lpDDSTarget_DDS7=lpDDS7;
  932. if (this->lpDDPalTarget)
  933. this->lpDDPalTarget->Release();
  934. // already AddRef'd by GetPalette()
  935. this->lpDDPalTarget = lpPal;
  936. ret=CalcDDSurfInfo(this,TRUE); // this call will never fail due to external error
  937. DDASSERT(ret==D3D_OK);
  938. return ret;
  939. }
  940. catch (HRESULT ret)
  941. {
  942. if(lpPal)
  943. lpPal->Release();
  944. if(lpZ)
  945. lpZ->Release();
  946. if(lpZ_DDS7)
  947. lpZ_DDS7->Release();
  948. if(lpDDS)
  949. lpDDS->Release();
  950. return ret;
  951. }
  952. }
  953. //---------------------------------------------------------------------
  954. #undef DPF_MODNAME
  955. #define DPF_MODNAME "DIRECT3DDEVICEI::GetRenderTarget"
  956. HRESULT D3DAPI
  957. DIRECT3DDEVICEI::GetRenderTarget(LPDIRECTDRAWSURFACE7* lplpDDS)
  958. {
  959. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  960. // Release in the destructor
  961. if (!VALID_DIRECT3DDEVICE_PTR(this))
  962. {
  963. D3D_ERR( "Invalid Direct3DDevice pointer" );
  964. return DDERR_INVALIDOBJECT;
  965. }
  966. if ( !VALID_OUTPTR( lplpDDS ) )
  967. {
  968. D3D_ERR( "Invalid ptr to DDS ptr" );
  969. return DDERR_INVALIDPARAMS;
  970. }
  971. *lplpDDS = this->lpDDSTarget_DDS7;
  972. this->lpDDSTarget_DDS7->AddRef();
  973. return D3D_OK;
  974. }
  975. //---------------------------------------------------------------------
  976. #undef DPF_MODNAME
  977. #define DPF_MODNAME "DIRECT3DDEVICEI::SetClipStatus"
  978. #define D3DSTATUS_VALID 0x80000000L /* Reserved Status flag to indicate SetClipStatus is called */
  979. HRESULT D3DAPI DIRECT3DDEVICEI::SetClipStatus(LPD3DCLIPSTATUS status)
  980. {
  981. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock (MT only).
  982. // Release in the destructor
  983. #if DBG
  984. if (!VALID_DIRECT3DDEVICE_PTR(this))
  985. {
  986. D3D_ERR( "Invalid Direct3DDevice pointer" );
  987. return DDERR_INVALIDOBJECT;
  988. }
  989. if (! VALID_PTR(status, sizeof(D3DCLIPSTATUS)) )
  990. {
  991. D3D_ERR( "Invalid status pointer" );
  992. return DDERR_INVALIDPARAMS;
  993. }
  994. #endif
  995. // D3DCLIPSTATUS_EXTENTS3 not supported in Device7
  996. if (status->dwFlags & D3DCLIPSTATUS_EXTENTS3)
  997. {
  998. D3D_ERR( "D3DCLIPSTATUS_EXTENTS3 not supported for Device7" );
  999. return DDERR_INVALIDPARAMS;
  1000. }
  1001. if (status->dwFlags & D3DCLIPSTATUS_STATUS)
  1002. this->iClipStatus = status->dwStatus;
  1003. if (status->dwFlags & (D3DCLIPSTATUS_EXTENTS2 | D3DCLIPSTATUS_EXTENTS3))
  1004. {
  1005. this->rExtents.x1 = status->minx;
  1006. this->rExtents.y1 = status->miny;
  1007. this->rExtents.x2 = status->maxx;
  1008. this->rExtents.y2 = status->maxy;
  1009. }
  1010. return D3D_OK;
  1011. }
  1012. #undef DPF_MODNAME
  1013. #define DPF_MODNAME "Direct3DDevice::GetClipStatus"
  1014. HRESULT D3DAPI DIRECT3DDEVICEI::GetClipStatus(LPD3DCLIPSTATUS status)
  1015. {
  1016. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock (MT only).
  1017. // Release in the destructor
  1018. #if DBG
  1019. if (!VALID_DIRECT3DDEVICE_PTR(this))
  1020. {
  1021. D3D_ERR( "Invalid Direct3DDevice pointer" );
  1022. return DDERR_INVALIDOBJECT;
  1023. }
  1024. if (! VALID_PTR(status, sizeof(D3DCLIPSTATUS)) )
  1025. {
  1026. D3D_ERR( "Invalid status pointer" );
  1027. return DDERR_INVALIDPARAMS;
  1028. }
  1029. #endif
  1030. status->dwStatus = iClipStatus;
  1031. status->dwFlags = D3DCLIPSTATUS_EXTENTS2;
  1032. status->minx = this->rExtents.x1;
  1033. status->miny = this->rExtents.y1;
  1034. status->maxx = this->rExtents.x2;
  1035. status->maxy = this->rExtents.y2;
  1036. return D3D_OK;
  1037. }
  1038. #undef DPF_MODNAME
  1039. #define DPF_MODNAME "Direct3DDevice::UpdateTextures"
  1040. HRESULT DIRECT3DDEVICEI::UpdateTextures()
  1041. {
  1042. HRESULT result = D3D_OK;
  1043. DWORD dwSavedFlags = this->dwFlags;
  1044. this->dwFlags |= D3DPV_WITHINPRIMITIVE;
  1045. for (DWORD dwStage = 0; dwStage < this->dwMaxTextureBlendStages; dwStage++)
  1046. {
  1047. D3DTEXTUREHANDLE dwDDIHandle;
  1048. LPDIRECT3DTEXTUREI lpTexI = this->lpD3DMappedTexI[dwStage];
  1049. if(lpTexI)
  1050. {
  1051. if (lpTexI->bDirty)
  1052. {
  1053. if (lpTexI->InVidmem())
  1054. {
  1055. CLockD3DST lockObject(this, DPF_MODNAME, REMIND("")); // we access DDraw gbl in CopySurface
  1056. // 0xFFFFFFFF is equivalent to ALL_FACES, but in addition indicates to CopySurface
  1057. // that this is a sysmem -> vidmem transfer.
  1058. result = CopySurface(lpTexI->lpDDS,NULL,lpTexI->lpDDSSys,NULL,0xFFFFFFFF);
  1059. if (DD_OK != result)
  1060. {
  1061. D3D_ERR("Error copying surface while updating textures");
  1062. goto l_exit;
  1063. }
  1064. else
  1065. {
  1066. lpTexI->bDirty=FALSE;
  1067. D3D_INFO(4,"UpdateTextures: Dirty texture updated");
  1068. }
  1069. }
  1070. }
  1071. LPD3DI_TEXTUREBLOCK lpBlock;
  1072. if (m_dwStageDirty & (1 << dwStage))
  1073. {
  1074. lpBlock = NULL; // indicates to GetTextureDDIHandle to find the block for this (tex,dev)
  1075. }
  1076. else
  1077. {
  1078. lpBlock = this->lpD3DMappedBlock[dwStage]; // use the cached block
  1079. DDASSERT(lpBlock);
  1080. if (lpBlock->hTex) // have we created a handle for this (tex,dev)?
  1081. {
  1082. continue; //nothing need to be done further
  1083. }
  1084. }
  1085. result = GetTextureDDIHandle(lpTexI, &lpBlock);
  1086. if (result != D3D_OK)
  1087. {
  1088. D3D_ERR("Failed to get texture handle");
  1089. goto l_exit;
  1090. }
  1091. else
  1092. {
  1093. dwDDIHandle = lpBlock->hTex;
  1094. this->lpD3DMappedBlock[dwStage] = lpBlock;
  1095. BatchTexture(((LPDDRAWI_DDRAWSURFACE_INT)lpTexI->lpDDS)->lpLcl);
  1096. m_dwStageDirty &= ~(1 << dwStage); // reset stage dirty
  1097. }
  1098. }
  1099. else if (m_dwStageDirty & (1 << dwStage))
  1100. {
  1101. this->lpD3DMappedBlock[dwStage]=NULL; //a SetTexture(Stage,NULL) issued
  1102. dwDDIHandle = 0; //tell driver to disable this texture
  1103. m_dwStageDirty &= ~(1 << dwStage); // reset stage dirty
  1104. }
  1105. else
  1106. {
  1107. continue; //both zero, no action needed
  1108. }
  1109. #ifdef WIN95
  1110. if (IS_DP2HAL_DEVICE(this))
  1111. {
  1112. #endif
  1113. CDirect3DDeviceIDP2 *dp2dev = static_cast<CDirect3DDeviceIDP2 *>(this);
  1114. result = dp2dev->SetTSSI(dwStage, (D3DTEXTURESTAGESTATETYPE)D3DTSS_TEXTUREMAP, dwDDIHandle);
  1115. if(result != D3D_OK)
  1116. {
  1117. D3D_ERR("Failed to batch set texture instruction");
  1118. goto l_exit;
  1119. }
  1120. // Update runtime copy of state.
  1121. dp2dev->tsstates[dwStage][D3DTSS_TEXTUREMAP] = dwDDIHandle;
  1122. #ifdef WIN95
  1123. }
  1124. else
  1125. {
  1126. if(this->dwFEFlags & D3DFE_DISABLE_TEXTURES)
  1127. break;
  1128. CDirect3DDeviceIHW *dev = static_cast<CDirect3DDeviceIHW *>(this);
  1129. result = dev->SetRenderStateI(D3DRENDERSTATE_TEXTUREHANDLE, dwDDIHandle);
  1130. if(result != D3D_OK)
  1131. {
  1132. D3D_ERR("Failed to batch setrenderstate instruction");
  1133. goto l_exit;
  1134. }
  1135. // Update runtime copy of state.
  1136. dev->rstates[D3DRENDERSTATE_TEXTUREHANDLE] = dwDDIHandle;
  1137. }
  1138. #endif
  1139. }
  1140. l_exit:
  1141. this->dwFlags = dwSavedFlags;
  1142. return result;
  1143. }
  1144. //---------------------------------------------------------------------
  1145. // This function is called from HALEXE.CPP, from device::SetRenderState and
  1146. // from device::SetTexture.
  1147. //
  1148. #undef DPF_MODNAME
  1149. #define DPF_MODNAME "DIRECT3DDEVICEI::UpdateInternalState"
  1150. void DIRECT3DDEVICEI::UpdateInternalState(D3DRENDERSTATETYPE type, DWORD value)
  1151. {
  1152. switch (type)
  1153. {
  1154. case D3DRENDERSTATE_LIGHTING:
  1155. if (value)
  1156. this->dwDeviceFlags |= D3DDEV_LIGHTING;
  1157. else
  1158. this->dwDeviceFlags &= ~D3DDEV_LIGHTING;
  1159. ForceFVFRecompute();
  1160. break;
  1161. case D3DRENDERSTATE_FOGENABLE:
  1162. rstates[type] = value; // set rstates BEFORE calling SetFogFlags
  1163. SetFogFlags();
  1164. break;
  1165. case D3DRENDERSTATE_SPECULARENABLE:
  1166. this->dwFEFlags |= D3DFE_MATERIAL_DIRTY | D3DFE_LIGHTS_DIRTY | D3DFE_FRONTEND_DIRTY;
  1167. if (value)
  1168. this->dwDeviceFlags |= D3DDEV_SPECULARENABLE;
  1169. else
  1170. this->dwDeviceFlags &= ~D3DDEV_SPECULARENABLE;
  1171. ForceFVFRecompute();
  1172. break;
  1173. case D3DRENDERSTATE_AMBIENT:
  1174. {
  1175. const D3DVALUE SCALE = 1.0f/255.0f;
  1176. this->lighting.ambientSceneScaled.r = D3DVAL(RGBA_GETRED(value));
  1177. this->lighting.ambientSceneScaled.g = D3DVAL(RGBA_GETGREEN(value));
  1178. this->lighting.ambientSceneScaled.b = D3DVAL(RGBA_GETBLUE(value));
  1179. this->lighting.ambientScene.r = this->lighting.ambientSceneScaled.r * SCALE;
  1180. this->lighting.ambientScene.g = this->lighting.ambientSceneScaled.g * SCALE;
  1181. this->lighting.ambientScene.b = this->lighting.ambientSceneScaled.b * SCALE;
  1182. this->lighting.ambient_save = value;
  1183. this->dwFEFlags |= D3DFE_MATERIAL_DIRTY | D3DFE_FRONTEND_DIRTY;
  1184. break;
  1185. }
  1186. case D3DRENDERSTATE_RANGEFOGENABLE:
  1187. if (value)
  1188. this->dwDeviceFlags |= D3DDEV_RANGEBASEDFOG;
  1189. else
  1190. this->dwDeviceFlags &= ~D3DDEV_RANGEBASEDFOG;
  1191. break;
  1192. case D3DRENDERSTATE_FOGVERTEXMODE:
  1193. this->lighting.fog_mode = (D3DFOGMODE)value;
  1194. SetFogFlags();
  1195. break;
  1196. case D3DRENDERSTATE_COLORVERTEX:
  1197. if (value)
  1198. this->dwDeviceFlags |= D3DDEV_COLORVERTEX;
  1199. else
  1200. this->dwDeviceFlags &= ~D3DDEV_COLORVERTEX;
  1201. // Just to make it not take the FE fast path and call DoUpdateState()
  1202. // This is necessary since we update lighting.alpha and
  1203. // lighting.alphaSpecular in DoUpdateState.
  1204. ForceFVFRecompute();
  1205. break;
  1206. case D3DRENDERSTATE_CLIPPING:
  1207. if (!value)
  1208. {
  1209. this->dwDeviceFlags |= D3DDEV_DONOTCLIP;
  1210. // Clear clip union and intersection flags
  1211. this->dwClipIntersection = 0;
  1212. this->dwClipUnion = 0;
  1213. }
  1214. else
  1215. this->dwDeviceFlags &= ~D3DDEV_DONOTCLIP;
  1216. // This does not really require a "FVF" recompute,
  1217. // but is a convenient way of switching back from
  1218. // the fast path for DrawPrimitiveTL.
  1219. ForceFVFRecompute();
  1220. break;
  1221. case D3DRENDERSTATE_EXTENTS:
  1222. if (!value)
  1223. this->dwDeviceFlags |= D3DDEV_DONOTUPDATEEXTENTS;
  1224. else
  1225. this->dwDeviceFlags &= ~D3DDEV_DONOTUPDATEEXTENTS;
  1226. // This does not really require a "FVF" recompute,
  1227. // but is a convenient way of switching back from
  1228. // the fast path for DrawPrimitiveTL.
  1229. ForceFVFRecompute();
  1230. break;
  1231. case D3DRENDERSTATE_FOGDENSITY:
  1232. this->lighting.fog_density = *(D3DVALUE*)&value;
  1233. break;
  1234. case D3DRENDERSTATE_FOGSTART:
  1235. this->lighting.fog_start = *(D3DVALUE*)&value;
  1236. UpdateFogFactor(this);
  1237. break;
  1238. case D3DRENDERSTATE_FOGEND:
  1239. this->lighting.fog_end = *(D3DVALUE*)&value;
  1240. UpdateFogFactor(this);
  1241. break;
  1242. case D3DRENDERSTATE_LOCALVIEWER:
  1243. if (value)
  1244. this->dwDeviceFlags |= D3DDEV_LOCALVIEWER;
  1245. else
  1246. this->dwDeviceFlags &= ~D3DDEV_LOCALVIEWER;
  1247. this->dwFEFlags |= D3DFE_LIGHTS_DIRTY | D3DFE_FRONTEND_DIRTY;
  1248. break;
  1249. case D3DRENDERSTATE_NORMALIZENORMALS:
  1250. if (value)
  1251. {
  1252. if (this->dwDeviceFlags & D3DDEV_MODELSPACELIGHTING)
  1253. {
  1254. this->dwDeviceFlags &= ~D3DDEV_MODELSPACELIGHTING;
  1255. this->dwFEFlags |= D3DFE_NEED_TRANSFORM_LIGHTS | D3DFE_FRONTEND_DIRTY;
  1256. }
  1257. this->dwDeviceFlags |= D3DDEV_NORMALIZENORMALS;
  1258. }
  1259. else
  1260. {
  1261. this->dwDeviceFlags &= ~D3DDEV_NORMALIZENORMALS;
  1262. if (!(this->dwDeviceFlags & D3DDEV_MODELSPACELIGHTING))
  1263. this->dwFEFlags |= D3DFE_NEEDCHECKWORLDVIEWVMATRIX | D3DFE_FRONTEND_DIRTY;
  1264. }
  1265. break;
  1266. case D3DRENDERSTATE_EMISSIVEMATERIALSOURCE:
  1267. this->lighting.dwEmissiveSrcIndex = 2;
  1268. switch (value)
  1269. {
  1270. case D3DMCS_COLOR1:
  1271. this->lighting.dwEmissiveSrcIndex = 0;
  1272. break;
  1273. case D3DMCS_COLOR2:
  1274. this->lighting.dwEmissiveSrcIndex = 1;
  1275. break;
  1276. #if DBG
  1277. case D3DMCS_MATERIAL:
  1278. break;
  1279. default:
  1280. D3D_ERR("Illegal value for DIFFUSEMATERIALSOURCE");
  1281. goto error_exit;
  1282. #endif
  1283. }
  1284. break;
  1285. case D3DRENDERSTATE_DIFFUSEMATERIALSOURCE:
  1286. this->lighting.dwDiffuseSrcIndex = 2;
  1287. switch (value)
  1288. {
  1289. case D3DMCS_COLOR1:
  1290. this->lighting.dwDiffuseSrcIndex = 0;
  1291. break;
  1292. case D3DMCS_COLOR2:
  1293. this->lighting.dwDiffuseSrcIndex = 1;
  1294. break;
  1295. #if DBG
  1296. case D3DMCS_MATERIAL:
  1297. break;
  1298. default:
  1299. D3D_ERR("Illegal value for DIFFUSEMATERIALSOURCE");
  1300. goto error_exit;
  1301. #endif
  1302. }
  1303. break;
  1304. case D3DRENDERSTATE_AMBIENTMATERIALSOURCE:
  1305. this->lighting.dwAmbientSrcIndex = 2;
  1306. switch (value)
  1307. {
  1308. case D3DMCS_COLOR1:
  1309. this->lighting.dwAmbientSrcIndex = 0;
  1310. break;
  1311. case D3DMCS_COLOR2:
  1312. this->lighting.dwAmbientSrcIndex = 1;
  1313. break;
  1314. #if DBG
  1315. case D3DMCS_MATERIAL:
  1316. break;
  1317. default:
  1318. D3D_ERR("Illegal value for AMBIENTMATERIALSOURCE");
  1319. goto error_exit;
  1320. #endif
  1321. }
  1322. break;
  1323. case D3DRENDERSTATE_SPECULARMATERIALSOURCE:
  1324. this->lighting.dwSpecularSrcIndex = 2;
  1325. switch (value)
  1326. {
  1327. case D3DMCS_COLOR1:
  1328. this->lighting.dwSpecularSrcIndex = 0;
  1329. break;
  1330. case D3DMCS_COLOR2:
  1331. this->lighting.dwSpecularSrcIndex = 1;
  1332. break;
  1333. #if DBG
  1334. case D3DMCS_MATERIAL:
  1335. break;
  1336. default:
  1337. D3D_ERR("Illegal value for SPECULARMATERIALSOURCE");
  1338. goto error_exit;
  1339. #endif
  1340. }
  1341. break;
  1342. case D3DRENDERSTATE_VERTEXBLEND:
  1343. {
  1344. DWORD numBlendMatrices;
  1345. switch (value)
  1346. {
  1347. case D3DVBLEND_DISABLE:
  1348. numBlendMatrices = 0;
  1349. break;
  1350. case D3DVBLEND_1WEIGHT:
  1351. numBlendMatrices = 2;
  1352. break;
  1353. case D3DVBLEND_2WEIGHTS:
  1354. numBlendMatrices = 3;
  1355. break;
  1356. case D3DVBLEND_3WEIGHTS:
  1357. numBlendMatrices = 4;
  1358. break;
  1359. #if DBG
  1360. default:
  1361. D3D_ERR("Illegal value for D3DRENDERSTATE_VERTEXBLEND");
  1362. goto error_exit;
  1363. #endif
  1364. }
  1365. this->dwFEFlags |= D3DFE_VERTEXBLEND_DIRTY | D3DFE_FRONTEND_DIRTY;
  1366. }
  1367. break;
  1368. case D3DRENDERSTATE_CLIPPLANEENABLE:
  1369. {
  1370. this->dwFEFlags |= D3DFE_CLIPPLANES_DIRTY | D3DFE_FRONTEND_DIRTY;
  1371. this->dwMaxUserClipPlanes = 0;
  1372. break;
  1373. }
  1374. case D3DRENDERSTATE_SHADEMODE:
  1375. rstates[type] = value; // SetInterpolationFlags depends on the rstates
  1376. SetInterpolationFlags(this);
  1377. break;
  1378. default:
  1379. // WRAP render states could be re-mapped so we have to restore them before
  1380. // setting a new value
  1381. if (type >= D3DRENDERSTATE_WRAP0 && type <= D3DRENDERSTATE_WRAP7)
  1382. {
  1383. if (this->dwDeviceFlags & D3DDEV_REMAPTEXTUREINDICES)
  1384. {
  1385. RestoreTextureStages(this);
  1386. ForceFVFRecompute();
  1387. }
  1388. }
  1389. break;
  1390. }
  1391. rstates[type] = value; // set rstates for all other cases
  1392. return;
  1393. #if DBG
  1394. error_exit:
  1395. throw DDERR_INVALIDPARAMS;
  1396. #endif
  1397. }
  1398. //---------------------------------------------------------------------
  1399. #if DBG
  1400. static char ProfileStr[PROF_DRAWINDEXEDPRIMITIVEVB+1][32]=
  1401. {
  1402. "Execute",
  1403. "Begin",
  1404. "BeginIndexed",
  1405. "DrawPrimitive(Device2)",
  1406. "DrawIndexedPrimitive(Device2)",
  1407. "DrawPrimitiveStrided",
  1408. "DrawIndexedPrimitiveStrided",
  1409. "DrawPrimitive(Device7)",
  1410. "DrawIndexedPrimitive(Device7)",
  1411. "DrawPrimitiveVB",
  1412. "DrawIndexedPrimitiveVB",
  1413. };
  1414. static char PrimitiveStr[D3DPT_TRIANGLEFAN][16]=
  1415. {
  1416. "POINTLIST",
  1417. "LINELIST",
  1418. "LINESTRIP",
  1419. "TRIANGLELIST",
  1420. "TRIANGLESTRIP",
  1421. "TRIANGLEFAN",
  1422. };
  1423. static char VertexStr[D3DVT_TLVERTEX][16]=
  1424. {
  1425. "D3DVERTEX",
  1426. "D3DLVERTEX",
  1427. "D3DTLVERTEX",
  1428. };
  1429. #define PROFILE_LEVEL 0
  1430. void DIRECT3DDEVICEI::Profile(DWORD caller, D3DPRIMITIVETYPE dwPrimitive, DWORD dwVertex)
  1431. {
  1432. DWORD bitwisecaller= 1 << caller;
  1433. DWORD bitwisePrimitive = 1 << (DWORD)dwPrimitive;
  1434. DWORD bitwiseVertex1 = 1 << (dwVertex & 0x001F);
  1435. DWORD bitwiseVertex2 = 1 << ((dwVertex & 0x03E0) >> 5);
  1436. char str[256];
  1437. DDASSERT(PROF_DRAWINDEXEDPRIMITIVEVB >= caller);
  1438. DDASSERT(D3DPT_TRIANGLEFAN >= dwPrimitive && D3DPT_POINTLIST<= dwPrimitive);
  1439. if (dwCaller & bitwisecaller)
  1440. {
  1441. if (dwPrimitiveType[caller] & bitwisePrimitive)
  1442. {
  1443. if ((dwVertexType1[caller] & bitwiseVertex1) &&
  1444. (dwVertexType2[caller] & bitwiseVertex2))
  1445. {
  1446. return; //matching a previous api call, no spew, could count stat though
  1447. }
  1448. else
  1449. {
  1450. dwVertexType1[caller] |= bitwiseVertex1;
  1451. dwVertexType2[caller] |= bitwiseVertex2;
  1452. }
  1453. }
  1454. else
  1455. {
  1456. dwPrimitiveType[caller] |= bitwisePrimitive;
  1457. dwVertexType1[caller] |= bitwiseVertex1;
  1458. dwVertexType2[caller] |= bitwiseVertex2;
  1459. }
  1460. }
  1461. else
  1462. {
  1463. this->dwCaller |= bitwisecaller;
  1464. dwPrimitiveType[caller] |= bitwisePrimitive;
  1465. dwVertexType1[caller] |= bitwiseVertex1;
  1466. dwVertexType2[caller] |= bitwiseVertex2;
  1467. }
  1468. wsprintf( (LPSTR) str, ProfileStr[caller]);
  1469. strcat(str,":");
  1470. strcat(str,PrimitiveStr[dwPrimitive-1]);
  1471. if (dwVertex > D3DVT_TLVERTEX)
  1472. {
  1473. if (dwVertex == D3DFVF_VERTEX)
  1474. {
  1475. dwVertex = D3DVT_VERTEX;
  1476. }
  1477. else
  1478. if (dwVertex == D3DFVF_LVERTEX)
  1479. {
  1480. dwVertex = D3DVT_LVERTEX;
  1481. }
  1482. else
  1483. if (dwVertex == D3DFVF_TLVERTEX)
  1484. {
  1485. dwVertex = D3DVT_TLVERTEX;
  1486. }
  1487. else
  1488. {
  1489. D3D_INFO(PROFILE_LEVEL,"Profile:%s FVFType=%08lx",str,dwVertex);
  1490. return;
  1491. }
  1492. }
  1493. else
  1494. {
  1495. DDASSERT(dwVertex >= D3DVT_VERTEX);
  1496. }
  1497. strcat(str,":");
  1498. strcat(str,VertexStr[dwVertex-1]);
  1499. D3D_INFO(PROFILE_LEVEL,"Profile:%s",str);
  1500. }
  1501. #endif // DBG
  1502. //---------------------------------------------------------------------
  1503. #undef DPF_MODNAME
  1504. #define DPF_MODNAME "DIRECT3DDEVICEI::MultiplyTransform"
  1505. // MultiplyTransform -- this preconcatenates the new matrix to the specified
  1506. // transform matrix
  1507. //
  1508. // this really screams for overloaded matrix ops...
  1509. //
  1510. HRESULT D3DAPI
  1511. DIRECT3DDEVICEI::MultiplyTransform(D3DTRANSFORMSTATETYPE dtsTransformState, LPD3DMATRIX lpMat)
  1512. {
  1513. #if DBG
  1514. if (!VALID_D3DMATRIX_PTR(lpMat))
  1515. {
  1516. D3D_ERR( "Invalid matrix pointer" );
  1517. return DDERR_INVALIDPARAMS;
  1518. }
  1519. #endif
  1520. try
  1521. {
  1522. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock (MT only).
  1523. D3DMATRIXI mResult;
  1524. switch (dtsTransformState)
  1525. {
  1526. case D3DTRANSFORMSTATE_WORLD :
  1527. MatrixProduct(&mResult, (D3DMATRIXI*)lpMat, &this->transform.world[0]);
  1528. break;
  1529. case D3DTRANSFORMSTATE_WORLD1 :
  1530. MatrixProduct(&mResult, (D3DMATRIXI*)lpMat, &this->transform.world[1]);
  1531. break;
  1532. case D3DTRANSFORMSTATE_WORLD2 :
  1533. MatrixProduct(&mResult, (D3DMATRIXI*)lpMat, &this->transform.world[2]);
  1534. break;
  1535. case D3DTRANSFORMSTATE_WORLD3 :
  1536. MatrixProduct(&mResult, (D3DMATRIXI*)lpMat, &this->transform.world[3]);
  1537. break;
  1538. case D3DTRANSFORMSTATE_VIEW :
  1539. MatrixProduct(&mResult, (D3DMATRIXI*)lpMat, &this->transform.view);
  1540. break;
  1541. case D3DTRANSFORMSTATE_PROJECTION :
  1542. MatrixProduct(&mResult, (D3DMATRIXI*)lpMat, &this->transform.proj);
  1543. break;
  1544. case D3DTRANSFORMSTATE_TEXTURE0:
  1545. case D3DTRANSFORMSTATE_TEXTURE1:
  1546. case D3DTRANSFORMSTATE_TEXTURE2:
  1547. case D3DTRANSFORMSTATE_TEXTURE3:
  1548. case D3DTRANSFORMSTATE_TEXTURE4:
  1549. case D3DTRANSFORMSTATE_TEXTURE5:
  1550. case D3DTRANSFORMSTATE_TEXTURE6:
  1551. case D3DTRANSFORMSTATE_TEXTURE7:
  1552. {
  1553. DWORD dwIndex = dtsTransformState - D3DTRANSFORMSTATE_TEXTURE0;
  1554. MatrixProduct(&mResult, (D3DMATRIXI*)lpMat, &this->mTexture[dwIndex]);
  1555. break;
  1556. }
  1557. default :
  1558. D3D_ERR( "Invalid state value passed to MultiplyTransform" );
  1559. return DDERR_INVALIDPARAMS; /* Work Item: Generate new meaningful return code */
  1560. }
  1561. SetTransformI(dtsTransformState, (D3DMATRIX*)&mResult);
  1562. return D3D_OK;
  1563. }
  1564. catch(HRESULT ret)
  1565. {
  1566. return ret;
  1567. }
  1568. }
  1569. //---------------------------------------------------------------------
  1570. #undef DPF_MODNAME
  1571. #define DPF_MODNAME "DIRECT3DDEVICEI::BeginStateBlock"
  1572. HRESULT D3DAPI DIRECT3DDEVICEI::BeginStateBlock()
  1573. {
  1574. try
  1575. {
  1576. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND(""));
  1577. if (this->dwFEFlags & D3DFE_RECORDSTATEMODE)
  1578. {
  1579. D3D_ERR("Already in the state record mode");
  1580. return D3DERR_INBEGINSTATEBLOCK;
  1581. }
  1582. if (m_pStateSets->StartNewSet() != D3D_OK)
  1583. return DDERR_OUTOFMEMORY;
  1584. this->dwFEFlags |= D3DFE_RECORDSTATEMODE;
  1585. #ifdef VTABLE_HACK
  1586. VtblSetRenderStateRecord();
  1587. VtblSetTextureStageStateRecord();
  1588. VtblSetTextureRecord();
  1589. VtblApplyStateBlockRecord();
  1590. #endif VTABLE_HACK
  1591. return D3D_OK;
  1592. }
  1593. catch (HRESULT ret)
  1594. {
  1595. return ret;
  1596. }
  1597. }
  1598. //---------------------------------------------------------------------
  1599. #undef DPF_MODNAME
  1600. #define DPF_MODNAME "DIRECT3DDEVICEI::EndStateBlock"
  1601. HRESULT D3DAPI DIRECT3DDEVICEI::EndStateBlock(LPDWORD pdwHandle)
  1602. {
  1603. if (!VALID_PTR(pdwHandle, sizeof(DWORD)))
  1604. {
  1605. D3D_ERR( "Invalid DWORD pointer" );
  1606. return DDERR_INVALIDPARAMS;
  1607. }
  1608. try
  1609. {
  1610. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND(""));
  1611. if (!(this->dwFEFlags & D3DFE_RECORDSTATEMODE))
  1612. {
  1613. D3D_ERR("Not in state record mode");
  1614. return D3DERR_NOTINBEGINSTATEBLOCK;
  1615. }
  1616. this->dwFEFlags &= ~D3DFE_RECORDSTATEMODE;
  1617. m_pStateSets->EndSet();
  1618. #ifdef VTABLE_HACK
  1619. if (IS_DP2HAL_DEVICE(this) && (!IS_MT_DEVICE(this)))
  1620. {
  1621. VtblSetRenderStateExecute();
  1622. VtblSetTextureStageStateExecute();
  1623. VtblSetTextureExecute();
  1624. VtblApplyStateBlockExecute();
  1625. }
  1626. #endif VTABLE_HACK
  1627. this->WriteStateSetToDevice((D3DSTATEBLOCKTYPE)0);
  1628. *pdwHandle = m_pStateSets->GetCurrentHandle();
  1629. return D3D_OK;
  1630. }
  1631. catch(HRESULT ret)
  1632. {
  1633. m_pStateSets->Cleanup(m_pStateSets->GetCurrentHandle());
  1634. *pdwHandle = 0xFFFFFFFF;
  1635. return ret;
  1636. }
  1637. }
  1638. //---------------------------------------------------------------------
  1639. #undef DPF_MODNAME
  1640. #define DPF_MODNAME "DIRECT3DDEVICEI::DeleteStateBlock"
  1641. HRESULT D3DAPI DIRECT3DDEVICEI::DeleteStateBlock(DWORD dwHandle)
  1642. {
  1643. try
  1644. {
  1645. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND(""));
  1646. if (this->dwFEFlags & D3DFE_RECORDSTATEMODE)
  1647. {
  1648. D3D_ERR("We are in state record mode");
  1649. return D3DERR_INBEGINSTATEBLOCK;
  1650. }
  1651. m_pStateSets->DeleteStateSet(this, dwHandle);
  1652. return D3D_OK;
  1653. }
  1654. catch(HRESULT ret)
  1655. {
  1656. return ret;
  1657. }
  1658. }
  1659. //---------------------------------------------------------------------
  1660. #undef DPF_MODNAME
  1661. #define DPF_MODNAME "DIRECT3DDEVICEI::ApplyStateBlock"
  1662. HRESULT D3DAPI DIRECT3DDEVICEI::ApplyStateBlock(DWORD dwHandle)
  1663. {
  1664. try
  1665. {
  1666. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND(""));
  1667. if (this->dwFEFlags & D3DFE_RECORDSTATEMODE)
  1668. {
  1669. D3D_ERR("We are in state record mode");
  1670. return D3DERR_INBEGINSTATEBLOCK;
  1671. }
  1672. return ApplyStateBlockInternal(dwHandle);
  1673. }
  1674. catch(HRESULT ret)
  1675. {
  1676. return ret;
  1677. }
  1678. }
  1679. //---------------------------------------------------------------------
  1680. #undef DPF_MODNAME
  1681. #define DPF_MODNAME "DIRECT3DDEVICEI::ApplyStateBlockInternal"
  1682. HRESULT D3DAPI DIRECT3DDEVICEI::ApplyStateBlockInternal(DWORD dwHandle)
  1683. {
  1684. try
  1685. {
  1686. m_pStateSets->Execute(this, dwHandle);
  1687. return D3D_OK;
  1688. }
  1689. catch(HRESULT ret)
  1690. {
  1691. return ret;
  1692. }
  1693. }
  1694. //---------------------------------------------------------------------
  1695. #undef DPF_MODNAME
  1696. #define DPF_MODNAME "DIRECT3DDEVICEI::CaptureStateBlock"
  1697. HRESULT D3DAPI DIRECT3DDEVICEI::CaptureStateBlock(DWORD dwHandle)
  1698. {
  1699. try
  1700. {
  1701. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND(""));
  1702. if (this->dwFEFlags & D3DFE_RECORDSTATEMODE)
  1703. {
  1704. D3D_ERR("Cannot capture when in the state record mode");
  1705. return D3DERR_INBEGINSTATEBLOCK;
  1706. }
  1707. m_pStateSets->Capture(this, dwHandle);
  1708. return D3D_OK;
  1709. }
  1710. catch (HRESULT ret)
  1711. {
  1712. return ret;
  1713. }
  1714. }
  1715. //---------------------------------------------------------------------
  1716. #undef DPF_MODNAME
  1717. #define DPF_MODNAME "DIRECT3DDEVICEI::CreateStateBlock"
  1718. HRESULT D3DAPI DIRECT3DDEVICEI::CreateStateBlock(D3DSTATEBLOCKTYPE sbt, LPDWORD pdwHandle)
  1719. {
  1720. if (!VALID_PTR(pdwHandle, sizeof(DWORD)))
  1721. {
  1722. D3D_ERR( "Invalid DWORD pointer" );
  1723. return DDERR_INVALIDPARAMS;
  1724. }
  1725. try
  1726. {
  1727. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND(""));
  1728. if (this->dwFEFlags & D3DFE_RECORDSTATEMODE)
  1729. {
  1730. D3D_ERR("Cannot create state block when in the state record mode");
  1731. return D3DERR_INBEGINSTATEBLOCK;
  1732. }
  1733. if (m_pStateSets->StartNewSet() != D3D_OK)
  1734. return DDERR_OUTOFMEMORY;
  1735. m_pStateSets->CreatePredefined(this, sbt);
  1736. m_pStateSets->EndSet();
  1737. this->WriteStateSetToDevice(sbt);
  1738. *pdwHandle = m_pStateSets->GetCurrentHandle();
  1739. return D3D_OK;
  1740. }
  1741. catch (HRESULT ret)
  1742. {
  1743. m_pStateSets->Cleanup(m_pStateSets->GetCurrentHandle());
  1744. *pdwHandle = 0xFFFFFFFF;
  1745. return ret;
  1746. }
  1747. }
  1748. //---------------------------------------------------------------------
  1749. // Input:
  1750. // type - FVF control dword
  1751. //
  1752. // Returns D3D_OK, if the control dword is valid.
  1753. // DDERR_INVALIDPARAMS otherwise
  1754. //
  1755. #undef DPF_MODNAME
  1756. #define DPF_MODNAME "DIRECT3DDEVICEI::ValidateFVF"
  1757. HRESULT DIRECT3DDEVICEI::ValidateFVF(DWORD type)
  1758. {
  1759. DWORD dwTexCoord = FVF_TEXCOORD_NUMBER(type);
  1760. DWORD vertexType = type & D3DFVF_POSITION_MASK;
  1761. // Texture format bits above texture count should be zero
  1762. // Reserved field 0 and 2 should be 0
  1763. // Reserved 1 should be set only for LVERTEX
  1764. // Only two vertex position types allowed
  1765. if (type & g_TextureFormatMask[dwTexCoord])
  1766. {
  1767. D3D_ERR("FVF has incorrect texture format");
  1768. goto error;
  1769. }
  1770. if (type & 0xFFFF0000 && vertexType == D3DFVF_XYZRHW &&
  1771. this->deviceType < D3DDEVTYPE_DX7HAL)
  1772. {
  1773. D3D_ERR("The D3D device supports only two floats per texture coordinate set");
  1774. goto error;
  1775. }
  1776. if (type & (D3DFVF_RESERVED2 | D3DFVF_RESERVED0) ||
  1777. (type & D3DFVF_RESERVED1 && !(type & D3DFVF_LVERTEX)))
  1778. {
  1779. D3D_ERR("FVF has reserved bit(s) set");
  1780. goto error;
  1781. }
  1782. if (!(vertexType == D3DFVF_XYZRHW ||
  1783. vertexType == D3DFVF_XYZ ||
  1784. vertexType == D3DFVF_XYZB1 ||
  1785. vertexType == D3DFVF_XYZB2 ||
  1786. vertexType == D3DFVF_XYZB3 ||
  1787. vertexType == D3DFVF_XYZB4 ||
  1788. vertexType == D3DFVF_XYZB5))
  1789. {
  1790. D3D_ERR("FVF has incorrect position type");
  1791. goto error;
  1792. }
  1793. if (vertexType == D3DFVF_XYZRHW && type & D3DFVF_NORMAL)
  1794. {
  1795. D3D_ERR("Normal should not be used with XYZRHW position type");
  1796. goto error;
  1797. }
  1798. return D3D_OK;
  1799. error:
  1800. D3D_ERR("ValidateFVF() returns DDERR_INVALIDPARAMS");
  1801. return DDERR_INVALIDPARAMS;
  1802. }
  1803. //---------------------------------------------------------------------
  1804. // The function should bot be called by ProcessVertices.
  1805. // Computes nOutTexCoord and dwTextureIndexToCopy in case when a pre-DX6
  1806. // driver is used.
  1807. //
  1808. void ComputeTCI2CopyLegacy(LPDIRECT3DDEVICEI lpDevI,
  1809. DWORD dwNumInpTexCoord,
  1810. DWORD* pdwInpTexCoordSize,
  1811. BOOL bVertexTransformed)
  1812. {
  1813. lpDevI->dwTextureIndexToCopy = 0;
  1814. lpDevI->nOutTexCoord = 0;
  1815. lpDevI->dwTextureCoordSizeTotal = 0;
  1816. lpDevI->dwTextureCoordSize[0] = 0;
  1817. // If texture is enabled we care about texture gen mode and the texture
  1818. // index to copy
  1819. if (lpDevI->tsstates[0][D3DTSS_COLOROP] != D3DTOP_DISABLE)
  1820. {
  1821. DWORD dwTexIndex = lpDevI->tsstates[0][D3DTSS_TEXCOORDINDEX];
  1822. DWORD dwTexGenMode = dwTexIndex & ~0xFFFF;
  1823. dwTexIndex &= 0xFFFF;
  1824. if (bVertexTransformed)
  1825. {
  1826. lpDevI->dwTextureIndexToCopy = dwTexIndex;
  1827. // In case of clipping we need to clip as many texture
  1828. // coordinates as set in the texture stage state.
  1829. lpDevI->nOutTexCoord = min(dwNumInpTexCoord, lpDevI->dwTextureIndexToCopy+1);
  1830. for (DWORD i=0; i < lpDevI->nOutTexCoord; i++)
  1831. {
  1832. lpDevI->dwTextureCoordSizeTotal += pdwInpTexCoordSize[i];
  1833. lpDevI->dwTextureCoordSize[i] = pdwInpTexCoordSize[i];
  1834. }
  1835. }
  1836. else
  1837. if (dwTexGenMode == D3DTSS_TCI_CAMERASPACENORMAL ||
  1838. dwTexGenMode == D3DTSS_TCI_CAMERASPACEPOSITION ||
  1839. dwTexGenMode == D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR)
  1840. {
  1841. if (dwTexGenMode == D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR)
  1842. lpDevI->dwDeviceFlags |= D3DDEV_NORMALINCAMERASPACE | D3DDEV_POSITIONINCAMERASPACE;
  1843. else
  1844. if (dwTexGenMode == D3DTSS_TCI_CAMERASPACENORMAL)
  1845. lpDevI->dwDeviceFlags |= D3DDEV_NORMALINCAMERASPACE;
  1846. else
  1847. if (dwTexGenMode == D3DTSS_TCI_CAMERASPACEPOSITION)
  1848. lpDevI->dwDeviceFlags |= D3DDEV_POSITIONINCAMERASPACE;
  1849. lpDevI->dwDeviceFlags |= D3DDEV_REMAPTEXTUREINDICES;
  1850. LPD3DFE_TEXTURESTAGE pStage = &lpDevI->textureStage[0];
  1851. pStage->dwInpCoordIndex = 0;
  1852. pStage->dwTexGenMode = dwTexGenMode;
  1853. pStage->dwOrgStage = 0;
  1854. pStage->dwInpOffset = 0;
  1855. pStage->dwOutCoordIndex = 0;
  1856. if (lpDevI->dwFlags2 & __FLAGS2_TEXTRANSFORM0)
  1857. {
  1858. pStage->pmTextureTransform = &lpDevI->mTexture[0];
  1859. pStage->dwTexTransformFuncIndex = MakeTexTransformFuncIndex(3, 2);
  1860. }
  1861. else
  1862. {
  1863. pStage->pmTextureTransform = NULL;
  1864. }
  1865. pStage->dwOrgWrapMode = lpDevI->rstates[D3DRENDERSTATE_WRAP0];
  1866. // Texture index is used as an index to the new WRAP mode
  1867. DWORD dwNewWrapMode = lpDevI->rstates[D3DRENDERSTATE_WRAP0 + dwTexIndex];
  1868. if (dwNewWrapMode != pStage->dwOrgWrapMode)
  1869. {
  1870. lpDevI->rstates[D3DRENDERSTATE_WRAP0] = dwNewWrapMode;
  1871. lpDevI->SetRenderStateI(D3DRENDERSTATE_WRAP0, dwNewWrapMode);
  1872. }
  1873. lpDevI->nOutTexCoord = 1;
  1874. lpDevI->dwNumTextureStages = 1;
  1875. lpDevI->dwTextureCoordSizeTotal = 8;
  1876. lpDevI->dwTextureCoordSize[0] = 8;
  1877. }
  1878. else
  1879. if (dwNumInpTexCoord != 0)
  1880. {
  1881. lpDevI->nOutTexCoord = 1;
  1882. lpDevI->dwTextureIndexToCopy = dwTexIndex;
  1883. lpDevI->dwTextureCoordSizeTotal = 8;
  1884. lpDevI->dwTextureCoordSize[0] = 8;
  1885. }
  1886. }
  1887. }
  1888. //---------------------------------------------------------------------
  1889. // Computes output FVF id, based on input FVF id and device settingd
  1890. // Also computes nTexCoord field
  1891. // Number of texture coordinates is set based on dwVIDIn. ValidateFVF sould
  1892. // make sure that it is not greater than supported by the driver
  1893. // Last settings for dwVIDOut and dwVIDIn are saved to speed up processing
  1894. //
  1895. #undef DPF_MODNAME
  1896. #define DPF_MODNAME "DIRECT3DDEVICEI::SetupFVFData"
  1897. HRESULT DIRECT3DDEVICEI::SetupFVFData(DWORD *pdwInpVertexSize)
  1898. {
  1899. // We have to restore texture stage indices if previous primitive
  1900. // re-mapped them
  1901. if (this->dwDeviceFlags & D3DDEV_REMAPTEXTUREINDICES)
  1902. {
  1903. RestoreTextureStages(this);
  1904. }
  1905. this->dwFEFlags &= ~D3DFE_FVF_DIRTY;
  1906. this->nTexCoord = FVF_TEXCOORD_NUMBER(this->dwVIDIn);
  1907. DWORD dwInpTexSizeTotal = ComputeTextureCoordSize(this->dwVIDIn, this->dwInpTextureCoordSize);
  1908. // Compute size of dwVIDIn
  1909. DWORD dwInpVertexSize = GetVertexSizeFVF(this->dwVIDIn) + dwInpTexSizeTotal;
  1910. if (pdwInpVertexSize)
  1911. {
  1912. *pdwInpVertexSize = dwInpVertexSize;
  1913. }
  1914. // Compute how many texture coordinates to copy
  1915. ComputeTCI2CopyLegacy(this, this->nTexCoord, this->dwInpTextureCoordSize,
  1916. FVF_TRANSFORMED(this->dwVIDIn));
  1917. if (FVF_TRANSFORMED(this->dwVIDIn))
  1918. {
  1919. this->dwVIDOut = this->dwVIDIn;
  1920. ComputeOutputVertexOffsets(this);
  1921. this->dwOutputSize = dwInpVertexSize;
  1922. return D3D_OK;
  1923. }
  1924. else
  1925. {
  1926. this->dwVIDOut = D3DFVF_TLVERTEX;
  1927. this->dwOutputSize = sizeof(D3DTLVERTEX);
  1928. }
  1929. if (!(this->dwFlags & D3DPV_VBCALL))
  1930. UpdateGeometryLoopData(this);
  1931. this->dwDeviceFlags &= ~D3DDEV_TEXTURETRANSFORM;
  1932. // Stage 0 bit is used for the texture transform
  1933. if (this->dwFlags2 & __FLAGS2_TEXTRANSFORM0)
  1934. {
  1935. this->pmTexture[0] = &this->mTexture[0];
  1936. this->dwDeviceFlags |= D3DDEV_TEXTURETRANSFORM;
  1937. if ((this->tsstates[0][D3DTSS_TEXTURETRANSFORMFLAGS] & 0xFF) != 2)
  1938. {
  1939. D3D_ERR("The texture transform for the device should use 2 floats");
  1940. return DDERR_INVALIDPARAMS;
  1941. }
  1942. }
  1943. else
  1944. if (this->dwDeviceFlags & D3DDEV_REMAPTEXTUREINDICES)
  1945. {
  1946. D3D_ERR("Cannot use texture generation without texture transform for pre-DX6 device");
  1947. return DDERR_INVALIDPARAMS;
  1948. }
  1949. // In case if COLORVERTEX is TRUE, the vertexAlpha could be overriden
  1950. // by vertex alpha
  1951. this->lighting.alpha = (DWORD)this->lighting.materialAlpha;
  1952. this->lighting.alphaSpecular = (DWORD)this->lighting.materialAlphaS;
  1953. return D3D_OK;
  1954. }
  1955. //---------------------------------------------------------------------
  1956. // Returns TRUE, if driver state should not be updated
  1957. //
  1958. #undef DPF_MODNAME
  1959. #define DPF_MODNAME "DIRECT3DDEVICEI::UpdateInternalTextureStageState"
  1960. BOOL DIRECT3DDEVICEI::UpdateInternalTextureStageState
  1961. (DWORD dwStage, D3DTEXTURESTAGESTATETYPE dwState, DWORD dwValue)
  1962. {
  1963. BOOL ret = FALSE; // return TRUE if TSS should NOT be batched
  1964. if(dwState == D3DTSS_COLOROP)
  1965. {
  1966. if(dwValue == D3DTOP_DISABLE || tsstates[dwStage][D3DTSS_COLOROP] == D3DTOP_DISABLE)
  1967. ForceFVFRecompute();
  1968. }
  1969. else
  1970. if (dwState == D3DTSS_TEXCOORDINDEX)
  1971. {
  1972. if (this->dwDeviceFlags & D3DDEV_REMAPTEXTUREINDICES)
  1973. {
  1974. RestoreTextureStages(this);
  1975. ForceFVFRecompute();
  1976. }
  1977. else
  1978. if (TextureTransformEnabled(this))
  1979. {
  1980. // Force re-compute if a texture transfrom is enabled
  1981. ForceFVFRecompute();
  1982. }
  1983. DWORD dwTexGenMode = 0;
  1984. if (dwValue >= D3DDP_MAXTEXCOORD)
  1985. {
  1986. dwTexGenMode = dwValue & ~0xFFFF;
  1987. if(!IS_TLHAL_DEVICE(this))
  1988. ret = TRUE;
  1989. #if DBG
  1990. DWORD dwTexIndex = dwValue & 0xFFFF;
  1991. if (!(dwTexGenMode == D3DTSS_TCI_CAMERASPACENORMAL ||
  1992. dwTexGenMode == D3DTSS_TCI_CAMERASPACEPOSITION ||
  1993. dwTexGenMode == D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR) ||
  1994. dwTexIndex > D3DDP_MAXTEXCOORD)
  1995. {
  1996. D3D_ERR("Incorrect texture coordinate set index");
  1997. throw DDERR_INVALIDPARAMS;
  1998. }
  1999. #endif
  2000. }
  2001. DWORD dwTexGenBit = 0;
  2002. if (dwTexGenMode == D3DTSS_TCI_CAMERASPACENORMAL ||
  2003. dwTexGenMode == D3DTSS_TCI_CAMERASPACEPOSITION ||
  2004. dwTexGenMode == D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR)
  2005. {
  2006. dwTexGenBit = __FLAGS2_TEXGEN0 << dwStage; // To set internal "enable" dword
  2007. }
  2008. // Force to re-compute FVF only if enable state is changed
  2009. if ((this->dwFlags2 & dwTexGenBit) != dwTexGenBit)
  2010. {
  2011. ForceFVFRecompute();
  2012. this->dwFlags2 = (this->dwFlags2 & ~dwTexGenBit) | dwTexGenBit;
  2013. this->dwDeviceFlags &= ~(D3DDEV_POSITIONINCAMERASPACE | D3DDEV_NORMALINCAMERASPACE);
  2014. }
  2015. if (!(this->dwDeviceFlags & D3DDEV_FVF))
  2016. {
  2017. ForceFVFRecompute();
  2018. if (dwValue != 0)
  2019. ret = TRUE;
  2020. }
  2021. }
  2022. else
  2023. if (dwState == D3DTSS_TEXTURETRANSFORMFLAGS)
  2024. {
  2025. DWORD dwEnableBit = 1 << dwStage; // To check internal "enable" dword
  2026. // Force to re-compute FVF only if enable state is changed
  2027. if (dwValue == D3DTTFF_DISABLE)
  2028. {
  2029. if (this->dwFlags2 & dwEnableBit)
  2030. {
  2031. ForceFVFRecompute();
  2032. this->dwFlags2 &= ~dwEnableBit;
  2033. }
  2034. }
  2035. else
  2036. {
  2037. if (!(this->dwFlags2 & dwEnableBit))
  2038. {
  2039. ForceFVFRecompute();
  2040. this->dwFlags2 |= dwEnableBit;
  2041. }
  2042. }
  2043. if(this->deviceType == D3DDEVTYPE_DP2HAL)
  2044. ret = TRUE;
  2045. }
  2046. else if(dwState > D3DTSS_TEXTURETRANSFORMFLAGS)
  2047. {
  2048. if(this->deviceType == D3DDEVTYPE_DP2HAL)
  2049. ret = TRUE;
  2050. }
  2051. // Update runtime copy of state.
  2052. tsstates[dwStage][dwState] = dwValue;
  2053. return ret;
  2054. }
  2055. //---------------------------------------------------------------------
  2056. #undef DPF_MODNAME
  2057. #define DPF_MODNAME "DIRECT3DDEVICEI::SetClipPlaneI"
  2058. void DIRECT3DDEVICEI::SetClipPlaneI(DWORD dwPlaneIndex, D3DVALUE* pPlaneEquation)
  2059. {
  2060. D3DVALUE *p = &this->transform.userClipPlane[dwPlaneIndex].x;
  2061. p[0] = pPlaneEquation[0];
  2062. p[1] = pPlaneEquation[1];
  2063. p[2] = pPlaneEquation[2];
  2064. p[3] = pPlaneEquation[3];
  2065. this->dwFEFlags |= D3DFE_CLIPPLANES_DIRTY | D3DFE_FRONTEND_DIRTY;
  2066. this->dwMaxUserClipPlanes = 0;
  2067. }
  2068. //---------------------------------------------------------------------
  2069. #undef DPF_MODNAME
  2070. #define DPF_MODNAME "DIRECT3DDEVICEI::SetClipPlane"
  2071. HRESULT D3DAPI
  2072. DIRECT3DDEVICEI::SetClipPlane(DWORD dwPlaneIndex, D3DVALUE* pPlaneEquation)
  2073. {
  2074. #if DBG
  2075. if (dwPlaneIndex >= max(this->transform.dwMaxUserClipPlanes, __MAXUSERCLIPPLANES))
  2076. {
  2077. D3D_ERR("Plane index is too big");
  2078. return DDERR_INVALIDPARAMS;
  2079. }
  2080. if (!VALID_PTR(pPlaneEquation, sizeof(D3DVALUE)*4))
  2081. {
  2082. D3D_ERR( "Invalid plane pointer" );
  2083. return DDERR_INVALIDPARAMS;
  2084. }
  2085. #endif
  2086. try
  2087. {
  2088. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND(""));
  2089. if (this->dwFEFlags & D3DFE_RECORDSTATEMODE)
  2090. m_pStateSets->InsertClipPlane(dwPlaneIndex, pPlaneEquation);
  2091. else
  2092. SetClipPlaneI(dwPlaneIndex, pPlaneEquation);
  2093. return D3D_OK;
  2094. }
  2095. catch(HRESULT ret)
  2096. {
  2097. return ret;
  2098. }
  2099. }
  2100. //---------------------------------------------------------------------
  2101. #undef DPF_MODNAME
  2102. #define DPF_MODNAME "DIRECT3DDEVICEI::GetClipPlane"
  2103. HRESULT D3DAPI
  2104. DIRECT3DDEVICEI::GetClipPlane(DWORD dwPlaneIndex, D3DVALUE* pPlaneEquation)
  2105. {
  2106. #if DBG
  2107. if (dwPlaneIndex >= max(this->transform.dwMaxUserClipPlanes, __MAXUSERCLIPPLANES))
  2108. {
  2109. D3D_ERR("Plane index is too big");
  2110. return DDERR_INVALIDPARAMS;
  2111. }
  2112. if (!VALID_PTR(pPlaneEquation, sizeof(D3DVALUE)*4))
  2113. {
  2114. D3D_ERR( "Invalid plane pointer" );
  2115. return DDERR_INVALIDPARAMS;
  2116. }
  2117. #endif
  2118. try
  2119. {
  2120. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND(""));
  2121. D3DVALUE *p = &this->transform.userClipPlane[dwPlaneIndex].x;
  2122. pPlaneEquation[0] = p[0];
  2123. pPlaneEquation[1] = p[1];
  2124. pPlaneEquation[2] = p[2];
  2125. pPlaneEquation[3] = p[3];
  2126. return D3D_OK;
  2127. }
  2128. catch(HRESULT ret)
  2129. {
  2130. return ret;
  2131. }
  2132. }