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.

185 lines
7.0 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright (C) Microsoft Corporation, 1998.
  3. //
  4. // EdgeFunc.cpp
  5. //
  6. // Direct3D Reference Rasterizer - Edge Function Processing
  7. //
  8. ///////////////////////////////////////////////////////////////////////////////
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. //-----------------------------------------------------------------------------
  12. //
  13. // ComputeDeterminant - Computes triangle determinant for later use in edge
  14. // functions. Computed in fixed point but returned as single precision
  15. // floating point number.
  16. //
  17. //-----------------------------------------------------------------------------
  18. FLOAT
  19. ComputeDeterminant(
  20. FLOAT fX0, FLOAT fY0,
  21. FLOAT fX1, FLOAT fY1,
  22. FLOAT fX2, FLOAT fY2 )
  23. {
  24. // compute determinant with integer coordinates snapped to n.4 grid
  25. INT32 iDelX10 =
  26. AS_INT32( (DOUBLE)(fX1) + DOUBLE_4_SNAP ) -
  27. AS_INT32( (DOUBLE)(fX0) + DOUBLE_4_SNAP );
  28. INT32 iDelX02 =
  29. AS_INT32( (DOUBLE)(fX0) + DOUBLE_4_SNAP ) -
  30. AS_INT32( (DOUBLE)(fX2) + DOUBLE_4_SNAP );
  31. INT32 iDelY01 =
  32. AS_INT32( (DOUBLE)(fY0) + DOUBLE_4_SNAP ) -
  33. AS_INT32( (DOUBLE)(fY1) + DOUBLE_4_SNAP );
  34. INT32 iDelY20 =
  35. AS_INT32( (DOUBLE)(fY2) + DOUBLE_4_SNAP ) -
  36. AS_INT32( (DOUBLE)(fY0) + DOUBLE_4_SNAP );
  37. // iDet is n.8 fixed point value (n.4 * n.4 = n.8)
  38. INT64 iDet =
  39. ( (INT64)iDelX10 * (INT64)iDelY20 ) -
  40. ( (INT64)iDelX02 * (INT64)iDelY01 );
  41. // convert to float for return
  42. FLOAT fDet = (1./(FLOAT)(1<<8)) * (FLOAT)iDet;
  43. return fDet;
  44. }
  45. //-----------------------------------------------------------------------------
  46. //
  47. // Set - Computes edge function and associated information.
  48. //
  49. // Fragment processing boolean is passed to enable use of better techniques
  50. // than the simple but not particularly good subpixel point sample done here.
  51. //
  52. //-----------------------------------------------------------------------------
  53. void
  54. RREdgeFunc::Set(
  55. FLOAT fX0, FLOAT fY0, FLOAT fX1, FLOAT fY1,
  56. FLOAT fDet, BOOL bFragProcEnable )
  57. {
  58. // compute fixed point x,y coords snapped to n.4 with nearest-even round
  59. INT32 iX0 = AS_INT32( (DOUBLE)fX0 + DOUBLE_4_SNAP );
  60. INT32 iY0 = AS_INT32( (DOUBLE)fY0 + DOUBLE_4_SNAP );
  61. INT32 iX1 = AS_INT32( (DOUBLE)fX1 + DOUBLE_4_SNAP );
  62. INT32 iY1 = AS_INT32( (DOUBLE)fY1 + DOUBLE_4_SNAP );
  63. // compute A,B (gradient) terms - these are n.4 fixed point
  64. m_iA = iY0 - iY1;
  65. m_iB = iX1 - iX0;
  66. // flip gradient signs if backfacing so functions are consistently
  67. // greater than zero outside of primitive
  68. if ( fDet > 0. ) { m_iA = -m_iA; m_iB = -m_iB; }
  69. // compute C term
  70. //
  71. // function is by definition zero at the vertices, so:
  72. // 0 = A*Xv + B*Yv + C => C = - A*Xv - B*Yv
  73. //
  74. // A*Xv & B*Yv are n.4 * n.4 = n.8, so C is n.8 fixed point
  75. m_iC = - ( (INT64)iX0 * (INT64)m_iA ) - ( (INT64)iY0 * (INT64)m_iB );
  76. // compute edge function sign flags - must be done consistently for vertical
  77. // and horizontal cases to adhere to point sample fill rules and avoid
  78. // under- and over-coverage for antialiasing
  79. BOOL bEdgeAEQZero = ( m_iA == 0. );
  80. BOOL bEdgeBEQZero = ( m_iB == 0. );
  81. BOOL bEdgeAGTZero = ( m_iA > 0. );
  82. BOOL bEdgeBGTZero = ( m_iB > 0. );
  83. m_bAPos = bEdgeAEQZero ? bEdgeBGTZero : bEdgeAGTZero;
  84. m_bBPos = bEdgeBEQZero ? bEdgeAGTZero : bEdgeBGTZero;
  85. }
  86. //-----------------------------------------------------------------------------
  87. //
  88. // PSTest - Point sampling test, returns coverage mask of all zero's if point
  89. // is outside the edge, all 1's if point is inside. Supports the Direct3D
  90. // left-top fill rule.
  91. //
  92. //-----------------------------------------------------------------------------
  93. RRCvgMask
  94. RREdgeFunc::PSTest( INT16 iX, INT16 iY )
  95. {
  96. // evaluate edge distance function (n.8 fixed point)
  97. INT64 iEdgeDist =
  98. ( (INT64)m_iA * (INT64)(iX<<4) ) + // n.4 * n.4 = n.8
  99. ( (INT64)m_iB * (INT64)(iY<<4) ) + // n.4 * n.4 = n.8
  100. (INT64)m_iC; // n.8
  101. // pixel sample position is outside edge if distance is > zero
  102. //
  103. // This implements the D3D left-top fill rule
  104. //
  105. // For exactly-on-edge case (distance == zero), the sign of the Y gradient
  106. // is used to determine if the pixel is to be considered inside or outside
  107. // of the edge. For the non-horizontal case, the m_bAPos bit is based
  108. // simply on the sign of the Y slope. This implements the 'left' part of
  109. // the 'left-top' rule.
  110. //
  111. // For the horizontal case, the sign of the B gradient (X slope) is taken
  112. // into account in the computation of the m_bAPos bit when the A gradient
  113. // is exactly zero, which forces a pixel exactly on a 'top' edge to be
  114. // considered in and a pixel exactly on a 'bottom' edge to be considered out.
  115. //
  116. if ( ( iEdgeDist > 0 ) || ( ( iEdgeDist == 0 ) && m_bAPos ) )
  117. {
  118. // pixel is out
  119. return 0x0000;
  120. }
  121. // pixel is in
  122. return 0xFFFF;
  123. }
  124. //-----------------------------------------------------------------------------
  125. //
  126. // AATest - Anti alias edge test, returns coverage mask of all zero's if point
  127. // is outside the edge, all 1's if point is inside, and partial if point is on
  128. // or near the edge.
  129. //
  130. //-----------------------------------------------------------------------------
  131. RRCvgMask
  132. RREdgeFunc::AATest( INT16 iX, INT16 iY )
  133. {
  134. RRCvgMask Mask = 0;
  135. // n.4 integer representation of pixel center
  136. INT64 iX64Center = (INT64)(iX<<4);
  137. INT64 iY64Center = (INT64)(iY<<4);
  138. // step across 4x4 subpixel sample points and point sample 16 locations
  139. // to form coverage mask; area is split into eights to center samples
  140. // around pixel center (for example, the two inner sample positions are
  141. // each 1/8 of a pixel distance from the pixel center, and thus 1/4 of
  142. // a pixel distance apart)
  143. INT32 iYSub, iYEightths, iXSub, iXEightths;
  144. for (iYSub = 0, iYEightths = -3; iYSub < 4; iYSub++, iYEightths += 2)
  145. {
  146. for (iXSub = 0, iXEightths = -3; iXSub < 4; iXSub++, iXEightths += 2)
  147. {
  148. // compute sample location, which is some n/8 offset from the
  149. // pixel center (+/- 3/8 or 1/8)
  150. INT64 iX64 = iX64Center + (iXEightths<<1);
  151. INT64 iY64 = iY64Center + (iYEightths<<1);
  152. INT64 iEdgeDist =
  153. ( (INT64)m_iA * iX64 ) + // n.4 * n.4 = n.8
  154. ( (INT64)m_iB * iY64 ) + // n.4 * n.4 = n.8
  155. (INT64)m_iC; // n.8
  156. // if the center is in (same left-top rule as in point sample)
  157. if (!( ( iEdgeDist > 0 ) || ( ( iEdgeDist == 0 ) && m_bAPos ) ))
  158. {
  159. // pixel is in
  160. Mask |= 1 << (iXSub + iYSub*4);
  161. }
  162. }
  163. }
  164. return Mask;
  165. }
  166. ///////////////////////////////////////////////////////////////////////////////
  167. // end