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.

581 lines
21 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. #include <fixed.h>
  20. #if _X86_
  21. #define SHADER __GLcontext.polygon.shader
  22. #define GET_HALF_AREA(gc, a, b, c)\
  23. \
  24. __asm{ mov eax, a };\
  25. __asm{ mov ecx, c };\
  26. __asm{ mov ebx, b };\
  27. __asm{ mov edx, gc };\
  28. __asm{ fld DWORD PTR [OFFSET(__GLvertex.window.x)][eax] };\
  29. __asm{ fsub DWORD PTR [OFFSET(__GLvertex.window.x)][ecx] /* dxAC */ };\
  30. __asm{ fld DWORD PTR [OFFSET(__GLvertex.window.y)][ebx] };\
  31. __asm{ fsub DWORD PTR [OFFSET(__GLvertex.window.y)][ecx] /* dyBC dxAC */ };\
  32. __asm{ fld DWORD PTR [OFFSET(__GLvertex.window.x)][ebx] };\
  33. __asm{ fsub DWORD PTR [OFFSET(__GLvertex.window.x)][ecx] /* dxBC dyBC dxAC */ };\
  34. __asm{ fld DWORD PTR [OFFSET(__GLvertex.window.y)][eax] };\
  35. __asm{ fsub DWORD PTR [OFFSET(__GLvertex.window.y)][ecx] /* dyAC dxBC dyBC dxAC */ };\
  36. __asm{ fxch ST(2) /* dyBC dxBC dyAC dxAC */ };\
  37. __asm{ fst DWORD PTR [OFFSET(SHADER.dyBC)][edx] };\
  38. __asm{ fmul ST, ST(3) /* dxACdyBC dxBC dyAC dxAC */ };\
  39. __asm{ fxch ST(2) /* dyAC dxBC dxACdyBC dxAC */ };\
  40. __asm{ fst DWORD PTR [OFFSET(SHADER.dyAC)][edx] };\
  41. __asm{ fmul ST, ST(1) /* dxBCdyAC dxBC dxACdyBC dxAC */};\
  42. __asm{ fxch ST(1) /* dxBC dxBCdyAC dxACdyBC dxAC */};\
  43. __asm{ fstp DWORD PTR [OFFSET(SHADER.dxBC)][edx] /* dxBCdyAC dxACdyBC dxAC */ };\
  44. __asm{ fsubp ST(1), ST /* +1*/ /* area dxAC */ };\
  45. __asm{ fxch ST(1) /* dxAC area */ };\
  46. __asm{ fstp DWORD PTR [OFFSET(SHADER.dxAC)][edx] /* area */ };\
  47. __asm{ fstp DWORD PTR [OFFSET(SHADER.area)][edx] /* +1*/ /* (empty) */ };
  48. #define STORE_AREA_PARAMS
  49. #else
  50. #define GET_HALF_AREA(gc, a, b, c)\
  51. /* Compute signed half-area of the triangle */ \
  52. dxAC = a->window.x - c->window.x; \
  53. dxBC = b->window.x - c->window.x; \
  54. dyAC = a->window.y - c->window.y; \
  55. dyBC = b->window.y - c->window.y; \
  56. gc->polygon.shader.area = dxAC * dyBC - dxBC * dyAC;
  57. #define STORE_AREA_PARAMS\
  58. gc->polygon.shader.dxAC = dxAC; \
  59. gc->polygon.shader.dxBC = dxBC; \
  60. gc->polygon.shader.dyAC = dyAC; \
  61. gc->polygon.shader.dyBC = dyBC;
  62. #endif
  63. #define SORT_AND_CULL_FACE(a, b, c, face, ccw)\
  64. \
  65. /* \
  66. ** Sort vertices in y. Keep track if a reversal of the winding \
  67. ** occurs in direction (0 means no reversal, 1 means reversal). \
  68. ** Save old vertex pointers in case we end up not doing a fill. \
  69. */ \
  70. reversed = 0; \
  71. if (__GL_VERTEX_COMPARE(a->window.y, <, b->window.y)) { \
  72. if (__GL_VERTEX_COMPARE(b->window.y, <, c->window.y)) { \
  73. /* Already sorted */ \
  74. } else { \
  75. if (__GL_VERTEX_COMPARE(a->window.y, <, c->window.y)) { \
  76. temp=b; b=c; c=temp; \
  77. reversed = 1; \
  78. } else { \
  79. temp=a; a=c; c=b; b=temp; \
  80. } \
  81. } \
  82. } else { \
  83. if (__GL_VERTEX_COMPARE(b->window.y, <, c->window.y)) { \
  84. if (__GL_VERTEX_COMPARE(a->window.y, <, c->window.y)) { \
  85. temp=a; a=b; b=temp; \
  86. reversed = 1; \
  87. } else { \
  88. temp=a; a=b; b=c; c=temp; \
  89. } \
  90. } else { \
  91. temp=a; a=c; c=temp; \
  92. reversed = 1; \
  93. } \
  94. } \
  95. \
  96. GET_HALF_AREA(gc, a, b, c); \
  97. ccw = !__GL_FLOAT_LTZ(gc->polygon.shader.area); \
  98. \
  99. /* \
  100. ** Figure out if face is culled or not. The face check needs to be \
  101. ** based on the vertex winding before sorting. This code uses the \
  102. ** reversed flag to invert the sense of ccw - an xor accomplishes \
  103. ** this conversion without an if test. \
  104. ** \
  105. ** ccw reversed xor \
  106. ** --- -------- --- \
  107. ** 0 0 0 (remain !ccw) \
  108. ** 1 0 1 (remain ccw) \
  109. ** 0 1 1 (become ccw) \
  110. ** 1 1 0 (become cw) \
  111. */ \
  112. face = gc->polygon.face[ccw ^ reversed]; \
  113. if (face == gc->polygon.cullFace) { \
  114. /* Culled */ \
  115. return; \
  116. } \
  117. \
  118. STORE_AREA_PARAMS;
  119. // #define NO_RENDERING
  120. void __glTriangleOffsetZ( __GLcontext *gc, __GLvertex *a, __GLvertex *b,
  121. __GLvertex *c)
  122. {
  123. __GLfloat dzAC, dzBC;
  124. __GLfloat oneOverArea, t1, t2, t3, t4;
  125. __GLfloat zOffset;
  126. // Calc dzdxf, dzdyf values as in __glFillTriangle
  127. /* Pre-compute one over polygon area */
  128. if( gc->polygon.shader.area == 0.0f )
  129. oneOverArea = (__GLfloat)(__glOne / __GL_PGON_OFFSET_NEAR_ZERO);
  130. else
  131. oneOverArea = __glOne / gc->polygon.shader.area;
  132. /*
  133. ** Compute delta values for unit changes in x or y for each
  134. ** parameter.
  135. */
  136. t1 = gc->polygon.shader.dyAC * oneOverArea;
  137. t2 = gc->polygon.shader.dyBC * oneOverArea;
  138. t3 = gc->polygon.shader.dxAC * oneOverArea;
  139. t4 = gc->polygon.shader.dxBC * oneOverArea;
  140. dzAC = a->window.z - c->window.z;
  141. dzBC = b->window.z - c->window.z;
  142. gc->polygon.shader.dzdxf = dzAC * t2 - dzBC * t1;
  143. gc->polygon.shader.dzdyf = dzBC * t3 - dzAC * t4;
  144. zOffset = __glPolygonOffsetZ(gc);
  145. a->window.z += zOffset;
  146. b->window.z += zOffset;
  147. c->window.z += zOffset;
  148. }
  149. // Polygon offset z-munge: we modify the window.z of the vertices with the
  150. // offset z, then restore the z after rendering, due to the possibility of the
  151. // vertices being sent down multiple times by a higher-order primitive.
  152. #define SAVE_WINDOW_Z \
  153. awinz = a->window.z; bwinz = b->window.z; cwinz = c->window.z;
  154. #define RESTORE_WINDOW_Z \
  155. a->window.z = awinz; \
  156. b->window.z = bwinz; \
  157. c->window.z = cwinz;
  158. #ifdef GL_EXT_flat_paletted_lighting
  159. void __glPickLightingPalette(__GLcontext *gc)
  160. {
  161. __GLtexture *tex;
  162. GLint loffset;
  163. tex = gc->texture.currentTexture;
  164. loffset = (GLint)(gc->vertex.provoking->color->r *
  165. gc->oneOverRedVertexScale *
  166. tex->paletteDivision) << tex->paletteDivShift;
  167. tex->paletteData = tex->paletteTotalData+loffset;
  168. __glGenSetPaletteOffset(gc, tex, loffset);
  169. }
  170. #endif GL_EXT_flat_paletted_lighting
  171. /*
  172. ** Generic triangle handling code. This code is used when render mode
  173. ** is GL_RENDER and the polygon modes are not both fill.
  174. */
  175. void FASTCALL __glRenderTriangle(__GLcontext *gc, __GLvertex *a,
  176. __GLvertex *b, __GLvertex *c)
  177. {
  178. GLuint needs, modeFlags, faceNeeds;
  179. GLint ccw, colorFace, reversed, face;
  180. __GLfloat dxAC, dxBC, dyAC, dyBC;
  181. __GLvertex *oa, *ob, *oc;
  182. __GLvertex *temp;
  183. __GLfloat awinz, bwinz, cwinz;
  184. #ifdef NO_RENDERING
  185. return;
  186. #endif
  187. oa = a; ob = b; oc = c;
  188. SORT_AND_CULL_FACE(a, b, c, face, ccw);
  189. /*
  190. ** Pick face to use for coloring
  191. */
  192. modeFlags = gc->polygon.shader.modeFlags;
  193. #ifdef NT
  194. if (modeFlags & __GL_SHADE_SMOOTH_LIGHT)
  195. { /* Smooth shading */
  196. if (modeFlags & __GL_SHADE_TWOSIDED && face == __GL_BACKFACE)
  197. {
  198. a->color++;
  199. b->color++;
  200. c->color++;
  201. }
  202. }
  203. #ifdef GL_WIN_phong_shading
  204. else if (modeFlags & __GL_SHADE_PHONG)
  205. { /* Phong shading */
  206. if (modeFlags & __GL_SHADE_TWOSIDED && face == __GL_BACKFACE)
  207. gc->polygon.shader.phong.face = __GL_BACKFACE;
  208. else
  209. gc->polygon.shader.phong.face = __GL_FRONTFACE;
  210. }
  211. #endif //GL_WIN_phong_shading
  212. else
  213. { /* Flat shading */
  214. __GLvertex *pv = gc->vertex.provoking;
  215. if (modeFlags & __GL_SHADE_TWOSIDED && face == __GL_BACKFACE)
  216. pv->color++;
  217. a->color = pv->color;
  218. b->color = pv->color;
  219. c->color = pv->color;
  220. }
  221. #else
  222. if (modeFlags & __GL_SHADE_TWOSIDED) {
  223. colorFace = face;
  224. faceNeeds = gc->vertex.faceNeeds[face];
  225. } else {
  226. colorFace = __GL_FRONTFACE;
  227. faceNeeds = gc->vertex.faceNeeds[__GL_FRONTFACE];
  228. }
  229. /*
  230. ** Choose colors for the vertices.
  231. */
  232. needs = gc->vertex.needs;
  233. pv = gc->vertex.provoking;
  234. if (modeFlags & __GL_SHADE_SMOOTH_LIGHT) {
  235. /* Smooth shading */
  236. a->color = &a->colors[colorFace];
  237. b->color = &b->colors[colorFace];
  238. c->color = &c->colors[colorFace];
  239. needs |= faceNeeds;
  240. } else {
  241. GLuint pvneeds;
  242. /*
  243. ** Validate the lighting (and color) information in the provoking
  244. ** vertex only. Fill routines always use gc->vertex.provoking->color
  245. ** to find the color.
  246. */
  247. pv->color = &pv->colors[colorFace];
  248. a->color = pv->color;
  249. b->color = pv->color;
  250. c->color = pv->color;
  251. pvneeds = faceNeeds & (__GL_HAS_LIGHTING |
  252. __GL_HAS_FRONT_COLOR | __GL_HAS_BACK_COLOR);
  253. if (~pv->has & pvneeds) {
  254. (*pv->validate)(gc, pv, pvneeds);
  255. }
  256. }
  257. /* Validate vertices */
  258. if (~a->has & needs) (*a->validate)(gc, a, needs);
  259. if (~b->has & needs) (*b->validate)(gc, b, needs);
  260. if (~c->has & needs) (*c->validate)(gc, c, needs);
  261. #endif
  262. /* Render triangle using the faces polygon mode */
  263. switch (gc->polygon.mode[face]) {
  264. case __GL_POLYGON_MODE_FILL:
  265. if (__GL_FLOAT_NEZ(gc->polygon.shader.area)) {
  266. #ifdef GL_EXT_flat_paletted_lighting
  267. if ((gc->state.enables.general & __GL_PALETTED_LIGHTING_ENABLE) &&
  268. (modeFlags & __GL_SHADE_SMOOTH_LIGHT) == 0 &&
  269. gc->texture.currentTexture != NULL)
  270. {
  271. __glPickLightingPalette(gc);
  272. }
  273. #endif
  274. (*gc->procs.fillTriangle)(gc, a, b, c, (GLboolean) ccw);
  275. }
  276. break;
  277. case __GL_POLYGON_MODE_POINT:
  278. if( gc->state.enables.general & __GL_POLYGON_OFFSET_POINT_ENABLE ) {
  279. SAVE_WINDOW_Z;
  280. __glTriangleOffsetZ( gc, a, b, c );
  281. }
  282. #ifdef NT
  283. if (oa->has & __GL_HAS_EDGEFLAG_BOUNDARY)
  284. (*gc->procs.renderPoint)(gc, oa);
  285. if (ob->has & __GL_HAS_EDGEFLAG_BOUNDARY)
  286. (*gc->procs.renderPoint)(gc, ob);
  287. if (oc->has & __GL_HAS_EDGEFLAG_BOUNDARY)
  288. (*gc->procs.renderPoint)(gc, oc);
  289. if( gc->state.enables.general & __GL_POLYGON_OFFSET_POINT_ENABLE ) {
  290. RESTORE_WINDOW_Z;
  291. }
  292. break;
  293. #else
  294. if (oa->boundaryEdge) (*gc->procs.renderPoint)(gc, oa);
  295. if (ob->boundaryEdge) (*gc->procs.renderPoint)(gc, ob);
  296. if (oc->boundaryEdge) (*gc->procs.renderPoint)(gc, oc);
  297. break;
  298. #endif
  299. case __GL_POLYGON_MODE_LINE:
  300. if( gc->state.enables.general & __GL_POLYGON_OFFSET_LINE_ENABLE ) {
  301. SAVE_WINDOW_Z;
  302. __glTriangleOffsetZ( gc, a, b, c );
  303. }
  304. #ifdef NT
  305. (*gc->procs.lineBegin)(gc);
  306. if ((oa->has & __GL_HAS_EDGEFLAG_BOUNDARY) &&
  307. (ob->has & __GL_HAS_EDGEFLAG_BOUNDARY) &&
  308. (oc->has & __GL_HAS_EDGEFLAG_BOUNDARY))
  309. {
  310. // Is this an important case to optimize?
  311. (*gc->procs.renderLine)(gc, oa, ob, __GL_LVERT_FIRST);
  312. (*gc->procs.renderLine)(gc, ob, oc, 0);
  313. (*gc->procs.renderLine)(gc, oc, oa, 0);
  314. }
  315. else
  316. {
  317. if (oa->has & __GL_HAS_EDGEFLAG_BOUNDARY)
  318. {
  319. (*gc->procs.renderLine)(gc, oa, ob, __GL_LVERT_FIRST);
  320. }
  321. if (ob->has & __GL_HAS_EDGEFLAG_BOUNDARY)
  322. {
  323. (*gc->procs.renderLine)(gc, ob, oc, __GL_LVERT_FIRST);
  324. }
  325. if (oc->has & __GL_HAS_EDGEFLAG_BOUNDARY)
  326. {
  327. (*gc->procs.renderLine)(gc, oc, oa, __GL_LVERT_FIRST);
  328. }
  329. }
  330. (*gc->procs.lineEnd)(gc);
  331. if( gc->state.enables.general & __GL_POLYGON_OFFSET_LINE_ENABLE ) {
  332. RESTORE_WINDOW_Z;
  333. }
  334. break;
  335. #else
  336. if (oa->boundaryEdge) {
  337. (*gc->procs.renderLine)(gc, oa, ob);
  338. }
  339. if (ob->boundaryEdge) {
  340. (*gc->procs.renderLine)(gc, ob, oc);
  341. }
  342. if (oc->boundaryEdge) {
  343. (*gc->procs.renderLine)(gc, oc, oa);
  344. }
  345. break;
  346. #endif
  347. }
  348. /* Restore color pointers */
  349. a->color = &a->colors[__GL_FRONTFACE];
  350. b->color = &b->colors[__GL_FRONTFACE];
  351. c->color = &c->colors[__GL_FRONTFACE];
  352. #ifdef NT
  353. if (!(modeFlags & __GL_SHADE_SMOOTH_LIGHT)
  354. #ifdef GL_WIN_phong_shading
  355. && !(modeFlags & __GL_SHADE_PHONG)
  356. #endif //GL_WIN_phong_shading
  357. )
  358. {
  359. __GLvertex *pv = gc->vertex.provoking;
  360. pv->color = &pv->colors[__GL_FRONTFACE];
  361. }
  362. #else
  363. pv->color = &pv->colors[__GL_FRONTFACE];
  364. #endif
  365. }
  366. /************************************************************************/
  367. /*
  368. ** Generic triangle handling code. This code is used when render mode
  369. ** is GL_RENDER and both polygon modes are FILL and the triangle is
  370. ** being flat shaded.
  371. */
  372. void FASTCALL __glRenderFlatTriangle(__GLcontext *gc, __GLvertex *a, __GLvertex *b,
  373. __GLvertex *c)
  374. {
  375. GLuint needs, pvneeds, modeFlags, faceNeeds;
  376. GLint ccw, colorFace, reversed, face;
  377. __GLfloat dxAC, dxBC, dyAC, dyBC;
  378. __GLvertex *temp;
  379. #ifdef NO_RENDERING
  380. return;
  381. #endif
  382. SORT_AND_CULL_FACE(a, b, c, face, ccw);
  383. if (__GL_FLOAT_EQZ(gc->polygon.shader.area))
  384. return;
  385. /*
  386. ** Pick face to use for coloring
  387. */
  388. modeFlags = gc->polygon.shader.modeFlags;
  389. #ifdef GL_EXT_flat_paletted_lighting
  390. ASSERTOPENGL((modeFlags & __GL_SHADE_SMOOTH_LIGHT) == 0,
  391. "Flat triangle with smooth shading\n");
  392. if ((gc->state.enables.general & __GL_PALETTED_LIGHTING_ENABLE) &&
  393. gc->texture.currentTexture != NULL)
  394. {
  395. __glPickLightingPalette(gc);
  396. }
  397. #endif
  398. #ifdef NT
  399. //!!! don't we need to update a,b,c color pointers if cheap fog is enabled?
  400. if (modeFlags & __GL_SHADE_TWOSIDED && face == __GL_BACKFACE)
  401. {
  402. __GLvertex *pv = gc->vertex.provoking;
  403. /* Fill triangle */
  404. pv->color++;
  405. (*gc->procs.fillTriangle)(gc, a, b, c, (GLboolean) ccw);
  406. pv->color--;
  407. }
  408. else
  409. {
  410. /* Fill triangle */
  411. (*gc->procs.fillTriangle)(gc, a, b, c, (GLboolean) ccw);
  412. }
  413. #else
  414. if (modeFlags & __GL_SHADE_TWOSIDED) {
  415. colorFace = face;
  416. faceNeeds = gc->vertex.faceNeeds[face];
  417. } else {
  418. colorFace = __GL_FRONTFACE;
  419. faceNeeds = gc->vertex.faceNeeds[__GL_FRONTFACE];
  420. }
  421. /*
  422. ** Choose colors for the vertices.
  423. */
  424. needs = gc->vertex.needs;
  425. pv = gc->vertex.provoking;
  426. /*
  427. ** Validate the lighting (and color) information in the provoking
  428. ** vertex only. Fill routines always use gc->vertex.provoking->color
  429. ** to find the color.
  430. */
  431. pv->color = &pv->colors[colorFace];
  432. pvneeds = faceNeeds & (__GL_HAS_LIGHTING |
  433. __GL_HAS_FRONT_COLOR | __GL_HAS_BACK_COLOR);
  434. if (~pv->has & pvneeds) {
  435. (*pv->validate)(gc, pv, pvneeds);
  436. }
  437. /* Validate vertices */
  438. if (~a->has & needs) (*a->validate)(gc, a, needs);
  439. if (~b->has & needs) (*b->validate)(gc, b, needs);
  440. if (~c->has & needs) (*c->validate)(gc, c, needs);
  441. /* Fill triangle */
  442. (*gc->procs.fillTriangle)(gc, a, b, c, (GLboolean) ccw);
  443. /* Restore color pointers */
  444. pv->color = &pv->colors[__GL_FRONTFACE];
  445. #endif
  446. }
  447. /************************************************************************/
  448. /*
  449. ** Generic triangle handling code. This code is used when render mode
  450. ** is GL_RENDER and both polygon modes are FILL and the triangle is
  451. ** being smooth shaded.
  452. */
  453. void FASTCALL __glRenderSmoothTriangle(__GLcontext *gc, __GLvertex *a, __GLvertex *b,
  454. __GLvertex *c)
  455. {
  456. GLuint needs, modeFlags;
  457. GLint ccw, colorFace, reversed, face;
  458. __GLfloat dxAC, dxBC, dyAC, dyBC;
  459. __GLvertex *temp;
  460. #ifdef NO_RENDERING
  461. return;
  462. #endif
  463. SORT_AND_CULL_FACE(a, b, c, face, ccw);
  464. if (__GL_FLOAT_EQZ(gc->polygon.shader.area))
  465. return;
  466. /*
  467. ** Pick face to use for coloring
  468. */
  469. modeFlags = gc->polygon.shader.modeFlags;
  470. #ifdef GL_EXT_flat_paletted_lighting
  471. // No lighting because smooth shading is always on in this routine
  472. #endif
  473. #ifdef NT
  474. if (modeFlags & __GL_SHADE_TWOSIDED && face == __GL_BACKFACE)
  475. {
  476. /* Fill triangle */
  477. a->color++;
  478. b->color++;
  479. c->color++;
  480. (*gc->procs.fillTriangle)(gc, a, b, c, (GLboolean) ccw);
  481. a->color--;
  482. b->color--;
  483. c->color--;
  484. }
  485. else
  486. {
  487. /* Fill triangle */
  488. (*gc->procs.fillTriangle)(gc, a, b, c, (GLboolean) ccw);
  489. }
  490. #else
  491. needs = gc->vertex.needs;
  492. if (modeFlags & __GL_SHADE_TWOSIDED) {
  493. colorFace = face;
  494. needs |= gc->vertex.faceNeeds[face];
  495. } else {
  496. colorFace = __GL_FRONTFACE;
  497. needs |= gc->vertex.faceNeeds[__GL_FRONTFACE];
  498. }
  499. /*
  500. ** Choose colors for the vertices.
  501. */
  502. a->color = &a->colors[colorFace];
  503. b->color = &b->colors[colorFace];
  504. c->color = &c->colors[colorFace];
  505. /* Validate vertices */
  506. if (~a->has & needs) (*a->validate)(gc, a, needs);
  507. if (~b->has & needs) (*b->validate)(gc, b, needs);
  508. if (~c->has & needs) (*c->validate)(gc, c, needs);
  509. /* Fill triangle */
  510. (*gc->procs.fillTriangle)(gc, a, b, c, (GLboolean) ccw);
  511. /* Restore color pointers */
  512. a->color = &a->colors[__GL_FRONTFACE];
  513. b->color = &b->colors[__GL_FRONTFACE];
  514. c->color = &c->colors[__GL_FRONTFACE];
  515. #endif
  516. }
  517. void FASTCALL __glDontRenderTriangle(__GLcontext *gc, __GLvertex *a, __GLvertex *b,
  518. __GLvertex *c)
  519. {
  520. }