Source code of Windows XP (NT5)
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.

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