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.

1021 lines
34 KiB

  1. #include "pch.cpp"
  2. #pragma hdrstop
  3. const D3DVALUE __HUGE_PWR2 = 1024.0f*1024.0f*2.0f;
  4. //---------------------------------------------------------------------
  5. // This function should be called every time FVF ID is changed
  6. // All pv flags, input and output FVF id should be set before calling the
  7. // function.
  8. //---------------------------------------------------------------------
  9. void UpdateComponentOffsets (DWORD dwFVFIn,
  10. LPDWORD pNormalOffset,
  11. LPDWORD pDiffOffset,
  12. LPDWORD pSpecOffset,
  13. LPDWORD pTexOffset)
  14. {
  15. DWORD dwOffset = 0;
  16. switch( dwFVFIn & D3DFVF_POSITION_MASK )
  17. {
  18. case D3DFVF_XYZ:
  19. dwOffset = sizeof(D3DVECTOR);
  20. break;
  21. case D3DFVF_XYZB1:
  22. dwOffset = sizeof(D3DVECTOR) + sizeof(D3DVALUE);
  23. break;
  24. case D3DFVF_XYZB2:
  25. dwOffset = sizeof(D3DVECTOR) + 2*sizeof(D3DVALUE);
  26. break;
  27. case D3DFVF_XYZB3:
  28. dwOffset = sizeof(D3DVECTOR) + 3*sizeof(D3DVALUE);
  29. break;
  30. case D3DFVF_XYZB4:
  31. dwOffset = sizeof(D3DVECTOR) + 4*sizeof(D3DVALUE);
  32. break;
  33. case D3DFVF_XYZB5:
  34. dwOffset = sizeof(D3DVECTOR) + 5*sizeof(D3DVALUE);
  35. break;
  36. default:
  37. DPFM(0,TNL,("Unable to compute offsets, strange FVF bits set"));
  38. }
  39. *pNormalOffset = dwOffset;
  40. if (dwFVFIn & D3DFVF_NORMAL)
  41. dwOffset += sizeof(D3DVECTOR);
  42. if (dwFVFIn & D3DFVF_RESERVED1)
  43. dwOffset += sizeof(D3DVALUE);
  44. // Offset to the diffuse color
  45. *pDiffOffset = dwOffset;
  46. if (dwFVFIn & D3DFVF_DIFFUSE)
  47. dwOffset += sizeof(DWORD);
  48. // Offset to the specular color
  49. *pSpecOffset = dwOffset;
  50. if (dwFVFIn & D3DFVF_SPECULAR)
  51. dwOffset += sizeof(DWORD);
  52. // Offset to the texture data
  53. *pTexOffset = dwOffset;
  54. }
  55. //---------------------------------------------------------------------
  56. // SetupFVFData:
  57. // Compute Output FVF and the size of output vertices
  58. //---------------------------------------------------------------------
  59. void
  60. RRProcessVertices::SetupFVFData(BOOL bFogEnabled, BOOL bSpecularEnabled)
  61. {
  62. // Compute number of texture coordinates
  63. m_dwNumTexCoords = FVF_TEXCOORD_NUMBER(m_dwFVFIn);
  64. // Compute output FVF
  65. m_qwFVFOut = D3DFVF_XYZRHW;
  66. // If normal is present we have to compute specular and diffuse
  67. // Otherwise set these bits the same as input.
  68. // Not that normal should not be present for XYZRHW position type
  69. if (m_dwTLState & RRPV_DOLIGHTING)
  70. {
  71. m_qwFVFOut |= D3DFVF_DIFFUSE | D3DFVF_SPECULAR;
  72. }
  73. else
  74. {
  75. m_qwFVFOut |= (m_dwFVFIn & (D3DFVF_DIFFUSE | D3DFVF_SPECULAR));
  76. }
  77. // Always set specular flag if fog is enabled
  78. // if (this->rstates[D3DRENDERSTATE_FOGENABLE])
  79. if (bFogEnabled)
  80. {
  81. m_qwFVFOut |= D3DFVF_SPECULAR;
  82. }
  83. // Clear specular flag if specular disabled
  84. // else if (!this->rstates[D3DRENDERSTATE_SPECULARENABLE])
  85. else if (!bSpecularEnabled && !(m_dwFVFIn & D3DFVF_SPECULAR))
  86. {
  87. m_qwFVFOut &= ~D3DFVF_SPECULAR;
  88. }
  89. #ifdef __POINTSPRITES
  90. // Reserve space for point size, if needed
  91. if (m_dwTLState & RRPV_DOCOMPUTEPOINTSIZE)
  92. {
  93. m_qwFVFOut |= D3DFVF_S;
  94. }
  95. #endif
  96. // Reserve space for eye space info, if needed
  97. if (m_dwTLState & RRPV_DOPASSEYENORMAL)
  98. {
  99. m_qwFVFOut |= D3DFVFP_EYENORMAL;
  100. }
  101. if (m_dwTLState & RRPV_DOPASSEYEXYZ)
  102. {
  103. m_qwFVFOut |= D3DFVFP_EYEXYZ;
  104. }
  105. // Set up number of texture coordinates and copy texture formats
  106. m_qwFVFOut |= (m_dwNumTexCoords << D3DFVF_TEXCOUNT_SHIFT) |
  107. (m_dwFVFIn & 0xFFFF0000);
  108. // Compute size of texture coordinates
  109. // This size is the same for input and output FVFs,
  110. // because for DX7 drivers they have number of texture and texture formats
  111. m_dwTextureCoordSizeTotal = 0;
  112. ComputeTextureCoordSize(m_dwFVFIn, m_dwTexCoordSize,
  113. &m_dwTextureCoordSizeTotal);
  114. // Compute output size
  115. m_dwOutputVtxSize = GetFVFVertexSize( m_qwFVFOut );
  116. m_position.dwStride = GetFVFVertexSize( m_dwFVFIn );
  117. // Now compute the input FVF dependent offsets used by the Geometry loop
  118. UpdateComponentOffsets (m_dwFVFIn, &m_dwNormalOffset,
  119. &m_dwDiffuseOffset, &m_dwSpecularOffset,
  120. &m_dwTexOffset);
  121. return;
  122. }
  123. ///////////////////////////////////////////////////////////////////////////////
  124. // SavePrimitiveData
  125. ///////////////////////////////////////////////////////////////////////////////
  126. void
  127. ReferenceRasterizer::SavePrimitiveData(
  128. DWORD dwFVFIn,
  129. LPVOID pVtx,
  130. UINT cVertices,
  131. D3DPRIMITIVETYPE PrimType
  132. )
  133. {
  134. //
  135. // 1) Save the incoming information
  136. //
  137. m_primType = PrimType;
  138. m_position.lpvData = pVtx;
  139. // Force some state changes if the FVF is different
  140. if( dwFVFIn != m_dwFVFIn )
  141. {
  142. m_dwDirtyFlags |= RRPV_DIRTY_COLORVTX;
  143. }
  144. m_dwFVFIn = dwFVFIn;
  145. m_dwNumVertices = cVertices;
  146. // No indices to work with
  147. m_dwNumIndices = 0;
  148. m_pIndices = NULL;
  149. }
  150. void
  151. ReferenceRasterizer::SavePrimitiveData(
  152. DWORD dwFVFIn,
  153. LPVOID pVtx,
  154. UINT cVertices,
  155. D3DPRIMITIVETYPE PrimType,
  156. LPWORD pIndices,
  157. UINT cIndices
  158. )
  159. {
  160. //
  161. // 1) Save the incoming information
  162. //
  163. m_primType = PrimType;
  164. m_position.lpvData = pVtx;
  165. // Force some state changes if the FVF is different
  166. if( dwFVFIn != m_dwFVFIn )
  167. {
  168. m_dwDirtyFlags |= RRPV_DIRTY_COLORVTX;
  169. }
  170. m_dwFVFIn = dwFVFIn;
  171. m_dwNumVertices = cVertices;
  172. m_dwNumIndices = cIndices;
  173. m_pIndices = pIndices;
  174. }
  175. ///////////////////////////////////////////////////////////////////////////////
  176. // Process primitives implementation:
  177. // 1) Compute FVF info
  178. // 2) Grow buffers to the requisite size
  179. // 3) Initialize clipping state
  180. // 4) Update T&L state
  181. // 5) Transform, Light and compute clipping for vertices
  182. // 6) Clip and Draw the primitives
  183. //
  184. ///////////////////////////////////////////////////////////////////////////////
  185. HRESULT
  186. ReferenceRasterizer::ProcessPrimitive(
  187. BOOL bIndexedPrim
  188. )
  189. {
  190. HRESULT ret = D3D_OK;
  191. DWORD dwVertexPoolSize = 0;
  192. //
  193. // Update T&L state (must be before FVFData is set up)
  194. //
  195. // Update Lighting and related state and flags
  196. if ((ret = UpdateTLState()) != D3D_OK)
  197. return ret;
  198. //
  199. // Compute Output FVF and the size of output vertices
  200. //
  201. SetupFVFData(GetRenderState()[D3DRENDERSTATE_FOGENABLE],
  202. GetRenderState()[D3DRENDERSTATE_SPECULARENABLE]);
  203. //
  204. // Clipping information depends both on the output FVF computation
  205. // and the other State, so do it here after both have been computed
  206. //
  207. if (m_dwTLState & RRPV_DOCLIPPING)
  208. {
  209. // Figure out which pieces need to be interpolated in new vertices.
  210. m_clipping.dwInterpolate = 0;
  211. if (GetRenderState()[D3DRENDERSTATE_SHADEMODE] == D3DSHADE_GOURAUD)
  212. {
  213. m_clipping.dwInterpolate |= RRCLIP_INTERPOLATE_COLOR;
  214. if (m_qwFVFOut & D3DFVF_SPECULAR)
  215. {
  216. m_clipping.dwInterpolate |= RRCLIP_INTERPOLATE_SPECULAR;
  217. }
  218. }
  219. if (GetRenderState()[D3DRENDERSTATE_FOGENABLE])
  220. {
  221. m_clipping.dwInterpolate |= RRCLIP_INTERPOLATE_SPECULAR;
  222. }
  223. if (FVF_TEXCOORD_NUMBER(m_dwFVFIn) != 0)
  224. {
  225. m_clipping.dwInterpolate |= RRCLIP_INTERPOLATE_TEXTURE;
  226. }
  227. if (m_dwTLState & RRPV_DOCOMPUTEPOINTSIZE)
  228. {
  229. m_clipping.dwInterpolate |= RRCLIP_INTERPOLATE_S;
  230. }
  231. if (m_dwTLState & RRPV_DOPASSEYENORMAL)
  232. {
  233. m_clipping.dwInterpolate |= RRCLIP_INTERPOLATE_EYENORMAL;
  234. }
  235. if (m_dwTLState & RRPV_DOPASSEYEXYZ)
  236. {
  237. m_clipping.dwInterpolate |= RRCLIP_INTERPOLATE_EYEXYZ;
  238. }
  239. // Clear clip union and intersection flags
  240. m_clipIntersection = 0;
  241. m_clipUnion = 0;
  242. HRESULT hr = S_OK;
  243. HR_RET( UpdateClippingData( GetRenderState()[D3DRENDERSTATE_CLIPPLANEENABLE] ));
  244. }
  245. // This needs to be updated bbecause the rasterizer part of
  246. // the Reference Driver uses it.
  247. m_qwFVFControl = m_qwFVFOut;
  248. //
  249. // Grow buffers to the requisite size
  250. //
  251. // Size of the buffer required to transform into
  252. dwVertexPoolSize = m_dwNumVertices * m_dwOutputVtxSize;
  253. // Grow TLVBuf if required
  254. if (dwVertexPoolSize > this->m_TLVBuf.GetSize())
  255. {
  256. if (this->m_TLVBuf.Grow(dwVertexPoolSize) != D3D_OK)
  257. {
  258. DPFM(0,TNL,("Could not grow TL vertex buffer"));
  259. ret = DDERR_OUTOFMEMORY;
  260. return ret;
  261. }
  262. }
  263. this->m_pvOut = this->m_TLVBuf.GetAddress();
  264. // Grow ClipFlagBuf if required
  265. if (GetRenderState()[D3DRENDERSTATE_CLIPPING])
  266. {
  267. DWORD size = m_dwNumVertices * sizeof(RRCLIPCODE);
  268. if (size > this->m_ClipFlagBuf.GetSize())
  269. {
  270. if (this->m_ClipFlagBuf.Grow(size) != D3D_OK)
  271. {
  272. DPFM(0,TNL,("Could not grow clip buffer"));
  273. ret = DDERR_OUTOFMEMORY;
  274. return ret;
  275. }
  276. }
  277. this->m_pClipBuf = (RRCLIPCODE *)this->m_ClipFlagBuf.GetAddress();
  278. }
  279. //
  280. // Transform, Light and compute clipping for vertices
  281. //
  282. if (ProcessVertices())
  283. {
  284. // If the entire primitive lies outside the view frustum, quit
  285. // without drawing
  286. return D3D_OK;
  287. }
  288. //
  289. // Clip and Draw the primitives
  290. //
  291. if (bIndexedPrim)
  292. {
  293. if (!NeedClipping((m_dwTLState & RRPV_GUARDBAND), m_clipUnion))
  294. {
  295. ret = DoDrawOneIndexedPrimitive( this,
  296. m_dwOutputVtxSize,
  297. (PUINT8) m_pvOut,
  298. m_pIndices,
  299. m_primType,
  300. m_dwNumIndices
  301. );
  302. }
  303. else
  304. {
  305. ret = DrawOneClippedIndexedPrimitive();
  306. }
  307. }
  308. else
  309. {
  310. if (!NeedClipping((m_dwTLState & RRPV_GUARDBAND), m_clipUnion))
  311. {
  312. ret = DoDrawOnePrimitive( this,
  313. m_dwOutputVtxSize,
  314. (PUINT8) m_pvOut,
  315. m_primType,
  316. m_dwNumVertices
  317. );
  318. }
  319. else
  320. {
  321. ret = DrawOneClippedPrimitive();
  322. }
  323. }
  324. #if 0
  325. D3DFE_UpdateClipStatus(this);
  326. #endif //0
  327. return ret;
  328. }
  329. //---------------------------------------------------------------------
  330. // ReferenceRasterizer::UpdateTLState
  331. // Updates transform and lighting related state
  332. //---------------------------------------------------------------------
  333. HRESULT
  334. ReferenceRasterizer::UpdateTLState()
  335. {
  336. HRESULT hr = D3D_OK;
  337. //
  338. // Update Geometry Loop flags based on the current state set
  339. //
  340. // Need to compute the Min of what is in the FVF and the renderstate.
  341. m_numVertexBlends = min( GetRenderState()[D3DRENDERSTATE_VERTEXBLEND],
  342. ((m_dwFVFIn & D3DFVF_POSITION_MASK) >> 1) - 2 );
  343. #ifdef __POINTSPRITES
  344. //
  345. // Check prim type to see if point size computation is needed
  346. // Need to set this before the transform state is set
  347. //
  348. m_dwTLState &= ~RRPV_DOCOMPUTEPOINTSIZE;
  349. switch(m_primType)
  350. {
  351. case D3DPT_POINTLIST:
  352. m_dwTLState |= RRPV_DOCOMPUTEPOINTSIZE;
  353. break;
  354. }
  355. #endif
  356. m_dwTLState &= ~(RRPV_DOPASSEYENORMAL|RRPV_DOPASSEYEXYZ);
  357. for ( DWORD dwStage=0; dwStage<D3DHAL_TSS_MAXSTAGES; dwStage++ )
  358. {
  359. // check for disabled stage (subsequent are thus inactive)
  360. if ( GetTextureStageState(dwStage)[D3DTSS_COLOROP] == D3DTOP_DISABLE )
  361. {
  362. break;
  363. }
  364. switch ( GetTextureStageState(dwStage)[D3DTSS_TEXCOORDINDEX] & 0xffff0000)
  365. {
  366. case D3DTSS_TCI_CAMERASPACENORMAL:
  367. m_dwTLState |= RRPV_DOPASSEYENORMAL;
  368. break;
  369. case D3DTSS_TCI_CAMERASPACEPOSITION:
  370. m_dwTLState |= RRPV_DOPASSEYEXYZ;
  371. break;
  372. case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
  373. m_dwTLState |= (RRPV_DOPASSEYENORMAL|RRPV_DOPASSEYEXYZ);
  374. break;
  375. }
  376. }
  377. // Fog or not:
  378. // Compute fog if: 1) Fogging is enabled
  379. // 2) VertexFog mode is not FOG_NONE
  380. // 3) TableFog mode is FOG_NONE
  381. // If both table and vertex fog are not FOG_NONE, table fog
  382. // is applied.
  383. if (GetRenderState()[D3DRENDERSTATE_FOGENABLE] &&
  384. GetRenderState()[D3DRENDERSTATE_FOGVERTEXMODE] &&
  385. !GetRenderState()[D3DRENDERSTATE_FOGTABLEMODE])
  386. {
  387. m_dwTLState |= RRPV_DOFOG;
  388. // Range Fog
  389. if (GetRenderState()[D3DRENDERSTATE_RANGEFOGENABLE])
  390. {
  391. m_dwTLState |= RRPV_RANGEFOG;
  392. }
  393. else
  394. {
  395. m_dwTLState &= ~RRPV_RANGEFOG;
  396. }
  397. }
  398. else
  399. {
  400. m_dwTLState &= ~(RRPV_DOFOG | RRPV_RANGEFOG);
  401. }
  402. // Something changed in the transformation state
  403. // Recompute digested transform state
  404. HR_RET(UpdateXformData());
  405. // Something changed in the lighting state
  406. if ((m_dwTLState & RRPV_DOLIGHTING) &&
  407. (m_dwDirtyFlags & RRPV_DIRTY_LIGHTING))
  408. {
  409. //
  410. // Compute Colorvertex flags only if the lighting is enabled
  411. //
  412. m_dwTLState &= ~RRPV_COLORVERTEXFLAGS;
  413. m_lighting.pAmbientSrc = &m_lighting.matAmb;
  414. m_lighting.pDiffuseSrc = &m_lighting.matDiff;
  415. m_lighting.pSpecularSrc = &m_lighting.matSpec;
  416. m_lighting.pEmissiveSrc = &m_lighting.matEmis;
  417. m_lighting.pDiffuseAlphaSrc = &m_lighting.materialDiffAlpha;
  418. m_lighting.pSpecularAlphaSrc = &m_lighting.materialSpecAlpha;
  419. if (GetRenderState()[D3DRENDERSTATE_COLORVERTEX])
  420. {
  421. switch( GetRenderState()[D3DRENDERSTATE_AMBIENTMATERIALSOURCE] )
  422. {
  423. case D3DMCS_MATERIAL:
  424. break;
  425. case D3DMCS_COLOR1:
  426. {
  427. if (m_dwFVFIn & D3DFVF_DIFFUSE)
  428. {
  429. m_dwTLState |=
  430. (RRPV_VERTEXDIFFUSENEEDED | RRPV_COLORVERTEXAMB);
  431. m_lighting.pAmbientSrc = &m_lighting.vertexDiffuse;
  432. }
  433. }
  434. break;
  435. case D3DMCS_COLOR2:
  436. {
  437. if (m_dwFVFIn & D3DFVF_SPECULAR)
  438. {
  439. m_dwTLState |=
  440. (RRPV_VERTEXSPECULARNEEDED | RRPV_COLORVERTEXAMB);
  441. m_lighting.pAmbientSrc = &m_lighting.vertexSpecular;
  442. }
  443. }
  444. break;
  445. }
  446. switch( GetRenderState()[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE] )
  447. {
  448. case D3DMCS_MATERIAL:
  449. break;
  450. case D3DMCS_COLOR1:
  451. {
  452. if (m_dwFVFIn & D3DFVF_DIFFUSE)
  453. {
  454. m_dwTLState |=
  455. (RRPV_VERTEXDIFFUSENEEDED | RRPV_COLORVERTEXDIFF);
  456. m_lighting.pDiffuseSrc = &m_lighting.vertexDiffuse;
  457. m_lighting.pDiffuseAlphaSrc =
  458. &m_lighting.vertexDiffAlpha;
  459. }
  460. }
  461. break;
  462. case D3DMCS_COLOR2:
  463. {
  464. if (m_dwFVFIn & D3DFVF_SPECULAR)
  465. {
  466. m_dwTLState |=
  467. (RRPV_VERTEXSPECULARNEEDED | RRPV_COLORVERTEXDIFF);
  468. m_lighting.pDiffuseSrc = &m_lighting.vertexSpecular;
  469. m_lighting.pDiffuseAlphaSrc =
  470. &m_lighting.vertexSpecAlpha;
  471. }
  472. }
  473. break;
  474. }
  475. switch( GetRenderState()[D3DRENDERSTATE_SPECULARMATERIALSOURCE] )
  476. {
  477. case D3DMCS_MATERIAL:
  478. break;
  479. case D3DMCS_COLOR1:
  480. {
  481. if (m_dwFVFIn & D3DFVF_DIFFUSE)
  482. {
  483. m_dwTLState |=
  484. (RRPV_VERTEXDIFFUSENEEDED | RRPV_COLORVERTEXSPEC);
  485. m_lighting.pSpecularSrc = &m_lighting.vertexDiffuse;
  486. m_lighting.pSpecularAlphaSrc =
  487. &m_lighting.vertexDiffAlpha;
  488. }
  489. }
  490. break;
  491. case D3DMCS_COLOR2:
  492. {
  493. if (m_dwFVFIn & D3DFVF_SPECULAR)
  494. {
  495. m_dwTLState |=
  496. (RRPV_VERTEXSPECULARNEEDED | RRPV_COLORVERTEXSPEC);
  497. m_lighting.pSpecularSrc = &m_lighting.vertexSpecular;
  498. m_lighting.pSpecularAlphaSrc =
  499. &m_lighting.vertexSpecAlpha;
  500. }
  501. }
  502. break;
  503. }
  504. switch( GetRenderState()[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE] )
  505. {
  506. case D3DMCS_MATERIAL:
  507. break;
  508. case D3DMCS_COLOR1:
  509. {
  510. if (m_dwFVFIn & D3DFVF_DIFFUSE)
  511. {
  512. m_dwTLState |=
  513. (RRPV_VERTEXDIFFUSENEEDED | RRPV_COLORVERTEXEMIS);
  514. m_lighting.pEmissiveSrc = &m_lighting.vertexDiffuse;
  515. }
  516. }
  517. break;
  518. case D3DMCS_COLOR2:
  519. {
  520. if (m_dwFVFIn & D3DFVF_SPECULAR)
  521. {
  522. m_dwTLState |=
  523. (RRPV_VERTEXSPECULARNEEDED | RRPV_COLORVERTEXEMIS);
  524. m_lighting.pEmissiveSrc = &m_lighting.vertexSpecular;
  525. }
  526. }
  527. break;
  528. }
  529. }
  530. // If specular is needed in the output and has been provided
  531. // in the input, force the copy of specular data
  532. if ((m_dwFVFIn & D3DFVF_SPECULAR) &&
  533. (GetRenderState()[D3DRENDERSTATE_SPECULARENABLE] == FALSE))
  534. {
  535. m_dwTLState |= RRPV_VERTEXSPECULARNEEDED;
  536. }
  537. //
  538. // Update the remaining light state
  539. //
  540. HR_RET(UpdateLightingData());
  541. }
  542. if ((m_dwTLState & RRPV_DOFOG) &&
  543. (m_dwDirtyFlags & RRPV_DIRTY_FOG))
  544. {
  545. HR_RET(UpdateFogData());
  546. }
  547. return hr;
  548. }
  549. ///////////////////////////////////////////////////////////////////////////////
  550. // RRProcessVertices method implementations
  551. ///////////////////////////////////////////////////////////////////////////////
  552. //---------------------------------------------------------------------
  553. inline void MakeRRCOLOR( RRCOLOR *out, DWORD inputColor )
  554. {
  555. out->r = (D3DVALUE)RGBA_GETRED( inputColor );
  556. out->g = (D3DVALUE)RGBA_GETGREEN( inputColor );
  557. out->b = (D3DVALUE)RGBA_GETBLUE( inputColor );
  558. }
  559. //---------------------------------------------------------------------
  560. // RRProcessVertices::ComputeClipCodes
  561. //---------------------------------------------------------------------
  562. RRCLIPCODE
  563. RRProcessVertices::ComputeClipCodes(RRCLIPCODE* pclipIntersection, RRCLIPCODE* pclipUnion,
  564. FLOAT x_clip, FLOAT y_clip, FLOAT z_clip, FLOAT w_clip, FLOAT fPointSize)
  565. {
  566. // if true, need to deal with point size for clipping
  567. BOOL bPointSize = (fPointSize > 1.0f);
  568. D3DVALUE xx = w_clip - x_clip;
  569. D3DVALUE yy = w_clip - y_clip;
  570. D3DVALUE zz = w_clip - z_clip;
  571. // if (x < 0) clip |= RRCLIP_LEFTBIT;
  572. // if (x >= we) clip |= RRCLIP_RIGHTBIT;
  573. // if (y < 0) clip |= RRCLIP_BOTTOMBIT;
  574. // if (y >= we) clip |= RRCLIP_TOPBIT;
  575. // if (z < 0) clip |= RRCLIP_FRONTBIT;
  576. // if (z >= we) clip |= RRCLIP_BACKBIT;
  577. RRCLIPCODE clip = ((AS_INT32(x_clip) & 0x80000000) >> (32-RRCLIP_LEFTBIT)) |
  578. ((AS_INT32(y_clip) & 0x80000000) >> (32-RRCLIP_BOTTOMBIT))|
  579. ((AS_INT32(z_clip) & 0x80000000) >> (32-RRCLIP_FRONTBIT)) |
  580. ((AS_INT32(xx) & 0x80000000) >> (32-RRCLIP_RIGHTBIT)) |
  581. ((AS_INT32(yy) & 0x80000000) >> (32-RRCLIP_TOPBIT)) |
  582. ((AS_INT32(zz) & 0x80000000) >> (32-RRCLIP_BACKBIT));
  583. RRCLIPCODE clipBit = RRCLIP_USERCLIPPLANE0;
  584. for( DWORD j=0; j<RRMAX_USER_CLIPPLANES; j++)
  585. {
  586. if( m_xfmUserClipPlanes[j].bActive )
  587. {
  588. RRVECTOR4& plane = m_xfmUserClipPlanes[j].plane;
  589. FLOAT fComp = 0.0f;
  590. if (bPointSize)
  591. {
  592. // if clipping point sprites, take the sprite size into account
  593. // and set the user clip bit if the sprite might be clipped
  594. FLOAT x_clip_size = fPointSize*0.5f*w_clip/m_ViewData.scaleX;
  595. FLOAT y_clip_size = fPointSize*0.5f*w_clip/m_ViewData.scaleY;
  596. fComp = (FLOAT)sqrt(x_clip_size*x_clip_size + y_clip_size*y_clip_size);
  597. }
  598. if( (x_clip*plane.x +
  599. y_clip*plane.y +
  600. z_clip*plane.z +
  601. w_clip*plane.w) < fComp )
  602. {
  603. clip |= clipBit;
  604. }
  605. }
  606. clipBit <<= 1;
  607. }
  608. if (clip == 0)
  609. {
  610. *pclipIntersection = 0;
  611. return clip;
  612. }
  613. else
  614. {
  615. if (m_dwTLState & RRPV_GUARDBAND)
  616. {
  617. // We do guardband check in the projection space, so
  618. // we transform X and Y of the vertex there
  619. D3DVALUE xnew = x_clip * m_ViewData.gb11 +
  620. w_clip * m_ViewData.gb41;
  621. D3DVALUE ynew = y_clip * m_ViewData.gb22 +
  622. w_clip * m_ViewData.gb42;
  623. D3DVALUE xx = w_clip - xnew;
  624. D3DVALUE yy = w_clip - ynew;
  625. clip |= ((AS_INT32(xnew) & 0x80000000) >> (32-RRCLIPGB_LEFTBIT)) |
  626. ((AS_INT32(ynew) & 0x80000000) >> (32-RRCLIPGB_BOTTOMBIT)) |
  627. ((AS_INT32(xx) & 0x80000000) >> (32-RRCLIPGB_RIGHTBIT)) |
  628. ((AS_INT32(yy) & 0x80000000) >> (32-RRCLIPGB_TOPBIT));
  629. }
  630. if (bPointSize)
  631. {
  632. // point sprite could still be visible
  633. *pclipIntersection &= (clip & ~(RRCLIP_LEFT | RRCLIP_RIGHT | RRCLIP_TOP | RRCLIP_BOTTOM |
  634. RRCLIP_USERCLIPPLANE0 | RRCLIP_USERCLIPPLANE1 | RRCLIP_USERCLIPPLANE2 |
  635. RRCLIP_USERCLIPPLANE3 | RRCLIP_USERCLIPPLANE4 | RRCLIP_USERCLIPPLANE5));
  636. }
  637. else
  638. {
  639. *pclipIntersection &= clip;
  640. }
  641. *pclipUnion |= clip;
  642. return clip;
  643. }
  644. }
  645. //---------------------------------------------------------------------
  646. // RRProcessVertices::ProcessVertices
  647. //---------------------------------------------------------------------
  648. RRCLIPCODE
  649. RRProcessVertices::ProcessVertices()
  650. {
  651. D3DVERTEX *pin = (D3DVERTEX*)m_position.lpvData;
  652. DWORD in_size = m_position.dwStride;
  653. DWORD inFVF = m_dwFVFIn;
  654. D3DTLVERTEX *pout = (D3DTLVERTEX*)m_pvOut;
  655. DWORD out_size = m_dwOutputVtxSize;
  656. UINT64 outFVF = m_qwFVFOut;
  657. RRCLIPCODE *pclip = m_pClipBuf;
  658. DWORD flags = m_dwTLState;
  659. RRCLIPCODE clipIntersection = ~0;
  660. RRCLIPCODE clipUnion = 0;
  661. DWORD count = m_dwNumVertices;
  662. D3DLIGHTINGELEMENT le;
  663. BOOL bVertexInEyeSpace = FALSE;
  664. //
  665. // Number of vertices to blend. i.e number of blend-matrices to
  666. // use is numVertexBlends+1.
  667. //
  668. int numVertexBlends = m_numVertexBlends;
  669. m_lighting.outDiffuse = RR_DEFAULT_DIFFUSE;
  670. m_lighting.outSpecular = RR_DEFAULT_SPECULAR;
  671. //
  672. // The main transform loop
  673. //
  674. for (DWORD i = count; i; i--)
  675. {
  676. const D3DVECTOR *pNormal = (D3DVECTOR *)((LPBYTE)pin +
  677. m_dwNormalOffset);
  678. float x_clip=0.0f, y_clip=0.0f, z_clip=0.0f, w_clip=0.0f;
  679. float inv_w_clip=0.0f;
  680. float *pBlendFactors = (float *)((LPBYTE)pin + sizeof( D3DVALUE )*3);
  681. float cumulBlend = 0; // Blend accumulated so far
  682. ZeroMemory( &le, sizeof(D3DLIGHTINGELEMENT) );
  683. //
  684. // Transform vertex to the clipping space, and position and normal
  685. // into eye space, if needed.
  686. //
  687. for( int j=0; j<=numVertexBlends; j++)
  688. {
  689. float blend;
  690. if( numVertexBlends == 0 )
  691. {
  692. blend = 1.0f;
  693. }
  694. else if( j == numVertexBlends )
  695. {
  696. blend = 1.0f - cumulBlend;
  697. }
  698. else
  699. {
  700. blend = pBlendFactors[j];
  701. cumulBlend += pBlendFactors[j];
  702. }
  703. if (m_dwTLState & (RRPV_DOCOMPUTEPOINTSIZE|RRPV_DOPASSEYEXYZ|RRPV_DOLIGHTING))
  704. {
  705. le.dvPosition.x += (pin->x*m_xfmToEye[j]._11 +
  706. pin->y*m_xfmToEye[j]._21 +
  707. pin->z*m_xfmToEye[j]._31 +
  708. m_xfmToEye[j]._41) * blend;
  709. le.dvPosition.y += (pin->x*m_xfmToEye[j]._12 +
  710. pin->y*m_xfmToEye[j]._22 +
  711. pin->z*m_xfmToEye[j]._32 +
  712. m_xfmToEye[j]._42) * blend;
  713. le.dvPosition.z += (pin->x*m_xfmToEye[j]._13 +
  714. pin->y*m_xfmToEye[j]._23 +
  715. pin->z*m_xfmToEye[j]._33 +
  716. m_xfmToEye[j]._43) * blend;
  717. }
  718. if (m_dwTLState & (RRPV_DOPASSEYENORMAL|RRPV_DOLIGHTING))
  719. {
  720. // Transform vertex normal to the eye space
  721. // We use inverse transposed matrix
  722. le.dvNormal.x += (pNormal->x*m_xfmToEyeInv[j]._11 +
  723. pNormal->y*m_xfmToEyeInv[j]._12 +
  724. pNormal->z*m_xfmToEyeInv[j]._13) * blend;
  725. le.dvNormal.y += (pNormal->x*m_xfmToEyeInv[j]._21 +
  726. pNormal->y*m_xfmToEyeInv[j]._22 +
  727. pNormal->z*m_xfmToEyeInv[j]._23) * blend;
  728. le.dvNormal.z += (pNormal->x*m_xfmToEyeInv[j]._31 +
  729. pNormal->y*m_xfmToEyeInv[j]._32 +
  730. pNormal->z*m_xfmToEyeInv[j]._33) * blend;
  731. }
  732. // Apply WORLDj
  733. x_clip += (pin->x*m_xfmCurrent[j]._11 +
  734. pin->y*m_xfmCurrent[j]._21 +
  735. pin->z*m_xfmCurrent[j]._31 +
  736. m_xfmCurrent[j]._41) * blend;
  737. y_clip += (pin->x*m_xfmCurrent[j]._12 +
  738. pin->y*m_xfmCurrent[j]._22 +
  739. pin->z*m_xfmCurrent[j]._32 +
  740. m_xfmCurrent[j]._42) * blend;
  741. z_clip += (pin->x*m_xfmCurrent[j]._13 +
  742. pin->y*m_xfmCurrent[j]._23 +
  743. pin->z*m_xfmCurrent[j]._33 +
  744. m_xfmCurrent[j]._43) * blend;
  745. w_clip += (pin->x*m_xfmCurrent[j]._14 +
  746. pin->y*m_xfmCurrent[j]._24 +
  747. pin->z*m_xfmCurrent[j]._34 +
  748. m_xfmCurrent[j]._44) * blend;
  749. }
  750. if ((flags & RRPV_NORMALIZENORMALS) && (m_dwTLState & (RRPV_DOPASSEYENORMAL|RRPV_DOLIGHTING)))
  751. Normalize(le.dvNormal);
  752. RRFVFExtractor VtxOut( pout, outFVF, FALSE );
  753. FLOAT fPointSize = 0.0f;
  754. #ifdef __POINTSPRITES
  755. if (m_dwTLState & RRPV_DOCOMPUTEPOINTSIZE)
  756. {
  757. FLOAT fDist = (FLOAT)sqrt(le.dvPosition.x*le.dvPosition.x + le.dvPosition.y*le.dvPosition.y +
  758. le.dvPosition.z*le.dvPosition.z);
  759. if (inFVF & D3DFVF_S)
  760. {
  761. RRFVFExtractor VtxIn( pin, inFVF, FALSE );
  762. fPointSize = VtxIn.GetS();
  763. }
  764. else
  765. {
  766. // from D3DRENDERSTATE_POINTSIZE
  767. fPointSize = m_fPointSize;
  768. }
  769. fPointSize = fPointSize*(FLOAT)sqrt(1.0f/
  770. (m_fPointAttA + m_fPointAttB*fDist + m_fPointAttC*fDist*fDist));
  771. fPointSize = max(m_fPointSizeMin, fPointSize);
  772. fPointSize = min(RRMAX_POINT_SIZE, fPointSize);
  773. FLOAT *pfSOut = VtxOut.GetPtrS();
  774. *pfSOut = fPointSize;
  775. }
  776. #endif
  777. if (m_dwTLState & RRPV_DOPASSEYENORMAL)
  778. {
  779. FLOAT *pfEye = VtxOut.GetPtrEyeNormal();
  780. pfEye[0] = le.dvNormal.x;
  781. pfEye[1] = le.dvNormal.y;
  782. pfEye[2] = le.dvNormal.z;
  783. }
  784. if (m_dwTLState & RRPV_DOPASSEYEXYZ)
  785. {
  786. FLOAT *pfEye = VtxOut.GetPtrEyeXYZ();
  787. pfEye[0] = le.dvPosition.x;
  788. pfEye[1] = le.dvPosition.y;
  789. pfEye[2] = le.dvPosition.z;
  790. }
  791. //
  792. // Compute clip codes if needed
  793. //
  794. if (m_dwTLState & RRPV_DOCLIPPING)
  795. {
  796. RRCLIPCODE clip = ComputeClipCodes(&clipIntersection, &clipUnion,
  797. x_clip, y_clip, z_clip, w_clip, fPointSize);
  798. if (clip == 0)
  799. {
  800. *pclip++ = 0;
  801. inv_w_clip = D3DVAL(1)/w_clip;
  802. }
  803. else
  804. {
  805. if (m_dwTLState & RRPV_GUARDBAND)
  806. {
  807. if ((clip & ~RRCLIP_INGUARDBAND) == 0)
  808. {
  809. // If vertex is inside the guardband we have to compute
  810. // screen coordinates
  811. inv_w_clip = D3DVAL(1)/w_clip;
  812. *pclip++ = (RRCLIPCODE)clip;
  813. goto l_DoScreenCoord;
  814. }
  815. }
  816. *pclip++ = (RRCLIPCODE)clip;
  817. // If vertex is outside the frustum we can not compute screen
  818. // coordinates, hence store the clip coordinates
  819. pout->sx = x_clip;
  820. pout->sy = y_clip;
  821. pout->sz = z_clip;
  822. pout->rhw = w_clip;
  823. goto l_DoLighting;
  824. }
  825. }
  826. else
  827. {
  828. // We have to check this only for DONOTCLIP case, because otherwise
  829. // the vertex with "we = 0" will be clipped and screen coordinates
  830. // will not be computed
  831. // "clip" is not zero, if "we" is zero.
  832. if (!FLOAT_EQZ(w_clip))
  833. inv_w_clip = D3DVAL(1)/w_clip;
  834. else
  835. inv_w_clip = __HUGE_PWR2;
  836. }
  837. l_DoScreenCoord:
  838. pout->sx = x_clip * inv_w_clip * m_ViewData.scaleX +
  839. m_ViewData.offsetX;
  840. pout->sy = y_clip * inv_w_clip * m_ViewData.scaleY +
  841. m_ViewData.offsetY;
  842. pout->sz = z_clip * inv_w_clip * m_ViewData.scaleZ +
  843. m_ViewData.offsetZ;
  844. pout->rhw = inv_w_clip;
  845. l_DoLighting:
  846. DWORD *pOut = (DWORD*)((char*)pout + 4*sizeof(D3DVALUE));
  847. if (flags & RRPV_DOLIGHTING)
  848. {
  849. bVertexInEyeSpace = TRUE;
  850. //
  851. // If Diffuse color is needed, extract it for color vertex.
  852. //
  853. if (flags & RRPV_VERTEXDIFFUSENEEDED)
  854. {
  855. const DWORD color = *(DWORD*)((char*)pin + m_dwDiffuseOffset);
  856. MakeRRCOLOR(&m_lighting.vertexDiffuse, color);
  857. m_lighting.vertexDiffAlpha = color & 0xff000000;
  858. }
  859. //
  860. // If Specular color is needed and provided
  861. // , extract it for color vertex.
  862. //
  863. if (flags & RRPV_VERTEXSPECULARNEEDED)
  864. {
  865. const DWORD color = *(DWORD*)((char*)pin + m_dwSpecularOffset);
  866. MakeRRCOLOR(&m_lighting.vertexSpecular, color);
  867. m_lighting.vertexSpecAlpha = color & 0xff000000;
  868. }
  869. //
  870. // Light the vertex
  871. //
  872. LightVertex( &le );
  873. }
  874. else if (inFVF & (D3DFVF_DIFFUSE | D3DFVF_SPECULAR))
  875. {
  876. if (inFVF & D3DFVF_DIFFUSE)
  877. m_lighting.outDiffuse = *(DWORD*)((char*)pin + m_dwDiffuseOffset);
  878. if (inFVF & D3DFVF_SPECULAR)
  879. m_lighting.outSpecular = *(DWORD*)((char*)pin + m_dwSpecularOffset);
  880. }
  881. //
  882. // Compute Vertex Fog if needed
  883. //
  884. if (flags & RRPV_DOFOG)
  885. {
  886. FogVertex( *(D3DVECTOR*)(pin), &le, numVertexBlends,
  887. pBlendFactors, bVertexInEyeSpace );
  888. }
  889. if (outFVF & D3DFVF_DIFFUSE)
  890. *pOut++ = m_lighting.outDiffuse;
  891. if (outFVF & D3DFVF_SPECULAR)
  892. *pOut++ = m_lighting.outSpecular;;
  893. {
  894. memcpy(pOut, (char*)pin + m_dwTexOffset, m_dwTextureCoordSizeTotal);
  895. }
  896. pin = (D3DVERTEX*) ((char*) pin + in_size);
  897. pout = (D3DTLVERTEX*) ((char*) pout + out_size);
  898. }
  899. if (flags & RRPV_DOCLIPPING)
  900. {
  901. m_clipIntersection = clipIntersection;
  902. m_clipUnion = clipUnion;
  903. }
  904. else
  905. {
  906. m_clipIntersection = 0;
  907. m_clipUnion = 0;
  908. }
  909. // Returns whether all the vertices were off screen
  910. return m_clipIntersection;
  911. }
  912. ///////////////////////////////////////////////////////////////////////////////
  913. ///////////////////////////////////////////////////////////////////////////////