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.

322 lines
9.1 KiB

  1. /*
  2. ** Copyright 1991, 1992, 1993, 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. #include "precomp.h"
  18. #pragma hdrstop
  19. GLint FASTCALL Fetch(__GLstencilBuffer *sfb, GLint x, GLint y)
  20. {
  21. __GLstencilCell *fb;
  22. fb = __GL_STENCIL_ADDR(sfb, (__GLstencilCell*), x, y);
  23. return fb[0];
  24. }
  25. static void Store(__GLstencilBuffer *sfb, GLint x, GLint y,GLint v)
  26. {
  27. __GLstencilCell *fb;
  28. fb = __GL_STENCIL_ADDR(sfb, (__GLstencilCell*), x, y);
  29. fb[0] = (__GLstencilCell) ((v & sfb->buf.gc->state.stencil.writeMask)
  30. | (fb[0] & ~sfb->buf.gc->state.stencil.writeMask));
  31. }
  32. static GLboolean FASTCALL TestFunc(__GLstencilBuffer *sfb, GLint x, GLint y)
  33. {
  34. __GLstencilCell *fb;
  35. fb = __GL_STENCIL_ADDR(sfb, (__GLstencilCell*), x, y);
  36. return sfb->testFuncTable[fb[0] & sfb->buf.gc->state.stencil.mask];
  37. }
  38. static void FASTCALL FailOp(__GLstencilBuffer *sfb, GLint x, GLint y)
  39. {
  40. __GLstencilCell *fb;
  41. fb = __GL_STENCIL_ADDR(sfb, (__GLstencilCell*), x, y);
  42. fb[0] = sfb->failOpTable[fb[0]];
  43. }
  44. static void FASTCALL PassDepthFailOp(__GLstencilBuffer *sfb, GLint x, GLint y)
  45. {
  46. __GLstencilCell *fb;
  47. fb = __GL_STENCIL_ADDR(sfb, (__GLstencilCell*), x, y);
  48. fb[0] = sfb->depthFailOpTable[fb[0]];
  49. }
  50. static void FASTCALL DepthPassOp(__GLstencilBuffer *sfb, GLint x, GLint y)
  51. {
  52. __GLstencilCell *fb;
  53. fb = __GL_STENCIL_ADDR(sfb, (__GLstencilCell*), x, y);
  54. fb[0] = sfb->depthPassOpTable[fb[0]];
  55. }
  56. static GLboolean FASTCALL NoOp(__GLstencilBuffer *sfb, GLint x, GLint y)
  57. {
  58. return GL_FALSE;
  59. }
  60. /************************************************************************/
  61. static void FASTCALL Clear(__GLstencilBuffer *sfb)
  62. {
  63. __GLcontext *gc = sfb->buf.gc;
  64. __GLstencilCell *fb;
  65. GLint x, y, x1, y1, skip, w, w8, w1;
  66. __GLstencilCell sten = (__GLstencilCell)gc->state.stencil.clear;
  67. x = gc->transform.clipX0;
  68. y = gc->transform.clipY0;
  69. x1 = gc->transform.clipX1;
  70. y1 = gc->transform.clipY1;
  71. if (((w = x1 - x) == 0) || (y1 - y == 0)) {
  72. return;
  73. }
  74. fb = __GL_STENCIL_ADDR(sfb, (__GLstencilCell*), x, y);
  75. skip = sfb->buf.outerWidth - w;
  76. w8 = w >> 3;
  77. w1 = w & 7;
  78. if (gc->state.stencil.writeMask == __GL_MAX_STENCIL_VALUE) {
  79. for (; y < y1; y++) {
  80. w = w8;
  81. while (--w >= 0) {
  82. fb[0] = sten; fb[1] = sten; fb[2] = sten; fb[3] = sten;
  83. fb[4] = sten; fb[5] = sten; fb[6] = sten; fb[7] = sten;
  84. fb += 8;
  85. }
  86. w = w1;
  87. while (--w >= 0) {
  88. *fb++ = sten;
  89. }
  90. fb += skip;
  91. }
  92. } else {
  93. GLint mask;
  94. mask = gc->state.stencil.writeMask;
  95. sten = sten & mask;
  96. mask = ~mask;
  97. for (; y < y1; y++) {
  98. w = w8;
  99. while (--w >= 0) {
  100. fb[0] = (fb[0] & mask) | (sten);
  101. fb[1] = (fb[1] & mask) | (sten);
  102. fb[2] = (fb[2] & mask) | (sten);
  103. fb[3] = (fb[3] & mask) | (sten);
  104. fb[4] = (fb[4] & mask) | (sten);
  105. fb[5] = (fb[5] & mask) | (sten);
  106. fb[6] = (fb[6] & mask) | (sten);
  107. fb[7] = (fb[7] & mask) | (sten);
  108. fb += 8;
  109. }
  110. w = w1;
  111. while (--w >= 0) {
  112. fb[0] = (fb[0] & mask) | (sten);
  113. fb++;
  114. }
  115. fb += skip;
  116. }
  117. }
  118. }
  119. /************************************************************************/
  120. static void buildOpTable(__GLstencilCell *tp, GLenum op,
  121. __GLstencilCell reference, __GLstencilCell writeMask)
  122. {
  123. GLuint i;
  124. __GLstencilCell newValue;
  125. __GLstencilCell notWriteMask = ~writeMask;
  126. for (i = 0; i < __GL_STENCIL_RANGE; i++) {
  127. switch (op) {
  128. case GL_KEEP: newValue = (__GLstencilCell)i; break;
  129. case GL_ZERO: newValue = 0; break;
  130. case GL_REPLACE: newValue = reference; break;
  131. case GL_INVERT: newValue = ~i; break;
  132. case GL_INCR:
  133. /* Clamp so no overflow occurs */
  134. if (i == __GL_MAX_STENCIL_VALUE) {
  135. newValue = (__GLstencilCell)i;
  136. } else {
  137. newValue = i + 1;
  138. }
  139. break;
  140. case GL_DECR:
  141. /* Clamp so no underflow occurs */
  142. if (i == 0) {
  143. newValue = 0;
  144. } else {
  145. newValue = i - 1;
  146. }
  147. break;
  148. }
  149. *tp++ = (i & notWriteMask) | (newValue & writeMask);
  150. }
  151. }
  152. #ifdef NT
  153. void FASTCALL __glValidateStencil(__GLcontext *gc, __GLstencilBuffer *sfb)
  154. #else
  155. void FASTCALL __glValidateStencil(__GLcontext *gc)
  156. #endif // NT
  157. {
  158. GLint i;
  159. __GLstencilCell reference, mask, writeMask;
  160. __GLstencilCell refVal; //actual reference value, part of GL state
  161. GLenum testFunc;
  162. GLboolean *tp;
  163. /*
  164. ** Validate the stencil tables even if stenciling is disabled. This
  165. ** function is only called if the stencil func or op changes, and it
  166. ** won't get called later if stenciling is turned on, so we need to get
  167. ** it right now.
  168. */
  169. mask = (__GLstencilCell) gc->state.stencil.mask;
  170. refVal = ((__GLstencilCell) gc->state.stencil.reference);
  171. reference = (__GLstencilCell) (refVal & mask);
  172. testFunc = gc->state.stencil.testFunc;
  173. /*
  174. ** Build up test function table. The current stencil buffer value
  175. ** will be the index to this table.
  176. */
  177. tp = &gc->stencilBuffer.testFuncTable[0];
  178. // If we don't have a stencil buffer then set everything to
  179. // do nothing
  180. if (!gc->modes.haveStencilBuffer)
  181. {
  182. sfb->testFunc = NoOp;
  183. sfb->failOp = NoOp;
  184. sfb->passDepthFailOp = NoOp;
  185. sfb->depthPassOp = NoOp;
  186. return;
  187. }
  188. else if (tp != NULL && sfb->testFunc == NoOp)
  189. {
  190. // If we've recovered from not having a stencil buffer then
  191. // turn the functions back on
  192. sfb->testFunc = TestFunc;
  193. sfb->failOp = FailOp;
  194. sfb->passDepthFailOp = PassDepthFailOp;
  195. sfb->depthPassOp = DepthPassOp;
  196. }
  197. if (!tp)
  198. {
  199. gc->stencilBuffer.testFuncTable = tp = (GLboolean *)
  200. GCALLOC(gc, (sizeof(GLboolean)+3*sizeof(__GLstencilCell))*
  201. __GL_STENCIL_RANGE);
  202. if (!tp)
  203. {
  204. sfb->testFunc = NoOp;
  205. sfb->failOp = NoOp;
  206. sfb->passDepthFailOp = NoOp;
  207. sfb->depthPassOp = NoOp;
  208. gc->stencilBuffer.failOpTable =
  209. gc->stencilBuffer.depthFailOpTable =
  210. gc->stencilBuffer.depthPassOpTable = (__GLstencilCell*) NULL;
  211. return;
  212. }
  213. else
  214. {
  215. sfb->testFunc = TestFunc;
  216. sfb->failOp = FailOp;
  217. sfb->passDepthFailOp = PassDepthFailOp;
  218. sfb->depthPassOp = DepthPassOp;
  219. }
  220. gc->stencilBuffer.failOpTable = (__GLstencilCell*)
  221. (gc->stencilBuffer.testFuncTable + __GL_STENCIL_RANGE);
  222. gc->stencilBuffer.depthFailOpTable = (__GLstencilCell*)
  223. (gc->stencilBuffer.failOpTable + __GL_STENCIL_RANGE);
  224. gc->stencilBuffer.depthPassOpTable = (__GLstencilCell*)
  225. (gc->stencilBuffer.depthFailOpTable + __GL_STENCIL_RANGE);
  226. }
  227. for (i = 0; i < __GL_STENCIL_RANGE; i++) {
  228. switch (testFunc) {
  229. case GL_NEVER: *tp++ = GL_FALSE; break;
  230. case GL_LESS: *tp++ = reference < (i & mask); break;
  231. case GL_EQUAL: *tp++ = reference == (i & mask); break;
  232. case GL_LEQUAL: *tp++ = reference <= (i & mask); break;
  233. case GL_GREATER: *tp++ = reference > (i & mask); break;
  234. case GL_NOTEQUAL: *tp++ = reference != (i & mask); break;
  235. case GL_GEQUAL: *tp++ = reference >= (i & mask); break;
  236. case GL_ALWAYS: *tp++ = GL_TRUE; break;
  237. }
  238. }
  239. /*
  240. ** Build up fail op table.
  241. */
  242. writeMask = (__GLstencilCell) gc->state.stencil.writeMask;
  243. buildOpTable(&gc->stencilBuffer.failOpTable[0],
  244. gc->state.stencil.fail, refVal, writeMask);
  245. buildOpTable(&gc->stencilBuffer.depthFailOpTable[0],
  246. gc->state.stencil.depthFail, refVal, writeMask);
  247. buildOpTable(&gc->stencilBuffer.depthPassOpTable[0],
  248. gc->state.stencil.depthPass, refVal, writeMask);
  249. }
  250. /************************************************************************/
  251. static void FASTCALL Pick(__GLcontext *gc, __GLstencilBuffer *sfb)
  252. {
  253. #ifdef __GL_LINT
  254. sfb = sfb;
  255. #endif
  256. if (gc->validateMask & (__GL_VALIDATE_STENCIL_FUNC |
  257. __GL_VALIDATE_STENCIL_OP)) {
  258. #ifdef NT
  259. __glValidateStencil(gc, sfb);
  260. #else
  261. __glValidateStencil(gc);
  262. #endif // NT
  263. }
  264. }
  265. void FASTCALL __glInitStencil8(__GLcontext *gc, __GLstencilBuffer *sfb)
  266. {
  267. sfb->buf.elementSize = sizeof(__GLstencilCell);
  268. sfb->buf.gc = gc;
  269. sfb->pick = Pick;
  270. sfb->store = Store;
  271. sfb->fetch = Fetch;
  272. #ifndef NT
  273. // Initialized in __glValidateStencil.
  274. sfb->testFunc = TestFunc;
  275. sfb->failOp = FailOp;
  276. sfb->passDepthFailOp = PassDepthFailOp;
  277. sfb->depthPassOp = DepthPassOp;
  278. #endif // !NT
  279. sfb->clear = Clear;
  280. }
  281. void FASTCALL __glFreeStencil8(__GLcontext *gc, __GLstencilBuffer *fb)
  282. {
  283. #ifdef __GL_LINT
  284. gc = gc;
  285. fb = fb;
  286. #endif
  287. }