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.

700 lines
23 KiB

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