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.

1848 lines
60 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 "ddibase.h"
  14. //---------------------------------------------------------------------
  15. #if DBG
  16. void CPackedBitArray::CheckIndex(UINT index)
  17. {
  18. if (index >= m_size)
  19. {
  20. D3D_THROW_FAIL("Invalid index");
  21. }
  22. }
  23. #endif // DBG
  24. //---------------------------------------------------------------------
  25. inline void UpdateFogFactor(D3DFE_PROCESSVERTICES* lpDevI)
  26. {
  27. if (lpDevI->lighting.fog_end == lpDevI->lighting.fog_start)
  28. lpDevI->lighting.fog_factor = D3DVAL(0.0);
  29. else
  30. lpDevI->lighting.fog_factor = D3DVAL(255) /
  31. (lpDevI->lighting.fog_end - lpDevI->lighting.fog_start);
  32. }
  33. //---------------------------------------------------------------------
  34. #undef DPF_MODNAME
  35. #define DPF_MODNAME "CD3DHal::SetRenderState"
  36. HRESULT D3DAPI
  37. CD3DHal::SetRenderState(D3DRENDERSTATETYPE dwState, DWORD value)
  38. {
  39. API_ENTER(this); // Takes D3D Lock if necessary
  40. #if DBG
  41. if (dwState >= D3D_MAXRENDERSTATES || dwState == 0 )
  42. {
  43. D3D_ERR( "Invalid render state type. SetRenderState failed." );
  44. return D3DERR_INVALIDCALL;
  45. }
  46. #endif
  47. try
  48. {
  49. if (this->m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE)
  50. {
  51. if(this->CheckForRetiredRenderState(dwState))
  52. {
  53. m_pStateSets->InsertRenderState(dwState, value, CanHandleRenderState(dwState));
  54. }
  55. else
  56. {
  57. D3D_ERR("Invalid renderstate %d. SetRenderState failed.", dwState);
  58. return D3DERR_INVALIDCALL;
  59. }
  60. }
  61. else
  62. this->SetRenderStateFast(dwState, value);
  63. return D3D_OK;
  64. }
  65. catch(HRESULT ret)
  66. {
  67. D3D_ERR("SetRenderState failed.");
  68. return ret;
  69. }
  70. }
  71. //---------------------------------------------------------------------
  72. #undef DPF_MODNAME
  73. #define DPF_MODNAME "CD3DHal::SetRenderStateFast"
  74. HRESULT D3DAPI CD3DHal::SetRenderStateFast(D3DRENDERSTATETYPE dwState, DWORD value)
  75. {
  76. // NOTE: This can become a public API through the
  77. // v-table hack. This should only happen for
  78. // single-threaded apps; so we don't need
  79. // to take the critical section.
  80. // API_ENTER(this); // Takes D3D Lock if necessary
  81. #if DBG
  82. if (dwState >= D3D_MAXRENDERSTATES || dwState == 0 )
  83. {
  84. D3D_ERR( "Invalid render state type. SetRenderState failed." );
  85. return D3DERR_INVALIDCALL;
  86. }
  87. #endif
  88. if (!rsVec.IsBitSet(dwState))
  89. { // Fast path. We do not need any processing done in UpdateInternalState
  90. // other than updating rstates array
  91. if ( (this->rstates[dwState] == value)
  92. #if DBG
  93. && (dwState != D3DRS_DEBUGMONITORTOKEN) // don't filter these
  94. #endif
  95. )
  96. {
  97. D3D_WARN(4,"Ignoring redundant SetRenderState - %d", dwState);
  98. return D3D_OK;
  99. }
  100. this->rstates[dwState] = value;
  101. // Output state to the device driver
  102. try
  103. {
  104. m_pDDI->SetRenderState(dwState, value);
  105. }
  106. catch(HRESULT ret)
  107. {
  108. D3D_ERR("SetRenderState failed.");
  109. return ret;
  110. }
  111. }
  112. else
  113. {
  114. try
  115. {
  116. // Wrap modes could be re-programmed. We need to restore them before
  117. // filtering redundant values
  118. if (m_pv->dwDeviceFlags & D3DDEV_REMAPTEXTUREINDICES)
  119. {
  120. RestoreTextureStages(this);
  121. ForceFVFRecompute();
  122. }
  123. if ( (this->rstates[dwState] == value)
  124. #if DBG
  125. && (dwState != D3DRS_DEBUGMONITORTOKEN) // don't filter these
  126. #endif
  127. )
  128. {
  129. D3D_WARN(4,"Ignoring redundant SetRenderState - %d", dwState);
  130. return D3D_OK;
  131. }
  132. this->UpdateInternalState(dwState, value);
  133. // Vertex processing only render states will be passed to the
  134. // driver when we switch to the hardware vertex processing mode
  135. if ((!(rsVertexProcessingOnly.IsBitSet(dwState) &&
  136. m_dwRuntimeFlags & D3DRT_RSSOFTWAREPROCESSING)))
  137. {
  138. if (CanHandleRenderState(dwState))
  139. {
  140. #if DBG
  141. if(!CheckForRetiredRenderState(dwState))
  142. {
  143. D3D_ERR("Invalid (old) renderstate %d. SetRenderState failed.", dwState);
  144. return D3DERR_INVALIDCALL;
  145. }
  146. #endif // DBG
  147. m_pDDI->SetRenderState(dwState, value);
  148. }
  149. }
  150. }
  151. catch(HRESULT ret)
  152. {
  153. D3D_ERR("SetRenderState failed.");
  154. return ret;
  155. }
  156. }
  157. return D3D_OK;
  158. }
  159. //---------------------------------------------------------------------
  160. #undef DPF_MODNAME
  161. #define DPF_MODNAME "CD3DHal::SetRenderStateInternal"
  162. void
  163. CD3DHal::SetRenderStateInternal(D3DRENDERSTATETYPE dwState, DWORD dwValue)
  164. {
  165. if (this->rstates[dwState] == dwValue)
  166. {
  167. D3D_WARN(4,"Ignoring redundant SetRenderState - %d", dwState);
  168. return;
  169. }
  170. this->UpdateInternalState(dwState, dwValue);
  171. if (CanHandleRenderState(dwState))
  172. m_pDDI->SetRenderState(dwState, dwValue);
  173. }
  174. //---------------------------------------------------------------------
  175. #undef DPF_MODNAME
  176. #define DPF_MODNAME "Direct3DDevice::GetRenderState"
  177. HRESULT D3DAPI
  178. CD3DHal::GetRenderState(D3DRENDERSTATETYPE dwState, LPDWORD lpdwValue)
  179. {
  180. API_ENTER(this); // Takes D3D Lock if necessary
  181. #if DBG
  182. if (dwState >= D3D_MAXRENDERSTATES || dwState == 0)
  183. {
  184. D3D_ERR( "Invalid render state value. GetRenderState failed." );
  185. return D3DERR_INVALIDCALL;
  186. }
  187. #endif
  188. if (!VALID_WRITEPTR(lpdwValue, sizeof(DWORD)))
  189. {
  190. D3D_ERR( "Invalid DWORD pointer. GetRenderState failed." );
  191. return D3DERR_INVALIDCALL;
  192. }
  193. if(!CheckForRetiredRenderState(dwState))
  194. {
  195. D3D_ERR("invalid renderstate %d. GetRenderState failed.", dwState);
  196. return D3DERR_INVALIDCALL;
  197. }
  198. // WRAP render states could be re-mapped so we have to return the original
  199. // value
  200. if (dwState >= D3DRENDERSTATE_WRAP0 && dwState <= D3DRENDERSTATE_WRAP7)
  201. {
  202. if (m_pv->dwDeviceFlags & D3DDEV_REMAPTEXTUREINDICES)
  203. {
  204. DWORD dwTexCoordIndex = dwState - D3DRENDERSTATE_WRAP0;
  205. for (DWORD i=0; i < this->dwNumTextureStagesToRemap; i++)
  206. {
  207. LPD3DFE_TEXTURESTAGE pStage = &this->textureStageToRemap[i];
  208. if (pStage->dwInpCoordIndex == dwTexCoordIndex)
  209. {
  210. if (pStage->dwInpCoordIndex != pStage->dwOutCoordIndex)
  211. {
  212. *lpdwValue = pStage->dwOrgWrapMode;
  213. return D3D_OK;
  214. }
  215. }
  216. }
  217. }
  218. }
  219. *lpdwValue = this->rstates[dwState];
  220. return D3D_OK;
  221. }
  222. //---------------------------------------------------------------------
  223. #undef DPF_MODNAME
  224. #define DPF_MODNAME "CD3DHal::SetTextureStageState"
  225. HRESULT D3DAPI
  226. CD3DHal::SetTextureStageState(DWORD dwStage,
  227. D3DTEXTURESTAGESTATETYPE dwState,
  228. DWORD dwValue)
  229. {
  230. API_ENTER(this); // Takes D3D Lock if necessary
  231. #if DBG
  232. if ( (dwStage >= D3DHAL_TSS_MAXSTAGES) ||
  233. (dwState == 0) ||
  234. (dwState >= D3DTSS_MAX) ||
  235. (dwState == 12) ) // D3DTSS_ADDRESS no longer valid
  236. {
  237. D3D_ERR( "Invalid texture stage or state index. SetTextureStageState failed." );
  238. return D3DERR_INVALIDCALL;
  239. }
  240. #endif //DBG
  241. try
  242. {
  243. if (this->m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE)
  244. {
  245. m_pStateSets->InsertTextureStageState(dwStage, dwState, dwValue);
  246. return D3D_OK;
  247. }
  248. return this->SetTextureStageStateFast(dwStage, dwState, dwValue);
  249. }
  250. catch(HRESULT ret)
  251. {
  252. D3D_ERR("SetTextureStageState failed.");
  253. return ret;
  254. }
  255. }
  256. //---------------------------------------------------------------------
  257. #undef DPF_MODNAME
  258. #define DPF_MODNAME "CD3DHal::SetTextureStageStateFast"
  259. HRESULT D3DAPI
  260. CD3DHal::SetTextureStageStateFast(DWORD dwStage,
  261. D3DTEXTURESTAGESTATETYPE dwState,
  262. DWORD dwValue)
  263. {
  264. // NOTE: This can become a public API through the
  265. // v-table hack. This should only happen for
  266. // single-threaded apps; so we don't need
  267. // to take the critical section.
  268. // API_ENTER(this); // Takes D3D Lock if necessary
  269. #if DBG
  270. if ( (dwStage >= D3DHAL_TSS_MAXSTAGES) ||
  271. (dwState == 0) ||
  272. (dwState >= D3DTSS_MAX) ||
  273. (dwState == 12) ) // D3DTSS_ADDRESS no longer valid
  274. {
  275. D3D_ERR( "Invalid texture stage or state index. SetTextureStageState failed." );
  276. return D3DERR_INVALIDCALL;
  277. }
  278. #endif //DBG
  279. // Fast path. We do not need any processing done in UpdateInternalTSS other than updating tsstates array
  280. if (NeedInternalTSSUpdate(dwState))
  281. {
  282. // Texture stages could be re-programmed. We need to restore them before
  283. // filtering redundant values
  284. if (m_pv->dwDeviceFlags & D3DDEV_REMAPTEXTUREINDICES)
  285. {
  286. RestoreTextureStages(this);
  287. ForceFVFRecompute();
  288. }
  289. if (this->tsstates[dwStage][dwState] == dwValue)
  290. {
  291. D3D_WARN(4,"Ignoring redundant SetTextureStageState. Stage: %d, State: %d", dwStage, dwState);
  292. return D3D_OK;
  293. }
  294. if(this->UpdateInternalTextureStageState(dwStage, dwState, &dwValue))
  295. return D3D_OK;
  296. }
  297. else
  298. {
  299. if (this->tsstates[dwStage][dwState] == dwValue)
  300. {
  301. D3D_WARN(4,"Ignoring redundant SetTextureStageState. Stage: %d, State: %d", dwStage, dwState);
  302. return D3D_OK;
  303. }
  304. tsstates[dwStage][dwState] = dwValue;
  305. }
  306. if (dwStage >= m_dwMaxTextureBlendStages)
  307. return D3D_OK;
  308. try
  309. {
  310. m_pDDI->SetTSS(dwStage, dwState, dwValue);
  311. }
  312. catch (HRESULT ret)
  313. {
  314. D3D_ERR("SetTextureStageState failed.");
  315. return ret;
  316. }
  317. return D3D_OK;
  318. }
  319. //---------------------------------------------------------------------
  320. #undef DPF_MODNAME
  321. #define DPF_MODNAME "Direct3DDevice::GetTextureStageState"
  322. HRESULT D3DAPI
  323. CD3DHal::GetTextureStageState(DWORD dwStage,
  324. D3DTEXTURESTAGESTATETYPE dwState,
  325. LPDWORD pdwValue)
  326. {
  327. API_ENTER(this); // Takes D3D Lock if necessary
  328. #if DBG
  329. if ( (dwStage >= D3DHAL_TSS_MAXSTAGES) ||
  330. (dwState == 0) ||
  331. (dwState >= D3DTSS_MAX) ||
  332. (dwState == 12) ) // D3DTSS_ADDRESS no longer valid
  333. {
  334. D3D_ERR( "Invalid texture stage or state index. GetTextureStageState failed." );
  335. return D3DERR_INVALIDCALL;
  336. }
  337. #endif //DBG
  338. if (!VALID_WRITEPTR(pdwValue, sizeof(DWORD)))
  339. {
  340. D3D_ERR( "Invalid DWORD pointer. GetTextureStageState failed." );
  341. return D3DERR_INVALIDCALL;
  342. }
  343. // If texture indices were re-mapped we have to find and return the original value
  344. if (dwState == D3DTSS_TEXCOORDINDEX && m_pv->dwDeviceFlags & D3DDEV_REMAPTEXTUREINDICES)
  345. {
  346. RestoreTextureStages(this);
  347. ForceFVFRecompute();
  348. }
  349. // Don't bother to check for DX6 support, just return the
  350. // cached value.
  351. *pdwValue = tsstates[dwStage][dwState];
  352. return D3D_OK;
  353. }
  354. #ifdef FAST_PATH
  355. //-----------------------------------------------------------------------------
  356. #undef DPF_MODNAME
  357. #define DPF_MODNAME "CD3DHal::SetVertexShaderFast"
  358. HRESULT D3DAPI
  359. CD3DHal::SetVertexShaderFast(DWORD dwHandle)
  360. {
  361. try
  362. {
  363. #if DBG
  364. CheckVertexShaderHandle(dwHandle);
  365. #endif
  366. DXGASSERT((m_dwRuntimeFlags & (D3DRT_RECORDSTATEMODE | D3DRT_RSSOFTWAREPROCESSING)) == 0 &&
  367. (BehaviorFlags() & D3DCREATE_MULTITHREADED) == 0);
  368. // We need to set m_pCurrentShader becausu we do NPatch emulation in
  369. // hardware vertex processing mode
  370. static_cast<CD3DHal*>(this)->m_pCurrentShader = NULL;
  371. CVConstantData* pConst = NULL;
  372. #if DBG
  373. m_pv->dwDeviceFlags &= ~D3DDEV_VERTEXSHADERS;
  374. #endif
  375. if (!D3DVSD_ISLEGACY(dwHandle))
  376. {
  377. static_cast<CD3DHal*>(this)->m_pCurrentShader = (CVShader*)m_pVShaderArray->GetObject(dwHandle);
  378. CVShader* pShader = (CVShader*)m_pVShaderArray->GetObjectFast(dwHandle);
  379. pConst = pShader->m_Declaration.m_pConstants;
  380. #ifdef DBG
  381. if(!(pShader->m_dwFlags & CVShader::FIXEDFUNCTION))
  382. {
  383. // Programmable pipeline is used
  384. m_pv->dwDeviceFlags |= D3DDEV_VERTEXSHADERS;
  385. }
  386. #endif
  387. }
  388. // We can return earlier when we do not need to update constants
  389. if (pConst == NULL)
  390. {
  391. if (dwHandle == m_dwCurrentShaderHandle)
  392. return S_OK;
  393. }
  394. else
  395. // Update our copy of constants for Get()
  396. while (pConst)
  397. {
  398. HRESULT hr;
  399. hr = m_pv->pGeometryFuncs->LoadShaderConstants(pConst->m_dwAddress,
  400. pConst->m_dwCount,
  401. pConst->m_pData);
  402. if (FAILED(hr))
  403. {
  404. D3D_THROW_FAIL("Failed to load vertex shader constants");
  405. }
  406. pConst = (CVConstantData*)pConst->m_pNext;
  407. }
  408. m_dwCurrentShaderHandle = dwHandle;
  409. if (!(m_dwRuntimeFlags & D3DRT_EXECUTESTATEMODE))
  410. {
  411. m_pDDI->SetVertexShaderHW(dwHandle);
  412. }
  413. if (!IS_DX8HAL_DEVICE(this))
  414. {
  415. PickDrawPrimFn();
  416. }
  417. }
  418. catch(HRESULT hr)
  419. {
  420. D3D_ERR("SetVertexShader failed.");
  421. ClearVertexShaderHandle();
  422. return hr;
  423. }
  424. return S_OK;
  425. }
  426. #endif // FAST_PATH
  427. //----------------------------------------------------------------------
  428. #undef DPF_MODNAME
  429. #define DPF_MODNAME "CD3DHal::SetTransformI"
  430. void CD3DHal::SetTransformI(D3DTRANSFORMSTATETYPE state,
  431. CONST D3DMATRIX* lpMat)
  432. {
  433. if ((DWORD)state >= __WORLDMATRIXBASE &&
  434. (DWORD)state < (__WORLDMATRIXBASE + __MAXWORLDMATRICES))
  435. {
  436. // World matrix is set
  437. UINT index = (DWORD)state - __WORLDMATRIXBASE;
  438. *(LPD3DMATRIX)&m_pv->world[index] = *lpMat;
  439. if (index == 0)
  440. this->dwFEFlags |= D3DFE_WORLDMATRIX_DIRTY | D3DFE_FRONTEND_DIRTY;
  441. }
  442. else
  443. switch (state)
  444. {
  445. case D3DTS_VIEW :
  446. *(D3DMATRIX*)&m_pv->view = *lpMat;
  447. this->dwFEFlags |= D3DFE_VIEWMATRIX_DIRTY | D3DFE_FRONTEND_DIRTY;
  448. break;
  449. case D3DTS_PROJECTION :
  450. *(D3DMATRIX*)&this->transform.proj = *lpMat;
  451. this->dwFEFlags |= D3DFE_PROJMATRIX_DIRTY | D3DFE_FRONTEND_DIRTY;
  452. break;
  453. case D3DTS_TEXTURE0:
  454. case D3DTS_TEXTURE1:
  455. case D3DTS_TEXTURE2:
  456. case D3DTS_TEXTURE3:
  457. case D3DTS_TEXTURE4:
  458. case D3DTS_TEXTURE5:
  459. case D3DTS_TEXTURE6:
  460. case D3DTS_TEXTURE7:
  461. {
  462. m_pv->dwDeviceFlags |= D3DDEV_TEXTRANSFORMDIRTY;
  463. DWORD dwIndex = state - D3DTS_TEXTURE0;
  464. *(D3DMATRIX*)&m_pv->mTexture[dwIndex] = *lpMat;
  465. break;
  466. }
  467. }
  468. m_pv->MatrixStateCount++;
  469. if (!(m_dwRuntimeFlags & D3DRT_EXECUTESTATEMODE))
  470. {
  471. if (m_dwRuntimeFlags & D3DRT_RSSOFTWAREPROCESSING)
  472. this->pMatrixDirtyForDDI->SetBit(state);
  473. else
  474. m_pDDI->SetTransform(state, lpMat);
  475. // W range should always be updated
  476. if (state == D3DTS_PROJECTION)
  477. m_pDDI->UpdateWInfo(lpMat);
  478. }
  479. }
  480. //---------------------------------------------------------------------
  481. #undef DPF_MODNAME
  482. #define DPF_MODNAME "CD3DHal::GetTransform"
  483. HRESULT D3DAPI
  484. CD3DHal::GetTransform(D3DTRANSFORMSTATETYPE state, LPD3DMATRIX lpMat)
  485. {
  486. API_ENTER(this); // Takes D3D Lock if necessary
  487. HRESULT ret = D3D_OK;
  488. #if DBG
  489. if (!VALID_WRITEPTR(lpMat, sizeof(D3DMATRIX)))
  490. {
  491. D3D_ERR( "Invalid matrix pointer. GetTransform failed." );
  492. return D3DERR_INVALIDCALL;
  493. }
  494. #endif
  495. if ((DWORD)state >= __WORLDMATRIXBASE &&
  496. (DWORD)state < (__WORLDMATRIXBASE + __MAXWORLDMATRICES))
  497. {
  498. // World matrix is set
  499. UINT index = (DWORD)state - __WORLDMATRIXBASE;
  500. *lpMat = *(LPD3DMATRIX)&m_pv->world[index];
  501. }
  502. else
  503. switch (state) {
  504. case D3DTS_VIEW :
  505. *lpMat = *(LPD3DMATRIX)&m_pv->view._11;
  506. break;
  507. case D3DTS_PROJECTION :
  508. *lpMat = *(LPD3DMATRIX)&this->transform.proj._11;
  509. break;
  510. case D3DTS_TEXTURE0:
  511. case D3DTS_TEXTURE1:
  512. case D3DTS_TEXTURE2:
  513. case D3DTS_TEXTURE3:
  514. case D3DTS_TEXTURE4:
  515. case D3DTS_TEXTURE5:
  516. case D3DTS_TEXTURE6:
  517. case D3DTS_TEXTURE7:
  518. *lpMat = *(LPD3DMATRIX)&m_pv->mTexture[state-D3DTS_TEXTURE0]._11;
  519. break;
  520. default :
  521. D3D_ERR( "Invalid state value passed to GetTransform. GetTransform failed." );
  522. ret = D3DERR_INVALIDCALL; /* Work Item: Generate new meaningful return code */
  523. break;
  524. }
  525. return ret;
  526. } // end of D3DDev2_GetTransform()
  527. //---------------------------------------------------------------------
  528. #undef DPF_MODNAME
  529. #define DPF_MODNAME "CD3DHal::UpdateDriverStates"
  530. void
  531. CD3DHal::UpdateDriverStates()
  532. {
  533. // note we can't do a loop from 1 to D3DHAL_MAX_RSTATES(256) as some of
  534. // rstates are not valid states, passin them down to drivers(like
  535. // voodoo2 DX6 driver) will crash.
  536. static D3DRENDERSTATETYPE dx6states[] =
  537. {
  538. D3DRENDERSTATE_SPECULARENABLE,
  539. D3DRENDERSTATE_ZENABLE,
  540. D3DRENDERSTATE_FILLMODE,
  541. D3DRENDERSTATE_SHADEMODE,
  542. D3DRENDERSTATE_LINEPATTERN,
  543. D3DRENDERSTATE_ZWRITEENABLE,
  544. D3DRENDERSTATE_ALPHATESTENABLE,
  545. D3DRENDERSTATE_LASTPIXEL,
  546. D3DRENDERSTATE_SRCBLEND,
  547. D3DRENDERSTATE_DESTBLEND,
  548. D3DRENDERSTATE_CULLMODE,
  549. D3DRENDERSTATE_ZFUNC,
  550. D3DRENDERSTATE_ALPHAREF,
  551. D3DRENDERSTATE_ALPHAFUNC,
  552. D3DRENDERSTATE_DITHERENABLE,
  553. D3DRENDERSTATE_FOGENABLE,
  554. D3DRENDERSTATE_ZVISIBLE,
  555. D3DRENDERSTATE_STIPPLEDALPHA,
  556. D3DRENDERSTATE_FOGCOLOR,
  557. D3DRENDERSTATE_FOGTABLEMODE,
  558. D3DRENDERSTATE_FOGSTART,
  559. D3DRENDERSTATE_FOGEND,
  560. D3DRENDERSTATE_FOGDENSITY,
  561. D3DRENDERSTATE_COLORKEYENABLE,
  562. D3DRENDERSTATE_ALPHABLENDENABLE,
  563. D3DRENDERSTATE_ZBIAS,
  564. D3DRENDERSTATE_RANGEFOGENABLE,
  565. D3DRENDERSTATE_STIPPLEENABLE,
  566. D3DRENDERSTATE_MONOENABLE,
  567. D3DRENDERSTATE_ROP2,
  568. D3DRENDERSTATE_PLANEMASK,
  569. D3DRENDERSTATE_WRAPU,
  570. D3DRENDERSTATE_WRAPV,
  571. D3DRENDERSTATE_ANTIALIAS,
  572. D3DRENDERSTATE_SUBPIXEL,
  573. D3DRENDERSTATE_SUBPIXELX,
  574. D3DRENDERSTATE_EDGEANTIALIAS,
  575. D3DRENDERSTATE_STIPPLEPATTERN00,
  576. D3DRENDERSTATE_STIPPLEPATTERN01,
  577. D3DRENDERSTATE_STIPPLEPATTERN02,
  578. D3DRENDERSTATE_STIPPLEPATTERN03,
  579. D3DRENDERSTATE_STIPPLEPATTERN04,
  580. D3DRENDERSTATE_STIPPLEPATTERN05,
  581. D3DRENDERSTATE_STIPPLEPATTERN06,
  582. D3DRENDERSTATE_STIPPLEPATTERN07,
  583. D3DRENDERSTATE_STIPPLEPATTERN08,
  584. D3DRENDERSTATE_STIPPLEPATTERN09,
  585. D3DRENDERSTATE_STIPPLEPATTERN10,
  586. D3DRENDERSTATE_STIPPLEPATTERN11,
  587. D3DRENDERSTATE_STIPPLEPATTERN12,
  588. D3DRENDERSTATE_STIPPLEPATTERN13,
  589. D3DRENDERSTATE_STIPPLEPATTERN14,
  590. D3DRENDERSTATE_STIPPLEPATTERN15,
  591. D3DRENDERSTATE_STIPPLEPATTERN16,
  592. D3DRENDERSTATE_STIPPLEPATTERN17,
  593. D3DRENDERSTATE_STIPPLEPATTERN18,
  594. D3DRENDERSTATE_STIPPLEPATTERN19,
  595. D3DRENDERSTATE_STIPPLEPATTERN20,
  596. D3DRENDERSTATE_STIPPLEPATTERN21,
  597. D3DRENDERSTATE_STIPPLEPATTERN22,
  598. D3DRENDERSTATE_STIPPLEPATTERN23,
  599. D3DRENDERSTATE_STIPPLEPATTERN24,
  600. D3DRENDERSTATE_STIPPLEPATTERN25,
  601. D3DRENDERSTATE_STIPPLEPATTERN26,
  602. D3DRENDERSTATE_STIPPLEPATTERN27,
  603. D3DRENDERSTATE_STIPPLEPATTERN28,
  604. D3DRENDERSTATE_STIPPLEPATTERN29,
  605. D3DRENDERSTATE_STIPPLEPATTERN30,
  606. D3DRENDERSTATE_STIPPLEPATTERN31,
  607. D3DRENDERSTATE_TEXTUREPERSPECTIVE,
  608. D3DRENDERSTATE_STENCILENABLE,
  609. D3DRENDERSTATE_STENCILFAIL,
  610. D3DRENDERSTATE_STENCILZFAIL,
  611. D3DRENDERSTATE_STENCILPASS,
  612. D3DRENDERSTATE_STENCILFUNC,
  613. D3DRENDERSTATE_STENCILREF,
  614. D3DRENDERSTATE_STENCILMASK,
  615. D3DRENDERSTATE_STENCILWRITEMASK,
  616. D3DRENDERSTATE_TEXTUREFACTOR,
  617. D3DRENDERSTATE_WRAP0,
  618. D3DRENDERSTATE_WRAP1,
  619. D3DRENDERSTATE_WRAP2,
  620. D3DRENDERSTATE_WRAP3,
  621. D3DRENDERSTATE_WRAP4,
  622. D3DRENDERSTATE_WRAP5,
  623. D3DRENDERSTATE_WRAP6,
  624. D3DRENDERSTATE_WRAP7
  625. };
  626. HRESULT ret;
  627. for (DWORD i=0; i<sizeof(dx6states)/sizeof(D3DRENDERSTATETYPE); ++i)
  628. {
  629. m_pDDI->SetRenderState( dx6states[i], rstates[dx6states[i]] );
  630. }
  631. for( i = 0; i < m_dwMaxTextureBlendStages; i++ )
  632. {
  633. for( DWORD j = D3DTSS_COLOROP ; j < D3DTSS_TEXTURETRANSFORMFLAGS;
  634. ++j )
  635. {
  636. m_pDDI->SetTSS( i, (D3DTEXTURESTAGESTATETYPE)j,
  637. this->tsstates[i][j] );
  638. }
  639. }
  640. }
  641. //---------------------------------------------------------------------
  642. #undef DPF_MODNAME
  643. #define DPF_MODNAME "CD3DHal::SetClipStatus"
  644. HRESULT D3DAPI CD3DHal::SetClipStatus(CONST D3DCLIPSTATUS8* status)
  645. {
  646. API_ENTER(this); // Takes D3D Lock if necessary
  647. #if DBG
  648. if (!VALID_PTR(status, sizeof(D3DCLIPSTATUS8)) )
  649. {
  650. D3D_ERR( "Invalid status pointer. SetClipStatus failed." );
  651. return D3DERR_INVALIDCALL;
  652. }
  653. #endif
  654. m_ClipStatus = * status;
  655. return D3D_OK;
  656. }
  657. //---------------------------------------------------------------------
  658. #undef DPF_MODNAME
  659. #define DPF_MODNAME "Direct3DDevice::GetClipStatus"
  660. HRESULT D3DAPI CD3DHal::GetClipStatus(D3DCLIPSTATUS8* status)
  661. {
  662. API_ENTER(this); // Takes D3D Lock if necessary
  663. #if DBG
  664. if (! VALID_WRITEPTR(status, sizeof(D3DCLIPSTATUS8)) )
  665. {
  666. D3D_ERR( "Invalid status pointer. GetClipStatus failed." );
  667. return D3DERR_INVALIDCALL;
  668. }
  669. #endif
  670. *status = m_ClipStatus;
  671. return D3D_OK;
  672. }
  673. //---------------------------------------------------------------------
  674. #undef DPF_MODNAME
  675. #define DPF_MODNAME "CD3DHal::SwitchVertexProcessingMode"
  676. void CD3DHal::SwitchVertexProcessingMode(DWORD SoftwareMode)
  677. {
  678. m_pDDI->FlushStates(FALSE);
  679. // Invalidate all streams
  680. // What if a vertex buffer is batched?
  681. CVStream* pStream = m_pStream;
  682. for (UINT i=0; i < __NUMSTREAMS; i++)
  683. {
  684. pStream->m_pData = NULL;
  685. if (pStream->m_pVB)
  686. {
  687. m_pDDI->VBReleased(pStream->m_pVB);
  688. pStream->m_pVB->DecrementUseCount();
  689. pStream->m_pVB = NULL;
  690. }
  691. pStream++;
  692. }
  693. m_pIndexStream->m_pData = NULL;
  694. if (m_pIndexStream->m_pVBI)
  695. {
  696. m_pDDI->VBIReleased(m_pIndexStream->m_pVBI);
  697. m_pIndexStream->m_pVBI->DecrementUseCount();
  698. m_pIndexStream->m_pVBI = NULL;
  699. }
  700. ClearVertexShaderHandle();
  701. m_pCurrentShader = NULL;
  702. // Setup capabilities
  703. if (SoftwareMode)
  704. {
  705. m_MaxVertexShaderConst = D3DVS_CONSTREG_MAX_V1_1;
  706. m_dwRuntimeFlags |= D3DRT_RSSOFTWAREPROCESSING;
  707. m_dwNumStreams = __NUMSTREAMS;
  708. m_dwMaxUserClipPlanes = __MAXUSERCLIPPLANES;
  709. #ifdef FAST_PATH
  710. FastPathSetVertexShaderSlow();
  711. FastPathSetStreamSourceSlow();
  712. FastPathSetIndicesSlow();
  713. #endif // FAST_PATH
  714. }
  715. else
  716. {
  717. // We are switching from the software to the hardware mode
  718. m_dwRuntimeFlags &= ~D3DRT_RSSOFTWAREPROCESSING;
  719. #ifdef FAST_PATH
  720. FastPathSetVertexShaderFast();
  721. FastPathSetStreamSourceFast();
  722. FastPathSetIndicesFast();
  723. #endif // FAST_PATH
  724. // Update caps from the hardware
  725. m_dwNumStreams = max(1, GetD3DCaps()->MaxStreams);
  726. m_dwMaxUserClipPlanes = GetD3DCaps()->MaxUserClipPlanes;
  727. // Update vertex processing state in the driver. We did not pass the
  728. // state when it was changed for performance reasons
  729. for (UINT i=0; i < sizeof(rsVertexProcessingList) / sizeof(D3DRENDERSTATETYPE); ++i)
  730. {
  731. D3DRENDERSTATETYPE dwState = (D3DRENDERSTATETYPE)rsVertexProcessingList[i];
  732. if (CanHandleRenderState(dwState))
  733. m_pDDI->SetRenderState(dwState, this->rstates[dwState]);
  734. }
  735. // Update clip planes
  736. for (i=0; i < m_dwMaxUserClipPlanes; i++)
  737. m_pDDI->SetClipPlane(i, (float*)&this->transform.userClipPlane[i]);
  738. // Update lights
  739. const UINT size = m_pLightArray->GetSize();
  740. for (i = 0; i < size; i++)
  741. {
  742. DIRECT3DLIGHTI* pLight = static_cast<DIRECT3DLIGHTI*>
  743. ((*m_pLightArray)[i].m_pObj);
  744. if (pLight)
  745. {
  746. if (pLight->DirtyForDDI())
  747. {
  748. m_pDDI->SetLight(i, &pLight->m_Light);
  749. pLight->ClearDirtyForDDI();
  750. }
  751. }
  752. }
  753. // Update Enable/Disable light state. This is done separately to combine
  754. // multiple calls to the driver into one call.
  755. for (i = 0; i < size; i++)
  756. {
  757. DIRECT3DLIGHTI* pLight = static_cast<DIRECT3DLIGHTI*>
  758. ((*m_pLightArray)[i].m_pObj);
  759. if (pLight)
  760. {
  761. if (pLight->EnableDirtyForDDI())
  762. {
  763. m_pDDI->LightEnable(i, pLight->Enabled());
  764. pLight->ClearEnableDirtyForDDI();
  765. }
  766. }
  767. }
  768. // Update transformation matrices
  769. if (this->pMatrixDirtyForDDI->IsBitSet(D3DTS_VIEW))
  770. {
  771. m_pDDI->SetTransform(D3DTS_VIEW, &m_pv->view);
  772. this->pMatrixDirtyForDDI->ClearBit(D3DTS_VIEW);
  773. }
  774. if (this->pMatrixDirtyForDDI->IsBitSet(D3DTS_PROJECTION))
  775. {
  776. m_pDDI->SetTransform(D3DTS_PROJECTION, &this->transform.proj);
  777. this->pMatrixDirtyForDDI->ClearBit(D3DTS_PROJECTION);
  778. }
  779. for (i=D3DTS_TEXTURE0; i <= D3DTS_TEXTURE7; i++)
  780. {
  781. if (this->pMatrixDirtyForDDI->IsBitSet(i))
  782. {
  783. m_pDDI->SetTransform((D3DTRANSFORMSTATETYPE)i,
  784. &m_pv->mTexture[i - D3DTS_TEXTURE0]);
  785. this->pMatrixDirtyForDDI->ClearBit(i);
  786. }
  787. }
  788. for (i=0; i < __MAXWORLDMATRICES; i++)
  789. {
  790. UINT index = i + __WORLDMATRIXBASE;
  791. if (this->pMatrixDirtyForDDI->IsBitSet(index))
  792. {
  793. m_pDDI->SetTransform((D3DTRANSFORMSTATETYPE)index, &m_pv->world[i]);
  794. this->pMatrixDirtyForDDI->ClearBit(index);
  795. }
  796. }
  797. // Update material
  798. m_pDDI->SetMaterial(&m_pv->lighting.material);
  799. m_MaxVertexShaderConst = GetD3DCaps()->MaxVertexShaderConst;
  800. // Update vertex shader constants
  801. if (m_dwRuntimeFlags & D3DRT_NEED_VSCONST_UPDATE)
  802. {
  803. VVM_WORD data[D3DVS_CONSTREG_MAX_V1_1];
  804. UINT count = min(m_MaxVertexShaderConst, D3DVS_CONSTREG_MAX_V1_1);
  805. if (count)
  806. {
  807. m_pv->pGeometryFuncs->GetShaderConstants(0, count, &data);
  808. m_pDDI->SetVertexShaderConstant(0, &data, count);
  809. }
  810. m_dwRuntimeFlags &= ~D3DRT_NEED_VSCONST_UPDATE;
  811. }
  812. }
  813. PickDrawPrimFn();
  814. }
  815. //---------------------------------------------------------------------
  816. // This function is called from HALEXE.CPP, from device::SetRenderState and
  817. // from device::SetTexture.
  818. //
  819. #undef DPF_MODNAME
  820. #define DPF_MODNAME "CD3DHal::UpdateInternalState"
  821. void CD3DHal::UpdateInternalState(D3DRENDERSTATETYPE type, DWORD value)
  822. {
  823. switch (type)
  824. {
  825. case D3DRENDERSTATE_LIGHTING:
  826. if (value)
  827. m_pv->dwDeviceFlags |= D3DDEV_LIGHTING;
  828. else
  829. m_pv->dwDeviceFlags &= ~D3DDEV_LIGHTING;
  830. ForceFVFRecompute();
  831. break;
  832. case D3DRENDERSTATE_FOGENABLE:
  833. rstates[type] = value; // set rstates BEFORE calling SetFogFlags
  834. SetFogFlags();
  835. break;
  836. case D3DRENDERSTATE_SPECULARENABLE:
  837. this->dwFEFlags |= D3DFE_MATERIAL_DIRTY | D3DFE_LIGHTS_DIRTY | D3DFE_FRONTEND_DIRTY;
  838. if (value)
  839. m_pv->dwDeviceFlags |= D3DDEV_SPECULARENABLE;
  840. else
  841. m_pv->dwDeviceFlags &= ~D3DDEV_SPECULARENABLE;
  842. ForceFVFRecompute();
  843. break;
  844. case D3DRENDERSTATE_AMBIENT:
  845. {
  846. const D3DVALUE SCALE = 1.0f/255.0f;
  847. m_pv->lighting.ambientSceneScaled.r = D3DVAL(RGBA_GETRED(value));
  848. m_pv->lighting.ambientSceneScaled.g = D3DVAL(RGBA_GETGREEN(value));
  849. m_pv->lighting.ambientSceneScaled.b = D3DVAL(RGBA_GETBLUE(value));
  850. m_pv->lighting.ambientScene.r = m_pv->lighting.ambientSceneScaled.r * SCALE;
  851. m_pv->lighting.ambientScene.g = m_pv->lighting.ambientSceneScaled.g * SCALE;
  852. m_pv->lighting.ambientScene.b = m_pv->lighting.ambientSceneScaled.b * SCALE;
  853. m_pv->lighting.ambient_save = value;
  854. this->dwFEFlags |= D3DFE_MATERIAL_DIRTY | D3DFE_FRONTEND_DIRTY;
  855. break;
  856. }
  857. case D3DRENDERSTATE_RANGEFOGENABLE:
  858. if (value)
  859. m_pv->dwDeviceFlags |= D3DDEV_RANGEBASEDFOG;
  860. else
  861. m_pv->dwDeviceFlags &= ~D3DDEV_RANGEBASEDFOG;
  862. break;
  863. case D3DRENDERSTATE_FOGVERTEXMODE:
  864. m_pv->lighting.fog_mode = (D3DFOGMODE)value;
  865. SetFogFlags();
  866. break;
  867. case D3DRENDERSTATE_COLORVERTEX:
  868. if (value)
  869. m_pv->dwDeviceFlags |= D3DDEV_COLORVERTEX;
  870. else
  871. m_pv->dwDeviceFlags &= ~D3DDEV_COLORVERTEX;
  872. // It is faster to initialize these values here, than setting a dirty
  873. // bit ang going through the slow UpdateState path
  874. m_pv->lighting.alpha = (DWORD)m_pv->lighting.materialAlpha;
  875. m_pv->lighting.alphaSpecular = (DWORD)m_pv->lighting.materialAlphaS;
  876. break;
  877. case D3DRENDERSTATE_CLIPPING:
  878. if (!value)
  879. {
  880. m_pv->dwDeviceFlags |= D3DDEV_DONOTCLIP;
  881. // Clear clip union and intersection flags
  882. m_pv->dwClipIntersection = 0;
  883. m_pv->dwClipUnion = 0;
  884. }
  885. else
  886. m_pv->dwDeviceFlags &= ~D3DDEV_DONOTCLIP;
  887. // Change our internal ProcessPrimitive functions which depend on
  888. // the clipping state
  889. m_pDDI->PickProcessPrimitive();
  890. PickDrawPrimFn();
  891. break;
  892. case D3DRENDERSTATE_FOGDENSITY:
  893. m_pv->lighting.fog_density = *(D3DVALUE*)&value;
  894. break;
  895. case D3DRENDERSTATE_FOGSTART:
  896. m_pv->lighting.fog_start = *(D3DVALUE*)&value;
  897. UpdateFogFactor(this->m_pv);
  898. break;
  899. case D3DRENDERSTATE_FOGEND:
  900. m_pv->lighting.fog_end = *(D3DVALUE*)&value;
  901. UpdateFogFactor(this->m_pv);
  902. break;
  903. case D3DRENDERSTATE_LOCALVIEWER:
  904. if (value)
  905. m_pv->dwDeviceFlags |= D3DDEV_LOCALVIEWER;
  906. else
  907. m_pv->dwDeviceFlags &= ~D3DDEV_LOCALVIEWER;
  908. this->dwFEFlags |= D3DFE_LIGHTS_DIRTY | D3DFE_FRONTEND_DIRTY;
  909. break;
  910. case D3DRENDERSTATE_NORMALIZENORMALS:
  911. if (value)
  912. {
  913. if (m_pv->dwDeviceFlags & D3DDEV_MODELSPACELIGHTING)
  914. {
  915. m_pv->dwDeviceFlags &= ~D3DDEV_MODELSPACELIGHTING;
  916. this->dwFEFlags |= D3DFE_NEED_TRANSFORM_LIGHTS | D3DFE_FRONTEND_DIRTY;
  917. }
  918. m_pv->dwDeviceFlags |= D3DDEV_NORMALIZENORMALS;
  919. }
  920. else
  921. {
  922. m_pv->dwDeviceFlags &= ~D3DDEV_NORMALIZENORMALS;
  923. if (!(m_pv->dwDeviceFlags & D3DDEV_MODELSPACELIGHTING))
  924. this->dwFEFlags |= D3DFE_NEEDCHECKWORLDVIEWVMATRIX | D3DFE_FRONTEND_DIRTY;
  925. }
  926. break;
  927. case D3DRENDERSTATE_EMISSIVEMATERIALSOURCE:
  928. m_pv->lighting.dwEmissiveSrcIndex = 2;
  929. switch (value)
  930. {
  931. case D3DMCS_COLOR1:
  932. m_pv->lighting.dwEmissiveSrcIndex = 0;
  933. break;
  934. case D3DMCS_COLOR2:
  935. m_pv->lighting.dwEmissiveSrcIndex = 1;
  936. break;
  937. #if DBG
  938. case D3DMCS_MATERIAL:
  939. break;
  940. default:
  941. D3D_ERR("Illegal value for DIFFUSEMATERIALSOURCE");
  942. goto error_exit;
  943. #endif
  944. }
  945. break;
  946. case D3DRENDERSTATE_DIFFUSEMATERIALSOURCE:
  947. m_pv->lighting.dwDiffuseSrcIndex = 2;
  948. switch (value)
  949. {
  950. case D3DMCS_COLOR1:
  951. m_pv->lighting.dwDiffuseSrcIndex = 0;
  952. break;
  953. case D3DMCS_COLOR2:
  954. m_pv->lighting.dwDiffuseSrcIndex = 1;
  955. break;
  956. #if DBG
  957. case D3DMCS_MATERIAL:
  958. break;
  959. default:
  960. D3D_ERR("Illegal value for DIFFUSEMATERIALSOURCE");
  961. goto error_exit;
  962. #endif
  963. }
  964. break;
  965. case D3DRENDERSTATE_AMBIENTMATERIALSOURCE:
  966. m_pv->lighting.dwAmbientSrcIndex = 2;
  967. switch (value)
  968. {
  969. case D3DMCS_COLOR1:
  970. m_pv->lighting.dwAmbientSrcIndex = 0;
  971. break;
  972. case D3DMCS_COLOR2:
  973. m_pv->lighting.dwAmbientSrcIndex = 1;
  974. break;
  975. #if DBG
  976. case D3DMCS_MATERIAL:
  977. break;
  978. default:
  979. D3D_ERR("Illegal value for AMBIENTMATERIALSOURCE");
  980. goto error_exit;
  981. #endif
  982. }
  983. break;
  984. case D3DRENDERSTATE_SPECULARMATERIALSOURCE:
  985. m_pv->lighting.dwSpecularSrcIndex = 2;
  986. switch (value)
  987. {
  988. case D3DMCS_COLOR1:
  989. m_pv->lighting.dwSpecularSrcIndex = 0;
  990. break;
  991. case D3DMCS_COLOR2:
  992. m_pv->lighting.dwSpecularSrcIndex = 1;
  993. break;
  994. #if DBG
  995. case D3DMCS_MATERIAL:
  996. break;
  997. default:
  998. D3D_ERR("Illegal value for SPECULARMATERIALSOURCE");
  999. goto error_exit;
  1000. #endif
  1001. }
  1002. break;
  1003. case D3DRENDERSTATE_VERTEXBLEND:
  1004. {
  1005. #if DBG
  1006. switch (value)
  1007. {
  1008. case D3DVBF_DISABLE:
  1009. case D3DVBF_0WEIGHTS:
  1010. case D3DVBF_1WEIGHTS:
  1011. case D3DVBF_2WEIGHTS:
  1012. case D3DVBF_3WEIGHTS:
  1013. case D3DVBF_TWEENING:
  1014. break;
  1015. default:
  1016. D3D_ERR("Illegal value for D3DRENDERSTATE_VERTEXBLEND");
  1017. goto error_exit;
  1018. }
  1019. #endif
  1020. this->dwFEFlags |= D3DFE_VERTEXBLEND_DIRTY | D3DFE_FRONTEND_DIRTY;
  1021. break;
  1022. }
  1023. case D3DRENDERSTATE_CLIPPLANEENABLE:
  1024. {
  1025. this->dwFEFlags |= D3DFE_CLIPPLANES_DIRTY | D3DFE_FRONTEND_DIRTY;
  1026. m_pv->dwMaxUserClipPlanes = 0;
  1027. break;
  1028. }
  1029. case D3DRENDERSTATE_SHADEMODE:
  1030. if (value == D3DSHADE_FLAT)
  1031. m_pv->dwDeviceFlags |= D3DDEV_FLATSHADEMODE;
  1032. else
  1033. m_pv->dwDeviceFlags &= ~D3DDEV_FLATSHADEMODE;
  1034. break;
  1035. case D3DRS_SOFTWAREVERTEXPROCESSING:
  1036. // If DDI cannot do transformation and lighting,
  1037. // D3DRT_RSSOFTWAREPROCESSING is always set to TRUE
  1038. if( BehaviorFlags() & D3DCREATE_MIXED_VERTEXPROCESSING )
  1039. {
  1040. DDASSERT( m_pDDI->CanDoTL() );
  1041. if (value != this->rstates[type])
  1042. SwitchVertexProcessingMode(value);
  1043. }
  1044. break;
  1045. case D3DRS_POINTSCALEENABLE:
  1046. if (value)
  1047. {
  1048. // We need world-view matrix to scale point sprites
  1049. this->dwFEFlags |= D3DFE_WORLDVIEWMATRIX_DIRTY |
  1050. D3DFE_FRONTEND_DIRTY;
  1051. }
  1052. break;
  1053. case D3DRS_POINTSIZE:
  1054. if (*(float*)&value != 1.0f)
  1055. m_dwRuntimeFlags |= D3DRT_POINTSIZEINRS;
  1056. else
  1057. m_dwRuntimeFlags &= ~D3DRT_POINTSIZEINRS;
  1058. break;
  1059. case D3DRS_POINTSIZE_MAX:
  1060. {
  1061. float MaxPointSize = GetD3DCaps()->MaxPointSize;
  1062. if (MaxPointSize == 0)
  1063. MaxPointSize = __MAX_POINT_SIZE;
  1064. if (*(float*)&value <= MaxPointSize)
  1065. m_pv->PointSizeMax = *(float*)&value;
  1066. #if DBG
  1067. else
  1068. {
  1069. D3D_ERR("Max point size is greater than supported by the device");
  1070. goto error_exit;
  1071. }
  1072. #endif
  1073. }
  1074. break;
  1075. case D3DRS_INDEXEDVERTEXBLENDENABLE:
  1076. if (value)
  1077. m_pv->dwDeviceFlags |= D3DDEV_INDEXEDVERTEXBLENDENABLE;
  1078. else
  1079. m_pv->dwDeviceFlags &= ~D3DDEV_INDEXEDVERTEXBLENDENABLE;
  1080. ForceFVFRecompute();
  1081. break;
  1082. case D3DRS_PATCHSEGMENTS:
  1083. {
  1084. const D3DCAPS8* pCaps = GetD3DCaps();
  1085. if (!(pCaps->DevCaps & D3DDEVCAPS_NPATCHES) &&
  1086. (pCaps->DevCaps & D3DDEVCAPS_RTPATCHES))
  1087. {
  1088. if (*(float*)&value > 1.0f)
  1089. m_dwRuntimeFlags |= D3DRT_DONPATCHCONVERSION;
  1090. else
  1091. m_dwRuntimeFlags &= ~D3DRT_DONPATCHCONVERSION;
  1092. rstates[type] = value; // Must set before Pick
  1093. PickDrawPrimFn();
  1094. }
  1095. }
  1096. break;
  1097. default:
  1098. // WRAP render states could be re-mapped so we have to restore them before
  1099. // setting a new value
  1100. if (type >= D3DRENDERSTATE_WRAP0 && type <= D3DRENDERSTATE_WRAP7)
  1101. {
  1102. if (m_pv->dwDeviceFlags & D3DDEV_REMAPTEXTUREINDICES)
  1103. {
  1104. RestoreTextureStages(this);
  1105. ForceFVFRecompute();
  1106. }
  1107. }
  1108. break;
  1109. }
  1110. rstates[type] = value; // set rstates for all other cases
  1111. return;
  1112. #if DBG
  1113. error_exit:
  1114. throw D3DERR_INVALIDCALL;
  1115. #endif
  1116. }
  1117. //---------------------------------------------------------------------
  1118. #if DBG
  1119. static char ProfileStr[PROF_DRAWINDEXEDPRIMITIVEVB+1][32]=
  1120. {
  1121. "Execute",
  1122. "Begin",
  1123. "BeginIndexed",
  1124. "DrawPrimitive(Device2)",
  1125. "DrawIndexedPrimitive(Device2)",
  1126. "DrawPrimitiveStrided",
  1127. "DrawIndexedPrimitiveStrided",
  1128. "DrawPrimitive(Device7)",
  1129. "DrawIndexedPrimitive(Device7)",
  1130. "DrawPrimitiveVB",
  1131. "DrawIndexedPrimitiveVB",
  1132. };
  1133. static char PrimitiveStr[D3DPT_TRIANGLEFAN][16]=
  1134. {
  1135. "POINTLIST",
  1136. "LINELIST",
  1137. "LINESTRIP",
  1138. "TRIANGLELIST",
  1139. "TRIANGLESTRIP",
  1140. "TRIANGLEFAN",
  1141. };
  1142. static char VertexStr[D3DVT_TLVERTEX][16]=
  1143. {
  1144. "D3DVERTEX",
  1145. "D3DLVERTEX",
  1146. "D3DTLVERTEX",
  1147. };
  1148. #define PROFILE_LEVEL 0
  1149. void CD3DHal::Profile(DWORD caller, D3DPRIMITIVETYPE dwPrimitive, DWORD dwVertex)
  1150. {
  1151. DWORD bitwisecaller= 1 << caller;
  1152. DWORD bitwisePrimitive = 1 << (DWORD)dwPrimitive;
  1153. DWORD bitwiseVertex1 = 1 << (dwVertex & 0x001F);
  1154. DWORD bitwiseVertex2 = 1 << ((dwVertex & 0x03E0) >> 5);
  1155. char str[256];
  1156. DDASSERT(PROF_DRAWINDEXEDPRIMITIVEVB >= caller);
  1157. DDASSERT(D3DPT_TRIANGLEFAN >= dwPrimitive && D3DPT_POINTLIST<= dwPrimitive);
  1158. if (dwCaller & bitwisecaller)
  1159. {
  1160. if (dwPrimitiveType[caller] & bitwisePrimitive)
  1161. {
  1162. if ((dwVertexType1[caller] & bitwiseVertex1) &&
  1163. (dwVertexType2[caller] & bitwiseVertex2))
  1164. {
  1165. return; //matching a previous api call, no spew, could count stat though
  1166. }
  1167. else
  1168. {
  1169. dwVertexType1[caller] |= bitwiseVertex1;
  1170. dwVertexType2[caller] |= bitwiseVertex2;
  1171. }
  1172. }
  1173. else
  1174. {
  1175. dwPrimitiveType[caller] |= bitwisePrimitive;
  1176. dwVertexType1[caller] |= bitwiseVertex1;
  1177. dwVertexType2[caller] |= bitwiseVertex2;
  1178. }
  1179. }
  1180. else
  1181. {
  1182. this->dwCaller |= bitwisecaller;
  1183. dwPrimitiveType[caller] |= bitwisePrimitive;
  1184. dwVertexType1[caller] |= bitwiseVertex1;
  1185. dwVertexType2[caller] |= bitwiseVertex2;
  1186. }
  1187. wsprintf( (LPSTR) str, ProfileStr[caller]);
  1188. strcat(str,":");
  1189. strcat(str,PrimitiveStr[dwPrimitive-1]);
  1190. if (dwVertex > D3DVT_TLVERTEX)
  1191. {
  1192. if (dwVertex == D3DFVF_VERTEX)
  1193. {
  1194. dwVertex = D3DVT_VERTEX;
  1195. }
  1196. else
  1197. if (dwVertex == D3DFVF_TLVERTEX)
  1198. {
  1199. dwVertex = D3DVT_TLVERTEX;
  1200. }
  1201. else
  1202. {
  1203. D3D_INFO(PROFILE_LEVEL,"Profile:%s FVFType=%08lx",str,dwVertex);
  1204. return;
  1205. }
  1206. }
  1207. else
  1208. {
  1209. DDASSERT(dwVertex >= D3DVT_VERTEX);
  1210. }
  1211. strcat(str,":");
  1212. strcat(str,VertexStr[dwVertex-1]);
  1213. D3D_INFO(PROFILE_LEVEL,"Profile:%s",str);
  1214. }
  1215. #endif // DBG
  1216. //---------------------------------------------------------------------
  1217. #undef DPF_MODNAME
  1218. #define DPF_MODNAME "CD3DHal::MultiplyTransformI"
  1219. // MultiplyTransform -- this preconcatenates the new matrix to the specified
  1220. // transform matrix
  1221. //
  1222. // this really screams for overloaded matrix ops...
  1223. //
  1224. void
  1225. CD3DHal::MultiplyTransformI(D3DTRANSFORMSTATETYPE state, CONST D3DMATRIX* lpMat)
  1226. {
  1227. D3DMATRIXI mResult;
  1228. if ((DWORD)state >= __WORLDMATRIXBASE &&
  1229. (DWORD)state < (__WORLDMATRIXBASE + __MAXWORLDMATRICES))
  1230. {
  1231. // World matrix is set
  1232. UINT index = (DWORD)state - __WORLDMATRIXBASE;
  1233. MatrixProduct(&mResult, (D3DMATRIXI*)lpMat, &m_pv->world[index]);
  1234. m_pv->world[index] = mResult;
  1235. if (index == 0)
  1236. this->dwFEFlags |= D3DFE_WORLDMATRIX_DIRTY | D3DFE_FRONTEND_DIRTY;
  1237. }
  1238. else
  1239. switch (state)
  1240. {
  1241. case D3DTS_VIEW :
  1242. MatrixProduct(&mResult, (D3DMATRIXI*)lpMat, &m_pv->view);
  1243. m_pv->view = mResult;
  1244. this->dwFEFlags |= D3DFE_VIEWMATRIX_DIRTY | D3DFE_FRONTEND_DIRTY;
  1245. break;
  1246. case D3DTS_PROJECTION :
  1247. MatrixProduct(&mResult, (D3DMATRIXI*)lpMat, &this->transform.proj);
  1248. this->transform.proj = mResult;
  1249. this->dwFEFlags |= D3DFE_PROJMATRIX_DIRTY | D3DFE_FRONTEND_DIRTY;
  1250. break;
  1251. case D3DTS_TEXTURE0:
  1252. case D3DTS_TEXTURE1:
  1253. case D3DTS_TEXTURE2:
  1254. case D3DTS_TEXTURE3:
  1255. case D3DTS_TEXTURE4:
  1256. case D3DTS_TEXTURE5:
  1257. case D3DTS_TEXTURE6:
  1258. case D3DTS_TEXTURE7:
  1259. {
  1260. DWORD dwIndex = state - D3DTS_TEXTURE0;
  1261. MatrixProduct(&mResult, (D3DMATRIXI*)lpMat, &m_pv->mTexture[dwIndex]);
  1262. m_pv->mTexture[dwIndex] = mResult;
  1263. break;
  1264. }
  1265. default :
  1266. D3D_THROW_FAIL("Invalid state value passed to MultiplyTransform");
  1267. }
  1268. m_pv->MatrixStateCount++;
  1269. if (m_dwRuntimeFlags & D3DRT_RSSOFTWAREPROCESSING)
  1270. this->pMatrixDirtyForDDI->SetBit(state);
  1271. else
  1272. m_pDDI->SetTransform(state, (LPD3DMATRIX)&mResult);
  1273. // W range should always be updated
  1274. if (state == D3DTS_PROJECTION)
  1275. m_pDDI->UpdateWInfo((LPD3DMATRIX)&mResult);
  1276. }
  1277. //---------------------------------------------------------------------
  1278. #undef DPF_MODNAME
  1279. #define DPF_MODNAME "CD3DBase::BeginStateBlock"
  1280. HRESULT D3DAPI CD3DBase::BeginStateBlock()
  1281. {
  1282. API_ENTER(this); // Takes D3D Lock if necessary
  1283. try
  1284. {
  1285. if (this->m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE)
  1286. {
  1287. D3D_ERR("Already in the state record mode. BeginStateBlock failed.");
  1288. return D3DERR_INVALIDCALL;
  1289. }
  1290. if (m_pStateSets->StartNewSet() != D3D_OK)
  1291. {
  1292. D3D_ERR("Could not allocate memory for new state block. BeginStateBlock failed.");
  1293. return E_OUTOFMEMORY;
  1294. }
  1295. this->m_dwRuntimeFlags |= D3DRT_RECORDSTATEMODE;
  1296. #ifdef FAST_PATH
  1297. FastPathSetRenderStateRecord();
  1298. FastPathSetTextureStageStateRecord();
  1299. FastPathApplyStateBlockRecord();
  1300. FastPathSetTextureRecord();
  1301. FastPathSetVertexShaderSlow();
  1302. FastPathSetStreamSourceSlow();
  1303. FastPathSetIndicesSlow();
  1304. FastPathSetMaterialRecord();
  1305. FastPathMultiplyTransformRecord();
  1306. FastPathSetTransformRecord();
  1307. FastPathSetPixelShaderRecord();
  1308. FastPathSetPixelShaderConstantRecord();
  1309. FastPathSetVertexShaderConstantRecord();
  1310. #endif // FAST_PATH
  1311. return D3D_OK;
  1312. }
  1313. catch (HRESULT ret)
  1314. {
  1315. D3D_ERR("BeginStateBlock failed.");
  1316. return ret;
  1317. }
  1318. }
  1319. //---------------------------------------------------------------------
  1320. #undef DPF_MODNAME
  1321. #define DPF_MODNAME "CD3DBase::EndStateBlock"
  1322. HRESULT D3DAPI CD3DBase::EndStateBlock(LPDWORD pdwHandle)
  1323. {
  1324. API_ENTER(this); // Takes D3D Lock if necessary
  1325. if (!VALID_WRITEPTR(pdwHandle, sizeof(DWORD)))
  1326. {
  1327. D3D_ERR( "Invalid DWORD pointer. EndStateBlock failed." );
  1328. return D3DERR_INVALIDCALL;
  1329. }
  1330. try
  1331. {
  1332. if (!(this->m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE))
  1333. {
  1334. D3D_ERR("Not in state record mode. EndStateBlock failed.");
  1335. return D3DERR_INVALIDCALL;
  1336. }
  1337. this->m_dwRuntimeFlags &= ~D3DRT_RECORDSTATEMODE;
  1338. m_pStateSets->EndSet();
  1339. #ifdef FAST_PATH
  1340. FastPathSetRenderStateExecute();
  1341. FastPathSetTextureStageStateExecute();
  1342. FastPathSetMaterialExecute();
  1343. FastPathSetVertexShaderFast();
  1344. FastPathSetStreamSourceFast();
  1345. FastPathSetIndicesFast();
  1346. FastPathApplyStateBlockExecute();
  1347. FastPathSetTextureExecute();
  1348. FastPathSetTransformExecute();
  1349. FastPathMultiplyTransformExecute();
  1350. FastPathSetPixelShaderExecute();
  1351. FastPathSetPixelShaderConstantExecute();
  1352. FastPathSetVertexShaderConstantExecute();
  1353. #endif // FAST_PATH
  1354. this->m_pDDI->WriteStateSetToDevice((D3DSTATEBLOCKTYPE)0);
  1355. *pdwHandle = m_pStateSets->GetCurrentHandle();
  1356. return D3D_OK;
  1357. }
  1358. catch(HRESULT ret)
  1359. {
  1360. D3D_ERR("EndStateBlock failed.");
  1361. m_pStateSets->Cleanup(m_pStateSets->GetCurrentHandle());
  1362. *pdwHandle = 0xFFFFFFFF;
  1363. return ret;
  1364. }
  1365. }
  1366. //---------------------------------------------------------------------
  1367. #undef DPF_MODNAME
  1368. #define DPF_MODNAME "CD3DBase::DeleteStateBlock"
  1369. HRESULT D3DAPI CD3DBase::DeleteStateBlock(DWORD dwHandle)
  1370. {
  1371. API_ENTER(this); // Takes D3D Lock if necessary
  1372. try
  1373. {
  1374. if (this->m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE)
  1375. {
  1376. D3D_ERR("We are in state record mode. DeleteStateBlock failed.");
  1377. return D3DERR_INVALIDCALL;
  1378. }
  1379. m_pStateSets->DeleteStateSet(this, dwHandle);
  1380. return D3D_OK;
  1381. }
  1382. catch(HRESULT ret)
  1383. {
  1384. D3D_ERR("DeleteStateBlock failed.");
  1385. return ret;
  1386. }
  1387. }
  1388. //---------------------------------------------------------------------
  1389. #undef DPF_MODNAME
  1390. #define DPF_MODNAME "CD3DBase::ApplyStateBlock"
  1391. HRESULT D3DAPI CD3DBase::ApplyStateBlock(DWORD dwHandle)
  1392. {
  1393. API_ENTER(this); // Takes D3D Lock if necessary
  1394. try
  1395. {
  1396. if (this->m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE)
  1397. {
  1398. D3D_ERR("We are in state record mode. ApplyStateBlock failed.");
  1399. return D3DERR_INVALIDCALL;
  1400. }
  1401. return ApplyStateBlockFast(dwHandle);
  1402. }
  1403. catch(HRESULT ret)
  1404. {
  1405. D3D_ERR("ApplyStateBlock failed.");
  1406. return ret;
  1407. }
  1408. }
  1409. //---------------------------------------------------------------------
  1410. #undef DPF_MODNAME
  1411. #define DPF_MODNAME "CD3DBase::ApplyStateBlockFast"
  1412. HRESULT D3DAPI CD3DBase::ApplyStateBlockFast(DWORD dwHandle)
  1413. {
  1414. // NOTE: This can become a public API through the
  1415. // v-table hack. This should only happen for
  1416. // single-threaded apps; so we don't need
  1417. // to take the critical section.
  1418. // API_ENTER(this); // Takes D3D Lock if necessary
  1419. try
  1420. {
  1421. m_pStateSets->Execute(this, dwHandle);
  1422. return D3D_OK;
  1423. }
  1424. catch(HRESULT ret)
  1425. {
  1426. D3D_ERR("ApplyStateBlock failed.");
  1427. return ret;
  1428. }
  1429. }
  1430. //---------------------------------------------------------------------
  1431. #undef DPF_MODNAME
  1432. #define DPF_MODNAME "CD3DBase::CaptureStateBlock"
  1433. HRESULT D3DAPI CD3DBase::CaptureStateBlock(DWORD dwHandle)
  1434. {
  1435. API_ENTER(this); // Takes D3D Lock if necessary
  1436. try
  1437. {
  1438. if (this->m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE)
  1439. {
  1440. D3D_ERR("Cannot capture when in the state record mode. CaptureStateBlock failed.");
  1441. return D3DERR_INVALIDCALL;
  1442. }
  1443. m_pStateSets->Capture(this, dwHandle);
  1444. return D3D_OK;
  1445. }
  1446. catch (HRESULT ret)
  1447. {
  1448. D3D_ERR("CaptureStateBlock failed.");
  1449. return ret;
  1450. }
  1451. }
  1452. //---------------------------------------------------------------------
  1453. // Input:
  1454. // type - FVF control dword
  1455. //
  1456. // Returns D3D_OK, if the control dword is valid.
  1457. // D3DERR_INVALIDCALL otherwise
  1458. //
  1459. #undef DPF_MODNAME
  1460. #define DPF_MODNAME "CD3DBase::ValidateFVF"
  1461. HRESULT __declspec(nothrow) CD3DBase::ValidateFVF(DWORD type)
  1462. {
  1463. DWORD dwTexCoord = FVF_TEXCOORD_NUMBER(type);
  1464. DWORD vertexType = type & D3DFVF_POSITION_MASK;
  1465. // Texture format bits above texture count should be zero
  1466. // Reserved field 0 and 2 should be 0
  1467. // Reserved 1 should be set only for LVERTEX
  1468. // Only two vertex position types allowed
  1469. if (type & g_TextureFormatMask[dwTexCoord])
  1470. {
  1471. D3D_ERR("FVF Validation error: FVF has incorrect texture format");
  1472. goto error;
  1473. }
  1474. if (type & 0xFFFF0000 && vertexType == D3DFVF_XYZRHW &&
  1475. m_dwRuntimeFlags & D3DRT_ONLY2FLOATSPERTEXTURE)
  1476. {
  1477. D3D_ERR("FVF Validation error: The D3D device supports only two floats per texture coordinate set");
  1478. goto error;
  1479. }
  1480. if (type & D3DFVF_RESERVED0)
  1481. {
  1482. D3D_ERR("FVF has reserved bit(s) set");
  1483. goto error;
  1484. }
  1485. if (!(vertexType == D3DFVF_XYZRHW ||
  1486. vertexType == D3DFVF_XYZ ||
  1487. vertexType == D3DFVF_XYZB1 ||
  1488. vertexType == D3DFVF_XYZB2 ||
  1489. vertexType == D3DFVF_XYZB3 ||
  1490. vertexType == D3DFVF_XYZB4 ||
  1491. vertexType == D3DFVF_XYZB5))
  1492. {
  1493. D3D_ERR("FVF Validation error: FVF has incorrect position type");
  1494. goto error;
  1495. }
  1496. if (vertexType == D3DFVF_XYZRHW && type & D3DFVF_NORMAL)
  1497. {
  1498. D3D_ERR("FVF Validation error: Normal should not be used with XYZRHW position type");
  1499. goto error;
  1500. }
  1501. return D3D_OK;
  1502. error:
  1503. return D3DERR_INVALIDCALL;
  1504. }
  1505. //---------------------------------------------------------------------
  1506. // Returns TRUE, if driver state should not be updated
  1507. //
  1508. #undef DPF_MODNAME
  1509. #define DPF_MODNAME "CD3DHal::UpdateInternalTextureStageState"
  1510. BOOL CD3DHal::UpdateInternalTextureStageState
  1511. (DWORD dwStage, D3DTEXTURESTAGESTATETYPE dwState, DWORD* pValue)
  1512. {
  1513. DWORD dwValue = *pValue;
  1514. BOOL ret = FALSE; // return TRUE if TSS should NOT be batched
  1515. if(dwState == D3DTSS_COLOROP)
  1516. {
  1517. if(dwValue == D3DTOP_DISABLE || tsstates[dwStage][D3DTSS_COLOROP] == D3DTOP_DISABLE)
  1518. ForceFVFRecompute();
  1519. }
  1520. else
  1521. if (dwState == D3DTSS_TEXCOORDINDEX)
  1522. {
  1523. if (TextureTransformEnabled(this))
  1524. {
  1525. ForceFVFRecompute();
  1526. }
  1527. DWORD dwTexGenMode = 0;
  1528. if (dwValue >= D3DDP_MAXTEXCOORD)
  1529. {
  1530. dwTexGenMode = dwValue & ~0xFFFF;
  1531. if(!m_pDDI->CanDoTL())
  1532. ret = TRUE;
  1533. #if DBG
  1534. DWORD dwTexIndex = dwValue & 0xFFFF;
  1535. if (!(dwTexGenMode == D3DTSS_TCI_CAMERASPACENORMAL ||
  1536. dwTexGenMode == D3DTSS_TCI_CAMERASPACEPOSITION ||
  1537. dwTexGenMode == D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR) ||
  1538. dwTexIndex > D3DDP_MAXTEXCOORD)
  1539. {
  1540. D3D_ERR("Incorrect texture coordinate set index");
  1541. throw D3DERR_INVALIDCALL;
  1542. }
  1543. #endif
  1544. }
  1545. // Now we need to update internal flag (dwFlags2) which says whether
  1546. // texture generation for the stage is enabled
  1547. DWORD dwTexGenBit = __FLAGS2_TEXGEN0 << dwStage;
  1548. if (dwTexGenMode == D3DTSS_TCI_CAMERASPACENORMAL ||
  1549. dwTexGenMode == D3DTSS_TCI_CAMERASPACEPOSITION ||
  1550. dwTexGenMode == D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR)
  1551. {
  1552. // We need to update internal flags when tex gen mode is changed,
  1553. // so always call ForceFVFRecompute
  1554. ForceFVFRecompute();
  1555. m_pv->dwFlags2 |= dwTexGenBit;
  1556. }
  1557. else
  1558. {
  1559. // As optimization, recompute FVF only if texture generation for
  1560. // the stage was enabled
  1561. if (m_pv->dwFlags2 & dwTexGenBit)
  1562. {
  1563. ForceFVFRecompute();
  1564. m_pv->dwFlags2 &= ~dwTexGenBit;
  1565. }
  1566. }
  1567. }
  1568. else
  1569. if (dwState == D3DTSS_TEXTURETRANSFORMFLAGS)
  1570. {
  1571. DWORD dwEnableBit = 1 << dwStage; // To check internal "enable" dword
  1572. // Force to re-compute FVF only if enable state is changed
  1573. if ((dwValue & ~D3DTTFF_PROJECTED) == D3DTTFF_DISABLE)
  1574. {
  1575. if (m_pv->dwFlags2 & dwEnableBit)
  1576. {
  1577. ForceFVFRecompute();
  1578. m_pv->dwFlags2 &= ~dwEnableBit;
  1579. }
  1580. }
  1581. else
  1582. {
  1583. if (!(m_pv->dwFlags2 & dwEnableBit))
  1584. {
  1585. ForceFVFRecompute();
  1586. m_pv->dwFlags2 |= dwEnableBit;
  1587. }
  1588. }
  1589. // Do not pass texture transform flags to DX6 devices
  1590. if(GetDDIType() == D3DDDITYPE_DX6)
  1591. ret = TRUE;
  1592. // When we need to emulate projected textures we do not pass "projected"
  1593. // bit to the device. We also decrease the float count.
  1594. if (m_dwRuntimeFlags & D3DRT_EMULATEPROJECTEDTEXTURE)
  1595. {
  1596. // Compute projected bit
  1597. DWORD dwEnableBit = __FLAGS2_TEXPROJ0 << dwStage;
  1598. if (dwValue & D3DTTFF_PROJECTED)
  1599. {
  1600. // Remove projected bit. Note that tsstates will keep the
  1601. // original value
  1602. *pValue &= ~D3DTTFF_PROJECTED;
  1603. // Reduce float count
  1604. if (*pValue != D3DTTFF_DISABLE)
  1605. (*pValue)--;
  1606. if (!(m_pv->dwFlags2 & dwEnableBit))
  1607. {
  1608. ForceFVFRecompute();
  1609. m_pv->dwFlags2 |= dwEnableBit;
  1610. }
  1611. }
  1612. else
  1613. {
  1614. // Just clear projection enabled bit and recompute FVF
  1615. if (m_pv->dwFlags2 & dwEnableBit)
  1616. {
  1617. ForceFVFRecompute();
  1618. m_pv->dwFlags2 &= ~dwEnableBit;
  1619. }
  1620. }
  1621. }
  1622. }
  1623. else
  1624. if(dwState > D3DTSS_TEXTURETRANSFORMFLAGS)
  1625. {
  1626. if(GetDDIType() == D3DDDITYPE_DX6)
  1627. ret = TRUE;
  1628. }
  1629. // Update runtime copy of state.
  1630. tsstates[dwStage][dwState] = dwValue;
  1631. return ret;
  1632. }
  1633. //---------------------------------------------------------------------
  1634. #undef DPF_MODNAME
  1635. #define DPF_MODNAME "CD3DHal::SetClipPlaneI"
  1636. void CD3DHal::SetClipPlaneI(DWORD dwPlaneIndex, CONST D3DVALUE* pPlaneEquation)
  1637. {
  1638. D3DVALUE *p = &this->transform.userClipPlane[dwPlaneIndex].x;
  1639. p[0] = pPlaneEquation[0];
  1640. p[1] = pPlaneEquation[1];
  1641. p[2] = pPlaneEquation[2];
  1642. p[3] = pPlaneEquation[3];
  1643. this->dwFEFlags |= D3DFE_CLIPPLANES_DIRTY | D3DFE_FRONTEND_DIRTY;
  1644. if (!(m_dwRuntimeFlags & (D3DRT_EXECUTESTATEMODE |
  1645. D3DRT_RSSOFTWAREPROCESSING)))
  1646. {
  1647. m_pDDI->SetClipPlane(dwPlaneIndex,
  1648. pPlaneEquation);
  1649. }
  1650. }
  1651. //---------------------------------------------------------------------
  1652. #undef DPF_MODNAME
  1653. #define DPF_MODNAME "CD3DHal::GetClipPlane"
  1654. HRESULT D3DAPI
  1655. CD3DHal::GetClipPlane(DWORD dwPlaneIndex, D3DVALUE* pPlaneEquation)
  1656. {
  1657. API_ENTER(this); // Takes D3D Lock if necessary
  1658. #if DBG
  1659. if (dwPlaneIndex >= __MAXUSERCLIPPLANES)
  1660. {
  1661. D3D_ERR("Plane index is too big. GetClipPlane failed.");
  1662. return D3DERR_INVALIDCALL;
  1663. }
  1664. if (!VALID_WRITEPTR(pPlaneEquation, sizeof(D3DVALUE)*4))
  1665. {
  1666. D3D_ERR( "Invalid plane pointer. GetClipPlane failed." );
  1667. return D3DERR_INVALIDCALL;
  1668. }
  1669. #endif
  1670. try
  1671. {
  1672. D3DVALUE *p = &this->transform.userClipPlane[dwPlaneIndex].x;
  1673. pPlaneEquation[0] = p[0];
  1674. pPlaneEquation[1] = p[1];
  1675. pPlaneEquation[2] = p[2];
  1676. pPlaneEquation[3] = p[3];
  1677. }
  1678. catch(HRESULT ret)
  1679. {
  1680. D3D_ERR("GetClipPlane failed.");
  1681. return ret;
  1682. }
  1683. return D3D_OK;
  1684. }
  1685. //---------------------------------------------------------------------
  1686. #undef DPF_MODNAME
  1687. #define DPF_MODNAME "CD3DBase::CreateStateBlock"
  1688. HRESULT D3DAPI
  1689. CD3DBase::CreateStateBlock(D3DSTATEBLOCKTYPE sbt,
  1690. LPDWORD pdwHandle)
  1691. {
  1692. API_ENTER(this); // Takes D3D Lock if necessary
  1693. if (!VALID_WRITEPTR(pdwHandle, sizeof(DWORD)))
  1694. {
  1695. D3D_ERR( "Invalid DWORD pointer. CreateStateBlock failed." );
  1696. return D3DERR_INVALIDCALL;
  1697. }
  1698. try
  1699. {
  1700. if (this->m_dwRuntimeFlags & D3DRT_RECORDSTATEMODE)
  1701. {
  1702. D3D_ERR("Cannot create state block when in the state record mode. CreateStateBlock failed.");
  1703. return D3DERR_INVALIDCALL;
  1704. }
  1705. m_pStateSets->CreatePredefined(this, sbt);
  1706. *pdwHandle = m_pStateSets->GetCurrentHandle();
  1707. }
  1708. catch (HRESULT ret)
  1709. {
  1710. D3D_ERR("CreateStateBlock failed.");
  1711. m_pStateSets->Cleanup(m_pStateSets->GetCurrentHandle());
  1712. *pdwHandle = 0xFFFFFFFF;
  1713. return ret;
  1714. }
  1715. return D3D_OK;
  1716. }
  1717. //---------------------------------------------------------------------
  1718. // Restore indices in the texture stages which were re-mapped for texture
  1719. // transforms
  1720. // We have to do restore if
  1721. // - Set or Get render state is issued with _WRAP parameter
  1722. // - Set or Get texture stage is issued with TEXCOORDINDEX as a parameter
  1723. //
  1724. void RestoreTextureStages(LPD3DHAL pDevI)
  1725. {
  1726. D3DFE_PROCESSVERTICES* pv = pDevI->m_pv;
  1727. // dwVIDIn is used to force re-compute FVF in the
  1728. // SetTextureStageState. so we save and restore it.
  1729. DWORD dwVIDInSaved = pv->dwVIDIn;
  1730. pv->dwDeviceFlags &= ~D3DDEV_REMAPTEXTUREINDICES;
  1731. for (DWORD i=0; i < pDevI->dwNumTextureStagesToRemap; i++)
  1732. {
  1733. LPD3DFE_TEXTURESTAGE pStage = &pDevI->textureStageToRemap[i];
  1734. // Texture generation mode was stripped out of pStage->dwInpCoordIndex
  1735. DWORD dwInpIndex = pStage->dwInpCoordIndex + pStage->dwTexGenMode;
  1736. if (dwInpIndex != pStage->dwOutCoordIndex)
  1737. {
  1738. // We do not call UpdateInternalTextureStageState because it
  1739. // will call ForceRecomputeFVF and we do not want this.
  1740. pDevI->tsstates[pStage->dwOrgStage][D3DTSS_TEXCOORDINDEX] = dwInpIndex;
  1741. // Filter texgen modes for non-TL drivers
  1742. if (pDevI->m_pDDI->CanDoTL() || dwInpIndex < D3DDP_MAXTEXCOORD)
  1743. {
  1744. pDevI->m_pDDI->SetTSS(pStage->dwOrgStage, D3DTSS_TEXCOORDINDEX, dwInpIndex);
  1745. }
  1746. }
  1747. DWORD dwState = D3DRENDERSTATE_WRAP0 + pStage->dwOutCoordIndex;
  1748. if (pStage->dwOrgWrapMode != pDevI->rstates[dwState])
  1749. {
  1750. // We do not call UpdateInternaState because it
  1751. // will call ForceRecomputeFVF and we do not want this.
  1752. pDevI->rstates[dwState] = pStage->dwOrgWrapMode;
  1753. pDevI->m_pDDI->SetRenderState((D3DRENDERSTATETYPE)dwState,
  1754. pStage->dwOrgWrapMode);
  1755. }
  1756. }
  1757. pv->dwVIDIn = dwVIDInSaved;
  1758. }