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.

397 lines
14 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright (C) Microsoft Corporation, 1998.
  3. //
  4. // scancnv.cpp
  5. //
  6. // Direct3D Reference Rasterizer - Primitive Scan Conversion
  7. //
  8. ///////////////////////////////////////////////////////////////////////////////
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. ///////////////////////////////////////////////////////////////////////////////
  12. // //
  13. // Scan Conversion Utilities //
  14. // //
  15. ///////////////////////////////////////////////////////////////////////////////
  16. //-----------------------------------------------------------------------------
  17. //
  18. // ComputePixelAttrib(Clamp/Tex) - Evaluates given linear function at current
  19. // scan conversion position (m_SCCS.iX,iY). Return is FLOAT value.
  20. //
  21. // Clamp version clamps result to 0. to 1. range.
  22. //
  23. // Tex version does texture coordinate function (unclamped).
  24. //
  25. //-----------------------------------------------------------------------------
  26. FLOAT
  27. ReferenceRasterizer::ComputePixelAttrib( int iAttrib )
  28. {
  29. return m_pSCS->AttribFuncs[iAttrib].Eval();
  30. }
  31. FLOAT
  32. ReferenceRasterizer::ComputePixelAttribClamp( int iAttrib )
  33. {
  34. FLOAT fValue = ComputePixelAttrib( iAttrib );
  35. fValue = MAX( MIN( fValue, 1. ), 0. );
  36. return fValue;
  37. }
  38. //
  39. // iStage specifies set of transformed texture coordinates
  40. // iCrd specifies which value within coord
  41. FLOAT
  42. ReferenceRasterizer::ComputePixelAttribTex( int iStage, int iCrd )
  43. {
  44. return m_pSCS->TextureFuncs[iStage][iCrd].Eval(iStage);
  45. }
  46. //-----------------------------------------------------------------------------
  47. //
  48. // ComputeFogIntensity - Computes scalar fog intensity value and writes it to
  49. // the RRPixel.FogIntensity value.
  50. //
  51. //-----------------------------------------------------------------------------
  52. void
  53. ReferenceRasterizer::ComputeFogIntensity( RRPixel& Pixel )
  54. {
  55. FLOAT fFogDensity, fPow;
  56. FLOAT fFogStart, fFogEnd;
  57. // select fog index - this is either Z or W depending on the W range
  58. //
  59. // use Z if projection matrix is set to an affine projection, else use W
  60. // (both for perspective projection and an unset projection matrix - the
  61. // latter is preferred for legacy content which uses TLVERTEX)
  62. //
  63. FLOAT fFogIndex =
  64. ( ( 1.f == m_pRenderTarget->m_fWRange[0] ) &&
  65. ( 1.f == m_pRenderTarget->m_fWRange[1] ) )
  66. ? ( MAX( MIN( ComputePixelAttribClamp( ATTRFUNC_Z ),
  67. m_pSCS->fDepthMax ), m_pSCS->fDepthMin ) ) // use clamped Z for affine projection
  68. : ( Pixel.fW ); // use W for non-affine projection
  69. // compute fog intensity
  70. if ( m_dwRenderState[D3DRENDERSTATE_FOGENABLE] )
  71. {
  72. // select between vertex and table fog - vertex fog is selected if
  73. // fog is enabled but the renderstate fog table mode is disabled
  74. switch ( m_dwRenderState[D3DRENDERSTATE_FOGTABLEMODE] )
  75. {
  76. default:
  77. case D3DFOG_NONE:
  78. // table fog disabled, so use interpolated vertex fog value for fog intensity
  79. Pixel.FogIntensity = ComputePixelAttribClamp( ATTRFUNC_F );
  80. break;
  81. case D3DFOG_EXP:
  82. fFogDensity = m_fRenderState[D3DRENDERSTATE_FOGTABLEDENSITY];
  83. fPow = fFogDensity * fFogIndex;
  84. // note that exp(-x) returns a result in the range (0.0, 1.0]
  85. // for x >= 0
  86. Pixel.FogIntensity = (float)exp( -fPow );
  87. break;
  88. case D3DFOG_EXP2:
  89. fFogDensity = m_fRenderState[D3DRENDERSTATE_FOGTABLEDENSITY];
  90. fPow = fFogDensity * fFogIndex;
  91. Pixel.FogIntensity = (float)exp( -(fPow*fPow) );
  92. break;
  93. case D3DFOG_LINEAR:
  94. fFogStart = m_fRenderState[D3DRENDERSTATE_FOGTABLESTART];
  95. fFogEnd = m_fRenderState[D3DRENDERSTATE_FOGTABLEEND];
  96. if (fFogIndex >= fFogEnd)
  97. {
  98. Pixel.FogIntensity = 0.0f;
  99. }
  100. else if (fFogIndex <= fFogStart)
  101. {
  102. Pixel.FogIntensity = 1.0f;
  103. }
  104. else
  105. {
  106. Pixel.FogIntensity = ( fFogEnd - fFogIndex ) / ( fFogEnd - fFogStart );
  107. }
  108. break;
  109. }
  110. }
  111. }
  112. //-----------------------------------------------------------------------------
  113. //
  114. // DoScanCnvGenPixel - This is called for each generated pixel, and extracts and
  115. // processes attributes from the interpolator state, and passes the pixels on to
  116. // the pixel processing module.
  117. //
  118. //-----------------------------------------------------------------------------
  119. void
  120. ReferenceRasterizer::DoScanCnvGenPixel( RRCvgMask CvgMask, BOOL bTri )
  121. {
  122. // set per-pixel state for attribute evaluators
  123. m_pSCS->AttribFuncStatic.SetPerPixelData( m_pSCS->iX, m_pSCS->iY );
  124. // instantiate and fill out pixel struct
  125. RRPixel Pixel;
  126. memset(&Pixel, 0, sizeof(Pixel));
  127. Pixel.iX = m_pSCS->iX;
  128. Pixel.iY = m_pSCS->iY;
  129. Pixel.fW = m_pSCS->AttribFuncStatic.GetPixelW();
  130. Pixel.CvgMask = CvgMask;
  131. Pixel.Depth.SetSType(m_pRenderTarget->m_DepthSType);
  132. // get depth from clamp interpolator and clamp
  133. if ( m_dwRenderState[D3DRENDERSTATE_ZENABLE] ||
  134. m_dwRenderState[D3DRENDERSTATE_FOGENABLE])
  135. {
  136. if ( D3DZB_USEW == m_dwRenderState[D3DRENDERSTATE_ZENABLE] )
  137. {
  138. // depth buffering with W value
  139. FLOAT fW = Pixel.fW;
  140. // clamp to primitive range (due to sampling outside primitive for antialiasing)
  141. // (triangles only)
  142. if ( bTri )
  143. {
  144. fW = MAX( MIN( fW, m_pSCS->fDepthMax ), m_pSCS->fDepthMin );
  145. }
  146. // apply normalization to get to 0. to 1. range
  147. fW = (fW - m_fWBufferNorm[0]) * m_fWBufferNorm[1];
  148. Pixel.Depth = fW;
  149. }
  150. else
  151. {
  152. // depth buffering with Z value
  153. FLOAT fZ = ComputePixelAttribClamp( ATTRFUNC_Z );
  154. // clamp to primitive range (due to sampling outside primitive for antialiasing)
  155. // (triangles only)
  156. if ( bTri )
  157. {
  158. fZ = MAX( MIN( fZ, m_pSCS->fDepthMax ), m_pSCS->fDepthMin );
  159. }
  160. Pixel.Depth = fZ;
  161. }
  162. // snap off extra bits by converting to/from buffer format
  163. //
  164. // this is mainly because of storing RRDepth values in the fragment buffer
  165. // and then comparing these (higher resolution) values to the buffer value
  166. // when forming the fragment lists at each pixel - cleanly snapping off the
  167. // extra bits here solves this problem
  168. //
  169. switch ( m_pRenderTarget->m_DepthSType)
  170. {
  171. case RR_STYPE_Z16S0: Pixel.Depth = UINT16( Pixel.Depth ); break;
  172. case RR_STYPE_Z24S4:
  173. case RR_STYPE_Z24S8: Pixel.Depth = UINT32( Pixel.Depth ); break;
  174. case RR_STYPE_Z15S1: Pixel.Depth = UINT16( Pixel.Depth ); break;
  175. case RR_STYPE_Z32S0: Pixel.Depth = UINT32( Pixel.Depth ); break;
  176. case RR_STYPE_S1Z15: Pixel.Depth = UINT16( Pixel.Depth ); break;
  177. case RR_STYPE_S4Z24:
  178. case RR_STYPE_S8Z24: Pixel.Depth = UINT32( Pixel.Depth ); break;
  179. }
  180. }
  181. // set pixel diffuse color from clamped interpolator values
  182. Pixel.Color.A = ComputePixelAttribClamp( ATTRFUNC_A );
  183. Pixel.Color.R = ComputePixelAttribClamp( ATTRFUNC_R );
  184. Pixel.Color.G = ComputePixelAttribClamp( ATTRFUNC_G );
  185. Pixel.Color.B = ComputePixelAttribClamp( ATTRFUNC_B );
  186. // set pixel specular color from clamped interpolator values
  187. if ( m_qwFVFControl & D3DFVF_SPECULAR )
  188. {
  189. Pixel.Specular.A = ComputePixelAttribClamp( ATTRFUNC_SA );
  190. Pixel.Specular.R = ComputePixelAttribClamp( ATTRFUNC_SR );
  191. Pixel.Specular.G = ComputePixelAttribClamp( ATTRFUNC_SG );
  192. Pixel.Specular.B = ComputePixelAttribClamp( ATTRFUNC_SB );
  193. }
  194. // compute fog intensity
  195. ComputeFogIntensity( Pixel );
  196. // send to pixel processor
  197. DoPixel( Pixel );
  198. }
  199. ///////////////////////////////////////////////////////////////////////////////
  200. // //
  201. // Triangle Scan Conversion //
  202. // //
  203. ///////////////////////////////////////////////////////////////////////////////
  204. //-----------------------------------------------------------------------------
  205. //
  206. // DoScanCnvTri - Scans the bounding box of the triangle and generates pixels.
  207. //
  208. //-----------------------------------------------------------------------------
  209. void
  210. ReferenceRasterizer::DoScanCnvTri( int iEdgeCount )
  211. {
  212. DPFM(3,RAST,("DoScanCnvTri:\n"))
  213. //
  214. // do simple scan of surface-intersected triangle bounding box
  215. //
  216. for ( m_pSCS->iY = m_pSCS->iYMin;
  217. m_pSCS->iY <= m_pSCS->iYMax;
  218. m_pSCS->iY++ )
  219. {
  220. for ( m_pSCS->iX = m_pSCS->iXMin;
  221. m_pSCS->iX <= m_pSCS->iXMax;
  222. m_pSCS->iX++ )
  223. {
  224. RRCvgMask CvgMask = 0xFFFF; // assume pixel is inside all edges
  225. for ( int iEdge=0; iEdge<iEdgeCount; iEdge++ )
  226. {
  227. if ( m_bFragmentProcessingEnabled )
  228. {
  229. CvgMask &= m_pSCS->EdgeFuncs[iEdge].AATest( m_pSCS->iX, m_pSCS->iY) ;
  230. }
  231. else
  232. {
  233. CvgMask &= m_pSCS->EdgeFuncs[iEdge].PSTest( m_pSCS->iX, m_pSCS->iY) ;
  234. }
  235. }
  236. if ( CvgMask != 0x0000 )
  237. {
  238. // pixel is not out, so process it
  239. DoScanCnvGenPixel( CvgMask, TRUE );
  240. }
  241. }
  242. }
  243. }
  244. ///////////////////////////////////////////////////////////////////////////////
  245. // //
  246. // Line Scan Conversion //
  247. // //
  248. ///////////////////////////////////////////////////////////////////////////////
  249. //----------------------------------------------------------------------------
  250. //
  251. // LinePatternStateMachine
  252. //
  253. // Runs the line pattern state machine and returns TRUE if the pixel is to be
  254. // drawn, false otherwise. Always returns true if wRepeatFactor is 0, which
  255. // means pattern is disabled.
  256. //
  257. //----------------------------------------------------------------------------
  258. static BOOL LinePatternStateMachine(DWORD dwLinePattern, WORD& wRepeati, WORD& wPatterni)
  259. {
  260. union
  261. {
  262. D3DLINEPATTERN LPat;
  263. DWORD dwLPat;
  264. } LinePat;
  265. LinePat.dwLPat = dwLinePattern;
  266. if (LinePat.LPat.wRepeatFactor)
  267. {
  268. WORD wBit = (LinePat.LPat.wLinePattern >> wPatterni) & 1;
  269. if (++wRepeati >= LinePat.LPat.wRepeatFactor)
  270. {
  271. wRepeati = 0;
  272. wPatterni = (wPatterni+1) & 0xf;
  273. }
  274. return (BOOL)wBit;
  275. }
  276. else
  277. {
  278. return TRUE;
  279. }
  280. }
  281. //-----------------------------------------------------------------------------
  282. //
  283. // DivRoundDown(A,B) = ceiling(A/B - 1/2)
  284. //
  285. // ceiling(A/B - 1/2) == floor(A/B + 1/2 - epsilon)
  286. // == floor( (A + (B/2 - epsilon))/B )
  287. //
  288. // Does correct thing for all sign combinations of A and B.
  289. //
  290. //-----------------------------------------------------------------------------
  291. INT64 DivRoundDown(INT64 iA, INT32 iB)
  292. {
  293. INT32 i = 0;
  294. static const INT32 iEps[3] =
  295. {
  296. 1, // iA > 0, iB > 0
  297. 0, // iA < 0, iB > 0 OR iA > 0, iB < 0
  298. 1 // iA < 0, iB < 0
  299. };
  300. if (iA < 0)
  301. {
  302. i++;
  303. iA = -iA;
  304. }
  305. if (iB < 0)
  306. {
  307. i++;
  308. iB = -iB;
  309. }
  310. iA += (iB-iEps[i]) >> 1;
  311. iA /= iB;
  312. if (iEps[i] == 0)
  313. iA = -iA;
  314. return(iA);
  315. }
  316. //-----------------------------------------------------------------------------
  317. //
  318. // DoScanCnvLine - Walks the line major axis, computes the appropriate minor
  319. // axis coordinate, and generates pixels.
  320. //
  321. //-----------------------------------------------------------------------------
  322. void
  323. ReferenceRasterizer::DoScanCnvLine( void )
  324. {
  325. DPFM(3,RAST,("DoScanCnvLine:\n"))
  326. // step in major axis
  327. INT16 iMajorCoord = m_pSCS->iLineMin;
  328. int cSteps = abs( m_pSCS->iLineMax - m_pSCS->iLineMin );
  329. // state for line pattern state machine
  330. WORD wRepeati = 0;
  331. WORD wPatterni = 0;
  332. for ( int cStep = 0; cStep <= cSteps; cStep++ )
  333. {
  334. // evaluate line function to compute minor coord for this major
  335. INT64 iMinorCoord =
  336. ( ( m_pSCS->iLineEdgeFunc[0] * (INT64)(iMajorCoord<<4) ) + m_pSCS->iLineEdgeFunc[1] );
  337. iMinorCoord = DivRoundDown(iMinorCoord, m_pSCS->iLineEdgeFunc[2]<<4);
  338. m_pSCS->iX = m_pSCS->bXMajor ? iMajorCoord : iMinorCoord;
  339. m_pSCS->iY = m_pSCS->bXMajor ? iMinorCoord : iMajorCoord;
  340. // check if the point is inside the viewport
  341. if ( ( m_pSCS->iX >= m_pRenderTarget->m_Clip.left ) &&
  342. ( m_pSCS->iX <= m_pRenderTarget->m_Clip.right ) &&
  343. ( m_pSCS->iY >= m_pRenderTarget->m_Clip.top ) &&
  344. ( m_pSCS->iY <= m_pRenderTarget->m_Clip.bottom ) )
  345. {
  346. // The line pattern should have been walked in from its origin, which may have been
  347. // offscreen, to be completely correct.
  348. if (LinePatternStateMachine(m_dwRenderState[D3DRENDERSTATE_LINEPATTERN], wRepeati, wPatterni))
  349. {
  350. DoScanCnvGenPixel( 0xFFFF, FALSE );
  351. }
  352. }
  353. iMajorCoord += m_pSCS->iLineStep;
  354. }
  355. }
  356. ///////////////////////////////////////////////////////////////////////////////
  357. // end