s_triangle.c revision 571c8ecc8f9442fb8bbaa1f29b1d0d4f8e5b3cad
1/* $Id: s_triangle.c,v 1.31 2001/07/09 16:16:20 brianp Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version:  3.5
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#include "s_trispan.h"
51
52
53
54GLboolean _mesa_cull_triangle( GLcontext *ctx,
55			    const SWvertex *v0,
56			    const SWvertex *v1,
57			    const SWvertex *v2 )
58{
59   GLfloat ex = v1->win[0] - v0->win[0];
60   GLfloat ey = v1->win[1] - v0->win[1];
61   GLfloat fx = v2->win[0] - v0->win[0];
62   GLfloat fy = v2->win[1] - v0->win[1];
63   GLfloat c = ex*fy-ey*fx;
64
65   if (c * SWRAST_CONTEXT(ctx)->_backface_sign > 0)
66      return 0;
67
68   return 1;
69}
70
71
72
73/*
74 * Render a flat-shaded color index triangle.
75 */
76static void flat_ci_triangle( GLcontext *ctx,
77			      const SWvertex *v0,
78			      const SWvertex *v1,
79			      const SWvertex *v2 )
80{
81#define INTERP_Z 1
82#define INTERP_FOG 1
83
84#define RENDER_SPAN( span )						\
85   GLdepth zSpan[MAX_WIDTH];						\
86   GLfloat fogSpan[MAX_WIDTH];						\
87   GLuint i;								\
88   for (i = 0; i < span.count; i++) {					\
89      zSpan[i] = FixedToDepth(span.z);					\
90      span.z += span.zStep;						\
91      fogSpan[i] = span.fog;						\
92      span.fog += span.fogStep;						\
93   }									\
94   _mesa_write_monoindex_span(ctx, span.count, span.x, span.y,		\
95	                      zSpan, fogSpan, v0->index, NULL, GL_POLYGON );
96
97#include "s_tritemp.h"
98}
99
100
101
102/*
103 * Render a smooth-shaded color index triangle.
104 */
105static void smooth_ci_triangle( GLcontext *ctx,
106				const SWvertex *v0,
107				const SWvertex *v1,
108				const SWvertex *v2 )
109{
110#define INTERP_Z 1
111#define INTERP_FOG 1
112#define INTERP_INDEX 1
113
114#define RENDER_SPAN( span )						\
115   GLdepth zSpan[MAX_WIDTH];						\
116   GLfloat fogSpan[MAX_WIDTH];						\
117   GLuint indexSpan[MAX_WIDTH];						\
118   GLuint i;						                \
119   for (i = 0; i < span.count; i++) {					\
120      zSpan[i] = FixedToDepth(span.z);					\
121      span.z += span.zStep;						\
122      indexSpan[i] = FixedToInt(span.index);				\
123      span.index += span.indexStep;					\
124      fogSpan[i] = span.fog;						\
125      span.fog += span.fogStep;						\
126   }									\
127   _mesa_write_index_span(ctx, span.count, span.x, span.y,		\
128                          zSpan, fogSpan, indexSpan, NULL, GL_POLYGON);
129
130#include "s_tritemp.h"
131}
132
133
134
135/*
136 * Render a flat-shaded RGBA triangle.
137 */
138static void flat_rgba_triangle( GLcontext *ctx,
139				const SWvertex *v0,
140				const SWvertex *v1,
141				const SWvertex *v2 )
142{
143#define INTERP_Z 1
144#define INTERP_FOG 1
145#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
146
147#define RENDER_SPAN( span )						\
148   GLdepth zSpan[MAX_WIDTH];						\
149   GLfloat fogSpan[MAX_WIDTH];						\
150   GLuint i;								\
151   for (i = 0; i < span.count; i++) {					\
152      zSpan[i] = FixedToDepth(span.z);					\
153      span.z += span.zStep;						\
154      fogSpan[i] = span.fog;						\
155      span.fog += span.fogStep;						\
156   }									\
157   _mesa_write_monocolor_span(ctx, span.count, span.x, span.y, zSpan,	\
158                              fogSpan, v2->color, NULL, GL_POLYGON );
159
160#include "s_tritemp.h"
161
162   ASSERT(!ctx->Texture._ReallyEnabled);  /* texturing must be off */
163   ASSERT(ctx->Light.ShadeModel==GL_FLAT);
164}
165
166
167
168/*
169 * Render a smooth-shaded RGBA triangle.
170 */
171static void smooth_rgba_triangle( GLcontext *ctx,
172				  const SWvertex *v0,
173				  const SWvertex *v1,
174				  const SWvertex *v2 )
175{
176
177#define INTERP_Z 1
178#define INTERP_FOG 1
179#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
180#define INTERP_RGB 1
181#define INTERP_ALPHA 1
182
183#define RENDER_SPAN( span )					\
184   GLdepth zSpan[MAX_WIDTH];					\
185   GLchan rgbaSpan[MAX_WIDTH][4];				\
186   GLfloat fogSpan[MAX_WIDTH];					\
187   GLuint i;				        	        \
188   for (i = 0; i < span.count; i++) {				\
189      rgbaSpan[i][RCOMP] = FixedToInt(span.red);		\
190      rgbaSpan[i][GCOMP] = FixedToInt(span.green);		\
191      rgbaSpan[i][BCOMP] = FixedToInt(span.blue);		\
192      rgbaSpan[i][ACOMP] = FixedToInt(span.alpha);		\
193      span.red += span.redStep;					\
194      span.green += span.greenStep;				\
195      span.blue += span.blueStep;				\
196      span.alpha += span.alphaStep;				\
197      zSpan[i] = FixedToDepth(span.z);				\
198      span.z += span.zStep;					\
199      fogSpan[i] = span.fog;					\
200      span.fog += span.fogStep;					\
201   }								\
202   _mesa_write_rgba_span(ctx, span.count, span.x, span.y,	\
203                         (CONST GLdepth *) zSpan,		\
204                         fogSpan, rgbaSpan, NULL, GL_POLYGON);
205
206#include "s_tritemp.h"
207
208   ASSERT(!ctx->Texture._ReallyEnabled);  /* texturing must be off */
209   ASSERT(ctx->Light.ShadeModel==GL_SMOOTH);
210}
211
212
213/*
214 * Render an RGB, GL_DECAL, textured triangle.
215 * Interpolate S,T only w/out mipmapping or perspective correction.
216 *
217 * No fog.
218 */
219static void simple_textured_triangle( GLcontext *ctx,
220				      const SWvertex *v0,
221				      const SWvertex *v1,
222				      const SWvertex *v2 )
223{
224#define INTERP_INT_TEX 1
225#define S_SCALE twidth
226#define T_SCALE theight
227
228#define SETUP_CODE							\
229   SWcontext *swrast = SWRAST_CONTEXT(ctx);                             \
230   struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D;	\
231   GLint b = obj->BaseLevel;						\
232   const GLfloat twidth = (GLfloat) obj->Image[b]->Width;		\
233   const GLfloat theight = (GLfloat) obj->Image[b]->Height;		\
234   const GLint twidth_log2 = obj->Image[b]->WidthLog2;			\
235   const GLchan *texture = (const GLchan *) obj->Image[b]->Data;	\
236   const GLint smask = obj->Image[b]->Width - 1;			\
237   const GLint tmask = obj->Image[b]->Height - 1;			\
238   if (!texture) {							\
239      /* this shouldn't happen */					\
240      return;								\
241   }
242
243#define RENDER_SPAN( span  )						\
244   GLchan rgbSpan[MAX_WIDTH][3];					\
245   GLuint i;								\
246   span.intTex[0] -= FIXED_HALF; /* off-by-one error? */		\
247   span.intTex[1] -= FIXED_HALF;					\
248   for (i = 0; i < span.count; i++) {					\
249      GLint s = FixedToInt(span.intTex[0]) & smask;			\
250      GLint t = FixedToInt(span.intTex[1]) & tmask;			\
251      GLint pos = (t << twidth_log2) + s;				\
252      pos = pos + pos + pos;  /* multiply by 3 */			\
253      rgbSpan[i][RCOMP] = texture[pos];					\
254      rgbSpan[i][GCOMP] = texture[pos+1];				\
255      rgbSpan[i][BCOMP] = texture[pos+2];				\
256      span.intTex[0] += span.intTexStep[0];				\
257      span.intTex[1] += span.intTexStep[1];				\
258   }									\
259   (*swrast->Driver.WriteRGBSpan)(ctx, span.count, span.x, span.y,	\
260                                  (CONST GLchan (*)[3]) rgbSpan, NULL );
261
262#include "s_tritemp.h"
263}
264
265
266/*
267 * Render an RGB, GL_DECAL, textured triangle.
268 * Interpolate S,T, GL_LESS depth test, w/out mipmapping or
269 * perspective correction.
270 *
271 * No fog.
272 */
273static void simple_z_textured_triangle( GLcontext *ctx,
274					const SWvertex *v0,
275					const SWvertex *v1,
276					const SWvertex *v2 )
277{
278#define INTERP_Z 1
279#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
280#define INTERP_INT_TEX 1
281#define S_SCALE twidth
282#define T_SCALE theight
283
284#define SETUP_CODE							\
285   SWcontext *swrast = SWRAST_CONTEXT(ctx);                             \
286   struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D;	\
287   GLint b = obj->BaseLevel;						\
288   GLfloat twidth = (GLfloat) obj->Image[b]->Width;			\
289   GLfloat theight = (GLfloat) obj->Image[b]->Height;			\
290   GLint twidth_log2 = obj->Image[b]->WidthLog2;			\
291   const GLchan *texture = (const GLchan *) obj->Image[b]->Data;	\
292   GLint smask = obj->Image[b]->Width - 1;				\
293   GLint tmask = obj->Image[b]->Height - 1;				\
294   if (!texture) {							\
295      /* this shouldn't happen */					\
296      return;								\
297   }
298
299#define RENDER_SPAN( span )						\
300   GLchan rgbSpan[MAX_WIDTH][3];					\
301   GLubyte mask[MAX_WIDTH];						\
302   GLuint i;				    				\
303   span.intTex[0] -= FIXED_HALF; /* off-by-one error? */		\
304   span.intTex[1] -= FIXED_HALF;					\
305   for (i = 0; i < span.count; i++) {					\
306      const GLdepth z = FixedToDepth(span.z);				\
307      if (z < zRow[i]) {						\
308         GLint s = FixedToInt(span.intTex[0]) & smask;			\
309         GLint t = FixedToInt(span.intTex[1]) & tmask;			\
310         GLint pos = (t << twidth_log2) + s;				\
311         pos = pos + pos + pos;  /* multiply by 3 */			\
312         rgbSpan[i][RCOMP] = texture[pos];				\
313         rgbSpan[i][GCOMP] = texture[pos+1];				\
314         rgbSpan[i][BCOMP] = texture[pos+2];				\
315         zRow[i] = z;							\
316         mask[i] = 1;							\
317      }									\
318      else {								\
319         mask[i] = 0;							\
320      }									\
321      span.intTex[0] += span.intTexStep[0];				\
322      span.intTex[1] += span.intTexStep[1];				\
323      span.z += span.zStep;						\
324   }									\
325   (*swrast->Driver.WriteRGBSpan)(ctx, span.count, span.x, span.y,	\
326                                  (CONST GLchan (*)[3]) rgbSpan, mask );
327
328#include "s_tritemp.h"
329}
330
331
332
333struct affine_info
334{
335   GLenum filter;
336   GLenum format;
337   GLenum envmode;
338   GLint smask, tmask;
339   GLint twidth_log2;
340   const GLchan *texture;
341   GLchan er, eg, eb, ea;
342   GLint tbytesline, tsize;
343   GLint fixedToDepthShift;
344};
345
346static void
347affine_span(GLcontext *ctx, struct triangle_span *span,
348            struct affine_info *info)
349{
350   GLint tr, tg, tb, ta;
351
352  /* Instead of defining a function for each mode, a test is done
353   * between the outer and inner loops. This is to reduce code size
354   * and complexity. Observe that an optimizing compiler kills
355   * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST).
356   */
357
358#define NEAREST_RGB		\
359        tr = tex00[RCOMP];	\
360        tg = tex00[GCOMP];	\
361        tb = tex00[BCOMP];	\
362        ta = CHAN_MAX
363
364#define LINEAR_RGB							\
365	tr = (ti * (si * tex00[0] + sf * tex01[0]) +			\
366              tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT;	\
367	tg = (ti * (si * tex00[1] + sf * tex01[1]) +			\
368              tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT;	\
369	tb = (ti * (si * tex00[2] + sf * tex01[2]) +			\
370              tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT;	\
371	ta = CHAN_MAX
372
373#define NEAREST_RGBA		\
374        tr = tex00[RCOMP];	\
375        tg = tex00[GCOMP];	\
376        tb = tex00[BCOMP];	\
377        ta = tex00[ACOMP]
378
379#define LINEAR_RGBA							\
380	tr = (ti * (si * tex00[0] + sf * tex01[0]) +			\
381              tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT;	\
382	tg = (ti * (si * tex00[1] + sf * tex01[1]) +			\
383              tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT;	\
384	tb = (ti * (si * tex00[2] + sf * tex01[2]) +			\
385              tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT;	\
386	ta = (ti * (si * tex00[3] + sf * tex01[3]) +			\
387              tf * (si * tex10[3] + sf * tex11[3])) >> 2 * FIXED_SHIFT
388
389#define MODULATE							\
390        dest[RCOMP] = span->red * (tr + 1) >> (FIXED_SHIFT + 8);	\
391        dest[GCOMP] = span->green * (tg + 1) >> (FIXED_SHIFT + 8);	\
392        dest[BCOMP] = span->blue * (tb + 1) >> (FIXED_SHIFT + 8);	\
393        dest[ACOMP] = span->alpha * (ta + 1) >> (FIXED_SHIFT + 8)
394
395#define DECAL								\
396	dest[RCOMP] = ((CHAN_MAX - ta) * span->red			\
397           + ((ta + 1) * tr << FIXED_SHIFT)) >> (FIXED_SHIFT + 8);	\
398	dest[GCOMP] = ((CHAN_MAX - ta) * span->green			\
399           + ((ta + 1) * tg << FIXED_SHIFT)) >> (FIXED_SHIFT + 8);	\
400	dest[BCOMP] = ((CHAN_MAX - ta) * span->blue			\
401           + ((ta + 1) * tb << FIXED_SHIFT)) >> (FIXED_SHIFT + 8);	\
402	dest[ACOMP] = FixedToInt(span->alpha)
403
404#define BLEND								\
405        dest[RCOMP] = ((CHAN_MAX - tr) * span->red			\
406           + (tr + 1) * info->er) >> (FIXED_SHIFT + 8);			\
407        dest[GCOMP] = ((CHAN_MAX - tg) * span->green			\
408           + (tg + 1) * info->eg) >> (FIXED_SHIFT + 8);			\
409        dest[BCOMP] = ((CHAN_MAX - tb) * span->blue			\
410           + (tb + 1) * info->eb) >> (FIXED_SHIFT + 8);			\
411        dest[ACOMP] = span->alpha * (ta + 1) >> (FIXED_SHIFT + 8)
412
413#define REPLACE			\
414        dest[RCOMP] = tr;	\
415        dest[GCOMP] = tg;	\
416        dest[BCOMP] = tb;	\
417        dest[ACOMP] = ta
418
419#define ADD								\
420        dest[RCOMP] = ((span->red << 8)					\
421           + (tr + 1) * info->er) >> (FIXED_SHIFT + 8);			\
422        dest[GCOMP] = ((span->green << 8)				\
423           + (tg + 1) * info->eg) >> (FIXED_SHIFT + 8);			\
424        dest[BCOMP] = ((span->blue << 8)				\
425           + (tb + 1) * info->eb) >> (FIXED_SHIFT + 8);			\
426        dest[ACOMP] = span->alpha * (ta + 1) >> (FIXED_SHIFT + 8)
427
428/* shortcuts */
429
430#define NEAREST_RGB_REPLACE  NEAREST_RGB;REPLACE
431
432#define NEAREST_RGBA_REPLACE  *(GLint *)dest = *(GLint *)tex00
433
434#define SPAN_NEAREST(DO_TEX,COMP)					\
435	for (i = 0; i < span->count; i++) {				\
436           /* Isn't it necessary to use FixedFloor below?? */		\
437           GLint s = FixedToInt(span->intTex[0]) & info->smask;		\
438           GLint t = FixedToInt(span->intTex[1]) & info->tmask;		\
439           GLint pos = (t << info->twidth_log2) + s;			\
440           const GLchan *tex00 = info->texture + COMP * pos;		\
441	   zspan[i] = FixedToDepth(span->z);				\
442	   fogspan[i] = span->fog;					\
443           DO_TEX;							\
444	   span->fog += span->fogStep;					\
445	   span->z += span->zStep;					\
446           span->red += span->redStep;					\
447	   span->green += span->greenStep;				\
448           span->blue += span->blueStep;				\
449	   span->alpha += span->alphaStep;				\
450	   span->intTex[0] += span->intTexStep[0];			\
451	   span->intTex[1] += span->intTexStep[1];			\
452           dest += 4;							\
453	}
454
455#define SPAN_LINEAR(DO_TEX,COMP)					\
456	for (i = 0; i < span->count; i++) {				\
457           /* Isn't it necessary to use FixedFloor below?? */		\
458           GLint s = FixedToInt(span->intTex[0]) & info->smask;		\
459           GLint t = FixedToInt(span->intTex[1]) & info->tmask;		\
460           GLfixed sf = span->intTex[0] & FIXED_FRAC_MASK;		\
461           GLfixed tf = span->intTex[1] & FIXED_FRAC_MASK;		\
462           GLfixed si = FIXED_FRAC_MASK - sf;				\
463           GLfixed ti = FIXED_FRAC_MASK - tf;				\
464           GLint pos = (t << info->twidth_log2) + s;			\
465           const GLchan *tex00 = info->texture + COMP * pos;		\
466           const GLchan *tex10 = tex00 + info->tbytesline;		\
467           const GLchan *tex01 = tex00 + COMP;				\
468           const GLchan *tex11 = tex10 + COMP;				\
469           (void) ti;							\
470           (void) si;							\
471           if (t == info->tmask) {					\
472              tex10 -= info->tsize;					\
473              tex11 -= info->tsize;					\
474           }								\
475           if (s == info->smask) {					\
476              tex01 -= info->tbytesline;				\
477              tex11 -= info->tbytesline;				\
478           }								\
479	   zspan[i] = FixedToDepth(span->z);				\
480	   fogspan[i] = span->fog;					\
481           DO_TEX;							\
482	   span->fog += span->fogStep;					\
483	   span->z += span->zStep;					\
484           span->red += span->redStep;					\
485	   span->green += span->greenStep;				\
486           span->blue += span->blueStep;				\
487	   span->alpha += span->alphaStep;				\
488	   span->intTex[0] += span->intTexStep[0];			\
489	   span->intTex[1] += span->intTexStep[1];			\
490           dest += 4;							\
491	}
492
493#define FixedToDepth(F)  ((F) >> fixedToDepthShift)
494
495   GLuint i;
496   GLdepth zspan[MAX_WIDTH];
497   GLfloat fogspan[MAX_WIDTH];
498   GLchan rgba[MAX_WIDTH][4];
499   GLchan *dest = rgba[0];
500   const GLint fixedToDepthShift = info->fixedToDepthShift;
501
502   span->intTex[0] -= FIXED_HALF;
503   span->intTex[1] -= FIXED_HALF;
504   switch (info->filter) {
505   case GL_NEAREST:
506      switch (info->format) {
507      case GL_RGB:
508         switch (info->envmode) {
509         case GL_MODULATE:
510            SPAN_NEAREST(NEAREST_RGB;MODULATE,3);
511            break;
512         case GL_DECAL:
513         case GL_REPLACE:
514            SPAN_NEAREST(NEAREST_RGB_REPLACE,3);
515            break;
516         case GL_BLEND:
517            SPAN_NEAREST(NEAREST_RGB;BLEND,3);
518            break;
519         case GL_ADD:
520            SPAN_NEAREST(NEAREST_RGB;ADD,3);
521            break;
522         default:
523            abort();
524         }
525         break;
526      case GL_RGBA:
527         switch(info->envmode) {
528         case GL_MODULATE:
529            SPAN_NEAREST(NEAREST_RGBA;MODULATE,4);
530            break;
531         case GL_DECAL:
532            SPAN_NEAREST(NEAREST_RGBA;DECAL,4);
533            break;
534         case GL_BLEND:
535            SPAN_NEAREST(NEAREST_RGBA;BLEND,4);
536            break;
537         case GL_ADD:
538            SPAN_NEAREST(NEAREST_RGBA;ADD,4);
539            break;
540         case GL_REPLACE:
541            SPAN_NEAREST(NEAREST_RGBA_REPLACE,4);
542            break;
543         default:
544            abort();
545         }
546         break;
547      }
548      break;
549
550   case GL_LINEAR:
551      span->intTex[0] -= FIXED_HALF;
552      span->intTex[1] -= FIXED_HALF;
553      switch (info->format) {
554      case GL_RGB:
555         switch (info->envmode) {
556         case GL_MODULATE:
557            SPAN_LINEAR(LINEAR_RGB;MODULATE,3);
558            break;
559         case GL_DECAL:
560         case GL_REPLACE:
561            SPAN_LINEAR(LINEAR_RGB;REPLACE,3);
562            break;
563         case GL_BLEND:
564            SPAN_LINEAR(LINEAR_RGB;BLEND,3);
565            break;
566         case GL_ADD:
567            SPAN_LINEAR(LINEAR_RGB;ADD,3);
568            break;
569         default:
570            abort();
571         }
572         break;
573      case GL_RGBA:
574         switch (info->envmode) {
575         case GL_MODULATE:
576            SPAN_LINEAR(LINEAR_RGBA;MODULATE,4);
577            break;
578         case GL_DECAL:
579            SPAN_LINEAR(LINEAR_RGBA;DECAL,4);
580            break;
581         case GL_BLEND:
582            SPAN_LINEAR(LINEAR_RGBA;BLEND,4);
583            break;
584         case GL_ADD:
585            SPAN_LINEAR(LINEAR_RGBA;ADD,4);
586            break;
587         case GL_REPLACE:
588            SPAN_LINEAR(LINEAR_RGBA;REPLACE,4);
589            break;
590         default:
591            abort();
592         }		    break;
593      }
594      break;
595   }
596   _mesa_write_rgba_span(ctx, span->count, span->x, span->y,
597                         zspan, fogspan, rgba, NULL, GL_POLYGON);
598
599#undef SPAN_NEAREST
600#undef SPAN_LINEAR
601#undef FixedToDepth
602}
603
604
605
606/*
607 * Render an RGB/RGBA textured triangle without perspective correction.
608 */
609static void affine_textured_triangle( GLcontext *ctx,
610				      const SWvertex *v0,
611				      const SWvertex *v1,
612				      const SWvertex *v2 )
613{
614#define INTERP_Z 1
615#define INTERP_FOG 1
616#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
617#define INTERP_RGB 1
618#define INTERP_ALPHA 1
619#define INTERP_INT_TEX 1
620#define S_SCALE twidth
621#define T_SCALE theight
622
623#define SETUP_CODE							\
624   struct affine_info info;						\
625   struct gl_texture_unit *unit = ctx->Texture.Unit+0;			\
626   struct gl_texture_object *obj = unit->Current2D;			\
627   GLint b = obj->BaseLevel;						\
628   GLfloat twidth = (GLfloat) obj->Image[b]->Width;			\
629   GLfloat theight = (GLfloat) obj->Image[b]->Height;			\
630   info.fixedToDepthShift = ctx->Visual.depthBits <= 16 ? FIXED_SHIFT : 0;\
631   info.texture = (const GLchan *) obj->Image[b]->Data;			\
632   info.twidth_log2 = obj->Image[b]->WidthLog2;				\
633   info.smask = obj->Image[b]->Width - 1;				\
634   info.tmask = obj->Image[b]->Height - 1;				\
635   info.format = obj->Image[b]->Format;					\
636   info.filter = obj->MinFilter;					\
637   info.envmode = unit->EnvMode;					\
638									\
639   if (info.envmode == GL_BLEND) {					\
640      /* potential off-by-one error here? (1.0f -> 2048 -> 0) */	\
641      info.er = FloatToFixed(unit->EnvColor[RCOMP]);			\
642      info.eg = FloatToFixed(unit->EnvColor[GCOMP]);			\
643      info.eb = FloatToFixed(unit->EnvColor[BCOMP]);			\
644      info.ea = FloatToFixed(unit->EnvColor[ACOMP]);			\
645   }									\
646   if (!info.texture) {							\
647      /* this shouldn't happen */					\
648      return;								\
649   }									\
650									\
651   switch (info.format) {						\
652   case GL_ALPHA:							\
653   case GL_LUMINANCE:							\
654   case GL_INTENSITY:							\
655      info.tbytesline = obj->Image[b]->Width;				\
656      break;								\
657   case GL_LUMINANCE_ALPHA:						\
658      info.tbytesline = obj->Image[b]->Width * 2;			\
659      break;								\
660   case GL_RGB:								\
661      info.tbytesline = obj->Image[b]->Width * 3;			\
662      break;								\
663   case GL_RGBA:							\
664      info.tbytesline = obj->Image[b]->Width * 4;			\
665      break;								\
666   default:								\
667      _mesa_problem(NULL, "Bad texture format in affine_texture_triangle");\
668      return;								\
669   }									\
670   info.tsize = obj->Image[b]->Height * info.tbytesline;
671
672#define RENDER_SPAN( span )		\
673   affine_span(ctx, &span, &info);
674
675#include "s_tritemp.h"
676
677}
678
679
680struct persp_info
681{
682   GLenum filter;
683   GLenum format;
684   GLenum envmode;
685   GLint smask, tmask;
686   GLint twidth_log2;
687   const GLchan *texture;
688   GLchan er, eg, eb, ea;
689   GLint tbytesline, tsize;
690   GLint fixedToDepthShift;
691};
692
693static void
694fast_persp_span(GLcontext *ctx, struct triangle_span *span,
695		struct persp_info *info)
696{
697   GLint tr, tg, tb, ta;
698
699  /* Instead of defining a function for each mode, a test is done
700   * between the outer and inner loops. This is to reduce code size
701   * and complexity. Observe that an optimizing compiler kills
702   * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST).
703   */
704
705#define SPAN_NEAREST(DO_TEX,COMP)					\
706	for (i = 0; i < span->count; i++) {				\
707           GLdouble invQ = tex_coord[2] ?				\
708                                 (1.0 / tex_coord[2]) : 1.0;            \
709           GLfloat s_tmp = tex_coord[0] * invQ;				\
710           GLfloat t_tmp = tex_coord[1] * invQ;				\
711           GLint s = IFLOOR(s_tmp) & info->smask;	        	\
712           GLint t = IFLOOR(t_tmp) & info->tmask;	        	\
713           GLint pos = (t << info->twidth_log2) + s;			\
714           const GLchan *tex00 = info->texture + COMP * pos;		\
715	   zspan[i] = FixedToDepth(span->z);				\
716	   fogspan[i] = span->fog;					\
717           DO_TEX;							\
718	   span->fog += span->fogStep;					\
719	   span->z += span->zStep;					\
720           span->red += span->redStep;					\
721	   span->green += span->greenStep;				\
722           span->blue += span->blueStep;				\
723	   span->alpha += span->alphaStep;				\
724	   tex_coord[0] += tex_step[0];					\
725	   tex_coord[1] += tex_step[1];					\
726	   tex_coord[2] += tex_step[2];					\
727           dest += 4;							\
728	}
729
730#define SPAN_LINEAR(DO_TEX,COMP)					\
731	for (i = 0; i < span->count; i++) {				\
732           GLdouble invQ = tex_coord[2] ?				\
733                                 (1.0 / tex_coord[2]) : 1.0;            \
734           GLfloat s_tmp = tex_coord[0] * invQ - 0.5F;			\
735           GLfloat t_tmp = tex_coord[1] * invQ - 0.5F;			\
736           GLfixed s_fix = FloatToFixed(s_tmp);				\
737           GLfixed t_fix = FloatToFixed(t_tmp);		        	\
738           GLint s = FixedToInt(FixedFloor(s_fix)) & info->smask;	\
739           GLint t = FixedToInt(FixedFloor(t_fix)) & info->tmask;	\
740           GLfixed sf = s_fix & FIXED_FRAC_MASK;		\
741           GLfixed tf = t_fix & FIXED_FRAC_MASK;		\
742           GLfixed si = FIXED_FRAC_MASK - sf;				\
743           GLfixed ti = FIXED_FRAC_MASK - tf;				\
744           GLint pos = (t << info->twidth_log2) + s;			\
745           const GLchan *tex00 = info->texture + COMP * pos;		\
746           const GLchan *tex10 = tex00 + info->tbytesline;		\
747           const GLchan *tex01 = tex00 + COMP;				\
748           const GLchan *tex11 = tex10 + COMP;				\
749           (void) ti;							\
750           (void) si;							\
751           if (t == info->tmask) {					\
752              tex10 -= info->tsize;					\
753              tex11 -= info->tsize;					\
754           }								\
755           if (s == info->smask) {					\
756              tex01 -= info->tbytesline;				\
757              tex11 -= info->tbytesline;				\
758           }								\
759	   zspan[i] = FixedToDepth(span->z);				\
760	   fogspan[i] = span->fog;					\
761           DO_TEX;							\
762	   span->fog += span->fogStep;					\
763	   span->z += span->zStep;					\
764           span->red   += span->redStep;				\
765	   span->green += span->greenStep;				\
766           span->blue  += span->blueStep;				\
767	   span->alpha += span->alphaStep;				\
768	   tex_coord[0] += tex_step[0];					\
769	   tex_coord[1] += tex_step[1];					\
770	   tex_coord[2] += tex_step[2];					\
771           dest += 4;							\
772	}
773
774#define FixedToDepth(F)  ((F) >> fixedToDepthShift)
775
776   GLuint i;
777   GLdepth zspan[MAX_WIDTH];
778   GLfloat tex_coord[3], tex_step[3];
779   GLfloat fogspan[MAX_WIDTH];
780   GLchan rgba[MAX_WIDTH][4];
781   GLchan *dest = rgba[0];
782   const GLint fixedToDepthShift = info->fixedToDepthShift;
783
784   tex_coord[0] = span->tex[0][0]  * (info->smask + 1),
785     tex_step[0] = span->texStep[0][0] * (info->smask + 1);
786   tex_coord[1] = span->tex[0][1] * (info->tmask + 1),
787     tex_step[1] = span->texStep[0][1] * (info->tmask + 1);
788   /* span->tex[0][2] only if 3D-texturing, here only 2D */
789   tex_coord[2] = span->tex[0][3],
790     tex_step[2] = span->texStep[0][3];
791
792   switch (info->filter) {
793   case GL_NEAREST:
794      switch (info->format) {
795      case GL_RGB:
796         switch (info->envmode) {
797         case GL_MODULATE:
798            SPAN_NEAREST(NEAREST_RGB;MODULATE,3);
799            break;
800         case GL_DECAL:
801         case GL_REPLACE:
802            SPAN_NEAREST(NEAREST_RGB_REPLACE,3);
803            break;
804         case GL_BLEND:
805            SPAN_NEAREST(NEAREST_RGB;BLEND,3);
806            break;
807         case GL_ADD:
808            SPAN_NEAREST(NEAREST_RGB;ADD,3);
809            break;
810         default:
811            abort();
812         }
813         break;
814      case GL_RGBA:
815         switch(info->envmode) {
816         case GL_MODULATE:
817            SPAN_NEAREST(NEAREST_RGBA;MODULATE,4);
818            break;
819         case GL_DECAL:
820            SPAN_NEAREST(NEAREST_RGBA;DECAL,4);
821            break;
822         case GL_BLEND:
823            SPAN_NEAREST(NEAREST_RGBA;BLEND,4);
824            break;
825         case GL_ADD:
826            SPAN_NEAREST(NEAREST_RGBA;ADD,4);
827            break;
828         case GL_REPLACE:
829            SPAN_NEAREST(NEAREST_RGBA_REPLACE,4);
830            break;
831         default:
832            abort();
833         }
834         break;
835      }
836      break;
837
838   case GL_LINEAR:
839      switch (info->format) {
840      case GL_RGB:
841         switch (info->envmode) {
842         case GL_MODULATE:
843            SPAN_LINEAR(LINEAR_RGB;MODULATE,3);
844            break;
845         case GL_DECAL:
846         case GL_REPLACE:
847            SPAN_LINEAR(LINEAR_RGB;REPLACE,3);
848            break;
849         case GL_BLEND:
850            SPAN_LINEAR(LINEAR_RGB;BLEND,3);
851            break;
852         case GL_ADD:
853            SPAN_LINEAR(LINEAR_RGB;ADD,3);
854            break;
855         default:
856            abort();
857         }
858         break;
859      case GL_RGBA:
860         switch (info->envmode) {
861         case GL_MODULATE:
862            SPAN_LINEAR(LINEAR_RGBA;MODULATE,4);
863            break;
864         case GL_DECAL:
865            SPAN_LINEAR(LINEAR_RGBA;DECAL,4);
866            break;
867         case GL_BLEND:
868            SPAN_LINEAR(LINEAR_RGBA;BLEND,4);
869            break;
870         case GL_ADD:
871            SPAN_LINEAR(LINEAR_RGBA;ADD,4);
872            break;
873         case GL_REPLACE:
874            SPAN_LINEAR(LINEAR_RGBA;REPLACE,4);
875            break;
876         default:
877            abort();
878         }
879         break;
880      }
881      break;
882   }
883   /* This does not seem to be necessary, but I don't know !! */
884   /* span->tex[0][0] = tex_coord[0] / (info->smask + 1),
885      span->tex[0][1] = tex_coord[1] / (info->tmask + 1),*/
886   /* span->tex[0][2] only if 3D-texturing, here only 2D */
887   /* span->tex[0][3] = tex_coord[2]; */
888
889   _mesa_write_rgba_span(ctx, span->count, span->x, span->y,
890                         zspan, fogspan, rgba, NULL, GL_POLYGON);
891
892
893#undef SPAN_NEAREST
894#undef SPAN_LINEAR
895#undef FixedToDepth
896}
897
898
899/*
900 * Render an perspective corrected RGB/RGBA textured triangle.
901 * The Q (aka V in Mesa) coordinate must be zero such that the divide
902 * by interpolated Q/W comes out right.
903 *
904 */
905static void persp_textured_triangle( GLcontext *ctx,
906				     const SWvertex *v0,
907				     const SWvertex *v1,
908				     const SWvertex *v2 )
909{
910#define INTERP_Z 1
911#define INTERP_FOG 1
912#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
913#define INTERP_RGB 1
914#define INTERP_ALPHA 1
915#define INTERP_TEX 1
916
917#define SETUP_CODE							\
918   struct persp_info info;						\
919   struct gl_texture_unit *unit = ctx->Texture.Unit+0;			\
920   struct gl_texture_object *obj = unit->Current2D;			\
921   GLint b = obj->BaseLevel;						\
922   info.fixedToDepthShift = ctx->Visual.depthBits <= 16 ? FIXED_SHIFT : 0;\
923   info.texture = (const GLchan *) obj->Image[b]->Data;			\
924   info.twidth_log2 = obj->Image[b]->WidthLog2;				\
925   info.smask = obj->Image[b]->Width - 1;				\
926   info.tmask = obj->Image[b]->Height - 1;				\
927   info.format = obj->Image[b]->Format;					\
928   info.filter = obj->MinFilter;					\
929   info.envmode = unit->EnvMode;					\
930									\
931   if (info.envmode == GL_BLEND) {					\
932      /* potential off-by-one error here? (1.0f -> 2048 -> 0) */	\
933      info.er = FloatToFixed(unit->EnvColor[RCOMP]);			\
934      info.eg = FloatToFixed(unit->EnvColor[GCOMP]);			\
935      info.eb = FloatToFixed(unit->EnvColor[BCOMP]);			\
936      info.ea = FloatToFixed(unit->EnvColor[ACOMP]);			\
937   }									\
938   if (!info.texture) {							\
939      /* this shouldn't happen */					\
940      return;								\
941   }									\
942									\
943   switch (info.format) {						\
944   case GL_ALPHA:							\
945   case GL_LUMINANCE:							\
946   case GL_INTENSITY:							\
947      info.tbytesline = obj->Image[b]->Width;				\
948      break;								\
949   case GL_LUMINANCE_ALPHA:						\
950      info.tbytesline = obj->Image[b]->Width * 2;			\
951      break;								\
952   case GL_RGB:								\
953      info.tbytesline = obj->Image[b]->Width * 3;			\
954      break;								\
955   case GL_RGBA:							\
956      info.tbytesline = obj->Image[b]->Width * 4;			\
957      break;								\
958   default:								\
959      _mesa_problem(NULL, "Bad texture format in affine_texture_triangle");\
960      return;								\
961   }									\
962   info.tsize = obj->Image[b]->Height * info.tbytesline;
963
964#define RENDER_SPAN( span )		\
965   fast_persp_span(ctx, &span, &info);
966
967#include "s_tritemp.h"
968
969}
970
971/*
972 * Generate arrays of fragment colors, z, fog, texcoords, etc from a
973 * triangle span object.  Then call the span/fragment processsing
974 * functions in s_span.[ch].
975 */
976static void
977rasterize_span(GLcontext *ctx, const struct triangle_span *span)
978{
979   DEFMARRAY(GLchan, rgba, MAX_WIDTH, 4);
980   DEFMARRAY(GLchan, spec, MAX_WIDTH, 4);
981   DEFARRAY(GLuint, index, MAX_WIDTH);
982   DEFARRAY(GLuint, z, MAX_WIDTH);
983   DEFARRAY(GLfloat, fog, MAX_WIDTH);
984   DEFARRAY(GLfloat, sTex, MAX_WIDTH);
985   DEFARRAY(GLfloat, tTex, MAX_WIDTH);
986   DEFARRAY(GLfloat, rTex, MAX_WIDTH);
987   DEFARRAY(GLfloat, lambda, MAX_WIDTH);
988   DEFMARRAY(GLfloat, msTex, MAX_TEXTURE_UNITS, MAX_WIDTH);
989   DEFMARRAY(GLfloat, mtTex, MAX_TEXTURE_UNITS, MAX_WIDTH);
990   DEFMARRAY(GLfloat, mrTex, MAX_TEXTURE_UNITS, MAX_WIDTH);
991   DEFMARRAY(GLfloat, mLambda, MAX_TEXTURE_UNITS, MAX_WIDTH);
992
993   CHECKARRAY(rgba, return);
994   CHECKARRAY(spec, return);
995   CHECKARRAY(index, return);
996   CHECKARRAY(z, return);
997   CHECKARRAY(fog, return);
998   CHECKARRAY(sTex, return);
999   CHECKARRAY(tTex, return);
1000   CHECKARRAY(rTex, return);
1001   CHECKARRAY(lambda, return);
1002   CHECKARRAY(msTex, return);
1003   CHECKARRAY(mtTex, return);
1004   CHECKARRAY(mrTex, return);
1005   CHECKARRAY(mLambda, return);
1006
1007   if (span->activeMask & SPAN_RGBA) {
1008      GLfixed r = span->red;
1009      GLfixed g = span->green;
1010      GLfixed b = span->blue;
1011      GLfixed a = span->alpha;
1012      GLuint i;
1013      for (i = 0; i < span->count; i++) {
1014         rgba[i][RCOMP] = FixedToInt(r);
1015         rgba[i][GCOMP] = FixedToInt(g);
1016         rgba[i][BCOMP] = FixedToInt(b);
1017         rgba[i][ACOMP] = FixedToInt(a);
1018         r += span->redStep;
1019         g += span->greenStep;
1020         b += span->blueStep;
1021         a += span->alphaStep;
1022      }
1023   }
1024   if (span->activeMask & SPAN_SPEC) {
1025      GLfixed r = span->specRed;
1026      GLfixed g = span->specGreen;
1027      GLfixed b = span->specBlue;
1028      GLuint i;
1029      for (i = 0; i < span->count; i++) {
1030         spec[i][RCOMP] = FixedToInt(r);
1031         spec[i][GCOMP] = FixedToInt(g);
1032         spec[i][BCOMP] = FixedToInt(b);
1033         r += span->specRedStep;
1034         g += span->specGreenStep;
1035         b += span->specBlueStep;
1036      }
1037   }
1038   if (span->activeMask & SPAN_INDEX) {
1039      GLuint i;
1040      GLfixed ind = span->index;
1041      for (i = 0; i < span->count; i++) {
1042         index[i] = FixedToInt(ind);
1043         ind += span->indexStep;
1044      }
1045   }
1046   if (span->activeMask & SPAN_Z) {
1047      if (ctx->Visual.depthBits <= 16) {
1048         GLuint i;
1049         GLfixed zval = span->z;
1050         for (i = 0; i < span->count; i++) {
1051            z[i] = FixedToInt(zval);
1052            zval += span->zStep;
1053         }
1054      }
1055      else {
1056         /* Deep Z buffer, no fixed->int shift */
1057         GLuint i;
1058         GLfixed zval = span->z;
1059         for (i = 0; i < span->count; i++) {
1060            z[i] = zval;
1061            zval += span->zStep;
1062         }
1063      }
1064   }
1065   if (span->activeMask & SPAN_FOG) {
1066      GLuint i;
1067      GLfloat f = span->fog;
1068      for (i = 0; i < span->count; i++) {
1069         fog[i] = f;
1070         f += span->fogStep;
1071      }
1072   }
1073   if (span->activeMask & SPAN_TEXTURE) {
1074      if (ctx->Texture._ReallyEnabled & ~TEXTURE0_ANY) {
1075         /* multitexture */
1076         if (span->activeMask & SPAN_LAMBDA) {
1077            /* with lambda */
1078            GLuint u;
1079            for (u = 0; u < MAX_TEXTURE_UNITS; u++) {
1080               if (ctx->Texture.Unit[u]._ReallyEnabled) {
1081                  GLfloat s = span->tex[u][0];
1082                  GLfloat t = span->tex[u][1];
1083                  GLfloat r = span->tex[u][2];
1084                  GLfloat q = span->tex[u][3];
1085                  GLuint i;
1086                  for (i = 0; i < span->count; i++) {
1087                     const GLfloat invQ = (q == 0.0F) ? 1.0 : (1.0F / q);
1088                     msTex[u][i] = s * invQ;
1089                     mtTex[u][i] = t * invQ;
1090                     mrTex[u][i] = r * invQ;
1091                     mLambda[u][i] = log(span->rho[u] * invQ * invQ) * 1.442695F * 0.5F;
1092                     s += span->texStep[u][0];
1093                     t += span->texStep[u][1];
1094                     r += span->texStep[u][2];
1095                     q += span->texStep[u][3];
1096                  }
1097               }
1098            }
1099         }
1100         else {
1101            /* without lambda */
1102            GLuint u;
1103            for (u = 0; u < MAX_TEXTURE_UNITS; u++) {
1104               if (ctx->Texture.Unit[u]._ReallyEnabled) {
1105                  GLfloat s = span->tex[u][0];
1106                  GLfloat t = span->tex[u][1];
1107                  GLfloat r = span->tex[u][2];
1108                  GLfloat q = span->tex[u][3];
1109                  GLuint i;
1110                  for (i = 0; i < span->count; i++) {
1111                     const GLfloat invQ = (q == 0.0F) ? 1.0 : (1.0F / q);
1112                     msTex[u][i] = s * invQ;
1113                     mtTex[u][i] = t * invQ;
1114                     mrTex[u][i] = r * invQ;
1115                     s += span->texStep[u][0];
1116                     t += span->texStep[u][1];
1117                     r += span->texStep[u][2];
1118                     q += span->texStep[u][3];
1119                  }
1120               }
1121            }
1122         }
1123      }
1124      else {
1125         /* just texture unit 0 */
1126         if (span->activeMask & SPAN_LAMBDA) {
1127            /* with lambda */
1128            GLfloat s = span->tex[0][0];
1129            GLfloat t = span->tex[0][1];
1130            GLfloat r = span->tex[0][2];
1131            GLfloat q = span->tex[0][3];
1132            GLuint i;
1133            for (i = 0; i < span->count; i++) {
1134               const GLfloat invQ = (q == 0.0F) ? 1.0 : (1.0F / q);
1135               sTex[i] = s * invQ;
1136               tTex[i] = t * invQ;
1137               rTex[i] = r * invQ;
1138               lambda[i] = log(span->rho[0] * invQ * invQ) * 1.442695F * 0.5F;
1139               s += span->texStep[0][0];
1140               t += span->texStep[0][1];
1141               r += span->texStep[0][2];
1142               q += span->texStep[0][3];
1143            }
1144         }
1145         else {
1146            /* without lambda */
1147            GLfloat s = span->tex[0][0];
1148            GLfloat t = span->tex[0][1];
1149            GLfloat r = span->tex[0][2];
1150            GLfloat q = span->tex[0][3];
1151            GLuint i;
1152            for (i = 0; i < span->count; i++) {
1153               const GLfloat invQ = (q == 0.0F) ? 1.0 : (1.0F / q);
1154               sTex[i] = s * invQ;
1155               tTex[i] = t * invQ;
1156               rTex[i] = r * invQ;
1157               s += span->texStep[0][0];
1158               t += span->texStep[0][1];
1159               r += span->texStep[0][2];
1160               q += span->texStep[0][3];
1161            }
1162         }
1163      }
1164   }
1165   /* XXX keep this? */
1166   if (span->activeMask & SPAN_INT_TEXTURE) {
1167      GLint intTexcoord[MAX_WIDTH][2];
1168      GLfixed s = span->intTex[0];
1169      GLfixed t = span->intTex[1];
1170      GLuint i;
1171      for (i = 0; i < span->count; i++) {
1172         intTexcoord[i][0] = FixedToInt(s);
1173         intTexcoord[i][1] = FixedToInt(t);
1174         s += span->intTexStep[0];
1175         t += span->intTexStep[1];
1176      }
1177   }
1178
1179   /* examine activeMask and call a s_span.c function */
1180   if (span->activeMask & SPAN_TEXTURE) {
1181      const GLfloat *fogPtr;
1182      if (span->activeMask & SPAN_FOG)
1183         fogPtr = fog;
1184      else
1185         fogPtr = NULL;
1186
1187      if (ctx->Texture._ReallyEnabled & ~TEXTURE0_ANY) {
1188         if (span->activeMask & SPAN_SPEC) {
1189            _mesa_write_multitexture_span(ctx, span->count, span->x, span->y,
1190                                          z, fogPtr,
1191                                          (const GLfloat (*)[MAX_WIDTH]) msTex,
1192                                          (const GLfloat (*)[MAX_WIDTH]) mtTex,
1193                                          (const GLfloat (*)[MAX_WIDTH]) mrTex,
1194                                          (GLfloat (*)[MAX_WIDTH]) mLambda,
1195                                          rgba, (CONST GLchan (*)[4]) spec,
1196                                          NULL, GL_POLYGON );
1197         }
1198         else {
1199            _mesa_write_multitexture_span(ctx, span->count, span->x, span->y,
1200                                          z, fogPtr,
1201                                          (const GLfloat (*)[MAX_WIDTH]) msTex,
1202                                          (const GLfloat (*)[MAX_WIDTH]) mtTex,
1203                                          (const GLfloat (*)[MAX_WIDTH]) mrTex,
1204                                          (GLfloat (*)[MAX_WIDTH]) mLambda,
1205                                          rgba, NULL, NULL, GL_POLYGON);
1206         }
1207      }
1208      else {
1209         /* single texture */
1210         if (span->activeMask & SPAN_SPEC) {
1211            _mesa_write_texture_span(ctx, span->count, span->x, span->y,
1212                                     z, fogPtr, sTex, tTex, rTex, lambda,
1213                                     rgba, (CONST GLchan (*)[4]) spec,
1214                                     NULL, GL_POLYGON);
1215         }
1216         else {
1217            _mesa_write_texture_span(ctx, span->count, span->x, span->y,
1218                                     z, fogPtr, sTex, tTex, rTex, lambda,
1219                                     rgba, NULL, NULL, GL_POLYGON);
1220         }
1221      }
1222   }
1223   else {
1224      _mesa_problem(ctx, "rasterize_span() should only be used for texturing");
1225   }
1226
1227   UNDEFARRAY(rgba);
1228   UNDEFARRAY(spec);
1229   UNDEFARRAY(index);
1230   UNDEFARRAY(z);
1231   UNDEFARRAY(fog);
1232   UNDEFARRAY(sTex);
1233   UNDEFARRAY(tTex);
1234   UNDEFARRAY(rTex);
1235   UNDEFARRAY(lambda);
1236   UNDEFARRAY(msTex);
1237   UNDEFARRAY(mtTex);
1238   UNDEFARRAY(mrTex);
1239   UNDEFARRAY(mLambda);
1240}
1241
1242
1243
1244
1245/*
1246 * Render a smooth-shaded, textured, RGBA triangle.
1247 * Interpolate S,T,R with perspective correction, w/out mipmapping.
1248 */
1249static void general_textured_triangle( GLcontext *ctx,
1250				       const SWvertex *v0,
1251				       const SWvertex *v1,
1252				       const SWvertex *v2 )
1253{
1254#define INTERP_Z 1
1255#define INTERP_FOG 1
1256#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1257#define INTERP_RGB 1
1258#define INTERP_ALPHA 1
1259#define INTERP_TEX 1
1260
1261#define SETUP_CODE							\
1262   const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;	\
1263   const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\
1264   const GLboolean flatShade = (ctx->Light.ShadeModel==GL_FLAT);	\
1265   GLfixed rFlat, gFlat, bFlat, aFlat;					\
1266   DEFARRAY(GLfloat, sSpan, MAX_WIDTH);  /* mac 32k limitation */	\
1267   DEFARRAY(GLfloat, tSpan, MAX_WIDTH);  /* mac 32k limitation */	\
1268   DEFARRAY(GLfloat, uSpan, MAX_WIDTH);  /* mac 32k limitation */	\
1269   CHECKARRAY(sSpan, return);  /* mac 32k limitation */			\
1270   CHECKARRAY(tSpan, return);  /* mac 32k limitation */			\
1271   CHECKARRAY(uSpan, return);  /* mac 32k limitation */			\
1272   if (flatShade) {							\
1273      rFlat = IntToFixed(v2->color[RCOMP]);				\
1274      gFlat = IntToFixed(v2->color[GCOMP]);				\
1275      bFlat = IntToFixed(v2->color[BCOMP]);				\
1276      aFlat = IntToFixed(v2->color[ACOMP]);				\
1277   }									\
1278   span.texWidth[0] = (GLfloat) texImage->Width;			\
1279   span.texHeight[0] = (GLfloat) texImage->Height;			\
1280   (void) fixedToDepthShift;
1281
1282#define RENDER_SPAN( span )						\
1283   GLdepth zSpan[MAX_WIDTH];						\
1284   GLfloat fogSpan[MAX_WIDTH];						\
1285   GLchan rgbaSpan[MAX_WIDTH][4];					\
1286   GLuint i;								\
1287   if (flatShade) {							\
1288      span.red = rFlat;    span.redStep = 0;				\
1289      span.green = gFlat;  span.greenStep = 0;				\
1290      span.blue = bFlat;   span.blueStep = 0;				\
1291      span.alpha = aFlat;  span.alphaStep = 0;				\
1292   }									\
1293   /* NOTE: we could just call rasterize_span() here instead */		\
1294   for (i = 0; i < span.count; i++) {					\
1295      GLdouble invQ = span.tex[0][3] ? (1.0 / span.tex[0][3]) : 1.0;	\
1296      zSpan[i] = FixedToDepth(span.z);					\
1297      span.z += span.zStep;						\
1298      fogSpan[i] = span.fog;			          		\
1299      span.fog += span.fogStep;						\
1300      rgbaSpan[i][RCOMP] = FixedToInt(span.red);			\
1301      rgbaSpan[i][GCOMP] = FixedToInt(span.green);			\
1302      rgbaSpan[i][BCOMP] = FixedToInt(span.blue);			\
1303      rgbaSpan[i][ACOMP] = FixedToInt(span.alpha);			\
1304      span.red += span.redStep;						\
1305      span.green += span.greenStep;					\
1306      span.blue += span.blueStep;					\
1307      span.alpha += span.alphaStep;					\
1308      sSpan[i] = span.tex[0][0] * invQ;					\
1309      tSpan[i] = span.tex[0][1] * invQ;					\
1310      uSpan[i] = span.tex[0][2] * invQ;					\
1311      span.tex[0][0] += span.texStep[0][0];				\
1312      span.tex[0][1] += span.texStep[0][1];				\
1313      span.tex[0][2] += span.texStep[0][2];				\
1314      span.tex[0][3] += span.texStep[0][3];				\
1315   }									\
1316   _mesa_write_texture_span(ctx, span.count, span.x, span.y,		\
1317                            zSpan, fogSpan, sSpan, tSpan, uSpan,	\
1318                            NULL, rgbaSpan, NULL, NULL, GL_POLYGON );
1319
1320#define CLEANUP_CODE				\
1321   UNDEFARRAY(sSpan);  /* mac 32k limitation */	\
1322   UNDEFARRAY(tSpan);				\
1323   UNDEFARRAY(uSpan);
1324
1325#include "s_tritemp.h"
1326}
1327
1328
1329/*
1330 * Render a smooth-shaded, textured, RGBA triangle with separate specular
1331 * color interpolation.
1332 * Interpolate texcoords with perspective correction, w/out mipmapping.
1333 */
1334static void general_textured_spec_triangle( GLcontext *ctx,
1335					    const SWvertex *v0,
1336					    const SWvertex *v1,
1337					    const SWvertex *v2 )
1338{
1339#define INTERP_Z 1
1340#define INTERP_FOG 1
1341#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1342#define INTERP_RGB 1
1343#define INTERP_SPEC 1
1344#define INTERP_ALPHA 1
1345#define INTERP_TEX 1
1346
1347#define SETUP_CODE							\
1348   const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;	\
1349   const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\
1350   const GLboolean flatShade = (ctx->Light.ShadeModel == GL_FLAT);	\
1351   GLfixed rFlat, gFlat, bFlat, aFlat;					\
1352   GLfixed srFlat, sgFlat, sbFlat;					\
1353   if (flatShade) {							\
1354      rFlat = IntToFixed(v2->color[RCOMP]);				\
1355      gFlat = IntToFixed(v2->color[GCOMP]);				\
1356      bFlat = IntToFixed(v2->color[BCOMP]);				\
1357      aFlat = IntToFixed(v2->color[ACOMP]);				\
1358      srFlat = IntToFixed(v2->specular[RCOMP]);				\
1359      sgFlat = IntToFixed(v2->specular[GCOMP]);				\
1360      sbFlat = IntToFixed(v2->specular[BCOMP]);				\
1361   }									\
1362   span.texWidth[0] = (GLfloat) texImage->Width;			\
1363   span.texHeight[0] = (GLfloat) texImage->Height;			\
1364   (void) fixedToDepthShift;
1365
1366#define RENDER_SPAN( span )					\
1367   if (flatShade) {						\
1368      span.red = rFlat;    span.redStep = 0;			\
1369      span.green = gFlat;  span.greenStep = 0;			\
1370      span.blue = bFlat;   span.blueStep = 0;			\
1371      span.alpha = aFlat;  span.alphaStep = 0;			\
1372      span.specRed = srFlat;    span.specRedStep = 0;		\
1373      span.specGreen = sgFlat;  span.specGreenStep = 0;		\
1374      span.specBlue = sbFlat;   span.specBlueStep = 0;		\
1375   }								\
1376   rasterize_span(ctx, &span);
1377
1378#include "s_tritemp.h"
1379}
1380
1381
1382/*
1383 * Render a smooth-shaded, textured, RGBA triangle.
1384 * Interpolate S,T,R with perspective correction and compute lambda for
1385 * each fragment.  Lambda is used to determine whether to use the
1386 * minification or magnification filter.  If minification and using
1387 * mipmaps, lambda is also used to select the texture level of detail.
1388 */
1389static void lambda_textured_triangle( GLcontext *ctx,
1390				      const SWvertex *v0,
1391				      const SWvertex *v1,
1392				      const SWvertex *v2 )
1393{
1394#define INTERP_Z 1
1395#define INTERP_FOG 1
1396#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1397#define INTERP_RGB 1
1398#define INTERP_ALPHA 1
1399#define INTERP_TEX 1
1400#define INTERP_LAMBDA 1
1401
1402#define SETUP_CODE							\
1403   const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;	\
1404   const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\
1405   const GLboolean flatShade = (ctx->Light.ShadeModel==GL_FLAT);	\
1406   GLfixed rFlat, gFlat, bFlat, aFlat;					\
1407   GLfixed srFlat, sgFlat, sbFlat;					\
1408   if (flatShade) {							\
1409      rFlat = IntToFixed(v2->color[RCOMP]);				\
1410      gFlat = IntToFixed(v2->color[GCOMP]);				\
1411      bFlat = IntToFixed(v2->color[BCOMP]);				\
1412      aFlat = IntToFixed(v2->color[ACOMP]);				\
1413      srFlat = IntToFixed(v2->specular[RCOMP]);				\
1414      sgFlat = IntToFixed(v2->specular[GCOMP]);				\
1415      sbFlat = IntToFixed(v2->specular[BCOMP]);				\
1416   }									\
1417   span.texWidth[0] = (GLfloat) texImage->Width;			\
1418   span.texHeight[0] = (GLfloat) texImage->Height;			\
1419   (void) fixedToDepthShift;
1420
1421#define RENDER_SPAN( span )					\
1422   if (flatShade) {						\
1423      span.red = rFlat;    span.redStep = 0;			\
1424      span.green = gFlat;  span.greenStep = 0;			\
1425      span.blue = bFlat;   span.blueStep = 0;			\
1426      span.alpha = aFlat;  span.alphaStep = 0;			\
1427      span.specRed = srFlat;    span.specRedStep = 0;		\
1428      span.specGreen = sgFlat;  span.specGreenStep = 0;		\
1429      span.specBlue = sbFlat;   span.specBlueStep = 0;		\
1430   }								\
1431   rasterize_span(ctx, &span);
1432
1433#include "s_tritemp.h"
1434}
1435
1436
1437/*
1438 * Render a smooth-shaded, textured, RGBA triangle with separate specular
1439 * interpolation.
1440 * Interpolate S,T,R with perspective correction and compute lambda for
1441 * each fragment.  Lambda is used to determine whether to use the
1442 * minification or magnification filter.  If minification and using
1443 * mipmaps, lambda is also used to select the texture level of detail.
1444 */
1445static void lambda_textured_spec_triangle( GLcontext *ctx,
1446					   const SWvertex *v0,
1447					   const SWvertex *v1,
1448					   const SWvertex *v2 )
1449{
1450#define INTERP_Z 1
1451#define INTERP_FOG 1
1452#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1453#define INTERP_RGB 1
1454#define INTERP_SPEC 1
1455#define INTERP_ALPHA 1
1456#define INTERP_TEX 1
1457#define INTERP_LAMBDA 1
1458
1459#define SETUP_CODE							\
1460   const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;	\
1461   const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\
1462   const GLboolean flatShade = (ctx->Light.ShadeModel == GL_FLAT);	\
1463   GLfixed rFlat, gFlat, bFlat, aFlat;					\
1464   GLfixed srFlat, sgFlat, sbFlat;					\
1465   if (flatShade) {							\
1466      rFlat = IntToFixed(v2->color[RCOMP]);				\
1467      gFlat = IntToFixed(v2->color[GCOMP]);				\
1468      bFlat = IntToFixed(v2->color[BCOMP]);				\
1469      aFlat = IntToFixed(v2->color[ACOMP]);				\
1470      srFlat = IntToFixed(v2->specular[RCOMP]);				\
1471      sgFlat = IntToFixed(v2->specular[GCOMP]);				\
1472      sbFlat = IntToFixed(v2->specular[BCOMP]);				\
1473   }									\
1474   span.texWidth[0] = (GLfloat) texImage->Width;			\
1475   span.texHeight[0] = (GLfloat) texImage->Height;			\
1476   (void) fixedToDepthShift;
1477
1478#define RENDER_SPAN( span )					\
1479   if (flatShade) {						\
1480      span.red = rFlat;    span.redStep = 0;			\
1481      span.green = gFlat;  span.greenStep = 0;			\
1482      span.blue = bFlat;   span.blueStep = 0;			\
1483      span.alpha = aFlat;  span.alphaStep = 0;			\
1484      span.specRed = srFlat;    span.specRedStep = 0;		\
1485      span.specGreen = sgFlat;  span.specGreenStep = 0;		\
1486      span.specBlue = sbFlat;   span.specBlueStep = 0;		\
1487   }								\
1488   rasterize_span(ctx, &span);
1489
1490#include "s_tritemp.h"
1491}
1492
1493
1494/*
1495 * This is the big one!
1496 * Interpolate Z, RGB, Alpha, specular, fog, and N sets of texture coordinates
1497 * with lambda (LOD).
1498 * Yup, it's slow.
1499 */
1500static void
1501lambda_multitextured_triangle( GLcontext *ctx,
1502                               const SWvertex *v0,
1503                               const SWvertex *v1,
1504                               const SWvertex *v2 )
1505{
1506
1507#define INTERP_Z 1
1508#define INTERP_FOG 1
1509#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1510#define INTERP_RGB 1
1511#define INTERP_ALPHA 1
1512#define INTERP_SPEC 1
1513#define INTERP_MULTITEX 1
1514#define INTERP_LAMBDA 1
1515
1516#define SETUP_CODE							\
1517   const GLboolean flatShade = (ctx->Light.ShadeModel == GL_FLAT);	\
1518   GLfixed rFlat, gFlat, bFlat, aFlat;					\
1519   GLfixed srFlat, sgFlat, sbFlat;					\
1520   GLuint u;								\
1521   if (flatShade) {							\
1522      rFlat = IntToFixed(v2->color[RCOMP]);				\
1523      gFlat = IntToFixed(v2->color[GCOMP]);				\
1524      bFlat = IntToFixed(v2->color[BCOMP]);				\
1525      aFlat = IntToFixed(v2->color[ACOMP]);				\
1526      srFlat = IntToFixed(v2->specular[RCOMP]);				\
1527      sgFlat = IntToFixed(v2->specular[GCOMP]);				\
1528      sbFlat = IntToFixed(v2->specular[BCOMP]);				\
1529   }									\
1530   for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {			\
1531      if (ctx->Texture.Unit[u]._ReallyEnabled) {			\
1532         const struct gl_texture_object *texObj;			\
1533         const struct gl_texture_image *texImage;			\
1534         texObj = ctx->Texture.Unit[u]._Current;			\
1535         texImage = texObj->Image[texObj->BaseLevel];			\
1536         span.texWidth[u] = (GLfloat) texImage->Width;			\
1537         span.texHeight[u] = (GLfloat) texImage->Height;		\
1538      }									\
1539   }									\
1540   (void) fixedToDepthShift;
1541
1542#define RENDER_SPAN( span )					\
1543   if (flatShade) {						\
1544      span.red = rFlat;    span.redStep = 0;			\
1545      span.green = gFlat;  span.greenStep = 0;			\
1546      span.blue = bFlat;   span.blueStep = 0;			\
1547      span.alpha = aFlat;  span.alphaStep = 0;			\
1548      span.specRed = srFlat;    span.specRedStep = 0;		\
1549      span.specGreen = sgFlat;  span.specGreenStep = 0;		\
1550      span.specBlue = sbFlat;   span.specBlueStep = 0;		\
1551   }								\
1552   rasterize_span(ctx, &span);
1553
1554#include "s_tritemp.h"
1555
1556}
1557
1558
1559static void occlusion_zless_triangle( GLcontext *ctx,
1560				      const SWvertex *v0,
1561				      const SWvertex *v1,
1562				      const SWvertex *v2 )
1563{
1564   if (ctx->OcclusionResult) {
1565      return;
1566   }
1567
1568#define DO_OCCLUSION_TEST
1569#define INTERP_Z 1
1570#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1571
1572#define RENDER_SPAN( span )				\
1573   GLuint i;						\
1574   for (i = 0; i < span.count; i++) {			\
1575      GLdepth z = FixedToDepth(span.z);			\
1576      if (z < zRow[i]) {				\
1577         ctx->OcclusionResult = GL_TRUE;		\
1578         return;					\
1579      }							\
1580      span.z += span.zStep;				\
1581   }
1582
1583#include "s_tritemp.h"
1584}
1585
1586static void nodraw_triangle( GLcontext *ctx,
1587			     const SWvertex *v0,
1588			     const SWvertex *v1,
1589			     const SWvertex *v2 )
1590{
1591   (void) (ctx && v0 && v1 && v2);
1592}
1593
1594void _swrast_add_spec_terms_triangle( GLcontext *ctx,
1595				      const SWvertex *v0,
1596				      const SWvertex *v1,
1597				      const SWvertex *v2 )
1598{
1599   SWvertex *ncv0 = (SWvertex *)v0; /* drop const qualifier */
1600   SWvertex *ncv1 = (SWvertex *)v1;
1601   SWvertex *ncv2 = (SWvertex *)v2;
1602   GLchan c[3][4];
1603   COPY_CHAN4( c[0], ncv0->color );
1604   COPY_CHAN4( c[1], ncv1->color );
1605   COPY_CHAN4( c[2], ncv2->color );
1606   ACC_3V( ncv0->color, ncv0->specular );
1607   ACC_3V( ncv1->color, ncv1->specular );
1608   ACC_3V( ncv2->color, ncv2->specular );
1609   SWRAST_CONTEXT(ctx)->SpecTriangle( ctx, ncv0, ncv1, ncv2 );
1610   COPY_CHAN4( ncv0->color, c[0] );
1611   COPY_CHAN4( ncv1->color, c[1] );
1612   COPY_CHAN4( ncv2->color, c[2] );
1613}
1614
1615
1616
1617#ifdef DEBUG
1618
1619/* record the current triangle function name */
1620static const char *triFuncName = NULL;
1621
1622#define USE(triFunc)                   \
1623do {                                   \
1624    triFuncName = #triFunc;            \
1625    /*printf("%s\n", triFuncName);*/   \
1626    swrast->Triangle = triFunc;        \
1627} while (0)
1628
1629#else
1630
1631#define USE(triFunc)  swrast->Triangle = triFunc;
1632
1633#endif
1634
1635
1636
1637
1638/*
1639 * Determine which triangle rendering function to use given the current
1640 * rendering context.
1641 *
1642 * Please update the summary flag _SWRAST_NEW_TRIANGLE if you add or
1643 * remove tests to this code.
1644 */
1645void
1646_swrast_choose_triangle( GLcontext *ctx )
1647{
1648   SWcontext *swrast = SWRAST_CONTEXT(ctx);
1649   const GLboolean rgbmode = ctx->Visual.rgbMode;
1650
1651   if (ctx->Polygon.CullFlag &&
1652       ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) {
1653      USE(nodraw_triangle);
1654      return;
1655   }
1656
1657   if (ctx->RenderMode==GL_RENDER) {
1658
1659      if (ctx->Polygon.SmoothFlag) {
1660         _mesa_set_aa_triangle_function(ctx);
1661         ASSERT(swrast->Triangle);
1662         return;
1663      }
1664
1665      if (ctx->Depth.OcclusionTest &&
1666          ctx->Depth.Test &&
1667          ctx->Depth.Mask == GL_FALSE &&
1668          ctx->Depth.Func == GL_LESS &&
1669          !ctx->Stencil.Enabled) {
1670         if ((rgbmode &&
1671              ctx->Color.ColorMask[0] == 0 &&
1672              ctx->Color.ColorMask[1] == 0 &&
1673              ctx->Color.ColorMask[2] == 0 &&
1674              ctx->Color.ColorMask[3] == 0)
1675             ||
1676             (!rgbmode && ctx->Color.IndexMask == 0)) {
1677            USE(occlusion_zless_triangle);
1678            return;
1679         }
1680      }
1681
1682      if (ctx->Texture._ReallyEnabled) {
1683         /* Ugh, we do a _lot_ of tests to pick the best textured tri func */
1684	 const struct gl_texture_object *texObj2D;
1685         const struct gl_texture_image *texImg;
1686         GLenum minFilter, magFilter, envMode;
1687         GLint format;
1688         texObj2D = ctx->Texture.Unit[0].Current2D;
1689         texImg = texObj2D ? texObj2D->Image[texObj2D->BaseLevel] : NULL;
1690         format = texImg ? texImg->TexFormat->MesaFormat : -1;
1691         minFilter = texObj2D ? texObj2D->MinFilter : (GLenum) 0;
1692         magFilter = texObj2D ? texObj2D->MagFilter : (GLenum) 0;
1693         envMode = ctx->Texture.Unit[0].EnvMode;
1694
1695         /* First see if we can used an optimized 2-D texture function */
1696         if (ctx->Texture._ReallyEnabled==TEXTURE0_2D
1697             && texObj2D->WrapS==GL_REPEAT
1698	     && texObj2D->WrapT==GL_REPEAT
1699             && texImg->Border==0
1700             && (format == MESA_FORMAT_RGB || format == MESA_FORMAT_RGBA)
1701	     && minFilter == magFilter
1702	     && ctx->Light.Model.ColorControl == GL_SINGLE_COLOR
1703	     && ctx->Texture.Unit[0].EnvMode != GL_COMBINE_EXT) {
1704	    if (ctx->Hint.PerspectiveCorrection==GL_FASTEST) {
1705	       if (minFilter == GL_NEAREST
1706		   && format == MESA_FORMAT_RGB
1707		   && (envMode == GL_REPLACE || envMode == GL_DECAL)
1708		   && ((swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)
1709			&& ctx->Depth.Func == GL_LESS
1710			&& ctx->Depth.Mask == GL_TRUE)
1711		       || swrast->_RasterMask == TEXTURE_BIT)
1712		   && ctx->Polygon.StippleFlag == GL_FALSE) {
1713		  if (swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)) {
1714		     USE(simple_z_textured_triangle);
1715		  }
1716		  else {
1717		     USE(simple_textured_triangle);
1718		  }
1719	       }
1720	       else {
1721		 /* GL_MODULATE seems also not to work !! */
1722                  if (ctx->Texture.Unit[0].EnvMode==GL_ADD) {
1723                     USE(general_textured_triangle);
1724                  }
1725                  else {
1726                     USE(affine_textured_triangle);
1727                  }
1728	       }
1729	    }
1730	    else {
1731	      /* GL_MODULATE seems also not to work !! */
1732	       if (ctx->Texture.Unit[0].EnvMode==GL_ADD) {
1733		  USE(general_textured_triangle);
1734	       }
1735	       else {
1736		  USE(persp_textured_triangle);
1737	       }
1738	    }
1739	 }
1740         else {
1741            /* More complicated textures (mipmap, multi-tex, sep specular) */
1742            GLboolean needLambda;
1743            /* if mag filter != min filter we need to compute lambda */
1744            const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;
1745            if (obj && obj->MinFilter != obj->MagFilter)
1746               needLambda = GL_TRUE;
1747            else
1748               needLambda = GL_FALSE;
1749            if (ctx->Texture._ReallyEnabled > TEXTURE0_ANY) {
1750               USE(lambda_multitextured_triangle);
1751            }
1752            else if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
1753               /* separate specular color interpolation */
1754               if (needLambda) {
1755                  USE(lambda_textured_spec_triangle);
1756	       }
1757               else {
1758                  USE(general_textured_spec_triangle);
1759	       }
1760            }
1761            else {
1762               if (needLambda) {
1763		  USE(lambda_textured_triangle);
1764	       }
1765               else {
1766                  USE(general_textured_triangle);
1767	       }
1768            }
1769         }
1770      }
1771      else {
1772         ASSERT(!ctx->Texture._ReallyEnabled);
1773	 if (ctx->Light.ShadeModel==GL_SMOOTH) {
1774	    /* smooth shaded, no texturing, stippled or some raster ops */
1775            if (rgbmode) {
1776	       USE(smooth_rgba_triangle);
1777            }
1778            else {
1779               USE(smooth_ci_triangle);
1780            }
1781	 }
1782	 else {
1783	    /* flat shaded, no texturing, stippled or some raster ops */
1784            if (rgbmode) {
1785	       USE(flat_rgba_triangle);
1786            }
1787            else {
1788               USE(flat_ci_triangle);
1789            }
1790	 }
1791      }
1792   }
1793   else if (ctx->RenderMode==GL_FEEDBACK) {
1794      USE(_mesa_feedback_triangle);
1795   }
1796   else {
1797      /* GL_SELECT mode */
1798      USE(_mesa_select_triangle);
1799   }
1800}
1801