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.

342 lines
11 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright (C) Microsoft Corporation, 1998.
  3. //
  4. // cvgmask.cpp
  5. //
  6. // Direct3D Reference Rasterizer - Antialiasing Coverage Mask Generation
  7. //
  8. ///////////////////////////////////////////////////////////////////////////////
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. #if 0
  12. // from edgefunc.hpp
  13. // Normalization factor for antialising is stored in floating point. This is
  14. // computed during the setup and applied per-pixel after the (non-normalized)
  15. // edge distance is evaluated.
  16. //
  17. DOUBLE m_dNorm;
  18. INT16 m_iEdgeYGradBits; // 1.8 fixed point
  19. // from edgefunc.cpp ::Set
  20. if ( bFragProcEnable )
  21. {
  22. // compute normalization factor for antialiasing - normalizes for 'square'
  23. // distance (a.k.a 'manhatten' distance) such that an equidistant point
  24. // sweep of a distance of 0.5 is a square 1.0 pixel area.
  25. m_dNorm = 1.0 / ( fabs( fY0-fY1 ) + fabs( fX1-fX0 ) );
  26. // compute rounded fixed point Y gradient bits for generation of
  27. // antialiasing coverage mask
  28. m_iEdgeYGradBits = AS_INT16( ((fY0-fY1)*m_dNorm) + DOUBLE_8_SNAP );
  29. }
  30. // from ::AATest
  31. // The edge evaluation is done exactly the same as the point sample case, then
  32. // it is converted to double precision floating point for the normalization and
  33. // rounding. Using doubles makes it very easy to carry adequate precision in
  34. // the normalization factor and to convert to 32 bit signed integer (holding
  35. // the n.5 fixed point distance) with round to nearest even.
  36. //
  37. // evaluate edge distance function (n.8 fixed point)
  38. INT64 iEdgeDist =
  39. ( (INT64)m_iA * (INT64)(iX<<4) ) + // n.4 * n.4 = n.8
  40. ( (INT64)m_iB * (INT64)(iY<<4) ) + // n.4 * n.4 = n.8
  41. (INT64)m_iC; // n.8
  42. // convert to double (adjust for n.8 fixed point) for normalization
  43. // and rounding
  44. DOUBLE dEdgeDist = (DOUBLE)iEdgeDist * (1./(DOUBLE)(1<<8));
  45. // normalize edge distance
  46. dEdgeDist *= m_dNorm;
  47. // convert distance to fixed point with nearest-even round;
  48. // keep 5 fractional bits for antialiasing
  49. INT32 iEdgeDistRnd = AS_INT32( dEdgeDist + DOUBLE_5_SNAP );
  50. // pixel is fully outside of edge if out by +.5 or more
  51. if ( iEdgeDistRnd >= +(1<<4) ) return 0x0000;
  52. // pixel is fully inside of edge if in by -.5 or more
  53. if ( iEdgeDistRnd <= -(1<<4) ) return 0xFFFF;
  54. // here when pixel is within 1/2 (square distance) of edge
  55. // compute coverage mask for this edge
  56. return ComputeCoverageMask( m_iEdgeYGradBits, m_bAPos, m_bBPos, iEdgeDistRnd );
  57. #endif
  58. //-----------------------------------------------------------------------------
  59. //
  60. // Tables used in computation of coverage mask
  61. //
  62. //-----------------------------------------------------------------------------
  63. //-----------------------------------------------------------------------------
  64. // These are the ranges of the x gradient (the 'A' of F=Ax+By+c) for one
  65. // octant into which the edge slopes are binned.
  66. //-----------------------------------------------------------------------------
  67. #define A_RANGES 4
  68. static UINT16 uARanges[A_RANGES] = {
  69. // 0.0.8 values
  70. 0x00, // 0.00
  71. 0x40, // 0.25
  72. 0x55, // 0.33
  73. 0x66, // 0.40
  74. };
  75. //-----------------------------------------------------------------------------
  76. // These are the 16 bit coverage masks for each of the A ranges. The
  77. // 15 values within each range define the order in which the coverage
  78. // mask bits are enabled, thus the least-significant index is the number
  79. // of coverage mask bits that need to be enabled.
  80. //-----------------------------------------------------------------------------
  81. static UINT16 CvgMasks[A_RANGES][15] = {
  82. { // 0.000 .. 0.250
  83. 0x1,
  84. 0x3,
  85. 0x7,
  86. 0xF,
  87. 0x1F,
  88. 0x3F,
  89. 0x7F,
  90. 0xFF,
  91. 0x1FF,
  92. 0x3FF,
  93. 0x7FF,
  94. 0xFFF,
  95. 0x1FFF,
  96. 0x3FFF,
  97. 0x7FFF,
  98. },
  99. { // 0.250 .. 0.333
  100. 0x1,
  101. 0x3,
  102. 0x7,
  103. 0x17,
  104. 0x1F,
  105. 0x3F,
  106. 0x7F,
  107. 0x17F,
  108. 0x1FF,
  109. 0x3FF,
  110. 0x7FF,
  111. 0x17FF,
  112. 0x1FFF,
  113. 0x3FFF,
  114. 0x7FFF,
  115. },
  116. { // 0.333 .. 0.400
  117. 0x1,
  118. 0x3,
  119. 0x13,
  120. 0x17,
  121. 0x37,
  122. 0x3F,
  123. 0x13F,
  124. 0x17F,
  125. 0x37F,
  126. 0x3FF,
  127. 0x13FF,
  128. 0x17FF,
  129. 0x37FF,
  130. 0x3FFF,
  131. 0x7FFF,
  132. },
  133. { // 0.400 .. 0.500
  134. 0x1,
  135. 0x3,
  136. 0x13,
  137. 0x17,
  138. 0x37,
  139. 0x137,
  140. 0x13F,
  141. 0x17F,
  142. 0x37F,
  143. 0x137F,
  144. 0x13FF,
  145. 0x17FF,
  146. 0x37FF,
  147. 0x3FFF,
  148. 0x7FFF,
  149. },
  150. };
  151. //-----------------------------------------------------------------------------
  152. // This table is used for a rough area approximation. The [16] index
  153. // is the top 4 bits of the edge distance (i.e. the distance from the
  154. // edge to the center of the pixel). The [4] index is the top two bits
  155. // of the A gradient term. The return is the number of bits that should
  156. // be set in the coverage mask, which is a function of the area covered.
  157. //-----------------------------------------------------------------------------
  158. static INT16 nBitsA = 2;
  159. static INT16 nBitsE = 4;
  160. static INT16 nBitsToEnable[4][16] = {
  161. { // A: 0.000; B: 1.000
  162. 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16,
  163. },
  164. { // A: 0.125; B: 0.875
  165. 8, 9, 9, 10, 10, 11, 11, 12, 13, 13, 14, 14, 15, 15, 16, 16,
  166. },
  167. { // A: 0.250; B: 0.750
  168. 8, 9, 9, 10, 11, 11, 12, 13, 13, 14, 15, 15, 15, 16, 16, 16,
  169. },
  170. { // A: 0.375; B: 0.625
  171. 8, 9, 10, 10, 11, 12, 13, 13, 14, 14, 15, 15, 15, 16, 16, 16,
  172. },
  173. };
  174. //-----------------------------------------------------------------------------
  175. //
  176. // Mask manipulation functions - these are needed because coverage mask
  177. // table (indexed by angle) is for one octant only and need to be
  178. // munged in various ways for other octants
  179. //
  180. //-----------------------------------------------------------------------------
  181. static void
  182. doCvgMaskTBFlip(UINT16 &CvgMask)
  183. {
  184. UINT16 CvgMaskT = CvgMask;
  185. CvgMask = 0;
  186. CvgMask |= (((CvgMaskT >> 0) & 0x1) << 12);
  187. CvgMask |= (((CvgMaskT >> 1) & 0x1) << 13);
  188. CvgMask |= (((CvgMaskT >> 2) & 0x1) << 14);
  189. CvgMask |= (((CvgMaskT >> 3) & 0x1) << 15);
  190. CvgMask |= (((CvgMaskT >> 4) & 0x1) << 8);
  191. CvgMask |= (((CvgMaskT >> 5) & 0x1) << 9);
  192. CvgMask |= (((CvgMaskT >> 6) & 0x1) << 10);
  193. CvgMask |= (((CvgMaskT >> 7) & 0x1) << 11);
  194. CvgMask |= (((CvgMaskT >> 8) & 0x1) << 4);
  195. CvgMask |= (((CvgMaskT >> 9) & 0x1) << 5);
  196. CvgMask |= (((CvgMaskT >> 10) & 0x1) << 6);
  197. CvgMask |= (((CvgMaskT >> 11) & 0x1) << 7);
  198. CvgMask |= (((CvgMaskT >> 12) & 0x1) << 0);
  199. CvgMask |= (((CvgMaskT >> 13) & 0x1) << 1);
  200. CvgMask |= (((CvgMaskT >> 14) & 0x1) << 2);
  201. CvgMask |= (((CvgMaskT >> 15) & 0x1) << 3);
  202. }
  203. //-----------------------------------------------------------------------------
  204. static void
  205. doCvgMaskSFlip(UINT16 &CvgMask)
  206. {
  207. UINT16 CvgMaskT = CvgMask;
  208. CvgMask = 0;
  209. CvgMask |= (((CvgMaskT >> 0) & 0x1) << 0);
  210. CvgMask |= (((CvgMaskT >> 1) & 0x1) << 4);
  211. CvgMask |= (((CvgMaskT >> 2) & 0x1) << 8);
  212. CvgMask |= (((CvgMaskT >> 3) & 0x1) << 12);
  213. CvgMask |= (((CvgMaskT >> 4) & 0x1) << 1);
  214. CvgMask |= (((CvgMaskT >> 5) & 0x1) << 5);
  215. CvgMask |= (((CvgMaskT >> 6) & 0x1) << 9);
  216. CvgMask |= (((CvgMaskT >> 7) & 0x1) << 13);
  217. CvgMask |= (((CvgMaskT >> 8) & 0x1) << 2);
  218. CvgMask |= (((CvgMaskT >> 9) & 0x1) << 6);
  219. CvgMask |= (((CvgMaskT >> 10) & 0x1) << 10);
  220. CvgMask |= (((CvgMaskT >> 11) & 0x1) << 14);
  221. CvgMask |= (((CvgMaskT >> 12) & 0x1) << 3);
  222. CvgMask |= (((CvgMaskT >> 13) & 0x1) << 7);
  223. CvgMask |= (((CvgMaskT >> 14) & 0x1) << 11);
  224. CvgMask |= (((CvgMaskT >> 15) & 0x1) << 15);
  225. }
  226. //-----------------------------------------------------------------------------
  227. //
  228. // ComputeCoverageMask - Computes the 16 bit coverage mask. Called once per
  229. // pixel per crossing edge (i.e. up to 3 times per pixel).
  230. //
  231. // This is doing the algorithm described in Schilling's Siggraph paper, with
  232. // modifications to perform the operation for a single virtual octant and
  233. // then munging the result for the actual octant.
  234. //
  235. // Note that the A and B signs for the edges must be computed very carefully
  236. // to guarantee that shared edges will always result in full complimentary
  237. // coverage of pixels on the shared edge.
  238. //
  239. //-----------------------------------------------------------------------------
  240. RRCvgMask
  241. ComputeCoverageMask(
  242. INT16 iABits, // 1.8 value
  243. BOOL bAPos, BOOL bBPos,
  244. INT16 iEBits) // 1.5.5 value, but ranges from -.5 to +.5 here
  245. {
  246. RRCvgMask CvgMask; // return value
  247. // grab already rounded 8 bit value and take absolute value
  248. UINT16 uMagA = (iABits < 0) ? ((UINT16)-iABits) : ((UINT16)iABits);
  249. UINT16 uABits = uMagA & 0x1ff;
  250. // compute booleans for manipulating masks
  251. BOOL bMaskInvert = TRUE;
  252. BOOL bMaskRFlip = !(bAPos ^ bBPos);
  253. if (!bAPos) {
  254. iEBits = -iEBits;
  255. bMaskInvert = FALSE;
  256. }
  257. //
  258. // compute A offset from x or y axis
  259. //
  260. // mirror around 45 degree axis - keep track of this because
  261. // the 45 degree mirroring requires a side-to-side mask flip
  262. BOOL bMaskSFlip = (uABits > 0x80); // > 0.5F ?
  263. if (bMaskSFlip) { uABits = 0x100 - uABits; }
  264. // uABits is now a 0.0.8 value in the range 0x00 to 0x80
  265. //
  266. // determine number of bits to enable in mask based on the area covered
  267. //
  268. // extract bits from A for area lookup
  269. UINT16 uAAreaBits = (uABits == 0x80)
  270. ? ((1<<nBitsA)-1) : (uABits >> (7-nBitsA));
  271. // grab distance bits for area lookup - take absolute value and clamp
  272. UINT16 uEBits = (iEBits < 0) ? ((UINT16)-iEBits) : ((UINT16)iEBits);
  273. uEBits = MIN(uEBits,(UINT16)(((1<<nBitsE)-1))); // clamp
  274. // look up area in table - returns number of bits to enable
  275. INT16 iNumCvgBits = nBitsToEnable[uAAreaBits][uEBits];
  276. // flip for negative distance
  277. if (iEBits < 0) { iNumCvgBits = 16 - iNumCvgBits; }
  278. //
  279. // compute slope range index and look up coverage mask
  280. //
  281. INT16 iARange = 3;
  282. for (INT16 i=0; i<(A_RANGES-1); i++) {
  283. if ((uARanges[i] <= uABits) && (uABits < uARanges[i+1])) {
  284. iARange = i; break;
  285. }
  286. }
  287. // check for zero/full coverage else look up coverage mask
  288. if (0 == iNumCvgBits) {
  289. CvgMask = 0x0000;
  290. } else if (16 == iNumCvgBits) {
  291. CvgMask = 0xffff;
  292. } else {
  293. CvgMask = CvgMasks[iARange][iNumCvgBits-1];
  294. }
  295. //
  296. // adjust mask for different quadrants and directions
  297. //
  298. // first to side-to-side mask flip for 45 degree mirroring
  299. if (bMaskSFlip) { doCvgMaskSFlip(CvgMask); }
  300. // invert for 'backwards' line directions
  301. if (bMaskInvert) { CvgMask ^= 0xffff; }
  302. // flip for same sign quadrants
  303. if (bMaskRFlip) { doCvgMaskTBFlip(CvgMask); }
  304. return CvgMask;
  305. }
  306. ///////////////////////////////////////////////////////////////////////////////
  307. // end