s_triangle.c revision fa6b2fba7ad0504a63ab262f602c6f50f336ca1b
1/* $Id: s_triangle.c,v 1.44 2001/12/19 01:09:46 brianp Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version:  4.1
6 *
7 * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28/*
29 * When the device driver doesn't implement triangle rasterization it
30 * can hook in _swrast_Triangle, which eventually calls one of these
31 * functions to draw triangles.
32 */
33
34#include "glheader.h"
35#include "context.h"
36#include "colormac.h"
37#include "macros.h"
38#include "mem.h"
39#include "mmath.h"
40#include "texformat.h"
41#include "teximage.h"
42#include "texstate.h"
43
44#include "s_aatriangle.h"
45#include "s_context.h"
46#include "s_depth.h"
47#include "s_feedback.h"
48#include "s_span.h"
49#include "s_triangle.h"
50
51
52
53GLboolean _mesa_cull_triangle( GLcontext *ctx,
54			    const SWvertex *v0,
55			    const SWvertex *v1,
56			    const SWvertex *v2 )
57{
58   GLfloat ex = v1->win[0] - v0->win[0];
59   GLfloat ey = v1->win[1] - v0->win[1];
60   GLfloat fx = v2->win[0] - v0->win[0];
61   GLfloat fy = v2->win[1] - v0->win[1];
62   GLfloat c = ex*fy-ey*fx;
63
64   if (c * SWRAST_CONTEXT(ctx)->_backface_sign > 0)
65      return 0;
66
67   return 1;
68}
69
70
71
72/*
73 * Render a flat-shaded color index triangle.
74 */
75static void flat_ci_triangle( GLcontext *ctx,
76			      const SWvertex *v0,
77			      const SWvertex *v1,
78			      const SWvertex *v2 )
79{
80#define INTERP_Z 1
81#define INTERP_FOG 1
82
83#define RENDER_SPAN( span )						\
84   _mesa_write_monoindex_span(ctx, &span, v2->index, GL_POLYGON );
85
86#include "s_tritemp.h"
87}
88
89
90
91/*
92 * Render a smooth-shaded color index triangle.
93 */
94static void smooth_ci_triangle( GLcontext *ctx,
95				const SWvertex *v0,
96				const SWvertex *v1,
97				const SWvertex *v2 )
98{
99#define INTERP_Z 1
100#define INTERP_FOG 1
101#define INTERP_INDEX 1
102
103#define RENDER_SPAN( span )						\
104   GLuint i;						                \
105   SW_SPAN_SET_FLAG(span.filledColor);			                \
106   for (i = 0; i < span.end; i++) {					\
107      span.color.index[i] = FixedToInt(span.index);			\
108      span.index += span.indexStep;					\
109   }									\
110   _mesa_write_index_span(ctx, &span, GL_POLYGON);
111
112#include "s_tritemp.h"
113}
114
115
116
117/*
118 * Render a flat-shaded RGBA triangle.
119 */
120static void flat_rgba_triangle( GLcontext *ctx,
121				const SWvertex *v0,
122				const SWvertex *v1,
123				const SWvertex *v2 )
124{
125#define INTERP_Z 1
126#define INTERP_FOG 1
127#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
128
129#define RENDER_SPAN( span )						\
130   _mesa_write_monocolor_span(ctx, &span, v2->color, GL_POLYGON );
131
132#include "s_tritemp.h"
133
134   ASSERT(!ctx->Texture._ReallyEnabled);  /* texturing must be off */
135   ASSERT(ctx->Light.ShadeModel==GL_FLAT);
136}
137
138
139
140/*
141 * Render a smooth-shaded RGBA triangle.
142 */
143static void smooth_rgba_triangle( GLcontext *ctx,
144				  const SWvertex *v0,
145				  const SWvertex *v1,
146				  const SWvertex *v2 )
147{
148
149#define INTERP_Z 1
150#define INTERP_FOG 1
151#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
152#define INTERP_RGB 1
153#define INTERP_ALPHA 1
154
155#define RENDER_SPAN( span )					\
156   GLuint i;				        	        \
157   SW_SPAN_SET_FLAG(span.filledColor);			        \
158   for (i = 0; i < span.end; i++) {				\
159      span.color.rgba[i][RCOMP] = FixedToChan(span.red);	\
160      span.color.rgba[i][GCOMP] = FixedToChan(span.green);	\
161      span.color.rgba[i][BCOMP] = FixedToChan(span.blue);	\
162      span.color.rgba[i][ACOMP] = FixedToChan(span.alpha);	\
163      span.red += span.redStep;					\
164      span.green += span.greenStep;				\
165      span.blue += span.blueStep;				\
166      span.alpha += span.alphaStep;				\
167   }								\
168   _mesa_write_rgba_span(ctx, &span, GL_POLYGON);
169
170#include "s_tritemp.h"
171
172   ASSERT(!ctx->Texture._ReallyEnabled);  /* texturing must be off */
173   ASSERT(ctx->Light.ShadeModel==GL_SMOOTH);
174}
175
176
177/*
178 * Render an RGB, GL_DECAL, textured triangle.
179 * Interpolate S,T only w/out mipmapping or perspective correction.
180 *
181 * No fog.
182 */
183static void simple_textured_triangle( GLcontext *ctx,
184				      const SWvertex *v0,
185				      const SWvertex *v1,
186				      const SWvertex *v2 )
187{
188#define INTERP_INT_TEX 1
189#define S_SCALE twidth
190#define T_SCALE theight
191
192#define SETUP_CODE							\
193   SWcontext *swrast = SWRAST_CONTEXT(ctx);                             \
194   struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D;	\
195   GLint b = obj->BaseLevel;						\
196   const GLfloat twidth = (GLfloat) obj->Image[b]->Width;		\
197   const GLfloat theight = (GLfloat) obj->Image[b]->Height;		\
198   const GLint twidth_log2 = obj->Image[b]->WidthLog2;			\
199   const GLchan *texture = (const GLchan *) obj->Image[b]->Data;	\
200   const GLint smask = obj->Image[b]->Width - 1;			\
201   const GLint tmask = obj->Image[b]->Height - 1;			\
202   if (!texture) {							\
203      /* this shouldn't happen */					\
204      return;								\
205   }
206
207#define RENDER_SPAN( span  )						\
208   GLuint i;								\
209   SW_SPAN_SET_FLAG(span.filledColor);					\
210   span.intTex[0] -= FIXED_HALF; /* off-by-one error? */		\
211   span.intTex[1] -= FIXED_HALF;					\
212   for (i = 0; i < span.end; i++) {					\
213      GLint s = FixedToInt(span.intTex[0]) & smask;			\
214      GLint t = FixedToInt(span.intTex[1]) & tmask;			\
215      GLint pos = (t << twidth_log2) + s;				\
216      pos = pos + pos + pos;  /* multiply by 3 */			\
217      span.color.rgb[i][RCOMP] = texture[pos];				\
218      span.color.rgb[i][GCOMP] = texture[pos+1];			\
219      span.color.rgb[i][BCOMP] = texture[pos+2];			\
220      span.intTex[0] += span.intTexStep[0];				\
221      span.intTex[1] += span.intTexStep[1];				\
222   }									\
223   (*swrast->Driver.WriteRGBSpan)(ctx, span.end, span.x, span.y,	\
224                                  (CONST GLchan (*)[3]) span.color.rgb, NULL );
225
226#include "s_tritemp.h"
227}
228
229
230/*
231 * Render an RGB, GL_DECAL, textured triangle.
232 * Interpolate S,T, GL_LESS depth test, w/out mipmapping or
233 * perspective correction.
234 *
235 * No fog.
236 */
237static void simple_z_textured_triangle( GLcontext *ctx,
238					const SWvertex *v0,
239					const SWvertex *v1,
240					const SWvertex *v2 )
241{
242#define INTERP_Z 1
243#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
244#define INTERP_INT_TEX 1
245#define S_SCALE twidth
246#define T_SCALE theight
247
248#define SETUP_CODE							\
249   SWcontext *swrast = SWRAST_CONTEXT(ctx);                             \
250   struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D;	\
251   GLint b = obj->BaseLevel;						\
252   GLfloat twidth = (GLfloat) obj->Image[b]->Width;			\
253   GLfloat theight = (GLfloat) obj->Image[b]->Height;			\
254   GLint twidth_log2 = obj->Image[b]->WidthLog2;			\
255   const GLchan *texture = (const GLchan *) obj->Image[b]->Data;	\
256   GLint smask = obj->Image[b]->Width - 1;				\
257   GLint tmask = obj->Image[b]->Height - 1;				\
258   if (!texture) {							\
259      /* this shouldn't happen */					\
260      return;								\
261   }
262
263#define RENDER_SPAN( span )						\
264   GLuint i;				    				\
265   span.intTex[0] -= FIXED_HALF; /* off-by-one error? */		\
266   span.intTex[1] -= FIXED_HALF;					\
267   SW_SPAN_SET_FLAG(span.filledColor);					\
268   for (i = 0; i < span.end; i++) {					\
269      const GLdepth z = FixedToDepth(span.z);				\
270      if (z < zRow[i]) {						\
271         GLint s = FixedToInt(span.intTex[0]) & smask;			\
272         GLint t = FixedToInt(span.intTex[1]) & tmask;			\
273         GLint pos = (t << twidth_log2) + s;				\
274         pos = pos + pos + pos;  /* multiply by 3 */			\
275         span.color.rgb[i][RCOMP] = texture[pos];			\
276         span.color.rgb[i][GCOMP] = texture[pos+1];			\
277         span.color.rgb[i][BCOMP] = texture[pos+2];			\
278         zRow[i] = z;							\
279         span.mask[i] = 1;						\
280      }									\
281      else {								\
282         span.mask[i] = 0;						\
283      }									\
284      span.intTex[0] += span.intTexStep[0];				\
285      span.intTex[1] += span.intTexStep[1];				\
286      span.z += span.zStep;						\
287   }									\
288   (*swrast->Driver.WriteRGBSpan)(ctx, span.end, span.x, span.y,	\
289                                  (CONST GLchan (*)[3]) span.color.rgb, span.mask );
290
291#include "s_tritemp.h"
292}
293
294
295#if CHAN_TYPE != GL_FLOAT
296
297struct affine_info
298{
299   GLenum filter;
300   GLenum format;
301   GLenum envmode;
302   GLint smask, tmask;
303   GLint twidth_log2;
304   const GLchan *texture;
305   GLchan er, eg, eb, ea;
306   GLint tbytesline, tsize;
307};
308
309
310/* This function can handle GL_NEAREST or GL_LINEAR sampling of 2D RGB or RGBA
311 * textures with GL_REPLACE, GL_MODULATE, GL_BLEND, GL_DECAL or GL_ADD
312 * texture env modes.
313 */
314static INLINE void
315affine_span(GLcontext *ctx, struct sw_span *span,
316            struct affine_info *info)
317{
318   GLchan sample[4];  /* the filtered texture sample */
319
320   /* Instead of defining a function for each mode, a test is done
321    * between the outer and inner loops. This is to reduce code size
322    * and complexity. Observe that an optimizing compiler kills
323    * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST).
324    */
325
326#define NEAREST_RGB			\
327   sample[RCOMP] = tex00[RCOMP];	\
328   sample[GCOMP] = tex00[GCOMP];	\
329   sample[BCOMP] = tex00[BCOMP];	\
330   sample[ACOMP] = CHAN_MAX
331
332#define LINEAR_RGB							\
333   sample[RCOMP] = (ti * (si * tex00[0] + sf * tex01[0]) +		\
334             tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT;	\
335   sample[GCOMP] = (ti * (si * tex00[1] + sf * tex01[1]) +		\
336             tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT;	\
337   sample[BCOMP] = (ti * (si * tex00[2] + sf * tex01[2]) +		\
338             tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT;	\
339   sample[ACOMP] = CHAN_MAX
340
341#define NEAREST_RGBA  COPY_CHAN4(sample, tex00)
342
343#define LINEAR_RGBA							\
344   sample[RCOMP] = (ti * (si * tex00[0] + sf * tex01[0]) +		\
345               tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT;\
346   sample[GCOMP] = (ti * (si * tex00[1] + sf * tex01[1]) +		\
347               tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT;\
348   sample[BCOMP] = (ti * (si * tex00[2] + sf * tex01[2]) +		\
349               tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT;\
350   sample[ACOMP] = (ti * (si * tex00[3] + sf * tex01[3]) +		\
351               tf * (si * tex10[3] + sf * tex11[3])) >> 2 * FIXED_SHIFT
352
353#define MODULATE							   \
354   dest[RCOMP] = span->red   * (sample[RCOMP] + 1u) >> (FIXED_SHIFT + 8); \
355   dest[GCOMP] = span->green * (sample[GCOMP] + 1u) >> (FIXED_SHIFT + 8); \
356   dest[BCOMP] = span->blue  * (sample[BCOMP] + 1u) >> (FIXED_SHIFT + 8); \
357   dest[ACOMP] = span->alpha * (sample[ACOMP] + 1u) >> (FIXED_SHIFT + 8)
358
359#define DECAL								\
360   dest[RCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->red +		\
361               ((sample[ACOMP] + 1) * sample[RCOMP] << FIXED_SHIFT))	\
362               >> (FIXED_SHIFT + 8);					\
363   dest[GCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->green +		\
364               ((sample[ACOMP] + 1) * sample[GCOMP] << FIXED_SHIFT))	\
365               >> (FIXED_SHIFT + 8);					\
366   dest[BCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->blue +		\
367               ((sample[ACOMP] + 1) * sample[BCOMP] << FIXED_SHIFT))	\
368               >> (FIXED_SHIFT + 8);					\
369   dest[ACOMP] = FixedToInt(span->alpha)
370
371#define BLEND								\
372   dest[RCOMP] = ((CHAN_MAX - sample[RCOMP]) * span->red		\
373               + (sample[RCOMP] + 1) * info->er) >> (FIXED_SHIFT + 8);	\
374   dest[GCOMP] = ((CHAN_MAX - sample[GCOMP]) * span->green		\
375               + (sample[GCOMP] + 1) * info->eg) >> (FIXED_SHIFT + 8);	\
376   dest[BCOMP] = ((CHAN_MAX - sample[BCOMP]) * span->blue		\
377               + (sample[BCOMP] + 1) * info->eb) >> (FIXED_SHIFT + 8);	\
378   dest[ACOMP] = span->alpha * (sample[ACOMP] + 1) >> (FIXED_SHIFT + 8)
379
380#define REPLACE  COPY_CHAN4(dest, sample)
381
382#define ADD								\
383   {									\
384      GLint rSum = FixedToInt(span->red)   + (GLint) sample[RCOMP];	\
385      GLint gSum = FixedToInt(span->green) + (GLint) sample[GCOMP];	\
386      GLint bSum = FixedToInt(span->blue)  + (GLint) sample[BCOMP];	\
387      dest[RCOMP] = MIN2(rSum, CHAN_MAX);				\
388      dest[GCOMP] = MIN2(gSum, CHAN_MAX);				\
389      dest[BCOMP] = MIN2(bSum, CHAN_MAX);				\
390      dest[ACOMP] = span->alpha * (sample[ACOMP] + 1) >> (FIXED_SHIFT + 8); \
391  }
392
393/* shortcuts */
394
395#define NEAREST_RGB_REPLACE  NEAREST_RGB;REPLACE
396
397#define NEAREST_RGBA_REPLACE  COPY_CHAN4(dest, tex00)
398
399#define SPAN_NEAREST(DO_TEX,COMP)					\
400	for (i = 0; i < span->end; i++) {				\
401           /* Isn't it necessary to use FixedFloor below?? */		\
402           GLint s = FixedToInt(span->intTex[0]) & info->smask;		\
403           GLint t = FixedToInt(span->intTex[1]) & info->tmask;		\
404           GLint pos = (t << info->twidth_log2) + s;			\
405           const GLchan *tex00 = info->texture + COMP * pos;		\
406           DO_TEX;							\
407           span->red += span->redStep;					\
408	   span->green += span->greenStep;				\
409           span->blue += span->blueStep;				\
410	   span->alpha += span->alphaStep;				\
411	   span->intTex[0] += span->intTexStep[0];			\
412	   span->intTex[1] += span->intTexStep[1];			\
413           dest += 4;							\
414	}
415
416#define SPAN_LINEAR(DO_TEX,COMP)					\
417	for (i = 0; i < span->end; i++) {				\
418           /* Isn't it necessary to use FixedFloor below?? */		\
419           GLint s = FixedToInt(span->intTex[0]) & info->smask;		\
420           GLint t = FixedToInt(span->intTex[1]) & info->tmask;		\
421           GLfixed sf = span->intTex[0] & FIXED_FRAC_MASK;		\
422           GLfixed tf = span->intTex[1] & FIXED_FRAC_MASK;		\
423           GLfixed si = FIXED_FRAC_MASK - sf;				\
424           GLfixed ti = FIXED_FRAC_MASK - tf;				\
425           GLint pos = (t << info->twidth_log2) + s;			\
426           const GLchan *tex00 = info->texture + COMP * pos;		\
427           const GLchan *tex10 = tex00 + info->tbytesline;		\
428           const GLchan *tex01 = tex00 + COMP;				\
429           const GLchan *tex11 = tex10 + COMP;				\
430           (void) ti;							\
431           (void) si;							\
432           if (t == info->tmask) {					\
433              tex10 -= info->tsize;					\
434              tex11 -= info->tsize;					\
435           }								\
436           if (s == info->smask) {					\
437              tex01 -= info->tbytesline;				\
438              tex11 -= info->tbytesline;				\
439           }								\
440           DO_TEX;							\
441           span->red += span->redStep;					\
442	   span->green += span->greenStep;				\
443           span->blue += span->blueStep;				\
444	   span->alpha += span->alphaStep;				\
445	   span->intTex[0] += span->intTexStep[0];			\
446	   span->intTex[1] += span->intTexStep[1];			\
447           dest += 4;							\
448	}
449
450
451   GLuint i;
452   GLchan *dest = span->color.rgba[0];
453
454   SW_SPAN_SET_FLAG(span->filledColor);
455
456   span->intTex[0] -= FIXED_HALF;
457   span->intTex[1] -= FIXED_HALF;
458   switch (info->filter) {
459   case GL_NEAREST:
460      switch (info->format) {
461      case GL_RGB:
462         switch (info->envmode) {
463         case GL_MODULATE:
464            SPAN_NEAREST(NEAREST_RGB;MODULATE,3);
465            break;
466         case GL_DECAL:
467         case GL_REPLACE:
468            SPAN_NEAREST(NEAREST_RGB_REPLACE,3);
469            break;
470         case GL_BLEND:
471            SPAN_NEAREST(NEAREST_RGB;BLEND,3);
472            break;
473         case GL_ADD:
474            SPAN_NEAREST(NEAREST_RGB;ADD,3);
475            break;
476         default:
477            abort();
478         }
479         break;
480      case GL_RGBA:
481         switch(info->envmode) {
482         case GL_MODULATE:
483            SPAN_NEAREST(NEAREST_RGBA;MODULATE,4);
484            break;
485         case GL_DECAL:
486            SPAN_NEAREST(NEAREST_RGBA;DECAL,4);
487            break;
488         case GL_BLEND:
489            SPAN_NEAREST(NEAREST_RGBA;BLEND,4);
490            break;
491         case GL_ADD:
492            SPAN_NEAREST(NEAREST_RGBA;ADD,4);
493            break;
494         case GL_REPLACE:
495            SPAN_NEAREST(NEAREST_RGBA_REPLACE,4);
496            break;
497         default:
498            abort();
499         }
500         break;
501      }
502      break;
503
504   case GL_LINEAR:
505      span->intTex[0] -= FIXED_HALF;
506      span->intTex[1] -= FIXED_HALF;
507      switch (info->format) {
508      case GL_RGB:
509         switch (info->envmode) {
510         case GL_MODULATE:
511            SPAN_LINEAR(LINEAR_RGB;MODULATE,3);
512            break;
513         case GL_DECAL:
514         case GL_REPLACE:
515            SPAN_LINEAR(LINEAR_RGB;REPLACE,3);
516            break;
517         case GL_BLEND:
518            SPAN_LINEAR(LINEAR_RGB;BLEND,3);
519            break;
520         case GL_ADD:
521            SPAN_LINEAR(LINEAR_RGB;ADD,3);
522            break;
523         default:
524            abort();
525         }
526         break;
527      case GL_RGBA:
528         switch (info->envmode) {
529         case GL_MODULATE:
530            SPAN_LINEAR(LINEAR_RGBA;MODULATE,4);
531            break;
532         case GL_DECAL:
533            SPAN_LINEAR(LINEAR_RGBA;DECAL,4);
534            break;
535         case GL_BLEND:
536            SPAN_LINEAR(LINEAR_RGBA;BLEND,4);
537            break;
538         case GL_ADD:
539            SPAN_LINEAR(LINEAR_RGBA;ADD,4);
540            break;
541         case GL_REPLACE:
542            SPAN_LINEAR(LINEAR_RGBA;REPLACE,4);
543            break;
544         default:
545            abort();
546         }		    break;
547      }
548      break;
549   }
550   _mesa_write_rgba_span(ctx, span, GL_POLYGON);
551
552#undef SPAN_NEAREST
553#undef SPAN_LINEAR
554}
555
556
557
558/*
559 * Render an RGB/RGBA textured triangle without perspective correction.
560 */
561static void affine_textured_triangle( GLcontext *ctx,
562				      const SWvertex *v0,
563				      const SWvertex *v1,
564				      const SWvertex *v2 )
565{
566#define INTERP_Z 1
567#define INTERP_FOG 1
568#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
569#define INTERP_RGB 1
570#define INTERP_ALPHA 1
571#define INTERP_INT_TEX 1
572#define S_SCALE twidth
573#define T_SCALE theight
574
575#define SETUP_CODE							\
576   struct affine_info info;						\
577   struct gl_texture_unit *unit = ctx->Texture.Unit+0;			\
578   struct gl_texture_object *obj = unit->Current2D;			\
579   GLint b = obj->BaseLevel;						\
580   GLfloat twidth = (GLfloat) obj->Image[b]->Width;			\
581   GLfloat theight = (GLfloat) obj->Image[b]->Height;			\
582   info.texture = (const GLchan *) obj->Image[b]->Data;			\
583   info.twidth_log2 = obj->Image[b]->WidthLog2;				\
584   info.smask = obj->Image[b]->Width - 1;				\
585   info.tmask = obj->Image[b]->Height - 1;				\
586   info.format = obj->Image[b]->Format;					\
587   info.filter = obj->MinFilter;					\
588   info.envmode = unit->EnvMode;					\
589									\
590   if (info.envmode == GL_BLEND) {					\
591      /* potential off-by-one error here? (1.0f -> 2048 -> 0) */	\
592      info.er = FloatToFixed(unit->EnvColor[RCOMP]);			\
593      info.eg = FloatToFixed(unit->EnvColor[GCOMP]);			\
594      info.eb = FloatToFixed(unit->EnvColor[BCOMP]);			\
595      info.ea = FloatToFixed(unit->EnvColor[ACOMP]);			\
596   }									\
597   if (!info.texture) {							\
598      /* this shouldn't happen */					\
599      return;								\
600   }									\
601									\
602   switch (info.format) {						\
603   case GL_ALPHA:							\
604   case GL_LUMINANCE:							\
605   case GL_INTENSITY:							\
606      info.tbytesline = obj->Image[b]->Width;				\
607      break;								\
608   case GL_LUMINANCE_ALPHA:						\
609      info.tbytesline = obj->Image[b]->Width * 2;			\
610      break;								\
611   case GL_RGB:								\
612      info.tbytesline = obj->Image[b]->Width * 3;			\
613      break;								\
614   case GL_RGBA:							\
615      info.tbytesline = obj->Image[b]->Width * 4;			\
616      break;								\
617   default:								\
618      _mesa_problem(NULL, "Bad texture format in affine_texture_triangle");\
619      return;								\
620   }									\
621   info.tsize = obj->Image[b]->Height * info.tbytesline;
622
623#define RENDER_SPAN( span )   affine_span(ctx, &span, &info);
624
625#include "s_tritemp.h"
626
627}
628
629
630
631struct persp_info
632{
633   GLenum filter;
634   GLenum format;
635   GLenum envmode;
636   GLint smask, tmask;
637   GLint twidth_log2;
638   const GLchan *texture;
639   GLchan er, eg, eb, ea;   /* texture env color */
640   GLint tbytesline, tsize;
641};
642
643
644static INLINE void
645fast_persp_span(GLcontext *ctx, struct sw_span *span,
646		struct persp_info *info)
647{
648   GLchan sample[4];  /* the filtered texture sample */
649
650  /* Instead of defining a function for each mode, a test is done
651   * between the outer and inner loops. This is to reduce code size
652   * and complexity. Observe that an optimizing compiler kills
653   * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST).
654   */
655#define SPAN_NEAREST(DO_TEX,COMP)					\
656	for (i = 0; i < span->end; i++) {				\
657           GLdouble invQ = tex_coord[2] ?				\
658                                 (1.0 / tex_coord[2]) : 1.0;            \
659           GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ);		\
660           GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ);		\
661           GLint s = IFLOOR(s_tmp) & info->smask;	        	\
662           GLint t = IFLOOR(t_tmp) & info->tmask;	        	\
663           GLint pos = (t << info->twidth_log2) + s;			\
664           const GLchan *tex00 = info->texture + COMP * pos;		\
665           DO_TEX;							\
666           span->red += span->redStep;					\
667	   span->green += span->greenStep;				\
668           span->blue += span->blueStep;				\
669	   span->alpha += span->alphaStep;				\
670	   tex_coord[0] += tex_step[0];					\
671	   tex_coord[1] += tex_step[1];					\
672	   tex_coord[2] += tex_step[2];					\
673           dest += 4;							\
674	}
675
676#define SPAN_LINEAR(DO_TEX,COMP)					\
677	for (i = 0; i < span->end; i++) {				\
678           GLdouble invQ = tex_coord[2] ?				\
679                                 (1.0 / tex_coord[2]) : 1.0;            \
680           GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ);		\
681           GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ);		\
682           GLfixed s_fix = FloatToFixed(s_tmp) - FIXED_HALF;		\
683           GLfixed t_fix = FloatToFixed(t_tmp) - FIXED_HALF;        	\
684           GLint s = FixedToInt(FixedFloor(s_fix)) & info->smask;	\
685           GLint t = FixedToInt(FixedFloor(t_fix)) & info->tmask;	\
686           GLfixed sf = s_fix & FIXED_FRAC_MASK;			\
687           GLfixed tf = t_fix & FIXED_FRAC_MASK;			\
688           GLfixed si = FIXED_FRAC_MASK - sf;				\
689           GLfixed ti = FIXED_FRAC_MASK - tf;				\
690           GLint pos = (t << info->twidth_log2) + s;			\
691           const GLchan *tex00 = info->texture + COMP * pos;		\
692           const GLchan *tex10 = tex00 + info->tbytesline;		\
693           const GLchan *tex01 = tex00 + COMP;				\
694           const GLchan *tex11 = tex10 + COMP;				\
695           (void) ti;							\
696           (void) si;							\
697           if (t == info->tmask) {					\
698              tex10 -= info->tsize;					\
699              tex11 -= info->tsize;					\
700           }								\
701           if (s == info->smask) {					\
702              tex01 -= info->tbytesline;				\
703              tex11 -= info->tbytesline;				\
704           }								\
705           DO_TEX;							\
706           span->red   += span->redStep;				\
707	   span->green += span->greenStep;				\
708           span->blue  += span->blueStep;				\
709	   span->alpha += span->alphaStep;				\
710	   tex_coord[0] += tex_step[0];					\
711	   tex_coord[1] += tex_step[1];					\
712	   tex_coord[2] += tex_step[2];					\
713           dest += 4;							\
714	}
715
716   GLuint i;
717   GLfloat tex_coord[3], tex_step[3];
718   GLchan *dest = span->color.rgba[0];
719
720   SW_SPAN_SET_FLAG(span->filledColor);
721
722   tex_coord[0] = span->tex[0][0]  * (info->smask + 1),
723     tex_step[0] = span->texStep[0][0] * (info->smask + 1);
724   tex_coord[1] = span->tex[0][1] * (info->tmask + 1),
725     tex_step[1] = span->texStep[0][1] * (info->tmask + 1);
726   /* span->tex[0][2] only if 3D-texturing, here only 2D */
727   tex_coord[2] = span->tex[0][3],
728     tex_step[2] = span->texStep[0][3];
729
730   switch (info->filter) {
731   case GL_NEAREST:
732      switch (info->format) {
733      case GL_RGB:
734         switch (info->envmode) {
735         case GL_MODULATE:
736            SPAN_NEAREST(NEAREST_RGB;MODULATE,3);
737            break;
738         case GL_DECAL:
739         case GL_REPLACE:
740            SPAN_NEAREST(NEAREST_RGB_REPLACE,3);
741            break;
742         case GL_BLEND:
743            SPAN_NEAREST(NEAREST_RGB;BLEND,3);
744            break;
745         case GL_ADD:
746            SPAN_NEAREST(NEAREST_RGB;ADD,3);
747            break;
748         default:
749            abort();
750         }
751         break;
752      case GL_RGBA:
753         switch(info->envmode) {
754         case GL_MODULATE:
755            SPAN_NEAREST(NEAREST_RGBA;MODULATE,4);
756            break;
757         case GL_DECAL:
758            SPAN_NEAREST(NEAREST_RGBA;DECAL,4);
759            break;
760         case GL_BLEND:
761            SPAN_NEAREST(NEAREST_RGBA;BLEND,4);
762            break;
763         case GL_ADD:
764            SPAN_NEAREST(NEAREST_RGBA;ADD,4);
765            break;
766         case GL_REPLACE:
767            SPAN_NEAREST(NEAREST_RGBA_REPLACE,4);
768            break;
769         default:
770            abort();
771         }
772         break;
773      }
774      break;
775
776   case GL_LINEAR:
777      switch (info->format) {
778      case GL_RGB:
779         switch (info->envmode) {
780         case GL_MODULATE:
781            SPAN_LINEAR(LINEAR_RGB;MODULATE,3);
782            break;
783         case GL_DECAL:
784         case GL_REPLACE:
785            SPAN_LINEAR(LINEAR_RGB;REPLACE,3);
786            break;
787         case GL_BLEND:
788            SPAN_LINEAR(LINEAR_RGB;BLEND,3);
789            break;
790         case GL_ADD:
791            SPAN_LINEAR(LINEAR_RGB;ADD,3);
792            break;
793         default:
794            abort();
795         }
796         break;
797      case GL_RGBA:
798         switch (info->envmode) {
799         case GL_MODULATE:
800            SPAN_LINEAR(LINEAR_RGBA;MODULATE,4);
801            break;
802         case GL_DECAL:
803            SPAN_LINEAR(LINEAR_RGBA;DECAL,4);
804            break;
805         case GL_BLEND:
806            SPAN_LINEAR(LINEAR_RGBA;BLEND,4);
807            break;
808         case GL_ADD:
809            SPAN_LINEAR(LINEAR_RGBA;ADD,4);
810            break;
811         case GL_REPLACE:
812            SPAN_LINEAR(LINEAR_RGBA;REPLACE,4);
813            break;
814         default:
815            abort();
816         }
817         break;
818      }
819      break;
820   }
821
822   _mesa_write_rgba_span(ctx, span, GL_POLYGON);
823
824
825#undef SPAN_NEAREST
826#undef SPAN_LINEAR
827}
828
829
830/*
831 * Render an perspective corrected RGB/RGBA textured triangle.
832 * The Q (aka V in Mesa) coordinate must be zero such that the divide
833 * by interpolated Q/W comes out right.
834 *
835 */
836static void persp_textured_triangle( GLcontext *ctx,
837				     const SWvertex *v0,
838				     const SWvertex *v1,
839				     const SWvertex *v2 )
840{
841#define INTERP_Z 1
842#define INTERP_FOG 1
843#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
844#define INTERP_RGB 1
845#define INTERP_ALPHA 1
846#define INTERP_TEX 1
847
848#define SETUP_CODE							\
849   struct persp_info info;						\
850   struct gl_texture_unit *unit = ctx->Texture.Unit+0;			\
851   struct gl_texture_object *obj = unit->Current2D;			\
852   GLint b = obj->BaseLevel;						\
853   info.texture = (const GLchan *) obj->Image[b]->Data;			\
854   info.twidth_log2 = obj->Image[b]->WidthLog2;				\
855   info.smask = obj->Image[b]->Width - 1;				\
856   info.tmask = obj->Image[b]->Height - 1;				\
857   info.format = obj->Image[b]->Format;					\
858   info.filter = obj->MinFilter;					\
859   info.envmode = unit->EnvMode;					\
860									\
861   if (info.envmode == GL_BLEND) {					\
862      /* potential off-by-one error here? (1.0f -> 2048 -> 0) */	\
863      info.er = FloatToFixed(unit->EnvColor[RCOMP]);			\
864      info.eg = FloatToFixed(unit->EnvColor[GCOMP]);			\
865      info.eb = FloatToFixed(unit->EnvColor[BCOMP]);			\
866      info.ea = FloatToFixed(unit->EnvColor[ACOMP]);			\
867   }									\
868   if (!info.texture) {							\
869      /* this shouldn't happen */					\
870      return;								\
871   }									\
872									\
873   switch (info.format) {						\
874   case GL_ALPHA:							\
875   case GL_LUMINANCE:							\
876   case GL_INTENSITY:							\
877      info.tbytesline = obj->Image[b]->Width;				\
878      break;								\
879   case GL_LUMINANCE_ALPHA:						\
880      info.tbytesline = obj->Image[b]->Width * 2;			\
881      break;								\
882   case GL_RGB:								\
883      info.tbytesline = obj->Image[b]->Width * 3;			\
884      break;								\
885   case GL_RGBA:							\
886      info.tbytesline = obj->Image[b]->Width * 4;			\
887      break;								\
888   default:								\
889      _mesa_problem(NULL, "Bad texture format in persp_textured_triangle");\
890      return;								\
891   }									\
892   info.tsize = obj->Image[b]->Height * info.tbytesline;
893
894#define RENDER_SPAN( span )   fast_persp_span(ctx, &span, &info);
895
896#include "s_tritemp.h"
897
898}
899
900
901#endif /* CHAN_BITS != GL_FLOAT */
902
903
904
905
906/*
907 * Render a smooth-shaded, textured, RGBA triangle.
908 * Interpolate S,T,R with perspective correction, w/out mipmapping.
909 */
910static void general_textured_triangle( GLcontext *ctx,
911				       const SWvertex *v0,
912				       const SWvertex *v1,
913				       const SWvertex *v2 )
914{
915#define INTERP_Z 1
916#define INTERP_FOG 1
917#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
918#define INTERP_RGB 1
919#define INTERP_ALPHA 1
920#define INTERP_TEX 1
921
922#define SETUP_CODE							\
923   const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;	\
924   const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\
925   span.texWidth[0] = (GLfloat) texImage->Width;			\
926   span.texHeight[0] = (GLfloat) texImage->Height;			\
927   (void) fixedToDepthShift;
928
929#define RENDER_SPAN( span )						\
930   GLfloat fogSpan[MAX_WIDTH];						\
931   GLuint i;								\
932   SW_SPAN_SET_FLAG(span.filledColor);					\
933   SW_SPAN_SET_FLAG(span.filledTex[0]);					\
934   /* NOTE: we could just call rasterize_span() here instead */		\
935   for (i = 0; i < span.end; i++) {					\
936      GLdouble invQ = span.tex[0][3] ? (1.0 / span.tex[0][3]) : 1.0;	\
937      span.depth[i] = FixedToDepth(span.z);				\
938      span.z += span.zStep;						\
939      fogSpan[i] = span.fog;			          		\
940      span.fog += span.fogStep;					\
941      span.color.rgba[i][RCOMP] = FixedToChan(span.red);		\
942      span.color.rgba[i][GCOMP] = FixedToChan(span.green);		\
943      span.color.rgba[i][BCOMP] = FixedToChan(span.blue);		\
944      span.color.rgba[i][ACOMP] = FixedToChan(span.alpha);		\
945      span.red += span.redStep;					\
946      span.green += span.greenStep;					\
947      span.blue += span.blueStep;					\
948      span.alpha += span.alphaStep;					\
949      span.texcoords[0][i][0] = (GLfloat) (span.tex[0][0] * invQ);	\
950      span.texcoords[0][i][1] = (GLfloat) (span.tex[0][1] * invQ);	\
951      span.texcoords[0][i][2] = (GLfloat) (span.tex[0][2] * invQ);	\
952      span.tex[0][0] += span.texStep[0][0];				\
953      span.tex[0][1] += span.texStep[0][1];				\
954      span.tex[0][2] += span.texStep[0][2];				\
955      span.tex[0][3] += span.texStep[0][3];				\
956   }									\
957   _old_write_texture_span( ctx, span.end, span.x, span.y,		\
958                            span.depth, fogSpan,			\
959			    span.texcoords[0],				\
960                            NULL, span.color.rgba, NULL, NULL, GL_POLYGON );
961
962#define CLEANUP_CODE				\
963   UNDEFARRAY(sSpan);  /* mac 32k limitation */	\
964   UNDEFARRAY(tSpan);				\
965   UNDEFARRAY(uSpan);
966
967#include "s_tritemp.h"
968}
969
970
971/*
972 * Render a smooth-shaded, textured, RGBA triangle with separate specular
973 * color interpolation.
974 * Interpolate texcoords with perspective correction, w/out mipmapping.
975 */
976static void general_textured_spec_triangle( GLcontext *ctx,
977					    const SWvertex *v0,
978					    const SWvertex *v1,
979					    const SWvertex *v2 )
980{
981#define INTERP_Z 1
982#define INTERP_FOG 1
983#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
984#define INTERP_RGB 1
985#define INTERP_SPEC 1
986#define INTERP_ALPHA 1
987#define INTERP_TEX 1
988
989#define SETUP_CODE							\
990   const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;	\
991   const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\
992   span.texWidth[0] = (GLfloat) texImage->Width;			\
993   span.texHeight[0] = (GLfloat) texImage->Height;			\
994   (void) fixedToDepthShift;
995
996#define RENDER_SPAN( span )   _mesa_rasterize_span(ctx, &span);
997
998#include "s_tritemp.h"
999}
1000
1001
1002/*
1003 * Render a smooth-shaded, textured, RGBA triangle.
1004 * Interpolate S,T,R with perspective correction and compute lambda for
1005 * each fragment.  Lambda is used to determine whether to use the
1006 * minification or magnification filter.  If minification and using
1007 * mipmaps, lambda is also used to select the texture level of detail.
1008 */
1009static void lambda_textured_triangle( GLcontext *ctx,
1010				      const SWvertex *v0,
1011				      const SWvertex *v1,
1012				      const SWvertex *v2 )
1013{
1014#define INTERP_Z 1
1015#define INTERP_FOG 1
1016#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1017#define INTERP_RGB 1
1018#define INTERP_ALPHA 1
1019#define INTERP_TEX 1
1020#define INTERP_LAMBDA 1
1021
1022#define SETUP_CODE							\
1023   const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;	\
1024   const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\
1025   span.texWidth[0] = (GLfloat) texImage->Width;			\
1026   span.texHeight[0] = (GLfloat) texImage->Height;			\
1027   (void) fixedToDepthShift;
1028
1029#define RENDER_SPAN( span )   _mesa_rasterize_span(ctx, &span);
1030
1031#include "s_tritemp.h"
1032}
1033
1034
1035/*
1036 * Render a smooth-shaded, textured, RGBA triangle with separate specular
1037 * interpolation.
1038 * Interpolate S,T,R with perspective correction and compute lambda for
1039 * each fragment.  Lambda is used to determine whether to use the
1040 * minification or magnification filter.  If minification and using
1041 * mipmaps, lambda is also used to select the texture level of detail.
1042 */
1043static void lambda_textured_spec_triangle( GLcontext *ctx,
1044					   const SWvertex *v0,
1045					   const SWvertex *v1,
1046					   const SWvertex *v2 )
1047{
1048#define INTERP_Z 1
1049#define INTERP_FOG 1
1050#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1051#define INTERP_RGB 1
1052#define INTERP_SPEC 1
1053#define INTERP_ALPHA 1
1054#define INTERP_TEX 1
1055#define INTERP_LAMBDA 1
1056
1057#define SETUP_CODE							\
1058   const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;	\
1059   const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\
1060   span.texWidth[0] = (GLfloat) texImage->Width;			\
1061   span.texHeight[0] = (GLfloat) texImage->Height;			\
1062   (void) fixedToDepthShift;
1063
1064#define RENDER_SPAN( span )   _mesa_rasterize_span(ctx, &span);
1065
1066#include "s_tritemp.h"
1067}
1068
1069
1070/*
1071 * This is the big one!
1072 * Interpolate Z, RGB, Alpha, specular, fog, and N sets of texture coordinates
1073 * with lambda (LOD).
1074 * Yup, it's slow.
1075 */
1076static void
1077lambda_multitextured_triangle( GLcontext *ctx,
1078                               const SWvertex *v0,
1079                               const SWvertex *v1,
1080                               const SWvertex *v2 )
1081{
1082
1083#define INTERP_Z 1
1084#define INTERP_FOG 1
1085#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1086#define INTERP_RGB 1
1087#define INTERP_ALPHA 1
1088#define INTERP_SPEC 1
1089#define INTERP_MULTITEX 1
1090#define INTERP_LAMBDA 1
1091
1092#define SETUP_CODE							\
1093   GLuint u;								\
1094   for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {			\
1095      if (ctx->Texture.Unit[u]._ReallyEnabled) {			\
1096         const struct gl_texture_object *texObj;			\
1097         const struct gl_texture_image *texImage;			\
1098         texObj = ctx->Texture.Unit[u]._Current;			\
1099         texImage = texObj->Image[texObj->BaseLevel];			\
1100         span.texWidth[u] = (GLfloat) texImage->Width;			\
1101         span.texHeight[u] = (GLfloat) texImage->Height;		\
1102      }									\
1103   }									\
1104   (void) fixedToDepthShift;
1105
1106#define RENDER_SPAN( span )   _mesa_rasterize_span(ctx, &span);
1107
1108#include "s_tritemp.h"
1109
1110}
1111
1112
1113static void occlusion_zless_triangle( GLcontext *ctx,
1114				      const SWvertex *v0,
1115				      const SWvertex *v1,
1116				      const SWvertex *v2 )
1117{
1118   if (ctx->OcclusionResult) {
1119      return;
1120   }
1121
1122#define DO_OCCLUSION_TEST
1123#define INTERP_Z 1
1124#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1125
1126#define RENDER_SPAN( span )				\
1127   GLuint i;						\
1128   for (i = 0; i < span.end; i++) {			\
1129      GLdepth z = FixedToDepth(span.z);		\
1130      if (z < zRow[i]) {				\
1131         ctx->OcclusionResult = GL_TRUE;		\
1132         return;					\
1133      }							\
1134      span.z += span.zStep;				\
1135   }
1136
1137#include "s_tritemp.h"
1138}
1139
1140static void nodraw_triangle( GLcontext *ctx,
1141			     const SWvertex *v0,
1142			     const SWvertex *v1,
1143			     const SWvertex *v2 )
1144{
1145   (void) (ctx && v0 && v1 && v2);
1146}
1147
1148
1149/*
1150 * This is used when separate specular color is enabled, but not
1151 * texturing.  We add the specular color to the primary color,
1152 * draw the triangle, then restore the original primary color.
1153 * Inefficient, but seldom needed.
1154 */
1155void _swrast_add_spec_terms_triangle( GLcontext *ctx,
1156				      const SWvertex *v0,
1157				      const SWvertex *v1,
1158				      const SWvertex *v2 )
1159{
1160   SWvertex *ncv0 = (SWvertex *)v0; /* drop const qualifier */
1161   SWvertex *ncv1 = (SWvertex *)v1;
1162   SWvertex *ncv2 = (SWvertex *)v2;
1163#if CHAN_TYPE == GL_FLOAT
1164   GLfloat rSum, gSum, bSum;
1165#else
1166   GLint rSum, gSum, bSum;
1167#endif
1168   GLchan c[3][4];
1169   /* save original colors */
1170   COPY_CHAN4( c[0], ncv0->color );
1171   COPY_CHAN4( c[1], ncv1->color );
1172   COPY_CHAN4( c[2], ncv2->color );
1173   /* sum v0 */
1174   rSum = ncv0->color[0] + ncv0->specular[0];
1175   gSum = ncv0->color[1] + ncv0->specular[1];
1176   bSum = ncv0->color[2] + ncv0->specular[2];
1177   ncv0->color[0] = MIN2(rSum, CHAN_MAX);
1178   ncv0->color[1] = MIN2(gSum, CHAN_MAX);
1179   ncv0->color[2] = MIN2(bSum, CHAN_MAX);
1180   /* sum v1 */
1181   rSum = ncv1->color[0] + ncv1->specular[0];
1182   gSum = ncv1->color[1] + ncv1->specular[1];
1183   bSum = ncv1->color[2] + ncv1->specular[2];
1184   ncv1->color[0] = MIN2(rSum, CHAN_MAX);
1185   ncv1->color[1] = MIN2(gSum, CHAN_MAX);
1186   ncv1->color[2] = MIN2(bSum, CHAN_MAX);
1187   /* sum v2 */
1188   rSum = ncv2->color[0] + ncv2->specular[0];
1189   gSum = ncv2->color[1] + ncv2->specular[1];
1190   bSum = ncv2->color[2] + ncv2->specular[2];
1191   ncv2->color[0] = MIN2(rSum, CHAN_MAX);
1192   ncv2->color[1] = MIN2(gSum, CHAN_MAX);
1193   ncv2->color[2] = MIN2(bSum, CHAN_MAX);
1194   /* draw */
1195   SWRAST_CONTEXT(ctx)->SpecTriangle( ctx, ncv0, ncv1, ncv2 );
1196   /* restore original colors */
1197   COPY_CHAN4( ncv0->color, c[0] );
1198   COPY_CHAN4( ncv1->color, c[1] );
1199   COPY_CHAN4( ncv2->color, c[2] );
1200}
1201
1202
1203
1204#ifdef DEBUG
1205
1206/* record the current triangle function name */
1207static const char *triFuncName = NULL;
1208
1209#define USE(triFunc)                   \
1210do {                                   \
1211    triFuncName = #triFunc;            \
1212    /*printf("%s\n", triFuncName);*/   \
1213    swrast->Triangle = triFunc;        \
1214} while (0)
1215
1216#else
1217
1218#define USE(triFunc)  swrast->Triangle = triFunc;
1219
1220#endif
1221
1222
1223
1224
1225/*
1226 * Determine which triangle rendering function to use given the current
1227 * rendering context.
1228 *
1229 * Please update the summary flag _SWRAST_NEW_TRIANGLE if you add or
1230 * remove tests to this code.
1231 */
1232void
1233_swrast_choose_triangle( GLcontext *ctx )
1234{
1235   SWcontext *swrast = SWRAST_CONTEXT(ctx);
1236   const GLboolean rgbmode = ctx->Visual.rgbMode;
1237
1238   if (ctx->Polygon.CullFlag &&
1239       ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) {
1240      USE(nodraw_triangle);
1241      return;
1242   }
1243
1244   if (ctx->RenderMode==GL_RENDER) {
1245
1246      if (ctx->Polygon.SmoothFlag) {
1247         _mesa_set_aa_triangle_function(ctx);
1248         ASSERT(swrast->Triangle);
1249         return;
1250      }
1251
1252      if (ctx->Depth.OcclusionTest &&
1253          ctx->Depth.Test &&
1254          ctx->Depth.Mask == GL_FALSE &&
1255          ctx->Depth.Func == GL_LESS &&
1256          !ctx->Stencil.Enabled) {
1257         if ((rgbmode &&
1258              ctx->Color.ColorMask[0] == 0 &&
1259              ctx->Color.ColorMask[1] == 0 &&
1260              ctx->Color.ColorMask[2] == 0 &&
1261              ctx->Color.ColorMask[3] == 0)
1262             ||
1263             (!rgbmode && ctx->Color.IndexMask == 0)) {
1264            USE(occlusion_zless_triangle);
1265            return;
1266         }
1267      }
1268
1269      if (ctx->Texture._ReallyEnabled) {
1270         /* Ugh, we do a _lot_ of tests to pick the best textured tri func */
1271	 const struct gl_texture_object *texObj2D;
1272         const struct gl_texture_image *texImg;
1273         GLenum minFilter, magFilter, envMode;
1274         GLint format;
1275         texObj2D = ctx->Texture.Unit[0].Current2D;
1276         texImg = texObj2D ? texObj2D->Image[texObj2D->BaseLevel] : NULL;
1277         format = texImg ? texImg->TexFormat->MesaFormat : -1;
1278         minFilter = texObj2D ? texObj2D->MinFilter : (GLenum) 0;
1279         magFilter = texObj2D ? texObj2D->MagFilter : (GLenum) 0;
1280         envMode = ctx->Texture.Unit[0].EnvMode;
1281
1282         /* First see if we can used an optimized 2-D texture function */
1283         if (ctx->Texture._ReallyEnabled==TEXTURE0_2D
1284             && texObj2D->WrapS==GL_REPEAT
1285	     && texObj2D->WrapT==GL_REPEAT
1286             && texImg->Border==0
1287             && (format == MESA_FORMAT_RGB || format == MESA_FORMAT_RGBA)
1288	     && minFilter == magFilter
1289	     && ctx->Light.Model.ColorControl == GL_SINGLE_COLOR
1290	     && ctx->Texture.Unit[0].EnvMode != GL_COMBINE_EXT) {
1291	    if (ctx->Hint.PerspectiveCorrection==GL_FASTEST) {
1292	       if (minFilter == GL_NEAREST
1293		   && format == MESA_FORMAT_RGB
1294		   && (envMode == GL_REPLACE || envMode == GL_DECAL)
1295		   && ((swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)
1296			&& ctx->Depth.Func == GL_LESS
1297			&& ctx->Depth.Mask == GL_TRUE)
1298		       || swrast->_RasterMask == TEXTURE_BIT)
1299		   && ctx->Polygon.StippleFlag == GL_FALSE) {
1300		  if (swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)) {
1301		     USE(simple_z_textured_triangle);
1302		  }
1303		  else {
1304		     USE(simple_textured_triangle);
1305		  }
1306	       }
1307	       else {
1308#if CHAN_TYPE == GL_FLOAT
1309                  USE(general_textured_triangle);
1310#else
1311                  USE(affine_textured_triangle);
1312#endif
1313	       }
1314	    }
1315	    else {
1316#if CHAN_TYPE == GL_FLOAT
1317               USE(general_textured_triangle);
1318#else
1319               USE(persp_textured_triangle);
1320#endif
1321	    }
1322	 }
1323         else {
1324            /* More complicated textures (mipmap, multi-tex, sep specular) */
1325            GLboolean needLambda;
1326            /* if mag filter != min filter we need to compute lambda */
1327            const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;
1328            if (obj && obj->MinFilter != obj->MagFilter)
1329               needLambda = GL_TRUE;
1330            else
1331               needLambda = GL_FALSE;
1332            if (ctx->Texture._ReallyEnabled > TEXTURE0_ANY) {
1333               USE(lambda_multitextured_triangle);
1334            }
1335            else if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
1336               /* separate specular color interpolation */
1337               if (needLambda) {
1338                  USE(lambda_textured_spec_triangle);
1339	       }
1340               else {
1341                  USE(general_textured_spec_triangle);
1342	       }
1343            }
1344            else {
1345               if (needLambda) {
1346		  USE(lambda_textured_triangle);
1347	       }
1348               else {
1349                  USE(general_textured_triangle);
1350	       }
1351            }
1352         }
1353      }
1354      else {
1355         ASSERT(!ctx->Texture._ReallyEnabled);
1356	 if (ctx->Light.ShadeModel==GL_SMOOTH) {
1357	    /* smooth shaded, no texturing, stippled or some raster ops */
1358            if (rgbmode) {
1359	       USE(smooth_rgba_triangle);
1360            }
1361            else {
1362               USE(smooth_ci_triangle);
1363            }
1364	 }
1365	 else {
1366	    /* flat shaded, no texturing, stippled or some raster ops */
1367            if (rgbmode) {
1368	       USE(flat_rgba_triangle);
1369            }
1370            else {
1371               USE(flat_ci_triangle);
1372            }
1373	 }
1374      }
1375   }
1376   else if (ctx->RenderMode==GL_FEEDBACK) {
1377      USE(_mesa_feedback_triangle);
1378   }
1379   else {
1380      /* GL_SELECT mode */
1381      USE(_mesa_select_triangle);
1382   }
1383}
1384