s_triangle.c revision decc6e2a32ef49e673c081f30e19b8970155d887
1/*
2 * Mesa 3-D graphics library
3 * Version:  7.3
4 *
5 * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26/*
27 * When the device driver doesn't implement triangle rasterization it
28 * can hook in _swrast_Triangle, which eventually calls one of these
29 * functions to draw triangles.
30 */
31
32#include "main/glheader.h"
33#include "main/context.h"
34#include "main/colormac.h"
35#include "main/imports.h"
36#include "main/macros.h"
37#include "main/mtypes.h"
38#include "main/state.h"
39#include "program/prog_instruction.h"
40
41#include "s_aatriangle.h"
42#include "s_context.h"
43#include "s_feedback.h"
44#include "s_span.h"
45#include "s_triangle.h"
46
47
48/**
49 * Test if a triangle should be culled.  Used for feedback and selection mode.
50 * \return GL_TRUE if the triangle is to be culled, GL_FALSE otherwise.
51 */
52GLboolean
53_swrast_culltriangle( struct gl_context *ctx,
54                      const SWvertex *v0,
55                      const SWvertex *v1,
56                      const SWvertex *v2 )
57{
58   SWcontext *swrast = SWRAST_CONTEXT(ctx);
59   GLfloat ex = v1->attrib[FRAG_ATTRIB_WPOS][0] - v0->attrib[FRAG_ATTRIB_WPOS][0];
60   GLfloat ey = v1->attrib[FRAG_ATTRIB_WPOS][1] - v0->attrib[FRAG_ATTRIB_WPOS][1];
61   GLfloat fx = v2->attrib[FRAG_ATTRIB_WPOS][0] - v0->attrib[FRAG_ATTRIB_WPOS][0];
62   GLfloat fy = v2->attrib[FRAG_ATTRIB_WPOS][1] - v0->attrib[FRAG_ATTRIB_WPOS][1];
63   GLfloat c = ex*fy-ey*fx;
64
65   if (c * swrast->_BackfaceSign * swrast->_BackfaceCullSign <= 0.0F)
66      return GL_FALSE;
67
68   return GL_TRUE;
69}
70
71
72
73/*
74 * Render a flat-shaded RGBA triangle.
75 */
76#define NAME flat_rgba_triangle
77#define INTERP_Z 1
78#define SETUP_CODE				\
79   ASSERT(ctx->Texture._EnabledCoordUnits == 0);\
80   ASSERT(ctx->Light.ShadeModel==GL_FLAT);	\
81   span.interpMask |= SPAN_RGBA;		\
82   span.red = ChanToFixed(v2->color[0]);	\
83   span.green = ChanToFixed(v2->color[1]);	\
84   span.blue = ChanToFixed(v2->color[2]);	\
85   span.alpha = ChanToFixed(v2->color[3]);	\
86   span.redStep = 0;				\
87   span.greenStep = 0;				\
88   span.blueStep = 0;				\
89   span.alphaStep = 0;
90#define RENDER_SPAN( span )  _swrast_write_rgba_span(ctx, &span);
91#include "s_tritemp.h"
92
93
94
95/*
96 * Render a smooth-shaded RGBA triangle.
97 */
98#define NAME smooth_rgba_triangle
99#define INTERP_Z 1
100#define INTERP_RGB 1
101#define INTERP_ALPHA 1
102#define SETUP_CODE				\
103   {						\
104      /* texturing must be off */		\
105      ASSERT(ctx->Texture._EnabledCoordUnits == 0);	\
106      ASSERT(ctx->Light.ShadeModel==GL_SMOOTH);	\
107   }
108#define RENDER_SPAN( span )  _swrast_write_rgba_span(ctx, &span);
109#include "s_tritemp.h"
110
111
112
113/*
114 * Render an RGB, GL_DECAL, textured triangle.
115 * Interpolate S,T only w/out mipmapping or perspective correction.
116 *
117 * No fog.  No depth testing.
118 */
119#define NAME simple_textured_triangle
120#define INTERP_INT_TEX 1
121#define S_SCALE twidth
122#define T_SCALE theight
123
124#define SETUP_CODE							\
125   struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];	\
126   const struct gl_texture_object *obj = 				\
127      ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX];		\
128   const struct gl_texture_image *texImg =				\
129      obj->Image[0][obj->BaseLevel];					\
130   const GLfloat twidth = (GLfloat) texImg->Width;			\
131   const GLfloat theight = (GLfloat) texImg->Height;			\
132   const GLint twidth_log2 = texImg->WidthLog2;				\
133   const GLubyte *texture = (const GLubyte *) texImg->Data;		\
134   const GLint smask = texImg->Width - 1;				\
135   const GLint tmask = texImg->Height - 1;				\
136   ASSERT(texImg->TexFormat == MESA_FORMAT_RGB888);			\
137   if (!rb || !texture) {						\
138      return;								\
139   }
140
141#define RENDER_SPAN( span )						\
142   GLuint i;								\
143   GLubyte rgb[MAX_WIDTH][3];						\
144   span.intTex[0] -= FIXED_HALF; /* off-by-one error? */		\
145   span.intTex[1] -= FIXED_HALF;					\
146   for (i = 0; i < span.end; i++) {					\
147      GLint s = FixedToInt(span.intTex[0]) & smask;			\
148      GLint t = FixedToInt(span.intTex[1]) & tmask;			\
149      GLint pos = (t << twidth_log2) + s;				\
150      pos = pos + pos + pos;  /* multiply by 3 */			\
151      rgb[i][RCOMP] = texture[pos+2];					\
152      rgb[i][GCOMP] = texture[pos+1];					\
153      rgb[i][BCOMP] = texture[pos+0];					\
154      span.intTex[0] += span.intTexStep[0];				\
155      span.intTex[1] += span.intTexStep[1];				\
156   }									\
157   rb->PutRowRGB(ctx, rb, span.end, span.x, span.y, rgb, NULL);
158
159#include "s_tritemp.h"
160
161
162
163/*
164 * Render an RGB, GL_DECAL, textured triangle.
165 * Interpolate S,T, GL_LESS depth test, w/out mipmapping or
166 * perspective correction.
167 * Depth buffer bits must be <= sizeof(DEFAULT_SOFTWARE_DEPTH_TYPE)
168 *
169 * No fog.
170 */
171#define NAME simple_z_textured_triangle
172#define INTERP_Z 1
173#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
174#define INTERP_INT_TEX 1
175#define S_SCALE twidth
176#define T_SCALE theight
177
178#define SETUP_CODE							\
179   struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];	\
180   const struct gl_texture_object *obj = 				\
181      ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX];		\
182   const struct gl_texture_image *texImg = 				\
183       obj->Image[0][obj->BaseLevel]; 					\
184   const GLfloat twidth = (GLfloat) texImg->Width;			\
185   const GLfloat theight = (GLfloat) texImg->Height;			\
186   const GLint twidth_log2 = texImg->WidthLog2;				\
187   const GLubyte *texture = (const GLubyte *) texImg->Data;		\
188   const GLint smask = texImg->Width - 1;				\
189   const GLint tmask = texImg->Height - 1;				\
190   ASSERT(texImg->TexFormat == MESA_FORMAT_RGB888);			\
191   if (!rb || !texture) {						\
192      return;								\
193   }
194
195#define RENDER_SPAN( span )						\
196   GLuint i;				    				\
197   GLubyte rgb[MAX_WIDTH][3];						\
198   span.intTex[0] -= FIXED_HALF; /* off-by-one error? */		\
199   span.intTex[1] -= FIXED_HALF;					\
200   for (i = 0; i < span.end; i++) {					\
201      const GLuint z = FixedToDepth(span.z);				\
202      if (z < zRow[i]) {						\
203         GLint s = FixedToInt(span.intTex[0]) & smask;			\
204         GLint t = FixedToInt(span.intTex[1]) & tmask;			\
205         GLint pos = (t << twidth_log2) + s;				\
206         pos = pos + pos + pos;  /* multiply by 3 */			\
207         rgb[i][RCOMP] = texture[pos+2];				\
208         rgb[i][GCOMP] = texture[pos+1];				\
209         rgb[i][BCOMP] = texture[pos+0];				\
210         zRow[i] = z;							\
211         span.array->mask[i] = 1;					\
212      }									\
213      else {								\
214         span.array->mask[i] = 0;					\
215      }									\
216      span.intTex[0] += span.intTexStep[0];				\
217      span.intTex[1] += span.intTexStep[1];				\
218      span.z += span.zStep;						\
219   }									\
220   rb->PutRowRGB(ctx, rb, span.end, span.x, span.y, rgb, span.array->mask);
221
222#include "s_tritemp.h"
223
224
225#if CHAN_TYPE != GL_FLOAT
226
227struct affine_info
228{
229   GLenum filter;
230   GLenum format;
231   GLenum envmode;
232   GLint smask, tmask;
233   GLint twidth_log2;
234   const GLchan *texture;
235   GLfixed er, eg, eb, ea;
236   GLint tbytesline, tsize;
237};
238
239
240static INLINE GLint
241ilerp(GLint t, GLint a, GLint b)
242{
243   return a + ((t * (b - a)) >> FIXED_SHIFT);
244}
245
246static INLINE GLint
247ilerp_2d(GLint ia, GLint ib, GLint v00, GLint v10, GLint v01, GLint v11)
248{
249   const GLint temp0 = ilerp(ia, v00, v10);
250   const GLint temp1 = ilerp(ia, v01, v11);
251   return ilerp(ib, temp0, temp1);
252}
253
254
255/* This function can handle GL_NEAREST or GL_LINEAR sampling of 2D RGB or RGBA
256 * textures with GL_REPLACE, GL_MODULATE, GL_BLEND, GL_DECAL or GL_ADD
257 * texture env modes.
258 */
259static INLINE void
260affine_span(struct gl_context *ctx, SWspan *span,
261            struct affine_info *info)
262{
263   GLchan sample[4];  /* the filtered texture sample */
264   const GLuint texEnableSave = ctx->Texture._EnabledCoordUnits;
265
266   /* Instead of defining a function for each mode, a test is done
267    * between the outer and inner loops. This is to reduce code size
268    * and complexity. Observe that an optimizing compiler kills
269    * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST).
270    */
271
272#define NEAREST_RGB		\
273   sample[RCOMP] = tex00[2];	\
274   sample[GCOMP] = tex00[1];	\
275   sample[BCOMP] = tex00[0];	\
276   sample[ACOMP] = CHAN_MAX;
277
278#define LINEAR_RGB							\
279   sample[RCOMP] = ilerp_2d(sf, tf, tex00[2], tex01[2], tex10[2], tex11[2]);\
280   sample[GCOMP] = ilerp_2d(sf, tf, tex00[1], tex01[1], tex10[1], tex11[1]);\
281   sample[BCOMP] = ilerp_2d(sf, tf, tex00[0], tex01[0], tex10[0], tex11[0]);\
282   sample[ACOMP] = CHAN_MAX;
283
284#define NEAREST_RGBA  \
285   sample[RCOMP] = tex00[3];	\
286   sample[GCOMP] = tex00[2];	\
287   sample[BCOMP] = tex00[1];	\
288   sample[ACOMP] = tex00[0];
289
290#define LINEAR_RGBA							\
291   sample[RCOMP] = ilerp_2d(sf, tf, tex00[3], tex01[3], tex10[3], tex11[3]);\
292   sample[GCOMP] = ilerp_2d(sf, tf, tex00[2], tex01[2], tex10[2], tex11[2]);\
293   sample[BCOMP] = ilerp_2d(sf, tf, tex00[1], tex01[1], tex10[1], tex11[1]);\
294   sample[ACOMP] = ilerp_2d(sf, tf, tex00[0], tex01[0], tex10[0], tex11[0])
295
296#define MODULATE							  \
297   dest[RCOMP] = span->red   * (sample[RCOMP] + 1u) >> (FIXED_SHIFT + 8); \
298   dest[GCOMP] = span->green * (sample[GCOMP] + 1u) >> (FIXED_SHIFT + 8); \
299   dest[BCOMP] = span->blue  * (sample[BCOMP] + 1u) >> (FIXED_SHIFT + 8); \
300   dest[ACOMP] = span->alpha * (sample[ACOMP] + 1u) >> (FIXED_SHIFT + 8)
301
302#define DECAL								\
303   dest[RCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->red +		\
304               ((sample[ACOMP] + 1) * sample[RCOMP] << FIXED_SHIFT))	\
305               >> (FIXED_SHIFT + 8);					\
306   dest[GCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->green +		\
307               ((sample[ACOMP] + 1) * sample[GCOMP] << FIXED_SHIFT))	\
308               >> (FIXED_SHIFT + 8);					\
309   dest[BCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->blue +		\
310               ((sample[ACOMP] + 1) * sample[BCOMP] << FIXED_SHIFT))	\
311               >> (FIXED_SHIFT + 8);					\
312   dest[ACOMP] = FixedToInt(span->alpha)
313
314#define BLEND								\
315   dest[RCOMP] = ((CHAN_MAX - sample[RCOMP]) * span->red		\
316               + (sample[RCOMP] + 1) * info->er) >> (FIXED_SHIFT + 8);	\
317   dest[GCOMP] = ((CHAN_MAX - sample[GCOMP]) * span->green		\
318               + (sample[GCOMP] + 1) * info->eg) >> (FIXED_SHIFT + 8);	\
319   dest[BCOMP] = ((CHAN_MAX - sample[BCOMP]) * span->blue		\
320               + (sample[BCOMP] + 1) * info->eb) >> (FIXED_SHIFT + 8);	\
321   dest[ACOMP] = span->alpha * (sample[ACOMP] + 1) >> (FIXED_SHIFT + 8)
322
323#define REPLACE  COPY_CHAN4(dest, sample)
324
325#define ADD								\
326   {									\
327      GLint rSum = FixedToInt(span->red)   + (GLint) sample[RCOMP];	\
328      GLint gSum = FixedToInt(span->green) + (GLint) sample[GCOMP];	\
329      GLint bSum = FixedToInt(span->blue)  + (GLint) sample[BCOMP];	\
330      dest[RCOMP] = MIN2(rSum, CHAN_MAX);				\
331      dest[GCOMP] = MIN2(gSum, CHAN_MAX);				\
332      dest[BCOMP] = MIN2(bSum, CHAN_MAX);				\
333      dest[ACOMP] = span->alpha * (sample[ACOMP] + 1) >> (FIXED_SHIFT + 8); \
334  }
335
336/* shortcuts */
337
338#define NEAREST_RGB_REPLACE		\
339   NEAREST_RGB;				\
340   dest[0] = sample[0];			\
341   dest[1] = sample[1];			\
342   dest[2] = sample[2];			\
343   dest[3] = FixedToInt(span->alpha);
344
345#define NEAREST_RGBA_REPLACE  \
346   dest[RCOMP] = tex00[3]; \
347   dest[GCOMP] = tex00[2]; \
348   dest[BCOMP] = tex00[1]; \
349   dest[ACOMP] = tex00[0]
350
351#define SPAN_NEAREST(DO_TEX, COMPS)					\
352	for (i = 0; i < span->end; i++) {				\
353           /* Isn't it necessary to use FixedFloor below?? */		\
354           GLint s = FixedToInt(span->intTex[0]) & info->smask;		\
355           GLint t = FixedToInt(span->intTex[1]) & info->tmask;		\
356           GLint pos = (t << info->twidth_log2) + s;			\
357           const GLchan *tex00 = info->texture + COMPS * pos;		\
358           DO_TEX;							\
359           span->red += span->redStep;					\
360	   span->green += span->greenStep;				\
361           span->blue += span->blueStep;				\
362	   span->alpha += span->alphaStep;				\
363	   span->intTex[0] += span->intTexStep[0];			\
364	   span->intTex[1] += span->intTexStep[1];			\
365           dest += 4;							\
366	}
367
368#define SPAN_LINEAR(DO_TEX, COMPS)					\
369	for (i = 0; i < span->end; i++) {				\
370           /* Isn't it necessary to use FixedFloor below?? */		\
371           const GLint s = FixedToInt(span->intTex[0]) & info->smask;	\
372           const GLint t = FixedToInt(span->intTex[1]) & info->tmask;	\
373           const GLfixed sf = span->intTex[0] & FIXED_FRAC_MASK;	\
374           const GLfixed tf = span->intTex[1] & FIXED_FRAC_MASK;	\
375           const GLint pos = (t << info->twidth_log2) + s;		\
376           const GLchan *tex00 = info->texture + COMPS * pos;		\
377           const GLchan *tex10 = tex00 + info->tbytesline;		\
378           const GLchan *tex01 = tex00 + COMPS;				\
379           const GLchan *tex11 = tex10 + COMPS;				\
380           if (t == info->tmask) {					\
381              tex10 -= info->tsize;					\
382              tex11 -= info->tsize;					\
383           }								\
384           if (s == info->smask) {					\
385              tex01 -= info->tbytesline;				\
386              tex11 -= info->tbytesline;				\
387           }								\
388           DO_TEX;							\
389           span->red += span->redStep;					\
390	   span->green += span->greenStep;				\
391           span->blue += span->blueStep;				\
392	   span->alpha += span->alphaStep;				\
393	   span->intTex[0] += span->intTexStep[0];			\
394	   span->intTex[1] += span->intTexStep[1];			\
395           dest += 4;							\
396	}
397
398
399   GLuint i;
400   GLchan *dest = span->array->rgba[0];
401
402   /* Disable tex units so they're not re-applied in swrast_write_rgba_span */
403   ctx->Texture._EnabledCoordUnits = 0x0;
404
405   span->intTex[0] -= FIXED_HALF;
406   span->intTex[1] -= FIXED_HALF;
407   switch (info->filter) {
408   case GL_NEAREST:
409      switch (info->format) {
410      case MESA_FORMAT_RGB888:
411         switch (info->envmode) {
412         case GL_MODULATE:
413            SPAN_NEAREST(NEAREST_RGB;MODULATE,3);
414            break;
415         case GL_DECAL:
416         case GL_REPLACE:
417            SPAN_NEAREST(NEAREST_RGB_REPLACE,3);
418            break;
419         case GL_BLEND:
420            SPAN_NEAREST(NEAREST_RGB;BLEND,3);
421            break;
422         case GL_ADD:
423            SPAN_NEAREST(NEAREST_RGB;ADD,3);
424            break;
425         default:
426            _mesa_problem(ctx, "bad tex env mode in SPAN_LINEAR");
427            return;
428         }
429         break;
430      case MESA_FORMAT_RGBA8888:
431         switch(info->envmode) {
432         case GL_MODULATE:
433            SPAN_NEAREST(NEAREST_RGBA;MODULATE,4);
434            break;
435         case GL_DECAL:
436            SPAN_NEAREST(NEAREST_RGBA;DECAL,4);
437            break;
438         case GL_BLEND:
439            SPAN_NEAREST(NEAREST_RGBA;BLEND,4);
440            break;
441         case GL_ADD:
442            SPAN_NEAREST(NEAREST_RGBA;ADD,4);
443            break;
444         case GL_REPLACE:
445            SPAN_NEAREST(NEAREST_RGBA_REPLACE,4);
446            break;
447         default:
448            _mesa_problem(ctx, "bad tex env mode (2) in SPAN_LINEAR");
449            return;
450         }
451         break;
452      }
453      break;
454
455   case GL_LINEAR:
456      span->intTex[0] -= FIXED_HALF;
457      span->intTex[1] -= FIXED_HALF;
458      switch (info->format) {
459      case MESA_FORMAT_RGB888:
460         switch (info->envmode) {
461         case GL_MODULATE:
462            SPAN_LINEAR(LINEAR_RGB;MODULATE,3);
463            break;
464         case GL_DECAL:
465         case GL_REPLACE:
466            SPAN_LINEAR(LINEAR_RGB;REPLACE,3);
467            break;
468         case GL_BLEND:
469            SPAN_LINEAR(LINEAR_RGB;BLEND,3);
470            break;
471         case GL_ADD:
472            SPAN_LINEAR(LINEAR_RGB;ADD,3);
473            break;
474         default:
475            _mesa_problem(ctx, "bad tex env mode (3) in SPAN_LINEAR");
476            return;
477         }
478         break;
479      case MESA_FORMAT_RGBA8888:
480         switch (info->envmode) {
481         case GL_MODULATE:
482            SPAN_LINEAR(LINEAR_RGBA;MODULATE,4);
483            break;
484         case GL_DECAL:
485            SPAN_LINEAR(LINEAR_RGBA;DECAL,4);
486            break;
487         case GL_BLEND:
488            SPAN_LINEAR(LINEAR_RGBA;BLEND,4);
489            break;
490         case GL_ADD:
491            SPAN_LINEAR(LINEAR_RGBA;ADD,4);
492            break;
493         case GL_REPLACE:
494            SPAN_LINEAR(LINEAR_RGBA;REPLACE,4);
495            break;
496         default:
497            _mesa_problem(ctx, "bad tex env mode (4) in SPAN_LINEAR");
498            return;
499         }
500         break;
501      }
502      break;
503   }
504   span->interpMask &= ~SPAN_RGBA;
505   ASSERT(span->arrayMask & SPAN_RGBA);
506
507   _swrast_write_rgba_span(ctx, span);
508
509   /* re-enable texture units */
510   ctx->Texture._EnabledCoordUnits = texEnableSave;
511
512#undef SPAN_NEAREST
513#undef SPAN_LINEAR
514}
515
516
517
518/*
519 * Render an RGB/RGBA textured triangle without perspective correction.
520 */
521#define NAME affine_textured_triangle
522#define INTERP_Z 1
523#define INTERP_RGB 1
524#define INTERP_ALPHA 1
525#define INTERP_INT_TEX 1
526#define S_SCALE twidth
527#define T_SCALE theight
528
529#define SETUP_CODE							\
530   struct affine_info info;						\
531   struct gl_texture_unit *unit = ctx->Texture.Unit+0;			\
532   const struct gl_texture_object *obj = 				\
533      ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX];		\
534   const struct gl_texture_image *texImg = 				\
535      obj->Image[0][obj->BaseLevel]; 					\
536   const GLfloat twidth = (GLfloat) texImg->Width;			\
537   const GLfloat theight = (GLfloat) texImg->Height;			\
538   info.texture = (const GLchan *) texImg->Data;			\
539   info.twidth_log2 = texImg->WidthLog2;				\
540   info.smask = texImg->Width - 1;					\
541   info.tmask = texImg->Height - 1;					\
542   info.format = texImg->TexFormat;					\
543   info.filter = obj->MinFilter;					\
544   info.envmode = unit->EnvMode;					\
545   info.er = 0;					\
546   info.eg = 0;					\
547   info.eb = 0;					\
548   span.arrayMask |= SPAN_RGBA;						\
549									\
550   if (info.envmode == GL_BLEND) {					\
551      /* potential off-by-one error here? (1.0f -> 2048 -> 0) */	\
552      info.er = FloatToFixed(unit->EnvColor[RCOMP] * CHAN_MAXF);	\
553      info.eg = FloatToFixed(unit->EnvColor[GCOMP] * CHAN_MAXF);	\
554      info.eb = FloatToFixed(unit->EnvColor[BCOMP] * CHAN_MAXF);	\
555      info.ea = FloatToFixed(unit->EnvColor[ACOMP] * CHAN_MAXF);	\
556   }									\
557   if (!info.texture) {							\
558      /* this shouldn't happen */					\
559      return;								\
560   }									\
561									\
562   switch (info.format) {						\
563   case MESA_FORMAT_RGB888:						\
564      info.tbytesline = texImg->Width * 3;				\
565      break;								\
566   case MESA_FORMAT_RGBA8888:						\
567      info.tbytesline = texImg->Width * 4;				\
568      break;								\
569   default:								\
570      _mesa_problem(NULL, "Bad texture format in affine_texture_triangle");\
571      return;								\
572   }									\
573   info.tsize = texImg->Height * info.tbytesline;
574
575#define RENDER_SPAN( span )   affine_span(ctx, &span, &info);
576
577#include "s_tritemp.h"
578
579
580
581struct persp_info
582{
583   GLenum filter;
584   GLenum format;
585   GLenum envmode;
586   GLint smask, tmask;
587   GLint twidth_log2;
588   const GLchan *texture;
589   GLfixed er, eg, eb, ea;   /* texture env color */
590   GLint tbytesline, tsize;
591};
592
593
594static INLINE void
595fast_persp_span(struct gl_context *ctx, SWspan *span,
596		struct persp_info *info)
597{
598   GLchan sample[4];  /* the filtered texture sample */
599
600  /* Instead of defining a function for each mode, a test is done
601   * between the outer and inner loops. This is to reduce code size
602   * and complexity. Observe that an optimizing compiler kills
603   * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST).
604   */
605#define SPAN_NEAREST(DO_TEX,COMP)					\
606	for (i = 0; i < span->end; i++) {				\
607           GLdouble invQ = tex_coord[2] ?				\
608                                 (1.0 / tex_coord[2]) : 1.0;            \
609           GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ);		\
610           GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ);		\
611           GLint s = IFLOOR(s_tmp) & info->smask;	        	\
612           GLint t = IFLOOR(t_tmp) & info->tmask;	        	\
613           GLint pos = (t << info->twidth_log2) + s;			\
614           const GLchan *tex00 = info->texture + COMP * pos;		\
615           DO_TEX;							\
616           span->red += span->redStep;					\
617	   span->green += span->greenStep;				\
618           span->blue += span->blueStep;				\
619	   span->alpha += span->alphaStep;				\
620	   tex_coord[0] += tex_step[0];					\
621	   tex_coord[1] += tex_step[1];					\
622	   tex_coord[2] += tex_step[2];					\
623           dest += 4;							\
624	}
625
626#define SPAN_LINEAR(DO_TEX,COMP)					\
627	for (i = 0; i < span->end; i++) {				\
628           GLdouble invQ = tex_coord[2] ?				\
629                                 (1.0 / tex_coord[2]) : 1.0;            \
630           const GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ);	\
631           const GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ);	\
632           const GLfixed s_fix = FloatToFixed(s_tmp) - FIXED_HALF;	\
633           const GLfixed t_fix = FloatToFixed(t_tmp) - FIXED_HALF;      \
634           const GLint s = FixedToInt(FixedFloor(s_fix)) & info->smask;	\
635           const GLint t = FixedToInt(FixedFloor(t_fix)) & info->tmask;	\
636           const GLfixed sf = s_fix & FIXED_FRAC_MASK;			\
637           const GLfixed tf = t_fix & FIXED_FRAC_MASK;			\
638           const GLint pos = (t << info->twidth_log2) + s;		\
639           const GLchan *tex00 = info->texture + COMP * pos;		\
640           const GLchan *tex10 = tex00 + info->tbytesline;		\
641           const GLchan *tex01 = tex00 + COMP;				\
642           const GLchan *tex11 = tex10 + COMP;				\
643           if (t == info->tmask) {					\
644              tex10 -= info->tsize;					\
645              tex11 -= info->tsize;					\
646           }								\
647           if (s == info->smask) {					\
648              tex01 -= info->tbytesline;				\
649              tex11 -= info->tbytesline;				\
650           }								\
651           DO_TEX;							\
652           span->red   += span->redStep;				\
653	   span->green += span->greenStep;				\
654           span->blue  += span->blueStep;				\
655	   span->alpha += span->alphaStep;				\
656	   tex_coord[0] += tex_step[0];					\
657	   tex_coord[1] += tex_step[1];					\
658	   tex_coord[2] += tex_step[2];					\
659           dest += 4;							\
660	}
661
662   GLuint i;
663   GLfloat tex_coord[3], tex_step[3];
664   GLchan *dest = span->array->rgba[0];
665
666   const GLuint texEnableSave = ctx->Texture._EnabledCoordUnits;
667   ctx->Texture._EnabledCoordUnits = 0;
668
669   tex_coord[0] = span->attrStart[FRAG_ATTRIB_TEX0][0]  * (info->smask + 1);
670   tex_step[0] = span->attrStepX[FRAG_ATTRIB_TEX0][0] * (info->smask + 1);
671   tex_coord[1] = span->attrStart[FRAG_ATTRIB_TEX0][1] * (info->tmask + 1);
672   tex_step[1] = span->attrStepX[FRAG_ATTRIB_TEX0][1] * (info->tmask + 1);
673   /* span->attrStart[FRAG_ATTRIB_TEX0][2] only if 3D-texturing, here only 2D */
674   tex_coord[2] = span->attrStart[FRAG_ATTRIB_TEX0][3];
675   tex_step[2] = span->attrStepX[FRAG_ATTRIB_TEX0][3];
676
677   switch (info->filter) {
678   case GL_NEAREST:
679      switch (info->format) {
680      case MESA_FORMAT_RGB888:
681         switch (info->envmode) {
682         case GL_MODULATE:
683            SPAN_NEAREST(NEAREST_RGB;MODULATE,3);
684            break;
685         case GL_DECAL:
686         case GL_REPLACE:
687            SPAN_NEAREST(NEAREST_RGB_REPLACE,3);
688            break;
689         case GL_BLEND:
690            SPAN_NEAREST(NEAREST_RGB;BLEND,3);
691            break;
692         case GL_ADD:
693            SPAN_NEAREST(NEAREST_RGB;ADD,3);
694            break;
695         default:
696            _mesa_problem(ctx, "bad tex env mode (5) in SPAN_LINEAR");
697            return;
698         }
699         break;
700      case MESA_FORMAT_RGBA8888:
701         switch(info->envmode) {
702         case GL_MODULATE:
703            SPAN_NEAREST(NEAREST_RGBA;MODULATE,4);
704            break;
705         case GL_DECAL:
706            SPAN_NEAREST(NEAREST_RGBA;DECAL,4);
707            break;
708         case GL_BLEND:
709            SPAN_NEAREST(NEAREST_RGBA;BLEND,4);
710            break;
711         case GL_ADD:
712            SPAN_NEAREST(NEAREST_RGBA;ADD,4);
713            break;
714         case GL_REPLACE:
715            SPAN_NEAREST(NEAREST_RGBA_REPLACE,4);
716            break;
717         default:
718            _mesa_problem(ctx, "bad tex env mode (6) in SPAN_LINEAR");
719            return;
720         }
721         break;
722      }
723      break;
724
725   case GL_LINEAR:
726      switch (info->format) {
727      case MESA_FORMAT_RGB888:
728         switch (info->envmode) {
729         case GL_MODULATE:
730            SPAN_LINEAR(LINEAR_RGB;MODULATE,3);
731            break;
732         case GL_DECAL:
733         case GL_REPLACE:
734            SPAN_LINEAR(LINEAR_RGB;REPLACE,3);
735            break;
736         case GL_BLEND:
737            SPAN_LINEAR(LINEAR_RGB;BLEND,3);
738            break;
739         case GL_ADD:
740            SPAN_LINEAR(LINEAR_RGB;ADD,3);
741            break;
742         default:
743            _mesa_problem(ctx, "bad tex env mode (7) in SPAN_LINEAR");
744            return;
745         }
746         break;
747      case MESA_FORMAT_RGBA8888:
748         switch (info->envmode) {
749         case GL_MODULATE:
750            SPAN_LINEAR(LINEAR_RGBA;MODULATE,4);
751            break;
752         case GL_DECAL:
753            SPAN_LINEAR(LINEAR_RGBA;DECAL,4);
754            break;
755         case GL_BLEND:
756            SPAN_LINEAR(LINEAR_RGBA;BLEND,4);
757            break;
758         case GL_ADD:
759            SPAN_LINEAR(LINEAR_RGBA;ADD,4);
760            break;
761         case GL_REPLACE:
762            SPAN_LINEAR(LINEAR_RGBA;REPLACE,4);
763            break;
764         default:
765            _mesa_problem(ctx, "bad tex env mode (8) in SPAN_LINEAR");
766            return;
767         }
768         break;
769      }
770      break;
771   }
772
773   ASSERT(span->arrayMask & SPAN_RGBA);
774   _swrast_write_rgba_span(ctx, span);
775
776#undef SPAN_NEAREST
777#undef SPAN_LINEAR
778
779   /* restore state */
780   ctx->Texture._EnabledCoordUnits = texEnableSave;
781}
782
783
784/*
785 * Render an perspective corrected RGB/RGBA textured triangle.
786 * The Q (aka V in Mesa) coordinate must be zero such that the divide
787 * by interpolated Q/W comes out right.
788 *
789 */
790#define NAME persp_textured_triangle
791#define INTERP_Z 1
792#define INTERP_RGB 1
793#define INTERP_ALPHA 1
794#define INTERP_ATTRIBS 1
795
796#define SETUP_CODE							\
797   struct persp_info info;						\
798   const struct gl_texture_unit *unit = ctx->Texture.Unit+0;		\
799   const struct gl_texture_object *obj = 				\
800      ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX];		\
801   const struct gl_texture_image *texImg = 				\
802      obj->Image[0][obj->BaseLevel];			 		\
803   info.texture = (const GLchan *) texImg->Data;			\
804   info.twidth_log2 = texImg->WidthLog2;				\
805   info.smask = texImg->Width - 1;					\
806   info.tmask = texImg->Height - 1;					\
807   info.format = texImg->TexFormat;					\
808   info.filter = obj->MinFilter;					\
809   info.envmode = unit->EnvMode;					\
810   info.er = 0;					\
811   info.eg = 0;					\
812   info.eb = 0;					\
813									\
814   if (info.envmode == GL_BLEND) {					\
815      /* potential off-by-one error here? (1.0f -> 2048 -> 0) */	\
816      info.er = FloatToFixed(unit->EnvColor[RCOMP] * CHAN_MAXF);	\
817      info.eg = FloatToFixed(unit->EnvColor[GCOMP] * CHAN_MAXF);	\
818      info.eb = FloatToFixed(unit->EnvColor[BCOMP] * CHAN_MAXF);	\
819      info.ea = FloatToFixed(unit->EnvColor[ACOMP] * CHAN_MAXF);	\
820   }									\
821   if (!info.texture) {							\
822      /* this shouldn't happen */					\
823      return;								\
824   }									\
825									\
826   switch (info.format) {						\
827   case MESA_FORMAT_RGB888:						\
828      info.tbytesline = texImg->Width * 3;				\
829      break;								\
830   case MESA_FORMAT_RGBA8888:						\
831      info.tbytesline = texImg->Width * 4;				\
832      break;								\
833   default:								\
834      _mesa_problem(NULL, "Bad texture format in persp_textured_triangle");\
835      return;								\
836   }									\
837   info.tsize = texImg->Height * info.tbytesline;
838
839#define RENDER_SPAN( span )			\
840   span.interpMask &= ~SPAN_RGBA;		\
841   span.arrayMask |= SPAN_RGBA;			\
842   fast_persp_span(ctx, &span, &info);
843
844#include "s_tritemp.h"
845
846#endif /*CHAN_TYPE != GL_FLOAT*/
847
848
849
850/*
851 * Render an RGBA triangle with arbitrary attributes.
852 */
853#define NAME general_triangle
854#define INTERP_Z 1
855#define INTERP_RGB 1
856#define INTERP_ALPHA 1
857#define INTERP_ATTRIBS 1
858#define RENDER_SPAN( span )   _swrast_write_rgba_span(ctx, &span);
859#include "s_tritemp.h"
860
861
862
863
864/*
865 * Special tri function for occlusion testing
866 */
867#define NAME occlusion_zless_triangle
868#define INTERP_Z 1
869#define SETUP_CODE							\
870   struct gl_renderbuffer *rb = ctx->DrawBuffer->_DepthBuffer;		\
871   struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;	\
872   ASSERT(ctx->Depth.Test);						\
873   ASSERT(!ctx->Depth.Mask);						\
874   ASSERT(ctx->Depth.Func == GL_LESS);					\
875   if (!q) {								\
876      return;								\
877   }
878#define RENDER_SPAN( span )						\
879   if (rb->Format == MESA_FORMAT_Z16) {					\
880      GLuint i;								\
881      const GLushort *zRow = (const GLushort *)				\
882         rb->GetPointer(ctx, rb, span.x, span.y);			\
883      for (i = 0; i < span.end; i++) {					\
884         GLuint z = FixedToDepth(span.z);				\
885         if (z < zRow[i]) {						\
886            q->Result++;						\
887         }								\
888         span.z += span.zStep;						\
889      }									\
890   }									\
891   else {								\
892      GLuint i;								\
893      const GLuint *zRow = (const GLuint *)				\
894         rb->GetPointer(ctx, rb, span.x, span.y);			\
895      for (i = 0; i < span.end; i++) {					\
896         if ((GLuint)span.z < zRow[i]) {				\
897            q->Result++;						\
898         }								\
899         span.z += span.zStep;						\
900      }									\
901   }
902#include "s_tritemp.h"
903
904
905
906static void
907nodraw_triangle( struct gl_context *ctx,
908                 const SWvertex *v0,
909                 const SWvertex *v1,
910                 const SWvertex *v2 )
911{
912   (void) (ctx && v0 && v1 && v2);
913}
914
915
916/*
917 * This is used when separate specular color is enabled, but not
918 * texturing.  We add the specular color to the primary color,
919 * draw the triangle, then restore the original primary color.
920 * Inefficient, but seldom needed.
921 */
922void
923_swrast_add_spec_terms_triangle(struct gl_context *ctx, const SWvertex *v0,
924                                const SWvertex *v1, const SWvertex *v2)
925{
926   SWvertex *ncv0 = (SWvertex *)v0; /* drop const qualifier */
927   SWvertex *ncv1 = (SWvertex *)v1;
928   SWvertex *ncv2 = (SWvertex *)v2;
929   GLfloat rSum, gSum, bSum;
930   GLchan cSave[3][4];
931
932   /* save original colors */
933   COPY_CHAN4( cSave[0], ncv0->color );
934   COPY_CHAN4( cSave[1], ncv1->color );
935   COPY_CHAN4( cSave[2], ncv2->color );
936   /* sum v0 */
937   rSum = CHAN_TO_FLOAT(ncv0->color[0]) + ncv0->attrib[FRAG_ATTRIB_COL1][0];
938   gSum = CHAN_TO_FLOAT(ncv0->color[1]) + ncv0->attrib[FRAG_ATTRIB_COL1][1];
939   bSum = CHAN_TO_FLOAT(ncv0->color[2]) + ncv0->attrib[FRAG_ATTRIB_COL1][2];
940   UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[0], rSum);
941   UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[1], gSum);
942   UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[2], bSum);
943   /* sum v1 */
944   rSum = CHAN_TO_FLOAT(ncv1->color[0]) + ncv1->attrib[FRAG_ATTRIB_COL1][0];
945   gSum = CHAN_TO_FLOAT(ncv1->color[1]) + ncv1->attrib[FRAG_ATTRIB_COL1][1];
946   bSum = CHAN_TO_FLOAT(ncv1->color[2]) + ncv1->attrib[FRAG_ATTRIB_COL1][2];
947   UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[0], rSum);
948   UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[1], gSum);
949   UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[2], bSum);
950   /* sum v2 */
951   rSum = CHAN_TO_FLOAT(ncv2->color[0]) + ncv2->attrib[FRAG_ATTRIB_COL1][0];
952   gSum = CHAN_TO_FLOAT(ncv2->color[1]) + ncv2->attrib[FRAG_ATTRIB_COL1][1];
953   bSum = CHAN_TO_FLOAT(ncv2->color[2]) + ncv2->attrib[FRAG_ATTRIB_COL1][2];
954   UNCLAMPED_FLOAT_TO_CHAN(ncv2->color[0], rSum);
955   UNCLAMPED_FLOAT_TO_CHAN(ncv2->color[1], gSum);
956   UNCLAMPED_FLOAT_TO_CHAN(ncv2->color[2], bSum);
957   /* draw */
958   SWRAST_CONTEXT(ctx)->SpecTriangle( ctx, ncv0, ncv1, ncv2 );
959   /* restore original colors */
960   COPY_CHAN4( ncv0->color, cSave[0] );
961   COPY_CHAN4( ncv1->color, cSave[1] );
962   COPY_CHAN4( ncv2->color, cSave[2] );
963}
964
965
966
967#ifdef DEBUG
968
969/* record the current triangle function name */
970const char *_mesa_triFuncName = NULL;
971
972#define USE(triFunc)				\
973do {						\
974    _mesa_triFuncName = #triFunc;		\
975    /*printf("%s\n", _mesa_triFuncName);*/	\
976    swrast->Triangle = triFunc;			\
977} while (0)
978
979#else
980
981#define USE(triFunc)  swrast->Triangle = triFunc;
982
983#endif
984
985
986
987
988/*
989 * Determine which triangle rendering function to use given the current
990 * rendering context.
991 *
992 * Please update the summary flag _SWRAST_NEW_TRIANGLE if you add or
993 * remove tests to this code.
994 */
995void
996_swrast_choose_triangle( struct gl_context *ctx )
997{
998   SWcontext *swrast = SWRAST_CONTEXT(ctx);
999
1000   if (ctx->Polygon.CullFlag &&
1001       ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) {
1002      USE(nodraw_triangle);
1003      return;
1004   }
1005
1006   if (ctx->RenderMode==GL_RENDER) {
1007
1008      if (ctx->Polygon.SmoothFlag) {
1009         _swrast_set_aa_triangle_function(ctx);
1010         ASSERT(swrast->Triangle);
1011         return;
1012      }
1013
1014      /* special case for occlusion testing */
1015      if (ctx->Query.CurrentOcclusionObject &&
1016          ctx->Depth.Test &&
1017          ctx->Depth.Mask == GL_FALSE &&
1018          ctx->Depth.Func == GL_LESS &&
1019          !ctx->Stencil._Enabled) {
1020         if (ctx->Color.ColorMask[0][0] == 0 &&
1021	     ctx->Color.ColorMask[0][1] == 0 &&
1022	     ctx->Color.ColorMask[0][2] == 0 &&
1023	     ctx->Color.ColorMask[0][3] == 0) {
1024            USE(occlusion_zless_triangle);
1025            return;
1026         }
1027      }
1028
1029      /*
1030       * XXX should examine swrast->_ActiveAttribMask to determine what
1031       * needs to be interpolated.
1032       */
1033      if (ctx->Texture._EnabledCoordUnits ||
1034          ctx->FragmentProgram._Current ||
1035          ctx->ATIFragmentShader._Enabled ||
1036          _mesa_need_secondary_color(ctx) ||
1037          swrast->_FogEnabled) {
1038         /* Ugh, we do a _lot_ of tests to pick the best textured tri func */
1039         const struct gl_texture_object *texObj2D;
1040         const struct gl_texture_image *texImg;
1041         GLenum minFilter, magFilter, envMode;
1042         gl_format format;
1043         texObj2D = ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX];
1044
1045         texImg = texObj2D ? texObj2D->Image[0][texObj2D->BaseLevel] : NULL;
1046         format = texImg ? texImg->TexFormat : MESA_FORMAT_NONE;
1047         minFilter = texObj2D ? texObj2D->MinFilter : GL_NONE;
1048         magFilter = texObj2D ? texObj2D->MagFilter : GL_NONE;
1049         envMode = ctx->Texture.Unit[0].EnvMode;
1050
1051         /* First see if we can use an optimized 2-D texture function */
1052         if (ctx->Texture._EnabledCoordUnits == 0x1
1053             && !ctx->FragmentProgram._Current
1054             && !ctx->ATIFragmentShader._Enabled
1055             && ctx->Texture._EnabledUnits == 0x1
1056             && ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT
1057             && texObj2D->WrapS == GL_REPEAT
1058             && texObj2D->WrapT == GL_REPEAT
1059             && texObj2D->_Swizzle == SWIZZLE_NOOP
1060             && texImg->_IsPowerOfTwo
1061             && texImg->Border == 0
1062             && texImg->Width == texImg->RowStride
1063             && (format == MESA_FORMAT_RGB888 || format == MESA_FORMAT_RGBA8888)
1064             && minFilter == magFilter
1065             && ctx->Light.Model.ColorControl == GL_SINGLE_COLOR
1066             && !swrast->_FogEnabled
1067             && ctx->Texture.Unit[0].EnvMode != GL_COMBINE_EXT
1068             && ctx->Texture.Unit[0].EnvMode != GL_COMBINE4_NV) {
1069	    if (ctx->Hint.PerspectiveCorrection==GL_FASTEST) {
1070	       if (minFilter == GL_NEAREST
1071		   && format == MESA_FORMAT_RGB888
1072		   && (envMode == GL_REPLACE || envMode == GL_DECAL)
1073		   && ((swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)
1074			&& ctx->Depth.Func == GL_LESS
1075			&& ctx->Depth.Mask == GL_TRUE)
1076		       || swrast->_RasterMask == TEXTURE_BIT)
1077		   && ctx->Polygon.StippleFlag == GL_FALSE
1078                   && ctx->DrawBuffer->Visual.depthBits <= 16) {
1079		  if (swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)) {
1080		     USE(simple_z_textured_triangle);
1081		  }
1082		  else {
1083		     USE(simple_textured_triangle);
1084		  }
1085	       }
1086	       else {
1087#if CHAN_BITS != 8
1088                  USE(general_triangle);
1089#else
1090                  if (format == MESA_FORMAT_RGBA8888 && !_mesa_little_endian()) {
1091                     /* We only handle RGBA8888 correctly on little endian
1092                      * in the optimized code above.
1093                      */
1094                     USE(general_triangle);
1095                  }
1096                  else {
1097                     USE(affine_textured_triangle);
1098                 }
1099#endif
1100	       }
1101	    }
1102	    else {
1103#if CHAN_BITS != 8
1104               USE(general_triangle);
1105#else
1106               USE(persp_textured_triangle);
1107#endif
1108	    }
1109	 }
1110         else {
1111            /* general case textured triangles */
1112            USE(general_triangle);
1113         }
1114      }
1115      else {
1116         ASSERT(!swrast->_FogEnabled);
1117         ASSERT(!_mesa_need_secondary_color(ctx));
1118	 if (ctx->Light.ShadeModel==GL_SMOOTH) {
1119	    /* smooth shaded, no texturing, stippled or some raster ops */
1120#if CHAN_BITS != 8
1121               USE(general_triangle);
1122#else
1123               USE(smooth_rgba_triangle);
1124#endif
1125	 }
1126	 else {
1127	    /* flat shaded, no texturing, stippled or some raster ops */
1128#if CHAN_BITS != 8
1129            USE(general_triangle);
1130#else
1131            USE(flat_rgba_triangle);
1132#endif
1133	 }
1134      }
1135   }
1136   else if (ctx->RenderMode==GL_FEEDBACK) {
1137      USE(_swrast_feedback_triangle);
1138   }
1139   else {
1140      /* GL_SELECT mode */
1141      USE(_swrast_select_triangle);
1142   }
1143}
1144