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.

664 lines
21 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // setup.cpp
  4. //
  5. // PrimProcessor setup methods.
  6. //
  7. // Copyright (C) Microsoft Corporation, 1997.
  8. //
  9. //----------------------------------------------------------------------------
  10. #include "pch.cpp"
  11. #pragma hdrstop
  12. DBG_DECLARE_FILE();
  13. //----------------------------------------------------------------------------
  14. //
  15. // MINMAX3
  16. //
  17. // Computes the min and max of three integer values.
  18. //
  19. //----------------------------------------------------------------------------
  20. #define MINMAX3(iV0, iV1, iV2, iMin, iMax) \
  21. if ((iV0) <= (iV1)) \
  22. { \
  23. if ((iV1) <= (iV2)) \
  24. { \
  25. (iMin) = (iV0); \
  26. (iMax) = (iV2); \
  27. } \
  28. else if ((iV0) <= (iV2)) \
  29. { \
  30. (iMin) = (iV0); \
  31. (iMax) = (iV1); \
  32. } \
  33. else \
  34. { \
  35. (iMin) = (iV2); \
  36. (iMax) = (iV1); \
  37. } \
  38. } \
  39. else if ((iV1) <= (iV2)) \
  40. { \
  41. (iMin) = (iV1); \
  42. if ((iV0) <= (iV2)) \
  43. { \
  44. (iMax) = (iV2); \
  45. } \
  46. else \
  47. { \
  48. (iMax) = (iV0); \
  49. } \
  50. } \
  51. else \
  52. { \
  53. (iMin) = (iV2); \
  54. (iMax) = (iV0); \
  55. }
  56. // Determine whether any of the given values are less than zero or greater
  57. // than one. Negative zero counts as less than zero so this check will
  58. // produce some false positives but that's OK.
  59. //
  60. // ATTENTION Just wipe this out for now. Need a test for W too close to
  61. // zero to avoid numerical problems.
  62. //#define NEEDS_NORMALIZE3(fV0, fV1, fV2) \
  63. // ((ASUINT32(fV0) | ASUINT32(fV1) | ASUINT32(fV2)) > INT32_FLOAT_ONE)
  64. #define NEEDS_NORMALIZE3(fV0, fV1, fV2) \
  65. (1)
  66. //----------------------------------------------------------------------------
  67. //
  68. // PrimProcessor::NormalizeTriRHW
  69. //
  70. // D3DTLVERTEX.dvRHW can be anything, but our internal structures only
  71. // allow for it being in the range [0, 1]. This function ensures that
  72. // the RHWs are in the proper range by finding the largest one and
  73. // scaling all of them down by it.
  74. //
  75. //----------------------------------------------------------------------------
  76. void
  77. PrimProcessor::NormalizeTriRHW(LPD3DTLVERTEX pV0, LPD3DTLVERTEX pV1,
  78. LPD3DTLVERTEX pV2)
  79. {
  80. // Save original values.
  81. m_dvV0RHW = pV0->dvRHW;
  82. m_dvV1RHW = pV1->dvRHW;
  83. m_dvV2RHW = pV2->dvRHW;
  84. // Produce a warning when a value is out of the desired range.
  85. #if DBG
  86. if (FLOAT_LTZ(pV0->dvRHW) ||
  87. FLOAT_LTZ(pV1->dvRHW) ||
  88. FLOAT_LTZ(pV2->dvRHW))
  89. {
  90. RSDPF(("Triangle RHW out of range %f,%f,%f\n",
  91. pV0->dvRHW, pV1->dvRHW, pV2->dvRHW));
  92. }
  93. #endif
  94. // Find bounds and compute scale.
  95. FLOAT fMax;
  96. if (pV0->dvRHW < pV1->dvRHW)
  97. {
  98. if (pV1->dvRHW < pV2->dvRHW)
  99. {
  100. fMax = pV2->dvRHW;
  101. }
  102. else if (pV0->dvRHW < pV2->dvRHW)
  103. {
  104. fMax = pV1->dvRHW;
  105. }
  106. else
  107. {
  108. fMax = pV1->dvRHW;
  109. }
  110. }
  111. else if (pV1->dvRHW < pV2->dvRHW)
  112. {
  113. if (pV0->dvRHW < pV2->dvRHW)
  114. {
  115. fMax = pV2->dvRHW;
  116. }
  117. else
  118. {
  119. fMax = pV0->dvRHW;
  120. }
  121. }
  122. else
  123. {
  124. fMax = pV0->dvRHW;
  125. }
  126. FLOAT fRHWScale;
  127. fRHWScale = NORMALIZED_RHW_MAX / fMax;
  128. // Scale all values by scaling factor.
  129. pV0->dvRHW = pV0->dvRHW * fRHWScale;
  130. pV1->dvRHW = pV1->dvRHW * fRHWScale;
  131. pV2->dvRHW = pV2->dvRHW * fRHWScale;
  132. #ifdef DBG_RHW_NORM
  133. RSDPF(("%f,%f,%f - %f,%f,%f\n",
  134. m_dvV0RHW, m_dvV1RHW, m_dvV2RHW,
  135. pV0->dvRHW, pV1->dvRHW, pV2->dvRHW));
  136. #endif
  137. }
  138. //----------------------------------------------------------------------------
  139. //
  140. // PrimProcessor::TriSetup
  141. //
  142. // Takes three vertices and does triangle setup, filling in both a
  143. // primitive structure for the triangle and a span structure for the first
  144. // span. All internal intermediates and DY values are computed.
  145. //
  146. // Uses the current D3DI_RASTPRIM and D3DI_RASTSPAN so these pointers must
  147. // be valid before calling this routine.
  148. //
  149. // Returns whether the triangle was kept or not. Culled triangles return
  150. // FALSE.
  151. //
  152. //----------------------------------------------------------------------------
  153. BOOL
  154. PrimProcessor::TriSetup(LPD3DTLVERTEX pV0,
  155. LPD3DTLVERTEX pV1,
  156. LPD3DTLVERTEX pV2)
  157. {
  158. // Preserve original first vertex for flat shading reference.
  159. m_StpCtx.pFlatVtx = pV0;
  160. //
  161. // Sort vertices in Y.
  162. // This can cause ordering changes from the original vertex set
  163. // so track reversals.
  164. //
  165. // Determinant computation and culling could be done before this.
  166. // Doing so causes headaches with computing deltas up front, though,
  167. // because the edges may change during sorting.
  168. //
  169. LPD3DTLVERTEX pVTmp;
  170. UINT uReversed;
  171. uReversed = 0;
  172. if (pV0->dvSY <= pV1->dvSY)
  173. {
  174. if (pV1->dvSY <= pV2->dvSY)
  175. {
  176. // Sorted.
  177. }
  178. else if (pV0->dvSY <= pV2->dvSY)
  179. {
  180. // Sorted order is 0 2 1.
  181. pVTmp = pV1;
  182. pV1 = pV2;
  183. pV2 = pVTmp;
  184. uReversed = 1;
  185. }
  186. else
  187. {
  188. // Sorted order is 2 0 1.
  189. pVTmp = pV0;
  190. pV0 = pV2;
  191. pV2 = pV1;
  192. pV1 = pVTmp;
  193. }
  194. }
  195. else if (pV1->dvSY < pV2->dvSY)
  196. {
  197. if (pV0->dvSY <= pV2->dvSY)
  198. {
  199. // Sorted order is 1 0 2.
  200. pVTmp = pV0;
  201. pV0 = pV1;
  202. pV1 = pVTmp;
  203. uReversed = 1;
  204. }
  205. else
  206. {
  207. // Sorted order is 1 2 0.
  208. pVTmp = pV0;
  209. pV0 = pV1;
  210. pV1 = pV2;
  211. pV2 = pVTmp;
  212. }
  213. }
  214. else
  215. {
  216. // Sorted order is 2 1 0.
  217. pVTmp = pV0;
  218. pV0 = pV2;
  219. pV2 = pVTmp;
  220. uReversed = 1;
  221. }
  222. FLOAT fX0 = pV0->dvSX;
  223. FLOAT fX1 = pV1->dvSX;
  224. FLOAT fX2 = pV2->dvSX;
  225. FLOAT fY0 = pV0->dvSY;
  226. FLOAT fY1 = pV1->dvSY;
  227. FLOAT fY2 = pV2->dvSY;
  228. //
  229. // Compute x,y deltas.
  230. //
  231. m_StpCtx.fDX10 = fX1 - fX0;
  232. m_StpCtx.fDX20 = fX2 - fX0;
  233. m_StpCtx.fDY10 = fY1 - fY0;
  234. m_StpCtx.fDY20 = fY2 - fY0;
  235. //
  236. // Compute determinant and do culling.
  237. //
  238. FLOAT fDet;
  239. fDet = m_StpCtx.fDX20 * m_StpCtx.fDY10 - m_StpCtx.fDX10 * m_StpCtx.fDY20;
  240. if (FLOAT_EQZ(fDet))
  241. {
  242. // No area, so bail out
  243. return FALSE;
  244. }
  245. // Get sign of determinant.
  246. UINT uDetCcw = FLOAT_GTZ(fDet) ? 1 : 0;
  247. // If culling is off the cull sign to check against is set to a
  248. // value that can't be matched so this single check is sufficient
  249. // for all three culling cases.
  250. //
  251. // Fold in sign reversal here rather than in uDetCcw because
  252. // we need the true sign later to determine whether the long edge is
  253. // to the left or the right.
  254. if ((uDetCcw ^ uReversed) == m_StpCtx.pCtx->uCullFaceSign)
  255. {
  256. return FALSE;
  257. }
  258. // Snap bounding vertex Y's to pixel centers and check for trivial reject.
  259. m_StpCtx.iY = ICEILF(fY0);
  260. m_iY2 = ICEILF(fY2);
  261. if (m_StpCtx.iY >= m_StpCtx.pCtx->Clip.bottom ||
  262. m_iY2 <= m_StpCtx.pCtx->Clip.top)
  263. {
  264. return FALSE;
  265. }
  266. INT iX0 = ICEILF(fX0);
  267. INT iX1 = ICEILF(fX1);
  268. INT iX2 = ICEILF(fX2);
  269. // Start 2 - 0 edge DXDY divide so that it's overlapped with the
  270. // integer processing done during X clip checking. The assumption
  271. // is that it's nearly zero cost when overlapped so it's worth
  272. // it to start it even when the clip check rejects the triangle.
  273. FLOAT fDX20, fDY20, fDXDY20;
  274. // Need to use stack variables so the assembly can understand the
  275. // address.
  276. fDX20 = m_StpCtx.fDX20;
  277. fDY20 = m_StpCtx.fDY20;
  278. FLD_BEGIN_DIVIDE(fDX20, fDY20, fDXDY20);
  279. // Computing the X triangle bounds involves quite a few operations,
  280. // but it allows for both trivial rejection and trivial acceptance.
  281. // Given that guard band clipping can lead to a lot of trivial rejections
  282. // and that there will usually be a lot of trivial acceptance cases,
  283. // the work is worth it.
  284. INT iMinX, iMaxX;
  285. BOOL bXAccept;
  286. MINMAX3(iX0, iX1, iX2, iMinX, iMaxX);
  287. m_iXWidth = iMaxX - iMinX;
  288. // Use X bounds for trivial reject and accept.
  289. if (iMinX >= m_StpCtx.pCtx->Clip.right ||
  290. iMaxX <= m_StpCtx.pCtx->Clip.left ||
  291. m_iXWidth <= 0)
  292. {
  293. bXAccept = FALSE;
  294. }
  295. else
  296. {
  297. if (iMinX >= m_StpCtx.pCtx->Clip.left &&
  298. iMaxX <= m_StpCtx.pCtx->Clip.right)
  299. {
  300. m_StpCtx.uFlags |= PRIMF_TRIVIAL_ACCEPT_X;
  301. }
  302. else
  303. {
  304. RSDPFM((RSM_XCLIP, "XClip bounds %5d - %5d, %5d\n",
  305. iMinX, iMaxX, m_iXWidth));
  306. }
  307. bXAccept = TRUE;
  308. }
  309. // Complete divide.
  310. FSTP_END_DIVIDE(fDXDY20);
  311. if (!bXAccept)
  312. {
  313. return FALSE;
  314. }
  315. // Clamp triangle Y's to clip rect.
  316. m_iY1 = ICEILF(fY1);
  317. if (m_StpCtx.iY < m_StpCtx.pCtx->Clip.top)
  318. {
  319. RSDPFM((RSM_YCLIP, "YClip iY %d to %d\n",
  320. m_StpCtx.iY, m_StpCtx.pCtx->Clip.top));
  321. m_StpCtx.iY = m_StpCtx.pCtx->Clip.top;
  322. if (m_iY1 < m_StpCtx.pCtx->Clip.top)
  323. {
  324. RSDPFM((RSM_YCLIP, "YClip iY1 %d to %d\n",
  325. m_iY1, m_StpCtx.pCtx->Clip.top));
  326. m_iY1 = m_StpCtx.pCtx->Clip.top;
  327. }
  328. }
  329. if (m_iY1 > m_StpCtx.pCtx->Clip.bottom)
  330. {
  331. RSDPFM((RSM_YCLIP, "YClip iY1 %d, iY2 %d to %d\n",
  332. m_iY1, m_iY2, m_StpCtx.pCtx->Clip.bottom));
  333. m_iY1 = m_StpCtx.pCtx->Clip.bottom;
  334. m_iY2 = m_StpCtx.pCtx->Clip.bottom;
  335. }
  336. else if (m_iY2 > m_StpCtx.pCtx->Clip.bottom)
  337. {
  338. RSDPFM((RSM_YCLIP, "YClip iY2 %d to %d\n",
  339. m_iY2, m_StpCtx.pCtx->Clip.bottom));
  340. m_iY2 = m_StpCtx.pCtx->Clip.bottom;
  341. }
  342. // Compute Y subpixel correction. This will include any Y
  343. // offset due to clamping.
  344. m_StpCtx.fDY = m_StpCtx.iY - fY0;
  345. // Compute trapzeoid heights. These will be restricted to
  346. // lie in the clip rect.
  347. RSASSERT(m_iY1 >= m_StpCtx.iY && m_iY2 >= m_iY1);
  348. m_uHeight10 = m_iY1 - m_StpCtx.iY;
  349. m_uHeight21 = m_iY2 - m_iY1;
  350. m_uHeight20 = m_uHeight10 + m_uHeight21;
  351. if (m_uHeight20 == 0)
  352. {
  353. // Triangle doesn't cover any pixels.
  354. return FALSE;
  355. }
  356. RSDPFM((RSM_TRIS, "Tstp (%.4f,%.4f) (%.4f,%.4f) (%.4f,%.4f)\n",
  357. fX0, fY0, fX1, fY1, fX2, fY2));
  358. RSDPFM((RSM_TRIS, " (%.4f,%.4f : %.4f,%.4f) %d:%d det %.4f\n",
  359. m_StpCtx.fDX10, m_StpCtx.fDY10,
  360. m_StpCtx.fDX20, m_StpCtx.fDY20,
  361. m_uHeight10, m_uHeight21, fDet));
  362. RSDPFM((RSM_Z, " Z (%f) (%f) (%f)\n",
  363. pV0->dvSZ, pV1->dvSZ, pV2->dvSZ));
  364. RSDPFM((RSM_DIFF, " diff (0x%08X) (0x%08X) (0x%08X)\n",
  365. pV0->dcColor, pV1->dcColor, pV2->dcColor));
  366. RSDPFM((RSM_DIDX, " didx (0x%08X) (0x%08X) (0x%08X)\n",
  367. pV0->dcColor, pV1->dcColor, pV2->dcColor));
  368. RSDPFM((RSM_SPEC, " spec (0x%08X) (0x%08X) (0x%08X)\n",
  369. pV0->dcSpecular & 0xffffff, pV1->dcSpecular & 0xffffff,
  370. pV2->dcSpecular & 0xffffff));
  371. RSDPFM((RSM_OOW, " OoW (%f) (%f) (%f)\n",
  372. pV0->dvRHW, pV1->dvRHW, pV2->dvRHW));
  373. RSDPFM((RSM_TEX1, " Tex1 (%f,%f) (%f,%f) (%f,%f)\n",
  374. pV0->dvTU, pV0->dvTV, pV1->dvTU, pV1->dvTV,
  375. pV2->dvTU, pV2->dvTV));
  376. RSDPFM((RSM_FOG, " Fog (0x%02X) (0x%02X) (0x%02X)\n",
  377. RGBA_GETALPHA(pV0->dcSpecular),
  378. RGBA_GETALPHA(pV1->dcSpecular),
  379. RGBA_GETALPHA(pV2->dcSpecular)));
  380. // Compute dx/dy for edges and initial X's.
  381. m_StpCtx.fDX = m_StpCtx.fDY * fDXDY20;
  382. FLOAT fX20 = fX0 + m_StpCtx.fDX;
  383. ComputeIntCarry(fX20, fDXDY20, &m_StpCtx.X20);
  384. m_StpCtx.fX20NC = (FLOAT)m_StpCtx.X20.iNC;
  385. m_StpCtx.fX20CY = (FLOAT)m_StpCtx.X20.iCY;
  386. RSDPFM((RSM_TRIS, " edge20 %f dxdy %f\n", fX20, fDXDY20));
  387. RSDPFM((RSM_TRIS, " (?.%d d %d nc %d cy %d)\n",
  388. m_StpCtx.X20.iFrac,
  389. m_StpCtx.X20.iDFrac, m_StpCtx.X20.iNC, m_StpCtx.X20.iCY));
  390. if (m_uHeight10 > 0)
  391. {
  392. FLOAT fDXDY10;
  393. FLOAT fX10;
  394. #ifdef CHECK_VERTICAL
  395. // This case probably doesn't occur enough to justify the code.
  396. if (FLOAT_EQZ(m_StpCtx.fDX10))
  397. {
  398. fDXDY10 = g_fZero;
  399. fX10 = fX0;
  400. }
  401. else
  402. #endif
  403. {
  404. fDXDY10 = m_StpCtx.fDX10 / m_StpCtx.fDY10;
  405. fX10 = fX0 + m_StpCtx.fDY * fDXDY10;
  406. }
  407. m_StpCtx.X10.iV = ICEILF(fX10);
  408. ComputeIntCarry(fX10, fDXDY10, &m_StpCtx.X10);
  409. RSDPFM((RSM_TRIS, " edge10 %f dxdy %f\n", fX10, fDXDY10));
  410. RSDPFM((RSM_TRIS, " (%d.%d d %d nc %d cy %d)\n",
  411. m_StpCtx.X10.iV, m_StpCtx.X10.iFrac,
  412. m_StpCtx.X10.iDFrac, m_StpCtx.X10.iNC, m_StpCtx.X10.iCY));
  413. }
  414. #if DBG
  415. else
  416. {
  417. // Make it easier to detect when an invalid edge is used.
  418. memset(&m_StpCtx.X10, 0, sizeof(m_StpCtx.X10));
  419. }
  420. #endif
  421. if (m_uHeight21 > 0)
  422. {
  423. FLOAT fDXDY21;
  424. FLOAT fX21;
  425. #ifdef CHECK_VERTICAL
  426. // This case probably doesn't occur enough to justify the code.
  427. if (FLOAT_COMPARE(fX1, ==, fX2))
  428. {
  429. fDXDY21 = g_fZero;
  430. fX21 = fX1;
  431. }
  432. else
  433. #endif
  434. {
  435. fDXDY21 = (fX2 - fX1) / (fY2 - fY1);
  436. fX21 = fX1 + (m_iY1 - fY1) * fDXDY21;
  437. }
  438. m_StpCtx.X21.iV = ICEILF(fX21);
  439. ComputeIntCarry(fX21, fDXDY21, &m_StpCtx.X21);
  440. RSDPFM((RSM_TRIS, " edge21 %f dxdy %f\n", fX21, fDXDY21));
  441. RSDPFM((RSM_TRIS, " (%d.%d d %d nc %d cy %d)\n",
  442. m_StpCtx.X21.iV, m_StpCtx.X21.iFrac,
  443. m_StpCtx.X21.iDFrac, m_StpCtx.X21.iNC, m_StpCtx.X21.iCY));
  444. }
  445. #if DBG
  446. else
  447. {
  448. // Make it easier to detect when an invalid edge is used.
  449. memset(&m_StpCtx.X21, 0, sizeof(m_StpCtx.X21));
  450. }
  451. #endif
  452. // The edge walker always walks the long edge so it may either
  453. // be a left or a right edge. Determine what side the long edge
  454. // is and perform appropriate snapping and subpixel adjustment
  455. // computations.
  456. //
  457. // The clip-clamped initial X pixel position is also computed and
  458. // any necessary offset added into the subpixel correction delta.
  459. if (uDetCcw)
  460. {
  461. // Long edge (0-2) is to the right.
  462. m_StpCtx.uFlags |= TRIF_X_DEC;
  463. m_StpCtx.pPrim->uFlags = D3DI_RASTPRIM_X_DEC;
  464. m_StpCtx.X20.iV = ICEILF(fX20) - 1;
  465. // Other edges are left edges. Bias them back by one
  466. // so that the span width computation can do R - L
  467. // rather than R - L + 1.
  468. m_StpCtx.X10.iV--;
  469. m_StpCtx.X21.iV--;
  470. // Clamp the initial X position.
  471. if (m_StpCtx.X20.iV >= m_StpCtx.pCtx->Clip.right)
  472. {
  473. m_StpCtx.iX = m_StpCtx.pCtx->Clip.right - 1;
  474. }
  475. else
  476. {
  477. m_StpCtx.iX = m_StpCtx.X20.iV;
  478. }
  479. }
  480. else
  481. {
  482. // Long edge (0-2) is to the left.
  483. m_StpCtx.pPrim->uFlags = 0;
  484. m_StpCtx.X20.iV = ICEILF(fX20);
  485. // Other edges are right edges. The ICEILF snapping done
  486. // already leaves them off by one so that R - L works.
  487. // Clamp the initial X position.
  488. if (m_StpCtx.X20.iV < m_StpCtx.pCtx->Clip.left)
  489. {
  490. m_StpCtx.iX = m_StpCtx.pCtx->Clip.left;
  491. }
  492. else
  493. {
  494. m_StpCtx.iX = m_StpCtx.X20.iV;
  495. }
  496. }
  497. // Update X subpixel correction. This delta includes any
  498. // offseting due to clamping of the initial pixel position.
  499. m_StpCtx.fDX += m_StpCtx.iX - fX20;
  500. RSDPFM((RSM_TRIS, " subp %f,%f\n", m_StpCtx.fDX, m_StpCtx.fDY));
  501. // Compute span-to-span steps for buffer pointers.
  502. m_StpCtx.DAttrNC.ipSurface = m_StpCtx.pCtx->iSurfaceStride +
  503. m_StpCtx.X20.iNC * m_StpCtx.pCtx->iSurfaceStep;
  504. m_StpCtx.DAttrNC.ipZ = m_StpCtx.pCtx->iZStride +
  505. m_StpCtx.X20.iNC * m_StpCtx.pCtx->iZStep;
  506. // Start one over determinant divide. Done after the multiplies
  507. // since integer multiplies require some of the FP unit.
  508. FLOAT fOoDet;
  509. FLD_BEGIN_DIVIDE(g_fOne, fDet, fOoDet);
  510. if (m_StpCtx.X20.iCY > m_StpCtx.X20.iNC)
  511. {
  512. m_StpCtx.DAttrCY.ipSurface = m_StpCtx.DAttrNC.ipSurface +
  513. m_StpCtx.pCtx->iSurfaceStep;
  514. m_StpCtx.DAttrCY.ipZ = m_StpCtx.DAttrNC.ipZ + m_StpCtx.pCtx->iZStep;
  515. }
  516. else
  517. {
  518. m_StpCtx.DAttrCY.ipSurface = m_StpCtx.DAttrNC.ipSurface -
  519. m_StpCtx.pCtx->iSurfaceStep;
  520. m_StpCtx.DAttrCY.ipZ = m_StpCtx.DAttrNC.ipZ - m_StpCtx.pCtx->iZStep;
  521. }
  522. //
  523. // Compute attribute functions.
  524. //
  525. // Set pure X/Y step deltas for surface and Z so that DX, DY, CY and NC all
  526. // have complete information and can be used interchangeably.
  527. if (m_StpCtx.uFlags & TRIF_X_DEC)
  528. {
  529. m_StpCtx.DAttrDX.ipSurface = -m_StpCtx.pCtx->iSurfaceStep;
  530. m_StpCtx.DAttrDX.ipZ = -m_StpCtx.pCtx->iZStep;
  531. }
  532. else
  533. {
  534. m_StpCtx.DAttrDX.ipSurface = m_StpCtx.pCtx->iSurfaceStep;
  535. m_StpCtx.DAttrDX.ipZ = m_StpCtx.pCtx->iZStep;
  536. }
  537. m_StpCtx.DAttrDY.ipSurface = m_StpCtx.pCtx->iSurfaceStride;
  538. m_StpCtx.DAttrDY.ipZ = m_StpCtx.pCtx->iZStride;
  539. // Finish overlapped divide.
  540. FSTP_END_DIVIDE(fOoDet);
  541. m_StpCtx.fOoDet = fOoDet;
  542. // The PrimProcessor is created zeroed out so the initial
  543. // state is FP clean. Later uses may put FP values in slots but
  544. // they should still be valid, so the optional computations here
  545. // should never result in FP garbage. It should therefore be
  546. // OK to use any mixture of attribute handlers since there should
  547. // never be any case where FP garbage will creep in.
  548. BOOL bNorm;
  549. // USED checks cannot be combined since TEX_USED is a multibit check.
  550. if ((m_StpCtx.uFlags & PRIMSF_TEX_USED) &&
  551. (m_StpCtx.uFlags & PRIMSF_PERSP_USED) &&
  552. (m_uPpFlags & PPF_NORMALIZE_RHW) &&
  553. NEEDS_NORMALIZE3(pV0->dvRHW, pV1->dvRHW, pV2->dvRHW))
  554. {
  555. NormalizeTriRHW(pV0, pV1, pV2);
  556. bNorm = TRUE;
  557. }
  558. else
  559. {
  560. bNorm = FALSE;
  561. }
  562. TriSetup_Start(&m_StpCtx, pV0, pV1, pV2);
  563. if (bNorm)
  564. {
  565. pV0->dvRHW = m_dvV0RHW;
  566. pV1->dvRHW = m_dvV1RHW;
  567. pV2->dvRHW = m_dvV2RHW;
  568. }
  569. return TRUE;
  570. }