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