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.

255 lines
6.5 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.12 $
  18. ** $Date: 1993/09/23 16:30:58 $
  19. */
  20. #include "precomp.h"
  21. #pragma hdrstop
  22. void APIPRIVATE __glim_SelectBuffer(GLsizei bufferLength, GLuint buffer[])
  23. {
  24. __GL_SETUP_NOT_IN_BEGIN();
  25. if (bufferLength < 0) {
  26. __glSetError(GL_INVALID_VALUE);
  27. return;
  28. }
  29. if (gc->renderMode == GL_SELECT) {
  30. __glSetError(GL_INVALID_OPERATION);
  31. return;
  32. }
  33. gc->select.overFlowed = GL_FALSE;
  34. gc->select.resultBase = buffer;
  35. gc->select.resultLength = bufferLength;
  36. gc->select.result = buffer;
  37. }
  38. void APIPRIVATE __glim_InitNames(void)
  39. {
  40. __GL_SETUP_NOT_IN_BEGIN();
  41. if (gc->renderMode == GL_SELECT) {
  42. gc->select.sp = gc->select.stack;
  43. gc->select.hit = GL_FALSE;
  44. }
  45. }
  46. void APIPRIVATE __glim_LoadName(GLuint name)
  47. {
  48. __GL_SETUP_NOT_IN_BEGIN();
  49. if (gc->renderMode == GL_SELECT) {
  50. if (gc->select.sp == gc->select.stack) {
  51. __glSetError(GL_INVALID_OPERATION);
  52. return;
  53. }
  54. gc->select.sp[ -1 ] = name;
  55. gc->select.hit = GL_FALSE;
  56. }
  57. }
  58. void APIPRIVATE __glim_PopName(void)
  59. {
  60. __GL_SETUP_NOT_IN_BEGIN();
  61. if (gc->renderMode == GL_SELECT) {
  62. if (gc->select.sp == gc->select.stack) {
  63. __glSetError(GL_STACK_UNDERFLOW);
  64. return;
  65. }
  66. gc->select.sp = gc->select.sp - 1;
  67. gc->select.hit = GL_FALSE;
  68. }
  69. }
  70. void APIPRIVATE __glim_PushName(GLuint name)
  71. {
  72. __GL_SETUP_NOT_IN_BEGIN();
  73. if (gc->renderMode == GL_SELECT) {
  74. // make sure that we have a stack
  75. ASSERTOPENGL(gc->select.stack != 0 && gc->select.sp != 0,
  76. "No selection stack\n");
  77. if (gc->select.sp >= &gc->select.stack[gc->constants.maxNameStackDepth]) {
  78. __glSetError(GL_STACK_OVERFLOW);
  79. return;
  80. }
  81. gc->select.sp[0] = name;
  82. gc->select.sp = gc->select.sp + 1;
  83. gc->select.hit = GL_FALSE;
  84. }
  85. }
  86. /************************************************************************/
  87. #define __GL_CONVERT_Z_TO_UINT(z) ((GLuint) z)
  88. /*
  89. ** Copy current name stack into the users result buffer.
  90. */
  91. void __glSelectHit(__GLcontext *gc, __GLfloat z)
  92. {
  93. GLuint *src;
  94. GLuint *dest = gc->select.result;
  95. GLuint *end = gc->select.resultBase + gc->select.resultLength;
  96. GLuint iz;
  97. if (gc->select.overFlowed) {
  98. return;
  99. }
  100. /* Scale z to [0, 2^32 -1] range.
  101. ** If buffer is 32 bit, no coversion necessary. Otherwise we
  102. ** have to unscale to [0,1] range and rescale to final range.
  103. ** 4294965000 is the number used throughout lighting code to
  104. ** come short of 2^32-1 to avoid floating point errors.
  105. */
  106. if (gc->depthBuffer.buf.depth == 32) {
  107. iz = __GL_CONVERT_Z_TO_UINT(z);
  108. } else {
  109. iz = z * 4294965000 / gc->depthBuffer.scale;
  110. }
  111. if (!gc->select.hit) {
  112. gc->select.hit = GL_TRUE;
  113. /* Put number of elements in name stack out first */
  114. if (dest == end) {
  115. overflow:
  116. gc->select.overFlowed = GL_TRUE;
  117. gc->select.result = end;
  118. return;
  119. }
  120. *dest++ = (GLint)((ULONG_PTR)(gc->select.sp - gc->select.stack));
  121. gc->select.hits++;
  122. /* Put out smallest z */
  123. if (dest == end) goto overflow;
  124. gc->select.z = dest;
  125. *dest++ = iz;
  126. /* Put out largest z */
  127. if (dest == end) goto overflow;
  128. *dest++ = iz;
  129. /* Copy name stack into output buffer */
  130. for (src = gc->select.stack; src < gc->select.sp; src++) {
  131. if (dest == end) {
  132. goto overflow;
  133. }
  134. *dest++ = *src;
  135. }
  136. gc->select.result = dest;
  137. } else {
  138. /* Update range of Z values */
  139. ASSERTOPENGL(gc->select.z != 0, "Select Z is zero\n");
  140. if (iz < gc->select.z[0]) {
  141. gc->select.z[0] = iz;
  142. }
  143. if (iz > gc->select.z[1]) {
  144. gc->select.z[1] = iz;
  145. }
  146. }
  147. }
  148. #ifdef NT
  149. void FASTCALL __glSelectTriangle(__GLcontext *gc, __GLvertex *a, __GLvertex *b,
  150. __GLvertex *c)
  151. {
  152. __GLfloat dxAC, dxBC, dyAC, dyBC, area;
  153. GLint ccw, face;
  154. // From __glRenderTriangle.
  155. /* Compute signed area of the triangle */
  156. dxAC = a->window.x - c->window.x;
  157. dxBC = b->window.x - c->window.x;
  158. dyAC = a->window.y - c->window.y;
  159. dyBC = b->window.y - c->window.y;
  160. area = dxAC * dyBC - dxBC * dyAC;
  161. ccw = area >= __glZero;
  162. face = gc->polygon.face[ccw];
  163. if (face == gc->polygon.cullFace)
  164. /* Culled */
  165. return;
  166. __glSelectHit(gc, a->window.z);
  167. __glSelectHit(gc, b->window.z);
  168. __glSelectHit(gc, c->window.z);
  169. }
  170. #else
  171. // SGIBUG - This code fails to take into account y inversion when
  172. // computing face orientation!
  173. void __glSelectTriangle(__GLcontext *gc, __GLvertex *a, __GLvertex *b,
  174. __GLvertex *c)
  175. {
  176. __GLfloat x, y, z, wInv;
  177. __GLfloat vpXScale, vpYScale, vpZScale;
  178. __GLfloat vpXCenter, vpYCenter, vpZCenter;
  179. __GLviewport *vp;
  180. /* Compute window coordinates first, if not already done */
  181. vp = &gc->state.viewport;
  182. vpXCenter = vp->xCenter;
  183. vpYCenter = vp->yCenter;
  184. vpZCenter = vp->zCenter;
  185. vpXScale = vp->xScale;
  186. vpYScale = vp->yScale;
  187. vpZScale = vp->zScale;
  188. if (gc->state.enables.general & __GL_CULL_FACE_ENABLE) {
  189. __GLfloat dxAC, dxBC, dyAC, dyBC, area;
  190. GLboolean ccw, frontFacing;
  191. /* Compute signed area of the triangle */
  192. dxAC = a->window.x - c->window.x;
  193. dxBC = b->window.x - c->window.x;
  194. dyAC = a->window.y - c->window.y;
  195. dyBC = b->window.y - c->window.y;
  196. area = dxAC * dyBC - dxBC * dyAC;
  197. ccw = area >= __glZero;
  198. if (gc->state.polygon.frontFaceDirection == GL_CCW) {
  199. frontFacing = ccw;
  200. } else {
  201. frontFacing = !ccw;
  202. }
  203. if ((gc->state.polygon.cull == GL_FRONT_AND_BACK) ||
  204. ((gc->state.polygon.cull == GL_FRONT) && frontFacing) ||
  205. ((gc->state.polygon.cull == GL_BACK) && !frontFacing)) {
  206. /* Culled */
  207. return;
  208. }
  209. }
  210. __glSelectHit(gc, a->window.z);
  211. __glSelectHit(gc, b->window.z);
  212. __glSelectHit(gc, c->window.z);
  213. }
  214. #endif
  215. void FASTCALL __glSelectLine(__GLcontext *gc, __GLvertex *a, __GLvertex *b,
  216. GLuint flags)
  217. {
  218. __glSelectHit(gc, a->window.z);
  219. __glSelectHit(gc, b->window.z);
  220. }
  221. void FASTCALL __glSelectPoint(__GLcontext *gc, __GLvertex *v)
  222. {
  223. __glSelectHit(gc, v->window.z);
  224. }