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.

304 lines
10 KiB

  1. /*
  2. ** Copyright 1991, Silicon Graphics, Inc.
  3. ** All Rights Reserved.
  4. **
  5. ** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6. ** the contents of this file may not be disclosed to third parties, copied or
  7. ** duplicated in any form, in whole or in part, without the prior written
  8. ** permission of Silicon Graphics, Inc.
  9. **
  10. ** RESTRICTED RIGHTS LEGEND:
  11. ** Use, duplication or disclosure by the Government is subject to restrictions
  12. ** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13. ** and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14. ** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15. ** rights reserved under the Copyright Laws of the United States.
  16. **
  17. ** $Revision: 1.10 $
  18. ** $Date: 1993/06/18 00:30:15 $
  19. */
  20. #include "precomp.h"
  21. #pragma hdrstop
  22. #include <fixed.h>
  23. /*
  24. ** This is a little wierd. What it does is to dither "comp" into the high
  25. ** n-4 bits, and add 16 * antiAliasPercent. Dithering of the low bits is
  26. ** left to the usual methods (the store and span procs, for example).
  27. */
  28. __GLfloat __glBuildAntiAliasIndex(__GLfloat index,
  29. __GLfloat antiAliasPercent)
  30. {
  31. GLint newlowbits;
  32. newlowbits = (GLint)((__GL_CI_ANTI_ALIAS_DIVISOR - 1) * antiAliasPercent + (__GLfloat) 0.5);
  33. return (((int) index) & ~(__GL_CI_ANTI_ALIAS_DIVISOR - 1)) | newlowbits;
  34. }
  35. /************************************************************************/
  36. /*
  37. ** To anti-alias points the below code operates a simple algrorithim that
  38. ** sub-samples the bounding box of the pixel area covered by the point.
  39. ** At each sub-sample the distance from the sample to the center of the
  40. ** point is computed and compared against the distance from the edge of
  41. ** the circle to the center. If the computed distance is <= the edge
  42. ** distance then the sample is inside the circle. All the samples for a
  43. ** particular pixel center are summed up and then the resulting value is
  44. ** divided by the total samples in the pixel. This gives us a coverage value
  45. ** to use to adjust the fragment alpha with before storing (there is
  46. ** an analagous affect when color index anti-aliasing is being done).
  47. **
  48. ** The code below implements this simple algrorithim, but has been tuned
  49. ** so it might be difficult to translate. Basically, every possible operation
  50. ** that could be moved out of the Coverage code (i.e., invariants across
  51. ** the coverage test) has been done. Also, the minimal area is sampled
  52. ** over.
  53. */
  54. /* Code below knows alot about these constants so beware */
  55. #define __GL_FILTER_SIZE __glOne
  56. #define __GL_HALF_FILTER_SIZE __glHalf
  57. #define __GL_SAMPLES 4
  58. #define __GL_SAMPLE_HIT ((__GLfloat) 0.0625) /* 1 / (4*4) */
  59. #define __GL_SAMPLE_DELTA ((__GLfloat) 0.25) /* 1 / 4 */
  60. #define __GL_HALF_SAMPLE_DELTA ((__GLfloat) 0.125)
  61. /* -halffilter + half delta */
  62. #define __GL_COORD_ADJUST ((__GLfloat) -0.375)
  63. /*
  64. ** Return an estimate of the pixel coverage using sub-sampling.
  65. **
  66. ** NOTE: The subtraction of xCenter,yCenter has been moved into the
  67. ** caller to save time. Consequently the starting coordinate may not be
  68. ** on a pixel center, but thats ok.
  69. */
  70. static __GLfloat Coverage(__GLfloat xStart, __GLfloat yStart,
  71. __GLfloat radiusSquared)
  72. {
  73. GLint i;
  74. __GLfloat delta, yBottom, sampleX, sampleY;
  75. __GLfloat hits, hitsInc;
  76. /*
  77. ** Get starting sample x & y positions. We take our starting
  78. ** coordinate, back off half a filter size then add half a delta to
  79. ** it. This constrains the sampling to lie entirely within the
  80. ** pixel, never on the edges of the pixel. The constants above
  81. ** have this adjustment pre-computed.
  82. */
  83. sampleX = xStart + __GL_COORD_ADJUST;
  84. yBottom = yStart + __GL_COORD_ADJUST;
  85. delta = __GL_SAMPLE_DELTA;
  86. hits = __glZero;
  87. hitsInc = __GL_SAMPLE_HIT;
  88. for (i = __GL_SAMPLES; --i >= 0; ) {
  89. __GLfloat check = radiusSquared - sampleX * sampleX;
  90. /* Unrolled inner loop - change this code if __GL_SAMPLES changes */
  91. sampleY = yBottom;
  92. if (sampleY * sampleY <= check) {
  93. hits += hitsInc;
  94. }
  95. sampleY += delta;
  96. if (sampleY * sampleY <= check) {
  97. hits += hitsInc;
  98. }
  99. sampleY += delta;
  100. if (sampleY * sampleY <= check) {
  101. hits += hitsInc;
  102. }
  103. sampleY += delta;
  104. if (sampleY * sampleY <= check) {
  105. hits += hitsInc;
  106. }
  107. sampleX += delta;
  108. }
  109. return hits;
  110. }
  111. void FASTCALL __glRenderAntiAliasedRGBPoint(__GLcontext *gc, __GLvertex *vx)
  112. {
  113. __GLfloat xCenter, yCenter, radius, radiusSquared, coverage, x, y;
  114. __GLfloat zero, one, oldAlpha, xStart;
  115. __GLfloat tmp;
  116. __GLfragment frag;
  117. GLint w, width, height, ixLeft, iyBottom;
  118. GLuint modeFlags = gc->polygon.shader.modeFlags;
  119. /*
  120. ** Determine area to compute coverage over. The area is bloated by
  121. ** the filter's width & height implicitly. By truncating to integer
  122. ** (NOTE: the x,y coordinate is always positive here) we are
  123. ** guaranteed to find the lowest coordinate that needs examination
  124. ** because of the nature of circles. Similarly, by truncating the
  125. ** ending coordinate and adding one we get the pixel just past the
  126. ** upper/right edge of the circle.
  127. */
  128. radius = gc->state.point.smoothSize * __glHalf;
  129. radiusSquared = radius * radius;
  130. xCenter = vx->window.x;
  131. yCenter = vx->window.y;
  132. /* Truncate down to get starting coordinate */
  133. tmp = xCenter-radius;
  134. ixLeft = __GL_VERTEX_FLOAT_TO_INT(tmp);
  135. tmp = yCenter-radius;
  136. iyBottom = __GL_VERTEX_FLOAT_TO_INT(tmp);
  137. /*
  138. ** Truncate down and add 1 to get the ending coordinate, then subtract
  139. ** out the start to get the width & height.
  140. */
  141. tmp = xCenter+radius;
  142. width = __GL_VERTEX_FLOAT_TO_INT(tmp) + 1 - ixLeft;
  143. tmp = yCenter+radius;
  144. height = __GL_VERTEX_FLOAT_TO_INT(tmp) + 1 - iyBottom;
  145. /*
  146. ** Setup fragment. The fragment base color will be constant
  147. ** (approximately) across the entire pixel. The only thing that will
  148. ** change is the alpha (for rgb) or the red component (for color
  149. ** index).
  150. */
  151. frag.z = (__GLzValue)vx->window.z;
  152. frag.color = *vx->color;
  153. if (modeFlags & __GL_SHADE_TEXTURE) {
  154. (*gc->procs.texture)(gc, &frag.color, vx->texture.x, vx->texture.y,
  155. __glOne);
  156. }
  157. if (gc->polygon.shader.modeFlags & __GL_SHADE_COMPUTE_FOG)
  158. {
  159. (*gc->procs.fogPoint)(gc, &frag, vx->eyeZ);
  160. }
  161. else if ((gc->polygon.shader.modeFlags & __GL_SHADE_INTERP_FOG)
  162. ||
  163. ((modeFlags & (__GL_SHADE_CHEAP_FOG | __GL_SHADE_SMOOTH_LIGHT))
  164. == __GL_SHADE_CHEAP_FOG))
  165. {
  166. (*gc->procs.fogColor)(gc, &frag.color, &frag.color, vx->fog);
  167. }
  168. /*
  169. ** Now render the circle centered on xCenter,yCenter. Move the
  170. ** subtraction of xCenter,yCenter outside of the loop to doing
  171. ** it up front in xStart and y. This way the coverage code can
  172. ** assume the incoming starting coordinate has been properly
  173. ** adjusted.
  174. */
  175. zero = __glZero;
  176. one = __glOne;
  177. oldAlpha = frag.color.a;
  178. xStart = ixLeft + __glHalf - xCenter;
  179. y = iyBottom + __glHalf - yCenter;
  180. frag.y = iyBottom;
  181. while (--height >= 0) {
  182. x = xStart;
  183. frag.x = ixLeft;
  184. for (w = width; --w >= 0; ) {
  185. coverage = Coverage(x, y, radiusSquared);
  186. if (coverage > zero) {
  187. frag.color.a = oldAlpha * coverage;
  188. (*gc->procs.store)(gc->drawBuffer, &frag);
  189. }
  190. x += one;
  191. frag.x++;
  192. }
  193. y += one;
  194. frag.y++;
  195. }
  196. }
  197. void FASTCALL __glRenderAntiAliasedCIPoint(__GLcontext *gc, __GLvertex *vx)
  198. {
  199. __GLfloat xCenter, yCenter, radius, radiusSquared, coverage, x, y;
  200. __GLfloat zero, one, oldIndex, xStart;
  201. __GLfloat tmp;
  202. __GLfragment frag;
  203. GLint w, width, height, ixLeft, iyBottom;
  204. /*
  205. ** Determine area to compute coverage over. The area is bloated by
  206. ** the filter's width & height implicitly. By truncating to integer
  207. ** (NOTE: the x,y coordinate is always positive here) we are
  208. ** guaranteed to find the lowest coordinate that needs examination
  209. ** because of the nature of circles. Similarly, by truncating the
  210. ** ending coordinate and adding one we get the pixel just past the
  211. ** upper/right edge of the circle.
  212. */
  213. radius = gc->state.point.smoothSize * __glHalf;
  214. radiusSquared = radius * radius;
  215. xCenter = vx->window.x;
  216. yCenter = vx->window.y;
  217. /* Truncate down to get starting coordinate */
  218. tmp = xCenter-radius;
  219. ixLeft = __GL_VERTEX_FLOAT_TO_INT(tmp);
  220. tmp = yCenter-radius;
  221. iyBottom = __GL_VERTEX_FLOAT_TO_INT(tmp);
  222. /*
  223. ** Truncate down and add 1 to get the ending coordinate, then subtract
  224. ** out the start to get the width & height.
  225. */
  226. tmp = xCenter+radius;
  227. width = __GL_VERTEX_FLOAT_TO_INT(tmp) + 1 - ixLeft;
  228. tmp = yCenter+radius;
  229. height = __GL_VERTEX_FLOAT_TO_INT(tmp) + 1 - iyBottom;
  230. /*
  231. ** Setup fragment. The fragment base color will be constant
  232. ** (approximately) across the entire pixel. The only thing that will
  233. ** change is the alpha (for rgb) or the red component (for color
  234. ** index).
  235. */
  236. frag.z = (__GLzValue)vx->window.z;
  237. frag.color.r = vx->color->r;
  238. if (gc->polygon.shader.modeFlags & __GL_SHADE_COMPUTE_FOG)
  239. {
  240. (*gc->procs.fogPoint)(gc, &frag, vx->eyeZ);
  241. }
  242. else if ((gc->polygon.shader.modeFlags & __GL_SHADE_INTERP_FOG)
  243. ||
  244. ((gc->polygon.shader.modeFlags & (__GL_SHADE_CHEAP_FOG |
  245. __GL_SHADE_SMOOTH_LIGHT))
  246. == __GL_SHADE_CHEAP_FOG))
  247. {
  248. (*gc->procs.fogColor)(gc, &frag.color, &frag.color, vx->fog);
  249. }
  250. /*
  251. ** Now render the circle centered on xCenter,yCenter. Move the
  252. ** subtraction of xCenter,yCenter outside of the loop to doing
  253. ** it up front in xStart and y. This way the coverage code can
  254. ** assume the incoming starting coordinate has been properly
  255. ** adjusted.
  256. */
  257. zero = __glZero;
  258. one = __glOne;
  259. oldIndex = frag.color.r;
  260. xStart = ixLeft + __glHalf - xCenter;
  261. y = iyBottom + __glHalf - yCenter;
  262. frag.y = iyBottom;
  263. while (--height >= 0) {
  264. x = xStart;
  265. frag.x = ixLeft;
  266. for (w = width; --w >= 0; ) {
  267. coverage = Coverage(x, y, radiusSquared);
  268. if (coverage > zero) {
  269. frag.color.r = __glBuildAntiAliasIndex(oldIndex, coverage);
  270. (*gc->procs.store)(gc->drawBuffer, &frag);
  271. }
  272. x += one;
  273. frag.x++;
  274. }
  275. y += one;
  276. frag.y++;
  277. }
  278. }