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.

693 lines
23 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // lstp.cpp
  4. //
  5. // Line 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. // LineSetup_Start
  16. //
  17. // Starts setup of line attributes.
  18. //
  19. //----------------------------------------------------------------------------
  20. void FASTCALL
  21. LineSetup_Start(PSETUPCTX pStpCtx,
  22. LPD3DTLVERTEX pV0,
  23. LPD3DTLVERTEX pV1)
  24. {
  25. FLOAT fZ0;
  26. if (pStpCtx->uFlags & PRIMSF_Z_USED)
  27. {
  28. FLOAT fZScale;
  29. if (pStpCtx->pCtx->iZBitCount == 16)
  30. {
  31. fZScale = Z16_SCALE;
  32. }
  33. else
  34. {
  35. fZScale = Z32_SCALE;
  36. }
  37. pStpCtx->DAttrDMajor.fZ =
  38. (pV1->dvSZ - pV0->dvSZ) * fZScale * pStpCtx->fOoLen;
  39. // fZ0 may be used later so set if from the vertex Z.
  40. fZ0 = pV0->dvSZ;
  41. pStpCtx->Attr.fZ = fZ0 * fZScale +
  42. pStpCtx->DAttrDMajor.fZ * pStpCtx->fDMajor;
  43. }
  44. if (pStpCtx->uFlags & PRIMSF_TEX_USED)
  45. {
  46. FLOAT fUoW, fVoW;
  47. if (pStpCtx->uFlags & PRIMSF_PERSP_USED)
  48. {
  49. pStpCtx->DAttrDMajor.fOoW =
  50. (pV1->dvRHW - pV0->dvRHW) * OOW_SCALE * pStpCtx->fOoLen;
  51. pStpCtx->Attr.fOoW = pV0->dvRHW * OOW_SCALE +
  52. pStpCtx->DAttrDMajor.fOoW * pStpCtx->fDMajor;
  53. fUoW = pV0->dvTU * pV0->dvRHW;
  54. fVoW = pV0->dvTV * pV0->dvRHW;
  55. pStpCtx->DAttrDMajor.fUoW[0] =
  56. PERSP_TEXTURE_DELTA(pV1->dvTU, pV1->dvRHW, pV0->dvTU, fUoW,
  57. pStpCtx->pCtx->pdwWrap[0] & D3DWRAP_U) *
  58. TEX_SCALE * pStpCtx->fOoLen;
  59. pStpCtx->DAttrDMajor.fVoW[0] =
  60. PERSP_TEXTURE_DELTA(pV1->dvTV, pV1->dvRHW, pV0->dvTV, fVoW,
  61. pStpCtx->pCtx->pdwWrap[0] & D3DWRAP_V) *
  62. TEX_SCALE * pStpCtx->fOoLen;
  63. }
  64. else
  65. {
  66. pStpCtx->DAttrDMajor.fOoW = g_fZero;
  67. pStpCtx->Attr.fOoW = OOW_SCALE;
  68. fUoW = pV0->dvTU;
  69. fVoW = pV0->dvTV;
  70. pStpCtx->DAttrDMajor.fUoW[0] =
  71. TextureDiff(pV1->dvTU, fUoW,
  72. pStpCtx->pCtx->pdwWrap[0] & D3DWRAP_U) *
  73. TEX_SCALE * pStpCtx->fOoLen;
  74. pStpCtx->DAttrDMajor.fVoW[0] =
  75. TextureDiff(pV1->dvTV, fVoW,
  76. pStpCtx->pCtx->pdwWrap[0] & D3DWRAP_V) *
  77. TEX_SCALE * pStpCtx->fOoLen;
  78. }
  79. pStpCtx->Attr.fUoW[0] = TEX_SCALE * fUoW +
  80. pStpCtx->DAttrDMajor.fUoW[0] * pStpCtx->fDMajor;
  81. pStpCtx->Attr.fVoW[0] = TEX_SCALE * fVoW +
  82. pStpCtx->DAttrDMajor.fVoW[0] * pStpCtx->fDMajor;
  83. }
  84. if (pStpCtx->uFlags & PRIMSF_TEX2_USED)
  85. {
  86. PRAST_GENERIC_VERTEX pVM0 = (PRAST_GENERIC_VERTEX)pV0;
  87. PRAST_GENERIC_VERTEX pVM1 = (PRAST_GENERIC_VERTEX)pV1;
  88. FLOAT fUoW, fVoW;
  89. for (INT32 i = 1; i < (INT32)pStpCtx->pCtx->cActTex; i++)
  90. {
  91. if (pStpCtx->uFlags & PRIMSF_PERSP_USED)
  92. {
  93. fUoW = pVM0->texCoord[i].dvTU * pVM0->dvRHW;
  94. fVoW = pVM0->texCoord[i].dvTV * pVM0->dvRHW;
  95. pStpCtx->DAttrDMajor.fUoW[i] =
  96. PERSP_TEXTURE_DELTA(pVM1->texCoord[i].dvTU, pVM1->dvRHW,
  97. pVM0->texCoord[i].dvTU, fUoW,
  98. pStpCtx->pCtx->pdwWrap[i] & D3DWRAP_U) *
  99. TEX_SCALE * pStpCtx->fOoLen;
  100. pStpCtx->DAttrDMajor.fVoW[i] =
  101. PERSP_TEXTURE_DELTA(pVM1->texCoord[i].dvTV, pVM1->dvRHW,
  102. pVM0->texCoord[i].dvTV, fVoW,
  103. pStpCtx->pCtx->pdwWrap[i] & D3DWRAP_V) *
  104. TEX_SCALE * pStpCtx->fOoLen;
  105. }
  106. else
  107. {
  108. fUoW = pVM0->texCoord[i].dvTU;
  109. fVoW = pVM0->texCoord[i].dvTV;
  110. pStpCtx->DAttrDMajor.fUoW[i] =
  111. TextureDiff(pVM1->texCoord[i].dvTU, fUoW,
  112. pStpCtx->pCtx->pdwWrap[i] & D3DWRAP_U) *
  113. TEX_SCALE * pStpCtx->fOoLen;
  114. pStpCtx->DAttrDMajor.fVoW[i] =
  115. TextureDiff(pVM1->texCoord[i].dvTV, fVoW,
  116. pStpCtx->pCtx->pdwWrap[i] & D3DWRAP_V) *
  117. TEX_SCALE * pStpCtx->fOoLen;
  118. }
  119. pStpCtx->Attr.fUoW[i] = TEX_SCALE * fUoW +
  120. pStpCtx->DAttrDMajor.fUoW[i] * pStpCtx->fDMajor;
  121. pStpCtx->Attr.fVoW[i] = TEX_SCALE * fVoW +
  122. pStpCtx->DAttrDMajor.fVoW[i] * pStpCtx->fDMajor;
  123. }
  124. }
  125. if (pStpCtx->uFlags & PRIMSF_FLAT_SHADED)
  126. {
  127. if (pStpCtx->uFlags & PRIMSF_DIFF_USED)
  128. {
  129. UINT uB, uG, uR, uA;
  130. SPLIT_COLOR(pStpCtx->pFlatVtx->dcColor, uB, uG, uR, uA);
  131. pStpCtx->DAttrDMajor.fB = g_fZero;
  132. pStpCtx->DAttrDMajor.fG = g_fZero;
  133. pStpCtx->DAttrDMajor.fR = g_fZero;
  134. pStpCtx->DAttrDMajor.fA = g_fZero;
  135. pStpCtx->Attr.fB = (FLOAT)(uB << COLOR_SHIFT);
  136. pStpCtx->Attr.fG = (FLOAT)(uG << COLOR_SHIFT);
  137. pStpCtx->Attr.fR = (FLOAT)(uR << COLOR_SHIFT);
  138. pStpCtx->Attr.fA = (FLOAT)(uA << COLOR_SHIFT);
  139. }
  140. else if (pStpCtx->uFlags & PRIMSF_DIDX_USED)
  141. {
  142. pStpCtx->DAttrDMajor.fDIdx = g_fZero;
  143. pStpCtx->DAttrDMajor.fDIdxA = g_fZero;
  144. pStpCtx->Attr.fDIdx =
  145. (FLOAT)(CI_MASKALPHA(pStpCtx->pFlatVtx->dcColor) <<
  146. INDEX_COLOR_FIXED_SHIFT);
  147. pStpCtx->Attr.fDIdxA =
  148. (FLOAT)(CI_GETALPHA(pStpCtx->pFlatVtx->dcColor) <<
  149. INDEX_COLOR_SHIFT);
  150. }
  151. if (pStpCtx->uFlags & PRIMSF_SPEC_USED)
  152. {
  153. UINT uB, uG, uR, uA;
  154. SPLIT_COLOR(pStpCtx->pFlatVtx->dcSpecular, uB, uG, uR, uA);
  155. pStpCtx->DAttrDMajor.fBS = g_fZero;
  156. pStpCtx->DAttrDMajor.fGS = g_fZero;
  157. pStpCtx->DAttrDMajor.fRS = g_fZero;
  158. pStpCtx->Attr.fBS = (FLOAT)(uB << COLOR_SHIFT);
  159. pStpCtx->Attr.fGS = (FLOAT)(uG << COLOR_SHIFT);
  160. pStpCtx->Attr.fRS = (FLOAT)(uR << COLOR_SHIFT);
  161. }
  162. }
  163. else
  164. {
  165. if (pStpCtx->uFlags & PRIMSF_DIFF_USED)
  166. {
  167. UINT uB, uG, uR, uA;
  168. FLOAT fDB, fDG, fDR, fDA;
  169. SPLIT_COLOR(pV0->dcColor, uB, uG, uR, uA);
  170. COLOR_DELTA(pV1->dcColor, uB, uG, uR, uA, fDB, fDG, fDR, fDA);
  171. pStpCtx->DAttrDMajor.fB = fDB * pStpCtx->fOoLen;
  172. pStpCtx->DAttrDMajor.fG = fDG * pStpCtx->fOoLen;
  173. pStpCtx->DAttrDMajor.fR = fDR * pStpCtx->fOoLen;
  174. pStpCtx->DAttrDMajor.fA = fDA * pStpCtx->fOoLen;
  175. pStpCtx->Attr.fB = (FLOAT)(uB << COLOR_SHIFT) +
  176. pStpCtx->DAttrDMajor.fB * pStpCtx->fDMajor;
  177. pStpCtx->Attr.fG = (FLOAT)(uG << COLOR_SHIFT) +
  178. pStpCtx->DAttrDMajor.fG * pStpCtx->fDMajor;
  179. pStpCtx->Attr.fR = (FLOAT)(uR << COLOR_SHIFT) +
  180. pStpCtx->DAttrDMajor.fR * pStpCtx->fDMajor;
  181. pStpCtx->Attr.fA = (FLOAT)(uA << COLOR_SHIFT) +
  182. pStpCtx->DAttrDMajor.fA * pStpCtx->fDMajor;
  183. }
  184. else if (pStpCtx->uFlags & PRIMSF_DIDX_USED)
  185. {
  186. INT32 iIdx, iA;
  187. FLOAT fDIdx, fDA;
  188. SPLIT_IDX_COLOR(pV0->dcColor, iIdx, iA);
  189. IDX_COLOR_DELTA(pV1->dcColor, iIdx, iA, fDIdx, fDA);
  190. pStpCtx->DAttrDMajor.fDIdx = fDIdx * pStpCtx->fOoLen;
  191. pStpCtx->DAttrDMajor.fDIdxA = fDA * pStpCtx->fOoLen;
  192. pStpCtx->Attr.fDIdx = (FLOAT)(iIdx << INDEX_COLOR_FIXED_SHIFT) +
  193. pStpCtx->DAttrDMajor.fDIdx * pStpCtx->fDMajor;
  194. pStpCtx->Attr.fDIdxA = (FLOAT)(iA << INDEX_COLOR_SHIFT) +
  195. pStpCtx->DAttrDMajor.fDIdxA * pStpCtx->fDMajor;
  196. }
  197. if (pStpCtx->uFlags & PRIMSF_SPEC_USED)
  198. {
  199. UINT uB, uG, uR, uA;
  200. FLOAT fDB, fDG, fDR, fDA;
  201. SPLIT_COLOR(pV0->dcSpecular, uB, uG, uR, uA);
  202. COLOR_DELTA(pV1->dcSpecular, uB, uG, uR, uA, fDB, fDG, fDR, fDA);
  203. pStpCtx->DAttrDMajor.fBS = fDB * pStpCtx->fOoLen;
  204. pStpCtx->DAttrDMajor.fGS = fDG * pStpCtx->fOoLen;
  205. pStpCtx->DAttrDMajor.fRS = fDR * pStpCtx->fOoLen;
  206. pStpCtx->Attr.fBS = (FLOAT)(uB << COLOR_SHIFT) +
  207. pStpCtx->DAttrDMajor.fBS * pStpCtx->fDMajor;
  208. pStpCtx->Attr.fGS = (FLOAT)(uG << COLOR_SHIFT) +
  209. pStpCtx->DAttrDMajor.fGS * pStpCtx->fDMajor;
  210. pStpCtx->Attr.fRS = (FLOAT)(uR << COLOR_SHIFT) +
  211. pStpCtx->DAttrDMajor.fRS * pStpCtx->fDMajor;
  212. }
  213. }
  214. if (pStpCtx->uFlags & PRIMSF_LOCAL_FOG_USED)
  215. {
  216. UINT uFog0, uFog1;
  217. #ifndef PWL_FOG
  218. // Check for global-into-local fog. If global fog is on,
  219. // compute the local fog values from table fog rather than
  220. // from the vertex.
  221. if (pStpCtx->uFlags & PRIMSF_GLOBAL_FOG_USED)
  222. {
  223. // Make sure Z information is valid.
  224. RSASSERT(pStpCtx->uFlags & PRIMSF_Z_USED);
  225. uFog0 = ComputeTableFog(pStpCtx->pCtx->pdwRenderState, fZ0);
  226. uFog1 = ComputeTableFog(pStpCtx->pCtx->pdwRenderState,
  227. pV1->dvSZ);
  228. }
  229. else
  230. #endif
  231. {
  232. uFog0 = (UINT)RGBA_GETALPHA(pV0->dcSpecular) << FOG_SHIFT;
  233. uFog1 = (UINT)RGBA_GETALPHA(pV1->dcSpecular) << FOG_SHIFT;
  234. }
  235. pStpCtx->DAttrDMajor.fFog =
  236. (FLOAT)((INT)uFog1 - (INT)uFog0) * pStpCtx->fOoLen;
  237. pStpCtx->Attr.fFog = (FLOAT)uFog0 +
  238. pStpCtx->DAttrDMajor.fFog * pStpCtx->fDMajor;
  239. }
  240. }
  241. // Determine whether any of the given values are less than zero or greater
  242. // than one. Negative zero counts as less than zero so this check will
  243. // produce some false positives but that's OK.
  244. #define NEEDS_NORMALIZE2(fV0, fV1) \
  245. ((ASUINT32(fV0) | ASUINT32(fV1)) > INT32_FLOAT_ONE)
  246. //----------------------------------------------------------------------------
  247. //
  248. // PrimProcessor::NormalizeLineRHW
  249. //
  250. // D3DTLVERTEX.dvRHW can be anything, but our internal structures only
  251. // allow for it being in the range [0, 1]. This function ensures that
  252. // the RHWs are in the proper range by finding the largest one and
  253. // scaling all of them down by it.
  254. //
  255. //----------------------------------------------------------------------------
  256. void
  257. PrimProcessor::NormalizeLineRHW(LPD3DTLVERTEX pV0, LPD3DTLVERTEX pV1)
  258. {
  259. // Save original values.
  260. m_dvV0RHW = pV0->dvRHW;
  261. m_dvV1RHW = pV1->dvRHW;
  262. // Produce a warning when a value is out of the desired range.
  263. #if DBG
  264. if (FLOAT_LTZ(pV0->dvRHW) || FLOAT_LTZ(pV1->dvRHW))
  265. {
  266. RSDPF(("Line RHW out of range %f,%f\n",
  267. pV0->dvRHW, pV1->dvRHW));
  268. }
  269. #endif
  270. // Find bounds and compute scale.
  271. FLOAT fMax;
  272. if (pV0->dvRHW < pV1->dvRHW)
  273. {
  274. fMax = pV1->dvRHW;
  275. }
  276. else
  277. {
  278. fMax = pV0->dvRHW;
  279. }
  280. FLOAT fRHWScale = NORMALIZED_RHW_MAX / fMax;
  281. // Scale all values by scaling factor.
  282. pV0->dvRHW = pV0->dvRHW * fRHWScale;
  283. pV1->dvRHW = pV1->dvRHW * fRHWScale;
  284. }
  285. //-----------------------------------------------------------------------------
  286. //
  287. // PrimProcessor::PointDiamondCheck
  288. //
  289. // Tests if vertex is within diamond of nearest candidate
  290. // position. The +.5 (lower-right) tests are used because this is
  291. // pixel-relative test - this corresponds to an upper-left test for
  292. // a vertex-relative position.
  293. //
  294. //-----------------------------------------------------------------------------
  295. BOOL
  296. PrimProcessor::PointDiamondCheck(INT32 iXFrac, INT32 iYFrac,
  297. BOOL bSlopeIsOne, BOOL bSlopeIsPosOne)
  298. {
  299. const INT32 iPosHalf = 0x8;
  300. const INT32 iNegHalf = -0x8;
  301. INT32 iFracAbsSum = labs( iXFrac ) + labs( iYFrac );
  302. // return TRUE if point is in fully-exclusive diamond
  303. if ( iFracAbsSum < iPosHalf )
  304. {
  305. return TRUE;
  306. }
  307. // else return TRUE if diamond is on left or top extreme of point
  308. if ( ( iXFrac == ( bSlopeIsPosOne ? iNegHalf : iPosHalf ) ) &&
  309. ( iYFrac == 0 ) )
  310. {
  311. return TRUE;
  312. }
  313. if ( ( iYFrac == iPosHalf ) &&
  314. ( iXFrac == 0 ) )
  315. {
  316. return TRUE;
  317. }
  318. // return true if slope is one, vertex is on edge,
  319. // and (other conditions...)
  320. if ( bSlopeIsOne && ( iFracAbsSum == iPosHalf ) )
  321. {
  322. if ( bSlopeIsPosOne && ( iXFrac < 0 ) && ( iYFrac > 0 ) )
  323. {
  324. return TRUE;
  325. }
  326. if ( !bSlopeIsPosOne && ( iXFrac > 0 ) && ( iYFrac > 0 ) )
  327. {
  328. return TRUE;
  329. }
  330. }
  331. return FALSE;
  332. }
  333. //----------------------------------------------------------------------------
  334. //
  335. // PrimProcessor::LineSetup
  336. //
  337. // Does attribute setup computations.
  338. //
  339. //----------------------------------------------------------------------------
  340. // Line computations are done in n.4 fixed-point to reduce vertex jitter,
  341. // move more computation to integer and to more easily match the GDI
  342. // line computations.
  343. #define LINE_FIX 4
  344. #define LINE_SNAP FLOAT_TWOPOW4
  345. #define OO_LINE_SNAP (1.0f / FLOAT_TWOPOW4)
  346. #define LINE_FIX_HALF (1 << (LINE_FIX - 1))
  347. #define LINE_FIX_NEAR_HALF (LINE_FIX_HALF - 1)
  348. BOOL
  349. PrimProcessor::LineSetup(LPD3DTLVERTEX pV0,
  350. LPD3DTLVERTEX pV1)
  351. {
  352. // compute fixed point vertex values, with cheap
  353. // rounding for better accuracy
  354. INT32 iX0 = FTOI(pV0->dvSX * LINE_SNAP + .5F);
  355. INT32 iX1 = FTOI(pV1->dvSX * LINE_SNAP + .5F);
  356. INT32 iY0 = FTOI(pV0->dvSY * LINE_SNAP + .5F);
  357. INT32 iY1 = FTOI(pV1->dvSY * LINE_SNAP + .5F);
  358. // compute x,y extents of the line (fixed point)
  359. INT32 iXSize = iX1 - iX0;
  360. INT32 iYSize = iY1 - iY0;
  361. // ignore zero length lines
  362. if ( iXSize == 0 && iYSize == 0 )
  363. {
  364. return FALSE;
  365. }
  366. INT32 iAbsXSize;
  367. INT32 iAbsYSize;
  368. if ( iXSize < 0 )
  369. {
  370. m_StpCtx.iDXCY = -1;
  371. iAbsXSize = -iXSize;
  372. }
  373. else
  374. {
  375. m_StpCtx.iDXCY = 1;
  376. iAbsXSize = iXSize;
  377. }
  378. if ( iYSize < 0 )
  379. {
  380. m_StpCtx.iDYCY = -1;
  381. iAbsYSize = -iYSize;
  382. }
  383. else
  384. {
  385. m_StpCtx.iDYCY = 1;
  386. iAbsYSize = iYSize;
  387. }
  388. BOOL bSlopeIsOne = iAbsXSize == iAbsYSize;
  389. BOOL bSlopeIsPosOne =
  390. bSlopeIsOne && ((iXSize ^ iYSize) & 0x80000000) == 0;
  391. // compute closest pixel for vertices
  392. //
  393. // n n
  394. // O-------* *-------O
  395. // n-.5 n+.5 n-.5 n+.5
  396. //
  397. // Nearest Ceiling Nearest Floor
  398. //
  399. // always nearest ceiling for Y; use nearest floor for X for
  400. // exception (slope == +1) case else use nearest ceiling
  401. //
  402. INT32 iXAdjust;
  403. if (bSlopeIsPosOne)
  404. {
  405. iXAdjust = LINE_FIX_HALF;
  406. }
  407. else
  408. {
  409. iXAdjust = LINE_FIX_NEAR_HALF;
  410. }
  411. INT32 iPixX0 = ( iX0 + iXAdjust ) >> LINE_FIX;
  412. INT32 iPixX1 = ( iX1 + iXAdjust ) >> LINE_FIX;
  413. INT32 iPixY0 = ( iY0 + LINE_FIX_NEAR_HALF ) >> LINE_FIX;
  414. INT32 iPixY1 = ( iY1 + LINE_FIX_NEAR_HALF ) >> LINE_FIX;
  415. // determine major axis and compute step values
  416. // sign of extent from V0 to V1 in major direction
  417. BOOL bLineMajorNeg;
  418. INT32 iLineMajor0;
  419. INT32 iLineMajor1;
  420. INT32 iLinePix0;
  421. INT32 iLinePix1;
  422. INT32 iLinePixStep;
  423. // use GreaterEqual compare here so X major will be used when slope is
  424. // exactly one - this forces the per-pixel evaluation to be done on the
  425. // Y axis and thus adheres to the rule of inclusive right (instead of
  426. // inclusive left) for slope == 1 cases
  427. if ( iAbsXSize >= iAbsYSize )
  428. {
  429. // here for X major
  430. m_StpCtx.uFlags |= LNF_X_MAJOR;
  431. iLineMajor0 = iX0;
  432. iLineMajor1 = iX1;
  433. iLinePix0 = iPixX0;
  434. iLinePix1 = iPixX1;
  435. iLinePixStep = m_StpCtx.iDXCY;
  436. bLineMajorNeg = iXSize & 0x80000000;
  437. m_StpCtx.iDXNC = m_StpCtx.iDXCY;
  438. m_StpCtx.iDYNC = 0;
  439. }
  440. else
  441. {
  442. // here for Y major
  443. iLineMajor0 = iY0;
  444. iLineMajor1 = iY1;
  445. iLinePix0 = iPixY0;
  446. iLinePix1 = iPixY1;
  447. iLinePixStep = m_StpCtx.iDYCY;
  448. bLineMajorNeg = iYSize & 0x80000000;
  449. m_StpCtx.iDXNC = 0;
  450. m_StpCtx.iDYNC = m_StpCtx.iDYCY;
  451. }
  452. // The multiplies here could be traded for sign tests but there'd
  453. // be four cases. On a PII the multiplies will be faster than
  454. // the branches.
  455. m_StpCtx.DAttrCY.ipSurface =
  456. m_StpCtx.iDYCY * m_StpCtx.pCtx->iSurfaceStride +
  457. m_StpCtx.iDXCY * m_StpCtx.pCtx->iSurfaceStep;
  458. m_StpCtx.DAttrNC.ipSurface =
  459. m_StpCtx.iDYNC * m_StpCtx.pCtx->iSurfaceStride +
  460. m_StpCtx.iDXNC * m_StpCtx.pCtx->iSurfaceStep;
  461. if (m_StpCtx.uFlags & PRIMSF_Z_USED)
  462. {
  463. m_StpCtx.DAttrCY.ipZ =
  464. m_StpCtx.iDYCY * m_StpCtx.pCtx->iZStride +
  465. m_StpCtx.iDXCY * m_StpCtx.pCtx->iZStep;
  466. m_StpCtx.DAttrNC.ipZ =
  467. m_StpCtx.iDYNC * m_StpCtx.pCtx->iZStride +
  468. m_StpCtx.iDXNC * m_StpCtx.pCtx->iZStep;
  469. }
  470. // check for vertices in/out of diamond
  471. BOOL bV0InDiamond = PointDiamondCheck( iX0 - (iPixX0 << LINE_FIX),
  472. iY0 - (iPixY0 << LINE_FIX),
  473. bSlopeIsOne, bSlopeIsPosOne );
  474. BOOL bV1InDiamond = PointDiamondCheck( iX1 - (iPixX1 << LINE_FIX),
  475. iY1 - (iPixY1 << LINE_FIX),
  476. bSlopeIsOne, bSlopeIsPosOne );
  477. #define LINEDIR_CMP( _A, _B ) \
  478. ( bLineMajorNeg ? ( (_A) > (_B) ) : ( (_A) < (_B) ) )
  479. // do first pixel handling - not in or behind diamond
  480. if ( !( bV0InDiamond ||
  481. LINEDIR_CMP( iLineMajor0, iLinePix0 << LINE_FIX ) ) )
  482. {
  483. iLinePix0 += iLinePixStep;
  484. }
  485. // do last-pixel handling - don't pull in extent if past diamond
  486. // (in which case the pixel is always filled) or if in diamond
  487. // and rendering last pixel
  488. if ( !( ( !bV1InDiamond &&
  489. LINEDIR_CMP( iLinePix1 << LINE_FIX, iLineMajor1 ) ||
  490. ( bV1InDiamond &&
  491. m_StpCtx.pCtx->pdwRenderState[D3DRENDERSTATE_LASTPIXEL] ) ) ) )
  492. {
  493. iLinePix1 -= iLinePixStep;
  494. }
  495. // compute extent along major axis
  496. m_StpCtx.cLinePix =
  497. bLineMajorNeg ? iLinePix0 - iLinePix1 + 1 : iLinePix1 - iLinePix0 + 1;
  498. // return if no major extent
  499. if ( m_StpCtx.cLinePix <= 0 )
  500. {
  501. return FALSE;
  502. }
  503. FLOAT fSlope;
  504. FLOAT fMinor0;
  505. // compute final axis-specific line values
  506. if ( iAbsXSize >= iAbsYSize )
  507. {
  508. m_StpCtx.iX = iLinePix0;
  509. if (bLineMajorNeg)
  510. {
  511. m_StpCtx.fDMajor =
  512. (iX0 - (m_StpCtx.iX << LINE_FIX)) * OO_LINE_SNAP;
  513. m_StpCtx.fOoLen = LINE_SNAP / (FLOAT)(iX0 - iX1);
  514. }
  515. else
  516. {
  517. m_StpCtx.fDMajor =
  518. ((m_StpCtx.iX << LINE_FIX) - iX0) * OO_LINE_SNAP;
  519. m_StpCtx.fOoLen = LINE_SNAP / (FLOAT)(iX1 - iX0);
  520. }
  521. fSlope = m_StpCtx.fOoLen * (iY1 - iY0) * OO_LINE_SNAP;
  522. fMinor0 = (iY0 + LINE_FIX_NEAR_HALF) * OO_LINE_SNAP +
  523. m_StpCtx.fDMajor * fSlope;
  524. m_StpCtx.iY = IFLOORF(fMinor0);
  525. m_StpCtx.iLineFrac = SCALED_FRACTION(fMinor0 - m_StpCtx.iY);
  526. m_StpCtx.iDLineFrac = SCALED_FRACTION(fSlope);
  527. }
  528. else
  529. {
  530. m_StpCtx.iY = iLinePix0;
  531. if (bLineMajorNeg)
  532. {
  533. m_StpCtx.fDMajor =
  534. (iY0 - (m_StpCtx.iY << LINE_FIX)) * OO_LINE_SNAP;
  535. m_StpCtx.fOoLen = LINE_SNAP / (FLOAT)(iY0 - iY1);
  536. }
  537. else
  538. {
  539. m_StpCtx.fDMajor =
  540. ((m_StpCtx.iY << LINE_FIX) - iY0) * OO_LINE_SNAP;
  541. m_StpCtx.fOoLen = LINE_SNAP / (FLOAT)(iY1 - iY0);
  542. }
  543. fSlope = m_StpCtx.fOoLen * (iX1 - iX0) * OO_LINE_SNAP;
  544. fMinor0 = (iX0 + iXAdjust) * OO_LINE_SNAP + m_StpCtx.fDMajor * fSlope;
  545. m_StpCtx.iX = IFLOORF(fMinor0);
  546. m_StpCtx.iLineFrac = SCALED_FRACTION(fMinor0 - m_StpCtx.iX);
  547. m_StpCtx.iDLineFrac = SCALED_FRACTION(fSlope);
  548. }
  549. #ifdef LINE_CORRECTION_BIAS
  550. // A fudge factor of one-half is thrown into the correction
  551. // to avoid undershoot due to negative corrections.
  552. // This shifts all the attributes along the line,
  553. // introducing error, but it's better than clamping
  554. // them. This is not done to the coordinates to avoid
  555. // perturbing them.
  556. m_StpCtx.fDMajor += g_fHalf;
  557. #else
  558. // The correction factor is clamped to positive numbers to
  559. // avoid undershooting with attribute values. This won't
  560. // cause overshooting issues because it moves attributes by
  561. // at most one-half.
  562. if (FLOAT_LTZ(m_StpCtx.fDMajor))
  563. {
  564. m_StpCtx.fDMajor = 0;
  565. }
  566. #endif
  567. RSDPFM((RSM_LINES, "Line %.2f,%.2f - %.2f,%.2f\n",
  568. pV0->dvSX, pV0->dvSY, pV1->dvSX, pV1->dvSY));
  569. RSDPFM((RSM_LINES, " %c major, %d,%d, %d pix\n",
  570. (m_StpCtx.uFlags & LNF_X_MAJOR) ? 'X' : 'Y',
  571. m_StpCtx.iX, m_StpCtx.iY, m_StpCtx.cLinePix));
  572. RSDPFM((RSM_LINES, " slope %f, dmajor %f, minor0 %f\n",
  573. fSlope, m_StpCtx.fDMajor, fMinor0));
  574. RSDPFM((RSM_LINES, " frac %d, dfrac %d\n",
  575. m_StpCtx.iLineFrac, m_StpCtx.iDLineFrac));
  576. BOOL bNorm;
  577. // USED checks cannot be combined since TEX_USED is a multibit check.
  578. if ((m_StpCtx.uFlags & PRIMSF_TEX_USED) &&
  579. (m_StpCtx.uFlags & PRIMSF_PERSP_USED) &&
  580. (m_uPpFlags & PPF_NORMALIZE_RHW) &&
  581. NEEDS_NORMALIZE2(pV0->dvRHW, pV1->dvRHW))
  582. {
  583. NormalizeLineRHW(pV0, pV1);
  584. bNorm = TRUE;
  585. }
  586. else
  587. {
  588. bNorm = FALSE;
  589. }
  590. LineSetup_Start(&m_StpCtx, pV0, pV1);
  591. if (bNorm)
  592. {
  593. pV0->dvRHW = m_dvV0RHW;
  594. pV1->dvRHW = m_dvV1RHW;
  595. }
  596. return TRUE;
  597. }