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