Source code of Windows XP (NT5)
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.

603 lines
19 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright (C) Microsoft Corporation, 2000.
  3. //
  4. // rastprim.cpp
  5. //
  6. // Direct3D Reference Device - Rasterizer Primitive Routines
  7. //
  8. ///////////////////////////////////////////////////////////////////////////////
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. //-----------------------------------------------------------------------------
  12. //
  13. //-----------------------------------------------------------------------------
  14. RefRast::~RefRast()
  15. {
  16. delete m_pLegacyPixelShader;
  17. }
  18. //-----------------------------------------------------------------------------
  19. //
  20. //-----------------------------------------------------------------------------
  21. void RefRast::Init( RefDev* pRD )
  22. {
  23. m_pRD = pRD;
  24. m_bIsLine = FALSE;
  25. m_iFlatVtx = 0;
  26. // initialize attributes xD Persp Clamp
  27. m_Attr[RDATTR_DEPTH ].Init( this, 1, FALSE, TRUE );
  28. m_Attr[RDATTR_FOG ].Init( this, 1, TRUE, TRUE );
  29. m_Attr[RDATTR_COLOR ].Init( this, 4, TRUE, TRUE );
  30. m_Attr[RDATTR_SPECULAR].Init( this, 4, TRUE, TRUE );
  31. m_Attr[RDATTR_TEXTURE0].Init( this, 4, TRUE, FALSE );
  32. m_Attr[RDATTR_TEXTURE1].Init( this, 4, TRUE, FALSE );
  33. m_Attr[RDATTR_TEXTURE2].Init( this, 4, TRUE, FALSE );
  34. m_Attr[RDATTR_TEXTURE3].Init( this, 4, TRUE, FALSE );
  35. m_Attr[RDATTR_TEXTURE4].Init( this, 4, TRUE, FALSE );
  36. m_Attr[RDATTR_TEXTURE5].Init( this, 4, TRUE, FALSE );
  37. m_Attr[RDATTR_TEXTURE6].Init( this, 4, TRUE, FALSE );
  38. m_Attr[RDATTR_TEXTURE7].Init( this, 4, TRUE, FALSE );
  39. m_iPix = 0;
  40. memset( m_bPixelIn, 0, sizeof(m_bPixelIn) );
  41. memset( m_bSampleCovered, 0, sizeof(m_bSampleCovered) );
  42. m_bLegacyPixelShade = TRUE;
  43. m_pCurrentPixelShader = NULL;
  44. m_CurrentPSInst = 0;
  45. #if DBG
  46. {
  47. DWORD v = 0;
  48. if( GetD3DRefRegValue(REG_DWORD, "VerboseCreatePixelShader", &v, sizeof(DWORD)) && v != 0 )
  49. m_bDebugPrintTranslatedPixelShaderTokens = TRUE;
  50. else
  51. m_bDebugPrintTranslatedPixelShaderTokens = FALSE;
  52. }
  53. #endif
  54. // default value registers
  55. UINT i, j;
  56. for( i = 0 ; i < 4; i++ )
  57. {
  58. for( j = 0; j < 4; j++ )
  59. {
  60. m_ZeroReg[i][j] = 0.0f;
  61. m_OneReg[i][j] = 1.0f;
  62. m_TwoReg[i][j] = 2.0f;
  63. }
  64. }
  65. m_bLegacyPixelShade = TRUE;
  66. m_pLegacyPixelShader = NULL;
  67. memset( m_bPixelDiscard, 0, sizeof(m_bPixelDiscard) );
  68. // multi-sample stuff
  69. m_CurrentSample = 0;
  70. m_SampleMask = 0xffffffff;
  71. SetSampleMode( 1, TRUE );
  72. m_bSampleCovered[0][0] =
  73. m_bSampleCovered[0][1] =
  74. m_bSampleCovered[0][2] =
  75. m_bSampleCovered[0][3] = TRUE;
  76. memset( m_TexCvg, 0, sizeof(m_TexCvg) );
  77. memset( m_TexFlt, 0, sizeof(m_TexFlt) );
  78. }
  79. //-----------------------------------------------------------------------------
  80. //
  81. // SampleAndInvertRHW - Sample 1/W at current given location, invert, return
  82. //
  83. //-----------------------------------------------------------------------------
  84. FLOAT RefRast::SampleAndInvertRHW( FLOAT fX, FLOAT fY )
  85. {
  86. FLOAT fPixelRHW = fX*m_fRHWA + fY*m_fRHWB + m_fRHWC;
  87. FLOAT fPixelW = ( 0. != fPixelRHW ) ? ( 1./fPixelRHW ) : ( 0. );
  88. return fPixelW;
  89. }
  90. //-----------------------------------------------------------------------------
  91. //
  92. //
  93. //-----------------------------------------------------------------------------
  94. BOOL
  95. RefRast::EvalPixelPosition( int iPix )
  96. {
  97. BOOL bPixelIn;
  98. if (m_SampleCount > 1)
  99. {
  100. bPixelIn = FALSE; // assume out, then set if any in
  101. // generating multiple samples, so must evaluate all
  102. // sample positions for in/out
  103. do
  104. {
  105. BOOL bPixelSampleIn = GetCurrentSampleMask();
  106. if (!bPixelSampleIn) continue;
  107. // get sample location
  108. INT32 iX = GetCurrentSampleX(iPix);
  109. INT32 iY = GetCurrentSampleY(iPix);
  110. // test each edge
  111. for ( int iEdge=0; iEdge<m_iEdgeCount; iEdge++ )
  112. {
  113. bPixelSampleIn &= m_Edge[iEdge].Test( iX, iY );
  114. if (!bPixelSampleIn) break;
  115. }
  116. m_bSampleCovered[m_CurrentSample][iPix] = bPixelSampleIn;
  117. // accumulate per-sample test into per-pixel test
  118. bPixelIn |= bPixelSampleIn;
  119. } while (NextSample());
  120. }
  121. else
  122. {
  123. bPixelIn = TRUE; // assume pixel is inside all edges
  124. // single sample, so just test pixel center
  125. for ( int iEdge=0; iEdge<m_iEdgeCount; iEdge++ )
  126. {
  127. bPixelIn &= m_Edge[iEdge].Test( m_iX[iPix]<<4, m_iY[iPix]<<4 );
  128. if (!bPixelIn) break;
  129. }
  130. }
  131. return bPixelIn;
  132. }
  133. ///////////////////////////////////////////////////////////////////////////////
  134. //
  135. // Triangle (& Point) Setup
  136. //
  137. ///////////////////////////////////////////////////////////////////////////////
  138. //-----------------------------------------------------------------------------
  139. //
  140. // PerTriangleSetup - Per-triangle portion of triangle setup excluding any
  141. // per-edge or per-attribute work. Includes snapping of x,y coords to n.4
  142. // grid to enable subsequent edge computations to be exact fixed point;
  143. // computation of determinant; culling; computation and intersection tests
  144. // of scan area; and setup of perspective correction function.
  145. //
  146. //-----------------------------------------------------------------------------
  147. BOOL RefRast::PerTriangleSetup(
  148. FLOAT* pVtx0, FLOAT* pVtx1, FLOAT* pVtx2,
  149. DWORD CullMode,
  150. RECT* pClip)
  151. {
  152. m_bIsLine = FALSE;
  153. FLOAT fX0 = *(pVtx0+0);
  154. FLOAT fY0 = *(pVtx0+1);
  155. FLOAT fX1 = *(pVtx1+0);
  156. FLOAT fY1 = *(pVtx1+1);
  157. FLOAT fX2 = *(pVtx2+0);
  158. FLOAT fY2 = *(pVtx2+1);
  159. // compute fixed point x,y coords snapped to n.4 with nearest-even round
  160. m_iX0 = FloatToNdot4(fX0);
  161. m_iY0 = FloatToNdot4(fY0);
  162. m_iX1 = FloatToNdot4(fX1);
  163. m_iY1 = FloatToNdot4(fY1);
  164. m_iX2 = FloatToNdot4(fX2);
  165. m_iY2 = FloatToNdot4(fY2);
  166. // compute integer deltas
  167. INT32 iDelX10 = m_iX1 - m_iX0;
  168. INT32 iDelX02 = m_iX0 - m_iX2;
  169. INT32 iDelY01 = m_iY0 - m_iY1;
  170. INT32 iDelY20 = m_iY2 - m_iY0;
  171. // compute determinant in n.8 fixed point (n.4 * n.4 = n.8)
  172. m_iDet =
  173. ( (INT64)iDelX10 * (INT64)iDelY20 ) -
  174. ( (INT64)iDelX02 * (INT64)iDelY01 );
  175. // check for degeneracy (no area)
  176. if ( 0 == m_iDet ) { return TRUE; }
  177. // do culling
  178. switch ( CullMode )
  179. {
  180. case D3DCULL_NONE: break;
  181. case D3DCULL_CW: if ( m_iDet > 0 ) { return TRUE; } break;
  182. case D3DCULL_CCW: if ( m_iDet < 0 ) { return TRUE; } break;
  183. }
  184. // compute bounding box for scan area
  185. FLOAT fXMin = MIN( fX0, MIN( fX1, fX2 ) );
  186. FLOAT fXMax = MAX( fX0, MAX( fX1, fX2 ) );
  187. FLOAT fYMin = MIN( fY0, MIN( fY1, fY2 ) );
  188. FLOAT fYMax = MAX( fY0, MAX( fY1, fY2 ) );
  189. // convert to integer (round to +inf)
  190. m_iXMin = (INT32)(fXMin+.5);
  191. m_iXMax = (INT32)(fXMax+.5);
  192. m_iYMin = (INT32)(fYMin+.5);
  193. m_iYMax = (INT32)(fYMax+.5);
  194. // clip bbox to rendering surface
  195. m_iXMin = MAX( m_iXMin, pClip->left );
  196. m_iXMax = MIN( m_iXMax, pClip->right );
  197. m_iYMin = MAX( m_iYMin, pClip->top );
  198. m_iYMax = MIN( m_iYMax, pClip->bottom );
  199. // reject if no coverage
  200. if ( ( m_iXMin < pClip->left ) ||
  201. ( m_iXMax > pClip->right ) ||
  202. ( m_iYMin < pClip->top ) ||
  203. ( m_iYMax > pClip->bottom ) )
  204. {
  205. return TRUE;
  206. }
  207. // compute float versions of snapped coord data
  208. m_fX0 = (FLOAT)m_iX0 * 1.0F/16.0F;
  209. m_fY0 = (FLOAT)m_iY0 * 1.0F/16.0F;
  210. m_fDelX10 = (FLOAT)iDelX10 * 1.0F/16.0F;
  211. m_fDelX02 = (FLOAT)iDelX02 * 1.0F/16.0F;
  212. m_fDelY01 = (FLOAT)iDelY01 * 1.0F/16.0F;
  213. m_fDelY20 = (FLOAT)iDelY20 * 1.0F/16.0F;
  214. // compute inverse determinant
  215. FLOAT fDet = (1./(FLOAT)(1<<8)) * (FLOAT)m_iDet;
  216. m_fTriOODet = 1.f/fDet;
  217. // compute linear function for 1/W (for perspective correction)
  218. m_fRHW0 = *(pVtx0+3);
  219. m_fRHW1 = *(pVtx1+3);
  220. m_fRHW2 = *(pVtx2+3);
  221. // compute linear deltas along two edges
  222. FLOAT fDelAttrib10 = m_fRHW1 - m_fRHW0;
  223. FLOAT fDelAttrib20 = m_fRHW2 - m_fRHW0;
  224. // compute A & B terms (dVdX and dVdY)
  225. m_fRHWA = m_fTriOODet * ( fDelAttrib10 * m_fDelY20 + fDelAttrib20 * m_fDelY01 );
  226. m_fRHWB = m_fTriOODet * ( fDelAttrib20 * m_fDelX10 + fDelAttrib10 * m_fDelX02 );
  227. // compute C term (Fv = A*Xv + B*Yv + C => C = Fv - A*Xv - B*Yv)
  228. m_fRHWC = m_fRHW0 - ( m_fRHWA * m_fX0 ) - ( m_fRHWB * m_fY0 );
  229. return FALSE;
  230. }
  231. ///////////////////////////////////////////////////////////////////////////////
  232. //
  233. // Line Setup & Evaluate
  234. //
  235. ///////////////////////////////////////////////////////////////////////////////
  236. //-----------------------------------------------------------------------------
  237. //
  238. // PointDiamondCheck - Tests if vertex is within diamond of nearest candidate
  239. // position. The +.5 (lower-right) tests are used because this is pixel-relative
  240. // test - this corresponds to an upper-left test for a vertex-relative position.
  241. //
  242. //-----------------------------------------------------------------------------
  243. static BOOL
  244. PointDiamondCheck(
  245. INT32 iXFrac, INT32 iYFrac,
  246. BOOL bSlopeIsOne, BOOL bSlopeIsPosOne )
  247. {
  248. const INT32 iPosHalf = 0x8;
  249. const INT32 iNegHalf = -0x8;
  250. INT32 iFracAbsSum = labs( iXFrac ) + labs( iYFrac );
  251. // return TRUE if point is in fully-exclusive diamond
  252. if ( iFracAbsSum < iPosHalf ) return TRUE;
  253. // else return TRUE if diamond is on left or top extreme of point
  254. if ( ( iXFrac == ( bSlopeIsPosOne ? iNegHalf : iPosHalf ) ) &&
  255. ( iYFrac == 0 ) )
  256. return TRUE;
  257. if ( ( iYFrac == iPosHalf ) &&
  258. ( iXFrac == 0 ) )
  259. return TRUE;
  260. // return true if slope is one, vertex is on edge, and (other conditions...)
  261. if ( bSlopeIsOne && ( iFracAbsSum == iPosHalf ) )
  262. {
  263. if ( bSlopeIsPosOne && ( iXFrac < 0 ) && ( iYFrac > 0 ) )
  264. return TRUE;
  265. if ( !bSlopeIsPosOne && ( iXFrac > 0 ) && ( iYFrac > 0 ) )
  266. return TRUE;
  267. }
  268. return FALSE;
  269. }
  270. //-----------------------------------------------------------------------------
  271. //
  272. // PerLineSetup - Does per-line setup including scan conversion
  273. //
  274. // This implements the Grid Intersect Quanization (GIQ) convention (which is
  275. // also used in Windows).
  276. //
  277. // Returns: TRUE if line is discarded; FALSE if line to be drawn
  278. //
  279. //-----------------------------------------------------------------------------
  280. BOOL
  281. RefRast::PerLineSetup(
  282. FLOAT* pVtx0, FLOAT* pVtx1,
  283. BOOL bLastPixel,
  284. RECT* pClip)
  285. {
  286. m_bIsLine = TRUE;
  287. FLOAT fX0 = *(pVtx0+0);
  288. FLOAT fY0 = *(pVtx0+1);
  289. FLOAT fX1 = *(pVtx1+0);
  290. FLOAT fY1 = *(pVtx1+1);
  291. // compute fixed point x,y coords snapped to n.4 with nearest-even round
  292. m_iX0 = FloatToNdot4( fX0 );
  293. m_iY0 = FloatToNdot4( fY0 );
  294. m_iX1 = FloatToNdot4( fX1 );
  295. m_iY1 = FloatToNdot4( fY1 );
  296. // compute x,y extents of the line (fixed point)
  297. INT32 iXSize = m_iX1 - m_iX0;
  298. INT32 iYSize = m_iY1 - m_iY0;
  299. if ( ( iXSize == 0 ) && ( iYSize == 0 ) ) { return TRUE; }
  300. // determine major direction and compute line function
  301. // use GreaterEqual compare here so X major will be used when slope is
  302. // exactly one - this forces the per-pixel evaluation to be done on the
  303. // Y axis and thus adheres to the rule of inclusive right (instead of
  304. // inclusive left) for slope == 1 cases
  305. if ( labs( iXSize ) >= labs( iYSize ) )
  306. {
  307. // here for X major
  308. m_bLineXMajor = TRUE;
  309. m_fLineMajorLength = (FLOAT)iXSize * (1./16.);
  310. // line function: y = F(x) = ( [0]*x + [1] ) / [2]
  311. m_iLineEdgeFunc[0] = iYSize;
  312. m_iLineEdgeFunc[1] = (INT64)m_iY0*(INT64)m_iX1 - (INT64)m_iY1*(INT64)m_iX0;
  313. m_iLineEdgeFunc[2] = iXSize;
  314. }
  315. else
  316. {
  317. // here for Y major
  318. m_bLineXMajor = FALSE;
  319. m_fLineMajorLength = (FLOAT)iYSize * (1./16.);
  320. // line function: x = F(y) = ( [0]*y + [1] ) / [2]
  321. m_iLineEdgeFunc[0] = iXSize;
  322. m_iLineEdgeFunc[1] = (INT64)m_iX0*(INT64)m_iY1 - (INT64)m_iX1*(INT64)m_iY0;
  323. m_iLineEdgeFunc[2] = iYSize;
  324. }
  325. BOOL bSlopeIsOne = ( labs( iXSize ) == labs( iYSize ) );
  326. BOOL bSlopeIsPosOne =
  327. bSlopeIsOne &&
  328. ( ( (FLOAT)m_iLineEdgeFunc[0]/(FLOAT)m_iLineEdgeFunc[2] ) > 0. );
  329. // compute candidate pixel location for line endpoints
  330. //
  331. // n n
  332. // O-------* *-------O
  333. // n-.5 n+.5 n-.5 n+.5
  334. //
  335. // Nearest Ceiling Nearest Floor
  336. //
  337. // always nearest ceiling for Y; use nearest floor for X for exception (slope == +1)
  338. // case else use nearest ceiling
  339. //
  340. // nearest ceiling of Y is ceil( Y - .5), and is done by converting to floor via:
  341. //
  342. // ceil( A/B ) = floor( (A+B-1)/B )
  343. //
  344. // where A is coordinate - .5, and B is 0x10 (thus A/B is an n.4 fixed point number)
  345. //
  346. // A+B-1 = ( (Y - half) + B - 1 = ( (Y-0x8) + 0x10 - 0x1 = Y + 0x7
  347. // since B is 2**4, divide by B is right shift by 4
  348. //
  349. INT32 iPixX0 = ( m_iX0 + ( bSlopeIsPosOne ? 0x8 : 0x7 ) ) >> 4;
  350. INT32 iPixX1 = ( m_iX1 + ( bSlopeIsPosOne ? 0x8 : 0x7 ) ) >> 4;
  351. INT32 iPixY0 = ( m_iY0 + 0x7 ) >> 4;
  352. INT32 iPixY1 = ( m_iY1 + 0x7 ) >> 4;
  353. // check for vertices in/out of diamond
  354. BOOL bV0InDiamond = PointDiamondCheck( m_iX0 - (iPixX0<<4), m_iY0 - (iPixY0<<4), bSlopeIsOne, bSlopeIsPosOne );
  355. BOOL bV1InDiamond = PointDiamondCheck( m_iX1 - (iPixX1<<4), m_iY1 - (iPixY1<<4), bSlopeIsOne, bSlopeIsPosOne );
  356. // compute step value
  357. m_iLineStep = ( m_fLineMajorLength > 0 ) ? ( +1 ) : ( -1 );
  358. // compute float and integer major start (V0) and end (V1) positions
  359. INT32 iLineMajor0 = ( m_bLineXMajor ) ? ( m_iX0 ) : ( m_iY0 );
  360. INT32 iLineMajor1 = ( m_bLineXMajor ) ? ( m_iX1 ) : ( m_iY1 );
  361. m_iLineMin = ( m_bLineXMajor ) ? ( iPixX0 ) : ( iPixY0 );
  362. m_iLineMax = ( m_bLineXMajor ) ? ( iPixX1 ) : ( iPixY1 );
  363. // need to do lots of compares which are flipped if major direction is negative
  364. #define LINEDIR_CMP( _A, _B ) \
  365. ( ( m_fLineMajorLength > 0 ) ? ( (_A) < (_B) ) : ( (_A) > (_B) ) )
  366. // do first pixel handling - keep first pixel if not in or behind diamond
  367. if ( !( bV0InDiamond || LINEDIR_CMP( iLineMajor0, (m_iLineMin<<4) ) ) )
  368. {
  369. m_iLineMin += m_iLineStep;
  370. }
  371. // do last-pixel handling - keep last pixel if past diamond (in which case
  372. // the pixel is always filled) or if in diamond and rendering last pixel
  373. if ( !( ( !bV1InDiamond && LINEDIR_CMP( (m_iLineMax<<4), iLineMajor1 ) ) ||
  374. ( bV1InDiamond && bLastPixel ) ) )
  375. {
  376. m_iLineMax -= m_iLineStep;
  377. }
  378. // return if no (major) extent (both before and after clamping to render buffer)
  379. if ( LINEDIR_CMP( m_iLineMax, m_iLineMin ) ) return TRUE;
  380. // snap major extent to render buffer
  381. INT16 iRendBufMajorMin = m_bLineXMajor ? pClip->left : pClip->top;
  382. INT16 iRendBufMajorMax = m_bLineXMajor ? pClip->right : pClip->bottom;
  383. if ( ( ( m_iLineMin < iRendBufMajorMin ) &&
  384. ( m_iLineMax < iRendBufMajorMin ) ) ||
  385. ( ( m_iLineMin > iRendBufMajorMax ) &&
  386. ( m_iLineMax > iRendBufMajorMax ) ) ) { return TRUE; }
  387. m_iLineMin = MAX( 0, MIN( iRendBufMajorMax, m_iLineMin ) );
  388. m_iLineMax = MAX( 0, MIN( iRendBufMajorMax, m_iLineMax ) );
  389. // return if no (major) extent
  390. if ( LINEDIR_CMP( m_iLineMax, m_iLineMin ) ) return TRUE;
  391. // number of steps to iterate
  392. m_cLineSteps = abs( m_iLineMax - m_iLineMin );
  393. // initial state for per-pixel line iterator
  394. m_iMajorCoord = m_iLineMin;
  395. // compute float versions of snapped coord data
  396. m_fX0 = (FLOAT)m_iX0 * 1.0F/16.0F;
  397. m_fY0 = (FLOAT)m_iY0 * 1.0F/16.0F;
  398. // compute linear function for 1/W (for perspective correction)
  399. m_fRHW0 = *(pVtx0+3);
  400. m_fRHW1 = *(pVtx1+3);
  401. FLOAT fDelta = ( m_fRHW1 - m_fRHW0 ) / m_fLineMajorLength;
  402. m_fRHWA = ( m_bLineXMajor ) ? ( fDelta ) : ( 0. );
  403. m_fRHWB = ( m_bLineXMajor ) ? ( 0. ) : ( fDelta );
  404. m_fRHWC = m_fRHW0 - ( m_fRHWA * m_fX0 ) - ( m_fRHWB * m_fY0 );
  405. return FALSE;
  406. }
  407. //-----------------------------------------------------------------------------
  408. //
  409. // DivRoundDown(A,B) = ceiling(A/B - 1/2)
  410. //
  411. // ceiling(A/B - 1/2) == floor(A/B + 1/2 - epsilon)
  412. // == floor( (A + (B/2 - epsilon))/B )
  413. //
  414. // Does correct thing for all sign combinations of A and B.
  415. //
  416. //-----------------------------------------------------------------------------
  417. static INT64
  418. DivRoundDown(INT64 iA, INT32 iB)
  419. {
  420. INT32 i = 0;
  421. static const INT32 iEps[3] =
  422. {
  423. 1, // iA > 0, iB > 0
  424. 0, // iA < 0, iB > 0 OR iA > 0, iB < 0
  425. 1 // iA < 0, iB < 0
  426. };
  427. if (iA < 0)
  428. {
  429. i++;
  430. iA = -iA;
  431. }
  432. if (iB < 0)
  433. {
  434. i++;
  435. iB = -iB;
  436. }
  437. iA += (iB-iEps[i]) >> 1;
  438. iA /= iB;
  439. if (iEps[i] == 0)
  440. iA = -iA;
  441. return(iA);
  442. }
  443. //-----------------------------------------------------------------------------
  444. //
  445. // DoScanCnvLine - Walks the line major axis, computes the appropriate minor
  446. // axis coordinate, and generates pixels.
  447. //
  448. //-----------------------------------------------------------------------------
  449. void
  450. RefRast::StepLine( void )
  451. {
  452. // evaluate line function to compute minor coord for this major
  453. INT64 iMinorCoord =
  454. ( ( m_iLineEdgeFunc[0] * (INT64)(m_iMajorCoord<<4) ) + m_iLineEdgeFunc[1] );
  455. iMinorCoord = DivRoundDown(iMinorCoord, m_iLineEdgeFunc[2]<<4);
  456. // grab x,y
  457. m_iX[0] = m_bLineXMajor ? m_iMajorCoord : iMinorCoord;
  458. m_iY[0] = m_bLineXMajor ? iMinorCoord : m_iMajorCoord;
  459. // step major for next evaluation
  460. m_iMajorCoord += m_iLineStep;
  461. }
  462. ///////////////////////////////////////////////////////////////////////////////
  463. //
  464. // Multi-Sample Controls
  465. //
  466. ///////////////////////////////////////////////////////////////////////////////
  467. #define _SetSampleDelta( _SampleNumber, _XOffset, _YOffset ) \
  468. { \
  469. m_SampleDelta[_SampleNumber][0] = ((INT32)((_XOffset)*16.F)); \
  470. m_SampleDelta[_SampleNumber][1] = ((INT32)((_YOffset)*16.F)); \
  471. }
  472. void
  473. RefRast::SetSampleMode( UINT MultiSamples, BOOL bAntialias )
  474. {
  475. switch (MultiSamples)
  476. {
  477. default:
  478. case 1:
  479. m_SampleCount = 1;
  480. _SetSampleDelta( 0, 0., 0. );
  481. break;
  482. case 4:
  483. m_SampleCount = 4;
  484. _SetSampleDelta( 0, -.25, -.25 );
  485. _SetSampleDelta( 1, +.25, -.25 );
  486. _SetSampleDelta( 2, +.25, +.25 );
  487. _SetSampleDelta( 3, -.25, +.25 );
  488. break;
  489. case 9:
  490. m_SampleCount = 9;
  491. _SetSampleDelta( 0, -.333, -.333 );
  492. _SetSampleDelta( 1, -.333, 0.0 );
  493. _SetSampleDelta( 2, -.333, +.333 );
  494. _SetSampleDelta( 3, 0.0, -.333 );
  495. _SetSampleDelta( 4, 0.0, 0.0 );
  496. _SetSampleDelta( 5, 0.0, +.333 );
  497. _SetSampleDelta( 6, +.333, -.333 );
  498. _SetSampleDelta( 7, +.333, 0.0 );
  499. _SetSampleDelta( 8, +.333, +.333 );
  500. break;
  501. }
  502. // if not FSAA then sample all at pixel center
  503. if (!bAntialias)
  504. {
  505. for (UINT Sample=0; Sample<m_SampleCount; Sample++)
  506. {
  507. _SetSampleDelta( Sample, 0., 0. );
  508. }
  509. }
  510. m_CurrentSample = 0;
  511. m_bSampleCovered[0][0] =
  512. m_bSampleCovered[0][1] =
  513. m_bSampleCovered[0][2] =
  514. m_bSampleCovered[0][3] = TRUE;
  515. }
  516. ///////////////////////////////////////////////////////////////////////////////
  517. // end