s_triangle.c revision 9bf68ad963ba92b5d1e725f965979042495a5313
1/* $Id: s_triangle.c,v 1.26 2001/05/14 16:23:04 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, 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, 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,		\
158                              zSpan, fogSpan, v2->color, 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, 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 = 0xff
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 = 0xff
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] = ((0xff - ta) * span->red				\
397           + ((ta + 1) * tr << FIXED_SHIFT)) >> (FIXED_SHIFT + 8);	\
398	dest[GCOMP] = ((0xff - ta) * span->green			\
399           + ((ta + 1) * tg << FIXED_SHIFT)) >> (FIXED_SHIFT + 8);	\
400	dest[BCOMP] = ((0xff - 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] = ((0xff - tr) * span->red				\
406           + (tr + 1) * info->er) >> (FIXED_SHIFT + 8);			\
407        dest[GCOMP] = ((0xff - tg) * span->green			\
408           + (tg + 1) * info->eg) >> (FIXED_SHIFT + 8);			\
409        dest[BCOMP] = ((0xff - 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 SPAN1(DO_TEX,COMP)						\
435	for (i = 0; i < span->count; i++) {				\
436           GLint s = FixedToInt(span->intTex[0]) & info->smask;		\
437           GLint t = FixedToInt(span->intTex[1]) & info->tmask;		\
438           GLint pos = (t << info->twidth_log2) + s;			\
439           const GLchan *tex00 = info->texture + COMP * pos;		\
440	   zspan[i] = FixedToDepth(span->z);				\
441	   fogspan[i] = span->fog;					\
442           DO_TEX;							\
443	   span->fog += span->fogStep;					\
444	   span->z += span->zStep;					\
445           span->red += span->redStep;					\
446	   span->green += span->greenStep;				\
447           span->blue += span->blueStep;				\
448	   span->alpha += span->alphaStep;				\
449	   span->intTex[0] += span->intTexStep[0];			\
450	   span->intTex[1] += span->intTexStep[1];			\
451           dest += 4;							\
452	}
453
454#define SPAN2(DO_TEX,COMP)						\
455	for (i = 0; i < span->count; i++) {				\
456           GLint s = FixedToInt(span->intTex[0]) & info->smask;		\
457           GLint t = FixedToInt(span->intTex[1]) & info->tmask;		\
458           GLint sf = span->intTex[0] & FIXED_FRAC_MASK;		\
459           GLint tf = span->intTex[1] & FIXED_FRAC_MASK;		\
460           GLint si = FIXED_FRAC_MASK - sf;				\
461           GLint ti = FIXED_FRAC_MASK - tf;				\
462           GLint pos = (t << info->twidth_log2) + s;			\
463           const GLchan *tex00 = info->texture + COMP * pos;		\
464           const GLchan *tex10 = tex00 + info->tbytesline;		\
465           const GLchan *tex01 = tex00 + COMP;				\
466           const GLchan *tex11 = tex10 + COMP;				\
467           (void) ti;							\
468           (void) si;							\
469           if (t == info->tmask) {					\
470              tex10 -= info->tsize;					\
471              tex11 -= info->tsize;					\
472           }								\
473           if (s == info->smask) {					\
474              tex01 -= info->tbytesline;				\
475              tex11 -= info->tbytesline;				\
476           }								\
477	   zspan[i] = FixedToDepth(span->z);				\
478	   fogspan[i] = span->fog;					\
479           DO_TEX;							\
480	   span->fog += span->fogStep;					\
481	   span->z += span->zStep;					\
482           span->red += span->redStep;					\
483	   span->green += span->greenStep;				\
484           span->blue += span->blueStep;				\
485	   span->alpha += span->alphaStep;				\
486	   span->intTex[0] += span->intTexStep[0];			\
487	   span->intTex[1] += span->intTexStep[1];			\
488           dest += 4;							\
489	}
490
491#define FixedToDepth(F)  ((F) >> fixedToDepthShift)
492
493   GLuint i;
494   GLdepth zspan[MAX_WIDTH];
495   GLfloat fogspan[MAX_WIDTH];
496   GLchan rgba[MAX_WIDTH][4];
497   GLchan *dest = rgba[0];
498   const GLint fixedToDepthShift = info->fixedToDepthShift;
499
500   span->intTex[0] -= FIXED_HALF;
501   span->intTex[1] -= FIXED_HALF;
502   switch (info->filter) {
503   case GL_NEAREST:
504      switch (info->format) {
505      case GL_RGB:
506         switch (info->envmode) {
507         case GL_MODULATE:
508            SPAN1(NEAREST_RGB;MODULATE,3);
509            break;
510         case GL_DECAL:
511         case GL_REPLACE:
512            SPAN1(NEAREST_RGB_REPLACE,3);
513            break;
514         case GL_BLEND:
515            SPAN1(NEAREST_RGB;BLEND,3);
516            break;
517         case GL_ADD:
518            SPAN1(NEAREST_RGB;ADD,3);
519            break;
520         default:
521            abort();
522         }
523         break;
524      case GL_RGBA:
525         switch(info->envmode) {
526         case GL_MODULATE:
527            SPAN1(NEAREST_RGBA;MODULATE,4);
528            break;
529         case GL_DECAL:
530            SPAN1(NEAREST_RGBA;DECAL,4);
531            break;
532         case GL_BLEND:
533            SPAN1(NEAREST_RGBA;BLEND,4);
534            break;
535         case GL_ADD:
536            SPAN1(NEAREST_RGBA;ADD,4);
537            break;
538         case GL_REPLACE:
539            SPAN1(NEAREST_RGBA_REPLACE,4);
540            break;
541         default:
542            abort();
543         }
544         break;
545      }
546      break;
547
548   case GL_LINEAR:
549      span->intTex[0] -= FIXED_HALF;
550      span->intTex[1] -= FIXED_HALF;
551      switch (info->format) {
552      case GL_RGB:
553         switch (info->envmode) {
554         case GL_MODULATE:
555            SPAN2(LINEAR_RGB;MODULATE,3);
556            break;
557         case GL_DECAL:
558         case GL_REPLACE:
559            SPAN2(LINEAR_RGB;REPLACE,3);
560            break;
561         case GL_BLEND:
562            SPAN2(LINEAR_RGB;BLEND,3);
563            break;
564         case GL_ADD:
565            SPAN2(LINEAR_RGB;ADD,3);
566            break;
567         default:
568            abort();
569         }
570         break;
571      case GL_RGBA:
572         switch (info->envmode) {
573         case GL_MODULATE:
574            SPAN2(LINEAR_RGBA;MODULATE,4);
575            break;
576         case GL_DECAL:
577            SPAN2(LINEAR_RGBA;DECAL,4);
578            break;
579         case GL_BLEND:
580            SPAN2(LINEAR_RGBA;BLEND,4);
581            break;
582         case GL_ADD:
583            SPAN2(LINEAR_RGBA;ADD,4);
584            break;
585         case GL_REPLACE:
586            SPAN2(LINEAR_RGBA;REPLACE,4);
587            break;
588         default:
589            abort();
590         }		    break;
591      }
592      break;
593   }
594   _mesa_write_rgba_span(ctx, span->count, span->x, span->y,
595                         zspan, fogspan, rgba, GL_POLYGON);
596
597#undef SPAN1
598#undef SPAN2
599#undef FixedToDepth
600}
601
602
603
604/*
605 * Render an RGB/RGBA textured triangle without perspective correction.
606 */
607static void affine_textured_triangle( GLcontext *ctx,
608				      const SWvertex *v0,
609				      const SWvertex *v1,
610				      const SWvertex *v2 )
611{
612#define INTERP_Z 1
613#define INTERP_FOG 1
614#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
615#define INTERP_RGB 1
616#define INTERP_ALPHA 1
617#define INTERP_INT_TEX 1
618#define S_SCALE twidth
619#define T_SCALE theight
620
621#define SETUP_CODE
622   struct affine_info info;
623   struct gl_texture_unit *unit = ctx->Texture.Unit+0;			\
624   struct gl_texture_object *obj = unit->Current2D;			\
625   GLint b = obj->BaseLevel;						\
626   GLfloat twidth = (GLfloat) obj->Image[b]->Width;			\
627   GLfloat theight = (GLfloat) obj->Image[b]->Height;			\
628   info.fixedToDepthShift = ctx->Visual.depthBits <= 16 ? FIXED_SHIFT : 0;\
629   info.texture = (const GLchan *) obj->Image[b]->Data;			\
630   info.twidth_log2 = obj->Image[b]->WidthLog2;				\
631   info.smask = obj->Image[b]->Width - 1;				\
632   info.tmask = obj->Image[b]->Height - 1;				\
633   info.format = obj->Image[b]->Format;					\
634   info.filter = obj->MinFilter;					\
635   info.envmode = unit->EnvMode;					\
636									\
637   if (info.envmode == GL_BLEND) {					\
638      /* potential off-by-one error here? (1.0f -> 2048 -> 0) */	\
639      info.er = FloatToFixed(unit->EnvColor[RCOMP]);			\
640      info.eg = FloatToFixed(unit->EnvColor[GCOMP]);			\
641      info.eb = FloatToFixed(unit->EnvColor[BCOMP]);			\
642      info.ea = FloatToFixed(unit->EnvColor[ACOMP]);			\
643   }									\
644   if (!info.texture) {							\
645      /* this shouldn't happen */					\
646      return;								\
647   }									\
648									\
649   switch (info.format) {						\
650   case GL_ALPHA:							\
651   case GL_LUMINANCE:							\
652   case GL_INTENSITY:							\
653      info.tbytesline = obj->Image[b]->Width;				\
654      break;								\
655   case GL_LUMINANCE_ALPHA:						\
656      info.tbytesline = obj->Image[b]->Width * 2;			\
657      break;								\
658   case GL_RGB:								\
659      info.tbytesline = obj->Image[b]->Width * 3;			\
660      break;								\
661   case GL_RGBA:							\
662      info.tbytesline = obj->Image[b]->Width * 4;			\
663      break;								\
664   default:								\
665      _mesa_problem(NULL, "Bad texture format in affine_texture_triangle");\
666      return;								\
667   }									\
668   info.tsize = obj->Image[b]->Height * info.tbytesline;
669
670#define RENDER_SPAN( span )		\
671   affine_span(ctx, &span, &info);
672
673#include "s_tritemp.h"
674
675}
676
677
678#if 0 /* XXX disabled because of texcoord interpolation errors */
679/*
680 * Render an perspective corrected RGB/RGBA textured triangle.
681 * The Q (aka V in Mesa) coordinate must be zero such that the divide
682 * by interpolated Q/W comes out right.
683 *
684 * This function only renders textured triangles that use GL_NEAREST.
685 * Perspective correction works right.
686 *
687 * This function written by Klaus Niederkrueger <klaus@math.leidenuniv.nl>
688 * Send all questions and bug reports to him.
689 */
690static void near_persp_textured_triangle(GLcontext *ctx,
691					 const SWvertex *v0,
692					 const SWvertex *v1,
693					 const SWvertex *v2 )
694{
695/* The BIAS value is used to shift negative values into positive values.
696 * Without this, negative texture values don't GL_REPEAT correctly at just
697 * below zero, because (int)-0.5 = 0 = (int)0.5. We're not going to worry
698 * about texture coords less than -BIAS. This could be fixed by using
699 * FLOORF etc. instead, but this is slower...
700 */
701#define BIAS 4096.0F
702
703#define INTERP_Z 1
704#define INTERP_FOG 1
705#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
706#define INTERP_RGB 1
707#define INTERP_ALPHA 1
708#define INTERP_TEX 1
709
710#define SETUP_CODE							\
711   struct gl_texture_unit *unit = ctx->Texture.Unit+0;			\
712   struct gl_texture_object *obj = unit->Current2D;			\
713   const GLint b = obj->BaseLevel;					\
714   const GLfloat twidth = (GLfloat) obj->Image[b]->Width;	      	\
715   const GLfloat theight = (GLfloat) obj->Image[b]->Height;		\
716   const GLint twidth_log2 = obj->Image[b]->WidthLog2;			\
717   const GLchan *texture = (const GLchan *) obj->Image[b]->Data;	\
718   const GLint smask = (obj->Image[b]->Width - 1);                      \
719   const GLint tmask = (obj->Image[b]->Height - 1);                     \
720   const GLint format = obj->Image[b]->Format;                          \
721   const GLint envmode = unit->EnvMode;                                 \
722   GLfloat sscale, tscale;                                              \
723   GLfixed er, eg, eb, ea;                                              \
724   GLint tr, tg, tb, ta;                                                \
725   if (!texture) {							\
726      /* this shouldn't happen */					\
727      return;								\
728   }									\
729   if (envmode == GL_BLEND || envmode == GL_ADD) {                      \
730      er = FloatToFixed(unit->EnvColor[RCOMP]);                         \
731      eg = FloatToFixed(unit->EnvColor[GCOMP]);                         \
732      eb = FloatToFixed(unit->EnvColor[BCOMP]);                         \
733      ea = FloatToFixed(unit->EnvColor[ACOMP]);                         \
734   }                                                                    \
735   sscale = twidth;                                                     \
736   tscale = theight;                                                    \
737
738
739#define OLD_SPAN(DO_TEX,COMP)                         \
740   for (i=0;i<n;i++) {                                \
741      GLfloat invQ = 1.0f / vv;                       \
742      GLint s = (int)(SS * invQ + BIAS) & smask;      \
743      GLint t = (int)(TT * invQ + BIAS) & tmask;      \
744      GLint pos = COMP * ((t << twidth_log2) + s);    \
745      const GLchan *tex00 = texture + pos;            \
746      zspan[i] = FixedToDepth(span.z);                   \
747      fogspan[i] = span.fog;                              \
748      DO_TEX;                                         \
749      span.fog += span.fogStep;                                 \
750      span.z += span.zStep;                                   \
751      span.red += span.redStep;                                   \
752      span.green += span.greenStep;                                   \
753      span.blue += span.blueStep;                                   \
754      span.alpha += span.alphaStep;                                   \
755      SS += dSdx;                                     \
756      TT += dTdx;                                     \
757      vv += dvdx;                                     \
758      dest += 4;                                      \
759   }
760
761#define X_Y_TEX_COORD(X, Y) ((((int)(X) & tmask) << twidth_log2) + ((int)(Y) & smask))
762#define Y_X_TEX_COORD(X, Y) ((((int)(Y) & tmask) << twidth_log2) + ((int)(X) & smask))
763
764#define SPAN1(DO_TEX, COMP, TEX_COORD) {                          \
765   GLfloat x_max = CEILF(x_tex);                                  \
766   GLfloat y_max = y_tex + (x_max - x_tex) * dy_dx;               \
767   GLint j, x_m = (int)x_max;                                     \
768   GLint pos;                                                     \
769   if ((int)y_max != (int)y_tex) {                                \
770      GLfloat x_mid = x_tex + (CEILF(y_tex)-y_tex) * dx_dy;       \
771      j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid);    \
772      pos = COMP * TEX_COORD(x_tex, y_tex);                       \
773      DRAW_LINE (DO_TEX);                                         \
774      y_tex = y_max;                                              \
775   }                                                              \
776   nominator += vv * x_max;                                       \
777   denominator -= dvdx * x_max;                                   \
778   j = nominator / denominator;                                   \
779   pos = COMP * TEX_COORD(x_tex, y_tex);                          \
780   DRAW_LINE (DO_TEX);                                            \
781   while (i<n)  {                                                 \
782      y_tex = y_max;                                              \
783      y_max += dy_dx;                                             \
784      if ((int)y_max != (int)y_tex) {                             \
785         GLfloat x_mid = (CEILF(y_tex)-y_tex) * dx_dy;            \
786         j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
787         pos = COMP * TEX_COORD(x_m, y_tex);                      \
788         DRAW_LINE (DO_TEX);                                      \
789         y_tex = y_max;                                           \
790      }                                                           \
791      nominator += vv;                                            \
792      denominator -= dvdx;                                        \
793      j = nominator/denominator;                                  \
794      pos = COMP * TEX_COORD(x_m, y_tex);                         \
795      DRAW_LINE (DO_TEX);                                         \
796      x_m ++;                                                     \
797   }                                                              \
798}
799
800#define SPAN2(DO_TEX, COMP, TEX_COORD)  {			\
801   GLfloat x_max = CEILF (x_tex);				\
802   GLfloat y_max = y_tex + (x_max - x_tex) * dy_dx;		\
803   GLint j, x_m = (int) x_max;					\
804   GLint pos;							\
805   if ((int)y_max != (int)y_tex) {				\
806      GLfloat x_mid = x_tex + (FLOORF(y_tex)-y_tex) * dx_dy;	\
807      j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid);	\
808      pos = COMP * TEX_COORD(x_tex, y_tex);			\
809      DRAW_LINE (DO_TEX);					\
810      y_tex = y_max;						\
811   }								\
812   nominator += vv * x_max;					\
813   denominator -= dvdx * x_max;					\
814   j = nominator / denominator;					\
815   pos = COMP * TEX_COORD(x_tex, y_tex);			\
816   DRAW_LINE (DO_TEX);						\
817   while (i<n)  {						\
818      y_tex = y_max;						\
819      y_max += dy_dx;						\
820      if ((int)y_max != (int)y_tex) {				\
821         GLfloat x_mid = (FLOORF(y_tex)-y_tex) * dx_dy;		\
822         j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid);\
823         pos = COMP * TEX_COORD(x_m, y_tex);			\
824         DRAW_LINE (DO_TEX);					\
825         y_tex = y_max;						\
826      }								\
827      nominator += vv;						\
828      denominator -= dvdx;					\
829      j = nominator/denominator;				\
830      pos = COMP * TEX_COORD(x_m, y_tex);			\
831      DRAW_LINE (DO_TEX);					\
832      x_m ++;							\
833   }								\
834}
835
836#define SPAN3(DO_TEX, COMP, TEX_COORD) {				\
837   GLfloat x_min = FLOORF (x_tex);					\
838   GLfloat y_min = y_tex + (x_min - x_tex) * dy_dx;			\
839   GLint j, x_m = (int)x_min;						\
840   GLint pos;								\
841   if ((int)y_min != (int)y_tex) {					\
842      GLfloat x_mid = x_tex + (CEILF(y_tex)-y_tex) * dx_dy;		\
843      j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid);		\
844      pos = COMP * TEX_COORD(x_m, y_tex);				\
845      DRAW_LINE (DO_TEX);						\
846      y_tex = y_min;							\
847   }									\
848   nominator += vv*x_min;						\
849   denominator -= dvdx*x_min;						\
850   j = nominator / denominator;						\
851   pos = COMP * TEX_COORD(x_m, y_tex);					\
852   DRAW_LINE (DO_TEX);							\
853   while (i<n) {							\
854      x_m --;								\
855      y_tex = y_min;							\
856      y_min -= dy_dx;							\
857      if ((int)y_min != (int)y_tex) {					\
858         GLfloat x_mid = (CEILF(y_tex)-y_tex) * dx_dy;			\
859         j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid);	\
860         pos = COMP * TEX_COORD(x_m, y_tex);				\
861         DRAW_LINE (DO_TEX);						\
862         y_tex = y_min;							\
863      }									\
864      nominator -= vv;							\
865      denominator += dvdx;						\
866      j = nominator/denominator;					\
867      pos = COMP * TEX_COORD(x_m, y_tex);				\
868      DRAW_LINE (DO_TEX);						\
869   }									\
870}
871
872#define SPAN4(DO_TEX, COMP, TEX_COORD)					\
873{									\
874   GLfloat x_min = FLOORF(x_tex);					\
875   GLint x_m = (int)x_min;						\
876   GLfloat y_min = y_tex + (x_min - x_tex) * dy_dx;			\
877   GLint j;								\
878   GLint pos;								\
879   if ((int)y_min != (int)y_tex) {					\
880      GLfloat x_mid = x_tex + (FLOORF(y_tex)-y_tex) * dx_dy;		\
881      j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid);		\
882      pos = COMP * TEX_COORD(x_m, y_tex);				\
883      DRAW_LINE (DO_TEX);						\
884      y_tex = y_min;							\
885   }									\
886   nominator += vv * x_min;						\
887   denominator -= dvdx * x_min;						\
888   j = nominator / denominator;						\
889   pos = COMP * TEX_COORD(x_m, y_tex);					\
890   DRAW_LINE (DO_TEX);							\
891   while (i<n)  {							\
892      x_m --;								\
893      y_tex = y_min;							\
894      y_min -= dy_dx;							\
895      if ((int)y_min != (int)y_tex) {					\
896         GLfloat x_mid = (FLOORF(y_tex)-y_tex) * dx_dy;			\
897         j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid);	\
898         pos = COMP * TEX_COORD(x_m, (y_tex));				\
899         DRAW_LINE (DO_TEX);						\
900         y_tex = y_min;							\
901      }									\
902      nominator -= vv;							\
903      denominator += dvdx;						\
904      j = nominator/denominator;					\
905      pos = COMP * TEX_COORD(x_m, y_tex);				\
906      DRAW_LINE (DO_TEX);						\
907   }									\
908}
909
910#define DRAW_LINE(DO_TEX)		\
911   {					\
912      GLchan *tex00 = texture + pos;	\
913      if (j>n || j<-100000)		\
914         j = n;				\
915      while (i<j) {			\
916         zspan[i] = FixedToDepth(span.z);	\
917         fogspan[i] = span.fog;             \
918         DO_TEX;			\
919         span.fog += span.fogStep;                \
920         span.z += span.zStep;			\
921         span.red += span.redStep;			\
922         span.green += span.greenStep;			\
923         span.blue += span.blueStep;			\
924         span.alpha += span.alphaStep;			\
925         dest += 4;			\
926         i++;				\
927      }					\
928   }
929
930#define INNER_LOOP( LEFT, RIGHT, Y )					\
931   {									\
932      GLint i = 0;							\
933      const GLint n = RIGHT-LEFT;					\
934      GLdepth zspan[MAX_WIDTH];						\
935      GLfloat fogspan[MAX_WIDTH];					\
936      GLchan rgba[MAX_WIDTH][4];					\
937      (void)uu; /* please GCC */					\
938      if (n > 0) {							\
939         GLchan *dest = rgba[0];					\
940         GLfloat SS = ss * sscale;					\
941         GLfloat TT = tt * tscale;					\
942         GLfloat dSdx = dsdx * sscale;					\
943         GLfloat dTdx = dtdx * tscale;					\
944         GLfloat x_tex;					                \
945         GLfloat y_tex;					                \
946         GLfloat dx_tex;	                                        \
947         GLfloat dy_tex;	                                        \
948         if (n<5) /* When line very short, setup-time > speed-gain. */	\
949            goto old_span;  /* So: take old method */			\
950         x_tex = SS / vv,					        \
951            y_tex = TT / vv;					        \
952         dx_tex = (SS + n * dSdx) / (vv + n * dvdx) - x_tex,	        \
953            dy_tex = (TT + n * dTdx) / (vv + n * dvdx) - y_tex;	        \
954	 /* Choose between walking over texture or over pixelline: */	\
955	 /* If there are few texels, walk over texture otherwise   */	\
956	 /* walk over pixelarray. The quotient on the right side   */	\
957	 /* should give the timeratio needed to draw one texel in  */	\
958	 /* comparison to one pixel. Depends on CPU.	 	   */	\
959         if (dx_tex*dx_tex + dy_tex*dy_tex < (n*n)/16) {		\
960            x_tex += BIAS;						\
961            y_tex += BIAS;						\
962            if (dx_tex*dx_tex > dy_tex*dy_tex) {			\
963	    /* if (FABSF(dx_tex) > FABSF(dy_tex)) */			\
964               GLfloat nominator = - SS - vv * BIAS;			\
965               GLfloat denominator = dvdx * BIAS + dSdx;		\
966               GLfloat dy_dx;						\
967               GLfloat dx_dy;						\
968               if (dy_tex != 0.0f) {					\
969                  dy_dx = dy_tex / dx_tex;                              \
970                  dx_dy = 1.0f/dy_dx;					\
971               }                                                        \
972               else                                                     \
973                  dy_dx = 0.0f;                                         \
974               if (dx_tex > 0.0f) {					\
975                  if (dy_tex > 0.0f) {					\
976                     switch (format) {					\
977                     case GL_RGB:					\
978                        switch (envmode) {				\
979                        case GL_MODULATE:				\
980                           SPAN1(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
981                           break;					\
982                        case GL_DECAL:					\
983                        case GL_REPLACE:				\
984                           SPAN1(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD);	\
985                           break;					\
986                        case GL_BLEND:					\
987                           SPAN1(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD);	\
988                           break;					\
989		        case GL_ADD:                                    \
990		           SPAN1(NEAREST_RGB;ADD,3, Y_X_TEX_COORD);     \
991		           break;                                       \
992                        default: /* unexpected env mode */		\
993                           abort();					\
994                        }						\
995                        break;						\
996                     case GL_RGBA:					\
997                        switch(envmode) {				\
998                        case GL_MODULATE:				\
999                           SPAN1(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
1000                           break;					\
1001                        case GL_DECAL:					\
1002                           SPAN1(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD);	\
1003                           break;					\
1004                        case GL_BLEND:					\
1005                           SPAN1(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD);	\
1006                           break;					\
1007		        case GL_ADD:                                    \
1008		           SPAN1(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD);    \
1009		           break;                                       \
1010                        case GL_REPLACE:				\
1011                           SPAN1(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
1012                           break;					\
1013                        default: /* unexpected env mode */		\
1014                           abort();					\
1015                        }						\
1016                        break;						\
1017                     }							\
1018                  }							\
1019                  else {  /* dy_tex <= 0.0f */				\
1020                     switch (format) {					\
1021                     case GL_RGB:					\
1022                        switch (envmode) {				\
1023                        case GL_MODULATE:				\
1024                           SPAN2(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
1025                           break;					\
1026                        case GL_DECAL:					\
1027                        case GL_REPLACE:				\
1028                           SPAN2(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD);	\
1029                           break;					\
1030                        case GL_BLEND:					\
1031                           SPAN2(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD);	\
1032                           break;					\
1033		        case GL_ADD:                                    \
1034		           SPAN2(NEAREST_RGB;ADD,3, Y_X_TEX_COORD);     \
1035		           break;                                       \
1036                        default: /* unexpected env mode */		\
1037                           abort();					\
1038                        }						\
1039                        break;						\
1040                     case GL_RGBA:					\
1041                        switch(envmode) {				\
1042                        case GL_MODULATE:				\
1043                           SPAN2(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
1044                           break;					\
1045                        case GL_DECAL:					\
1046                           SPAN2(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD);	\
1047                           break;					\
1048                        case GL_BLEND:					\
1049                           SPAN2(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD);	\
1050                           break;					\
1051		        case GL_ADD:                                    \
1052		           SPAN2(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD);    \
1053		           break;                                       \
1054                        case GL_REPLACE:				\
1055                           SPAN2(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
1056                           break;					\
1057                        default: /* unexpected env mode */		\
1058                           abort();					\
1059                        }						\
1060                        break;						\
1061                     }							\
1062                  }							\
1063               }							\
1064               else { /* dx_tex < 0.0f */				\
1065                  if (dy_tex > 0.0f) {					\
1066                     switch (format) {					\
1067                     case GL_RGB:					\
1068                        switch (envmode) {				\
1069                        case GL_MODULATE:				\
1070                           SPAN3(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
1071                           break;					\
1072                        case GL_DECAL:					\
1073                        case GL_REPLACE:				\
1074                           SPAN3(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD);	\
1075                           break;					\
1076                        case GL_BLEND:					\
1077                           SPAN3(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD);	\
1078                           break;					\
1079		        case GL_ADD:                                    \
1080		           SPAN3(NEAREST_RGB;ADD,3, Y_X_TEX_COORD);     \
1081		           break;                                       \
1082                        default: /* unexpected env mode */		\
1083                           abort();					\
1084                        }						\
1085                        break;						\
1086                     case GL_RGBA:					\
1087                        switch(envmode) {				\
1088                        case GL_MODULATE:				\
1089                           SPAN3(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
1090                           break;					\
1091                        case GL_DECAL:					\
1092                           SPAN3(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD);	\
1093                           break;					\
1094                          case GL_BLEND:				\
1095                           SPAN3(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD);	\
1096                           break;					\
1097		        case GL_ADD:                                    \
1098		           SPAN3(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD);    \
1099		           break;                                       \
1100                        case GL_REPLACE:				\
1101                           SPAN3(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
1102                           break;					\
1103                        default: /* unexpected env mode */		\
1104                           abort();					\
1105                        }						\
1106                        break;						\
1107                     }							\
1108                  }							\
1109                  else {  /* dy_tex <= 0.0f */				\
1110                     switch (format) {					\
1111                     case GL_RGB:					\
1112                        switch (envmode) {				\
1113                        case GL_MODULATE:				\
1114                           SPAN4(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
1115                           break;					\
1116                          case GL_DECAL:				\
1117                        case GL_REPLACE:				\
1118                           SPAN4(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD);	\
1119                           break;					\
1120                        case GL_BLEND:					\
1121                           SPAN4(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD);	\
1122                           break;					\
1123		        case GL_ADD:                                    \
1124		           SPAN4(NEAREST_RGB;ADD,3, Y_X_TEX_COORD);     \
1125		           break;                                       \
1126                        default:					\
1127                           abort();					\
1128                        }						\
1129                        break;						\
1130                     case GL_RGBA:					\
1131                        switch(envmode) {				\
1132                            case GL_MODULATE:				\
1133                           SPAN4(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
1134                           break;					\
1135                        case GL_DECAL:					\
1136                           SPAN4(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD);	\
1137                           break;					\
1138                        case GL_BLEND:					\
1139                           SPAN4(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD);	\
1140                           break;					\
1141		        case GL_ADD:                                    \
1142		           SPAN4(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD);    \
1143		           break;                                       \
1144                        case GL_REPLACE:				\
1145                           SPAN4(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
1146                           break;					\
1147                        default: /* unexpected env mode */		\
1148                           abort();					\
1149                        }						\
1150                        break;						\
1151                     }							\
1152                  }							\
1153               }							\
1154            }								\
1155            else {  /* FABSF(dx_tex) > FABSF(dy_tex) */		        \
1156               GLfloat swap;						\
1157               GLfloat dy_dx;						\
1158               GLfloat dx_dy;						\
1159               GLfloat nominator, denominator;				\
1160               if (dx_tex == 0.0f /* &&  dy_tex == 0.0f*/)		\
1161                  goto old_span; /* case so special, that use old */    \
1162               /* swap some x-values and y-values */			\
1163               SS = TT;							\
1164               dSdx = dTdx;						\
1165               swap = x_tex, x_tex = y_tex, y_tex = swap;		\
1166               swap = dx_tex, dx_tex = dy_tex, dy_tex = swap;		\
1167               nominator = - SS - vv * BIAS;				\
1168               denominator = dvdx * BIAS + dSdx;			\
1169               if (dy_tex != 0.0f) {					\
1170                  dy_dx = dy_tex / dx_tex;                              \
1171                  dx_dy = 1.0f/dy_dx;					\
1172               }                                                        \
1173               else                                                     \
1174                  dy_dx = 0.0f;                                         \
1175               if (dx_tex > 0.0f) {					\
1176                  if (dy_tex > 0.0f) {					\
1177		     switch (format) {					\
1178		     case GL_RGB:					\
1179			switch (envmode) {				\
1180			case GL_MODULATE:				\
1181                           SPAN1(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1182			   break;					\
1183                        case GL_DECAL:					\
1184                        case GL_REPLACE:                       		\
1185                           SPAN1(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD);	\
1186                           break;					\
1187                        case GL_BLEND:					\
1188                           SPAN1(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD);	\
1189                           break;					\
1190		        case GL_ADD:                                    \
1191		           SPAN1(NEAREST_RGB;ADD,3, X_Y_TEX_COORD);     \
1192		           break;                                       \
1193                        default: /* unexpected env mode */		\
1194                           abort();					\
1195                        }						\
1196                        break;						\
1197                     case GL_RGBA:					\
1198                        switch(envmode) {				\
1199                        case GL_MODULATE:				\
1200                           SPAN1(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1201                           break;					\
1202                        case GL_DECAL:					\
1203                           SPAN1(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD);  \
1204                           break;					\
1205                        case GL_BLEND:					\
1206                           SPAN1(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD);  \
1207                           break;					\
1208		        case GL_ADD:                                    \
1209		           SPAN1(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD);    \
1210		           break;                                       \
1211                        case GL_REPLACE:				\
1212                           SPAN1(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1213                           break;					\
1214                        default:					\
1215                           abort();					\
1216                        }						\
1217                        break;						\
1218                     }							\
1219                  }							\
1220                  else { /* dy_tex <= 0.0f */				\
1221                     switch (format) {					\
1222                     case GL_RGB:					\
1223                        switch (envmode) {				\
1224                        case GL_MODULATE:				\
1225                           SPAN2(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1226                           break;					\
1227                          case GL_DECAL:				\
1228                        case GL_REPLACE:				\
1229                           SPAN2(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD);	\
1230                           break;					\
1231                        case GL_BLEND:					\
1232                           SPAN2(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD);	\
1233                           break;					\
1234		        case GL_ADD:                                    \
1235		           SPAN2(NEAREST_RGB;ADD,3, X_Y_TEX_COORD);     \
1236		           break;                                       \
1237                        default:					\
1238                           abort();					\
1239                            }						\
1240                        break;						\
1241                     case GL_RGBA:					\
1242                        switch(envmode) {				\
1243                        case GL_MODULATE:				\
1244                           SPAN2(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1245                           break;					\
1246                        case GL_DECAL:					\
1247                           SPAN2(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD);	\
1248                           break;					\
1249                        case GL_BLEND:				        \
1250                           SPAN2(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD);	\
1251                           break;					\
1252		        case GL_ADD:                                    \
1253		           SPAN2(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD);    \
1254		           break;                                       \
1255                        case GL_REPLACE:				\
1256                           SPAN2(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1257                           break;					\
1258                        default:					\
1259                           abort();					\
1260                        }						\
1261                        break;						\
1262                     }							\
1263                  }							\
1264               }							\
1265               else { /* dx_tex < 0.0f */				\
1266                  if (dy_tex > 0.0f) {					\
1267                     switch (format) {					\
1268                     case GL_RGB:					\
1269                        switch (envmode) {				\
1270                        case GL_MODULATE:				\
1271                           SPAN3(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1272                           break;					\
1273                        case GL_DECAL:				\
1274                        case GL_REPLACE:				\
1275                           SPAN3(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD);	\
1276                           break;					\
1277                        case GL_BLEND:					\
1278                           SPAN3(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD);	\
1279                           break;					\
1280		        case GL_ADD:                                    \
1281		           SPAN3(NEAREST_RGB;ADD,3, X_Y_TEX_COORD);     \
1282		           break;                                       \
1283                        default:					\
1284                           abort();					\
1285                        }						\
1286                        break;						\
1287                     case GL_RGBA:					\
1288                        switch(envmode) {				\
1289                           case GL_MODULATE:				\
1290                           SPAN3(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1291                           break;					\
1292                        case GL_DECAL:					\
1293                           SPAN3(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD);	\
1294                           break;					\
1295                        case GL_BLEND:					\
1296                           SPAN3(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD);	\
1297                           break;					\
1298		        case GL_ADD:                                    \
1299		           SPAN3(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD);    \
1300		           break;                                       \
1301                        case GL_REPLACE:				\
1302                           SPAN3(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1303                           break;					\
1304                        default:					\
1305                           abort();					\
1306                        }						\
1307                        break;						\
1308                     }							\
1309                  }							\
1310                  else { /* dy_tex <= 0.0f */				\
1311                     switch (format) {					\
1312                     case GL_RGB:					\
1313                        switch (envmode) {				\
1314                        case GL_MODULATE:				\
1315                           SPAN4(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1316                           break;					\
1317                          case GL_DECAL:				\
1318                        case GL_REPLACE:				\
1319                           SPAN4(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD);	\
1320                           break;					\
1321                        case GL_BLEND:					\
1322                           SPAN4(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD);	\
1323                           break;					\
1324		        case GL_ADD:                                    \
1325		           SPAN4(NEAREST_RGB;ADD,3, X_Y_TEX_COORD);     \
1326		           break;                                       \
1327                        default:					\
1328                           abort();					\
1329                            }						\
1330                        break;						\
1331                     case GL_RGBA:					\
1332                        switch(envmode) {                      		\
1333                        case GL_MODULATE:				\
1334                           SPAN4(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1335                           break;					\
1336                        case GL_DECAL:					\
1337                           SPAN4(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD);	\
1338                           break;					\
1339                        case GL_BLEND:				        \
1340                           SPAN4(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD);	\
1341                           break;					\
1342		        case GL_ADD:                                    \
1343		           SPAN4(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD);    \
1344		           break;                                       \
1345                        case GL_REPLACE:				\
1346                           SPAN4(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1347                           break;					\
1348                        default:					\
1349                           abort();					\
1350                        }						\
1351                        break;						\
1352                     }							\
1353                  }							\
1354               }							\
1355            }								\
1356         }								\
1357         else {                                                		\
1358            old_span:                                                   \
1359            switch (format) {                                  		\
1360            case GL_RGB:						\
1361               switch (envmode) {                              		\
1362               case GL_MODULATE:					\
1363                  OLD_SPAN(NEAREST_RGB;MODULATE,3);			\
1364                  break;						\
1365               case GL_DECAL:						\
1366               case GL_REPLACE:						\
1367                  OLD_SPAN(NEAREST_RGB_REPLACE,3);			\
1368                  break;						\
1369               case GL_BLEND:						\
1370                  OLD_SPAN(NEAREST_RGB;BLEND,3);			\
1371                  break;						\
1372	       case GL_ADD:                                             \
1373		  OLD_SPAN(NEAREST_RGB;ADD,3);                          \
1374		  break;                                                \
1375               default:							\
1376                  abort();						\
1377               }							\
1378               break;							\
1379            case GL_RGBA:						\
1380               switch(envmode) {                               		\
1381               case GL_MODULATE:					\
1382                  OLD_SPAN(NEAREST_RGBA;MODULATE,4);			\
1383                  break;						\
1384               case GL_DECAL:						\
1385                  OLD_SPAN(NEAREST_RGBA;DECAL,4);			\
1386                  break;						\
1387               case GL_BLEND:						\
1388                  OLD_SPAN(NEAREST_RGBA;BLEND,4);			\
1389                  break;						\
1390	       case GL_ADD:                                             \
1391		  OLD_SPAN(NEAREST_RGBA;ADD,4);                         \
1392		  break;                                                \
1393               case GL_REPLACE:						\
1394                  OLD_SPAN(NEAREST_RGBA_REPLACE,4);			\
1395                  break;						\
1396               default:							\
1397                  abort();						\
1398               }							\
1399               break;							\
1400            }								\
1401         }								\
1402         _mesa_write_rgba_span( ctx, n, LEFT, Y, zspan,			\
1403                             fogspan, rgba, GL_POLYGON);		\
1404         span.red = span.green = span.blue = span.alpha = 0;					\
1405      }									\
1406   }									\
1407
1408#include "s_tritemp.h"
1409#undef OLD_SPAN
1410#undef SPAN1
1411#undef SPAN2
1412#undef SPAN3
1413#undef SPAN4
1414#undef X_Y_TEX_COORD
1415#undef Y_X_TEX_COORD
1416#undef DRAW_LINE
1417#undef BIAS
1418}
1419#endif
1420
1421
1422#if 0 /* XXX disabled because of texcoord interpolation errors */
1423/*
1424 * Render an perspective corrected RGB/RGBA textured triangle.
1425 * The Q (aka V in Mesa) coordinate must be zero such that the divide
1426 * by interpolated Q/W comes out right.
1427 *
1428 * This function written by Klaus Niederkrueger <klaus@math.leidenuniv.nl>
1429 * Send all questions and bug reports to him.
1430 */
1431static void lin_persp_textured_triangle( GLcontext *ctx,
1432					 const SWvertex *v0,
1433					 const SWvertex *v1,
1434					 const SWvertex *v2 )
1435{
1436#define INTERP_Z 1
1437#define INTERP_FOG 1
1438#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1439#define INTERP_RGB 1
1440#define INTERP_ALPHA 1
1441#define INTERP_TEX 1
1442
1443#define SETUP_CODE							\
1444   struct gl_texture_unit *unit = ctx->Texture.Unit+0;			\
1445   struct gl_texture_object *obj = unit->Current2D;			\
1446   const GLint b = obj->BaseLevel;					\
1447   const GLfloat twidth = (GLfloat) obj->Image[b]->Width;	        \
1448   const GLfloat theight = (GLfloat) obj->Image[b]->Height;		\
1449   const GLint twidth_log2 = obj->Image[b]->WidthLog2;			\
1450   GLchan *texture = obj->Image[b]->Data;				\
1451   const GLint smask = (obj->Image[b]->Width - 1);                      \
1452   const GLint tmask = (obj->Image[b]->Height - 1);                     \
1453   const GLint format = obj->Image[b]->Format;                          \
1454   const GLint envmode = unit->EnvMode;                                 \
1455   GLfloat sscale, tscale;                                              \
1456   GLint comp, tbytesline, tsize;                                       \
1457   GLfixed er, eg, eb, ea;                                              \
1458   GLint tr, tg, tb, ta;                                                \
1459   if (!texture) {							\
1460      return;								\
1461   }									\
1462   if (envmode == GL_BLEND || envmode == GL_ADD) {                      \
1463      er = FloatToFixed(unit->EnvColor[RCOMP]);                         \
1464      eg = FloatToFixed(unit->EnvColor[GCOMP]);                         \
1465      eb = FloatToFixed(unit->EnvColor[BCOMP]);                         \
1466      ea = FloatToFixed(unit->EnvColor[ACOMP]);                         \
1467   }                                                                    \
1468   switch (format) {                                                    \
1469   case GL_ALPHA:							\
1470   case GL_LUMINANCE:							\
1471   case GL_INTENSITY:							\
1472      comp = 1;                                                         \
1473      break;                                                            \
1474   case GL_LUMINANCE_ALPHA:						\
1475      comp = 2;                                                         \
1476      break;                                                            \
1477   case GL_RGB:								\
1478      comp = 3;                                                         \
1479      break;                                                            \
1480   case GL_RGBA:							\
1481      comp = 4;                                                         \
1482      break;                                                            \
1483   default:								\
1484      _mesa_problem(NULL, "Bad texture format in lin_persp_texture_triangle"); \
1485      return;                                                           \
1486   }                                                                    \
1487   sscale = FIXED_SCALE * twidth;                                       \
1488   tscale = FIXED_SCALE * theight;                                      \
1489   tbytesline = obj->Image[b]->Width * comp;                            \
1490   tsize = theight * tbytesline;
1491
1492
1493#define SPAN(DO_TEX,COMP)					\
1494        for (i=0;i<n;i++) {					\
1495           GLfloat invQ = 1.0f / vv;				\
1496           GLfixed span.intTex[0] = (int)(SS * invQ);		\
1497           GLfixed span.intTex[1] = (int)(TT * invQ);		\
1498	   GLint s = FixedToInt(span.intTex[0]) & smask;	\
1499	   GLint t = FixedToInt(span.intTex[1]) & tmask;	\
1500           GLint sf = span.intTex[0] & FIXED_FRAC_MASK;		\
1501           GLint tf = span.intTex[1] & FIXED_FRAC_MASK;		\
1502           GLint si = FIXED_FRAC_MASK - sf;			\
1503           GLint ti = FIXED_FRAC_MASK - tf;			\
1504           GLint pos = COMP * ((t << twidth_log2) + s);		\
1505           GLchan *tex00 = texture + pos;			\
1506           GLchan *tex10 = tex00 + tbytesline;			\
1507           GLchan *tex01 = tex00 + COMP;			\
1508           GLchan *tex11 = tex10 + COMP;			\
1509           if (t == tmask) {					\
1510              tex10 -= tsize;					\
1511              tex11 -= tsize;					\
1512           }							\
1513           if (s == smask) {					\
1514              tex01 -= tbytesline;				\
1515              tex11 -= tbytesline;				\
1516           }							\
1517	   zspan[i] = FixedToDepth(span.z);			\
1518	   fogspan[i] = span.fog;				\
1519           DO_TEX;						\
1520	   span.fog += span.fogStep;				\
1521	   span.z += span.zStep;				\
1522           span.red += span.redStep;				\
1523	   span.green += span.greenStep;			\
1524           span.blue += span.blueStep;				\
1525	   span.alpha += span.alphaStep;			\
1526           SS += dSdx;						\
1527           TT += dTdx;						\
1528	   vv += dvdx;						\
1529           dest += 4;						\
1530	}
1531
1532#define INNER_LOOP( LEFT, RIGHT, Y )			\
1533   {							\
1534      GLint i;						\
1535      const GLint n = RIGHT-LEFT;			\
1536      GLdepth zspan[MAX_WIDTH];				\
1537      GLfloat fogspan[MAX_WIDTH];			\
1538      GLchan rgba[MAX_WIDTH][4];			\
1539      (void) uu; /* please GCC */			\
1540      if (n > 0) {					\
1541         GLfloat SS = ss * sscale;			\
1542         GLfloat TT = tt * tscale;			\
1543         GLfloat dSdx = dsdx * sscale;			\
1544         GLfloat dTdx = dtdx * tscale;			\
1545         GLchan *dest = rgba[0];			\
1546         SS -= 0.5f * FIXED_SCALE * vv;			\
1547         TT -= 0.5f * FIXED_SCALE * vv;			\
1548         switch (format) {				\
1549         case GL_RGB:					\
1550            switch (envmode) {				\
1551            case GL_MODULATE:				\
1552               SPAN(LINEAR_RGB;MODULATE,3);		\
1553               break;					\
1554            case GL_DECAL:				\
1555            case GL_REPLACE:				\
1556               SPAN(LINEAR_RGB;REPLACE,3);		\
1557               break;					\
1558            case GL_BLEND:				\
1559               SPAN(LINEAR_RGB;BLEND,3);		\
1560               break;					\
1561            case GL_ADD:                                \
1562	       SPAN(LINEAR_RGB;ADD,3);                  \
1563	       break;                                   \
1564            default:					\
1565               abort();					\
1566            }						\
1567            break;					\
1568         case GL_RGBA:					\
1569            switch (envmode) {				\
1570            case GL_MODULATE:				\
1571               SPAN(LINEAR_RGBA;MODULATE,4);		\
1572               break;					\
1573            case GL_DECAL:				\
1574               SPAN(LINEAR_RGBA;DECAL,4);		\
1575               break;					\
1576            case GL_BLEND:				\
1577               SPAN(LINEAR_RGBA;BLEND,4);		\
1578               break;					\
1579            case GL_REPLACE:				\
1580               SPAN(LINEAR_RGBA;REPLACE,4);		\
1581               break;					\
1582            case GL_ADD:                                \
1583               SPAN(LINEAR_RGBA;ADD,4);                 \
1584               break;                                   \
1585            default: /* unexpected env mode */		\
1586               abort();					\
1587            }						\
1588         }						\
1589         _mesa_write_rgba_span( ctx, n, LEFT, Y, zspan,	\
1590                             fogspan,                   \
1591                             rgba, GL_POLYGON );	\
1592      }							\
1593   }
1594
1595#include "s_tritemp.h"
1596#undef SPAN
1597}
1598#endif
1599
1600
1601/*
1602 * Generate arrays of fragment colors, z, fog, texcoords, etc from a
1603 * triangle span object.  Then call the span/fragment processsing
1604 * functions in s_span.[ch].
1605 */
1606static void
1607rasterize_span(GLcontext *ctx, const struct triangle_span *span)
1608{
1609   GLchan rgba[MAX_WIDTH][4];
1610   GLchan spec[MAX_WIDTH][4];
1611   GLuint index[MAX_WIDTH];
1612   GLuint z[MAX_WIDTH];
1613   GLfloat fog[MAX_WIDTH];
1614   GLfloat sTex[MAX_WIDTH], tTex[MAX_WIDTH], rTex[MAX_WIDTH];
1615   GLfloat lambda[MAX_WIDTH];
1616   GLfloat msTex[MAX_TEXTURE_UNITS][MAX_WIDTH];
1617   GLfloat mtTex[MAX_TEXTURE_UNITS][MAX_WIDTH];
1618   GLfloat mrTex[MAX_TEXTURE_UNITS][MAX_WIDTH];
1619   GLfloat mLambda[MAX_TEXTURE_UNITS][MAX_WIDTH];
1620
1621   if (span->activeMask & SPAN_RGBA) {
1622      GLfixed r = span->red;
1623      GLfixed g = span->green;
1624      GLfixed b = span->blue;
1625      GLfixed a = span->alpha;
1626      GLuint i;
1627      for (i = 0; i < span->count; i++) {
1628         rgba[i][RCOMP] = FixedToInt(r);
1629         rgba[i][GCOMP] = FixedToInt(g);
1630         rgba[i][BCOMP] = FixedToInt(b);
1631         rgba[i][ACOMP] = FixedToInt(a);
1632         r += span->redStep;
1633         g += span->greenStep;
1634         b += span->blueStep;
1635         a += span->alphaStep;
1636      }
1637   }
1638   if (span->activeMask & SPAN_SPEC) {
1639      GLfixed r = span->specRed;
1640      GLfixed g = span->specGreen;
1641      GLfixed b = span->specBlue;
1642      GLuint i;
1643      for (i = 0; i < span->count; i++) {
1644         spec[i][RCOMP] = FixedToInt(r);
1645         spec[i][GCOMP] = FixedToInt(g);
1646         spec[i][BCOMP] = FixedToInt(b);
1647         r += span->specRedStep;
1648         g += span->specGreenStep;
1649         b += span->specBlueStep;
1650      }
1651   }
1652   if (span->activeMask & SPAN_INDEX) {
1653      GLuint i;
1654      GLfixed ind = span->index;
1655      for (i = 0; i < span->count; i++) {
1656         index[i] = FixedToInt(ind);
1657         ind += span->indexStep;
1658      }
1659   }
1660   if (span->activeMask & SPAN_Z) {
1661      if (ctx->Visual.depthBits <= 16) {
1662         GLuint i;
1663         GLfixed zval = span->z;
1664         for (i = 0; i < span->count; i++) {
1665            z[i] = FixedToInt(zval);
1666            zval += span->zStep;
1667         }
1668      }
1669      else {
1670         /* Deep Z buffer, no fixed->int shift */
1671         GLuint i;
1672         GLfixed zval = span->z;
1673         for (i = 0; i < span->count; i++) {
1674            z[i] = zval;
1675            zval += span->zStep;
1676         }
1677      }
1678   }
1679   if (span->activeMask & SPAN_FOG) {
1680      GLuint i;
1681      GLfloat f = span->fog;
1682      for (i = 0; i < span->count; i++) {
1683         fog[i] = f;
1684         f += span->fogStep;
1685      }
1686   }
1687   if (span->activeMask & SPAN_TEXTURE) {
1688      if (ctx->Texture._ReallyEnabled & ~TEXTURE0_ANY) {
1689         /* multitexture */
1690         if (span->activeMask & SPAN_LAMBDA) {
1691            /* with lambda */
1692            GLuint u;
1693            for (u = 0; u < MAX_TEXTURE_UNITS; u++) {
1694               if (ctx->Texture.Unit[u]._ReallyEnabled) {
1695                  GLfloat s = span->tex[u][0];
1696                  GLfloat t = span->tex[u][1];
1697                  GLfloat r = span->tex[u][2];
1698                  GLfloat q = span->tex[u][3];
1699                  GLuint i;
1700                  for (i = 0; i < span->count; i++) {
1701                     const GLfloat invQ = (q == 0.0F) ? 1.0 : (1.0F / q);
1702                     msTex[u][i] = s * invQ;
1703                     mtTex[u][i] = t * invQ;
1704                     mrTex[u][i] = r * invQ;
1705                     mLambda[u][i] = log(span->rho[u] * invQ * invQ) * 1.442695F * 0.5F;
1706                     s += span->texStep[u][0];
1707                     t += span->texStep[u][1];
1708                     r += span->texStep[u][2];
1709                     q += span->texStep[u][3];
1710                  }
1711               }
1712            }
1713         }
1714         else {
1715            /* without lambda */
1716            GLuint u;
1717            for (u = 0; u < MAX_TEXTURE_UNITS; u++) {
1718               if (ctx->Texture.Unit[u]._ReallyEnabled) {
1719                  GLfloat s = span->tex[u][0];
1720                  GLfloat t = span->tex[u][1];
1721                  GLfloat r = span->tex[u][2];
1722                  GLfloat q = span->tex[u][3];
1723                  GLuint i;
1724                  for (i = 0; i < span->count; i++) {
1725                     const GLfloat invQ = (q == 0.0F) ? 1.0 : (1.0F / q);
1726                     msTex[u][i] = s * invQ;
1727                     mtTex[u][i] = t * invQ;
1728                     mrTex[u][i] = r * invQ;
1729                     s += span->texStep[u][0];
1730                     t += span->texStep[u][1];
1731                     r += span->texStep[u][2];
1732                     q += span->texStep[u][3];
1733                  }
1734               }
1735            }
1736         }
1737      }
1738      else {
1739         /* just texture unit 0 */
1740         if (span->activeMask & SPAN_LAMBDA) {
1741            /* with lambda */
1742            GLfloat s = span->tex[0][0];
1743            GLfloat t = span->tex[0][1];
1744            GLfloat r = span->tex[0][2];
1745            GLfloat q = span->tex[0][3];
1746            GLuint i;
1747            for (i = 0; i < span->count; i++) {
1748               const GLfloat invQ = (q == 0.0F) ? 1.0 : (1.0F / q);
1749               sTex[i] = s * invQ;
1750               tTex[i] = t * invQ;
1751               rTex[i] = r * invQ;
1752               lambda[i] = log(span->rho[0] * invQ * invQ) * 1.442695F * 0.5F;
1753               s += span->texStep[0][0];
1754               t += span->texStep[0][1];
1755               r += span->texStep[0][2];
1756               q += span->texStep[0][3];
1757            }
1758         }
1759         else {
1760            /* without lambda */
1761            GLfloat s = span->tex[0][0];
1762            GLfloat t = span->tex[0][1];
1763            GLfloat r = span->tex[0][2];
1764            GLfloat q = span->tex[0][3];
1765            GLuint i;
1766            for (i = 0; i < span->count; i++) {
1767               const GLfloat invQ = (q == 0.0F) ? 1.0 : (1.0F / q);
1768               sTex[i] = s * invQ;
1769               tTex[i] = t * invQ;
1770               rTex[i] = r * invQ;
1771               s += span->texStep[0][0];
1772               t += span->texStep[0][1];
1773               r += span->texStep[0][2];
1774               q += span->texStep[0][3];
1775            }
1776         }
1777      }
1778   }
1779   /* XXX keep this? */
1780   if (span->activeMask & SPAN_INT_TEXTURE) {
1781      GLint intTexcoord[MAX_WIDTH][2];
1782      GLfixed s = span->intTex[0];
1783      GLfixed t = span->intTex[1];
1784      GLuint i;
1785      for (i = 0; i < span->count; i++) {
1786         intTexcoord[i][0] = FixedToInt(s);
1787         intTexcoord[i][1] = FixedToInt(t);
1788         s += span->intTexStep[0];
1789         t += span->intTexStep[1];
1790      }
1791   }
1792
1793   /* examine activeMask and call a s_span.c function */
1794   if (span->activeMask & SPAN_TEXTURE) {
1795      const GLfloat *fogPtr;
1796      if (span->activeMask & SPAN_FOG)
1797         fogPtr = fog;
1798      else
1799         fogPtr = NULL;
1800
1801      if (ctx->Texture._ReallyEnabled & ~TEXTURE0_ANY) {
1802         if (span->activeMask & SPAN_SPEC) {
1803            _mesa_write_multitexture_span(ctx, span->count, span->x, span->y,
1804                                          z, fogPtr,
1805                                          (const GLfloat (*)[MAX_WIDTH]) msTex,
1806                                          (const GLfloat (*)[MAX_WIDTH]) mtTex,
1807                                          (const GLfloat (*)[MAX_WIDTH]) mrTex,
1808                                          (GLfloat (*)[MAX_WIDTH]) mLambda,
1809                                          rgba, (CONST GLchan (*)[4]) spec,
1810                                          GL_POLYGON );
1811         }
1812         else {
1813            _mesa_write_multitexture_span(ctx, span->count, span->x, span->y,
1814                                          z, fogPtr,
1815                                          (const GLfloat (*)[MAX_WIDTH]) msTex,
1816                                          (const GLfloat (*)[MAX_WIDTH]) mtTex,
1817                                          (const GLfloat (*)[MAX_WIDTH]) mrTex,
1818                                          (GLfloat (*)[MAX_WIDTH]) mLambda,
1819                                          rgba, NULL, GL_POLYGON);
1820         }
1821      }
1822      else {
1823         /* single texture */
1824         if (span->activeMask & SPAN_SPEC) {
1825            _mesa_write_texture_span(ctx, span->count, span->x, span->y,
1826                                     z, fogPtr, sTex, tTex, rTex, lambda,
1827                                     rgba, (CONST GLchan (*)[4]) spec,
1828                                     GL_POLYGON);
1829         }
1830         else {
1831            _mesa_write_texture_span(ctx, span->count, span->x, span->y,
1832                                     z, fogPtr, sTex, tTex, rTex, lambda,
1833                                     rgba, NULL, GL_POLYGON);
1834         }
1835      }
1836   }
1837   else {
1838      _mesa_problem(ctx, "rasterize_span() should only be used for texturing");
1839   }
1840}
1841
1842
1843
1844
1845/*
1846 * Render a smooth-shaded, textured, RGBA triangle.
1847 * Interpolate S,T,R with perspective correction, w/out mipmapping.
1848 */
1849static void general_textured_triangle( GLcontext *ctx,
1850				       const SWvertex *v0,
1851				       const SWvertex *v1,
1852				       const SWvertex *v2 )
1853{
1854#define INTERP_Z 1
1855#define INTERP_FOG 1
1856#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1857#define INTERP_RGB 1
1858#define INTERP_ALPHA 1
1859#define INTERP_TEX 1
1860
1861#define SETUP_CODE							\
1862   const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;	\
1863   const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\
1864   const GLboolean flatShade = (ctx->Light.ShadeModel==GL_FLAT);	\
1865   GLfixed rFlat, gFlat, bFlat, aFlat;					\
1866   if (flatShade) {							\
1867      rFlat = IntToFixed(v2->color[RCOMP]);				\
1868      gFlat = IntToFixed(v2->color[GCOMP]);				\
1869      bFlat = IntToFixed(v2->color[BCOMP]);				\
1870      aFlat = IntToFixed(v2->color[ACOMP]);				\
1871   }									\
1872   span.texWidth[0] = (GLfloat) texImage->Width;			\
1873   span.texHeight[0] = (GLfloat) texImage->Height;			\
1874   (void) fixedToDepthShift;
1875
1876#define RENDER_SPAN( span )						\
1877   GLdepth zSpan[MAX_WIDTH];						\
1878   GLfloat fogSpan[MAX_WIDTH];						\
1879   GLchan rgbaSpan[MAX_WIDTH][4];					\
1880   GLfloat sSpan[MAX_WIDTH], tSpan[MAX_WIDTH], uSpan[MAX_WIDTH];	\
1881   GLuint i;								\
1882   if (flatShade) {							\
1883      span.red = rFlat;    span.redStep = 0;				\
1884      span.green = gFlat;  span.greenStep = 0;				\
1885      span.blue = bFlat;   span.blueStep = 0;				\
1886      span.alpha = aFlat;  span.alphaStep = 0;				\
1887   }									\
1888   /* NOTE: we could just call rasterize_span() here instead */		\
1889   for (i = 0; i < span.count; i++) {					\
1890      GLdouble invQ = span.tex[0][3] ? (1.0 / span.tex[0][3]) : 1.0;	\
1891      zSpan[i] = FixedToDepth(span.z);					\
1892      span.z += span.zStep;						\
1893      fogSpan[i] = span.fog;			          		\
1894      span.fog += span.fogStep;						\
1895      rgbaSpan[i][RCOMP] = FixedToInt(span.red);			\
1896      rgbaSpan[i][GCOMP] = FixedToInt(span.green);			\
1897      rgbaSpan[i][BCOMP] = FixedToInt(span.blue);			\
1898      rgbaSpan[i][ACOMP] = FixedToInt(span.alpha);			\
1899      span.red += span.redStep;						\
1900      span.green += span.greenStep;					\
1901      span.blue += span.blueStep;					\
1902      span.alpha += span.alphaStep;					\
1903      sSpan[i] = span.tex[0][0] * invQ;					\
1904      tSpan[i] = span.tex[0][1] * invQ;					\
1905      uSpan[i] = span.tex[0][2] * invQ;					\
1906      span.tex[0][0] += span.texStep[0][0];				\
1907      span.tex[0][1] += span.texStep[0][1];				\
1908      span.tex[0][2] += span.texStep[0][2];				\
1909      span.tex[0][3] += span.texStep[0][3];				\
1910   }									\
1911   _mesa_write_texture_span(ctx, span.count, span.x, span.y,		\
1912                            zSpan, fogSpan, sSpan, tSpan, uSpan,	\
1913                            NULL, rgbaSpan, NULL, GL_POLYGON );
1914
1915#include "s_tritemp.h"
1916}
1917
1918
1919/*
1920 * Render a smooth-shaded, textured, RGBA triangle with separate specular
1921 * color interpolation.
1922 * Interpolate texcoords with perspective correction, w/out mipmapping.
1923 */
1924static void general_textured_spec_triangle( GLcontext *ctx,
1925					    const SWvertex *v0,
1926					    const SWvertex *v1,
1927					    const SWvertex *v2 )
1928{
1929#define INTERP_Z 1
1930#define INTERP_FOG 1
1931#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1932#define INTERP_RGB 1
1933#define INTERP_SPEC 1
1934#define INTERP_ALPHA 1
1935#define INTERP_TEX 1
1936
1937#define SETUP_CODE							\
1938   const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;	\
1939   const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\
1940   const GLboolean flatShade = (ctx->Light.ShadeModel == GL_FLAT);	\
1941   GLfixed rFlat, gFlat, bFlat, aFlat;					\
1942   GLfixed srFlat, sgFlat, sbFlat;					\
1943   if (flatShade) {							\
1944      rFlat = IntToFixed(v2->color[RCOMP]);				\
1945      gFlat = IntToFixed(v2->color[GCOMP]);				\
1946      bFlat = IntToFixed(v2->color[BCOMP]);				\
1947      aFlat = IntToFixed(v2->color[ACOMP]);				\
1948      srFlat = IntToFixed(v2->specular[RCOMP]);				\
1949      sgFlat = IntToFixed(v2->specular[GCOMP]);				\
1950      sbFlat = IntToFixed(v2->specular[BCOMP]);				\
1951   }									\
1952   span.texWidth[0] = (GLfloat) texImage->Width;			\
1953   span.texHeight[0] = (GLfloat) texImage->Height;			\
1954   (void) fixedToDepthShift;
1955
1956#define RENDER_SPAN( span )					\
1957   if (flatShade) {						\
1958      span.red = rFlat;    span.redStep = 0;			\
1959      span.green = gFlat;  span.greenStep = 0;			\
1960      span.blue = bFlat;   span.blueStep = 0;			\
1961      span.alpha = aFlat;  span.alphaStep = 0;			\
1962      span.specRed = srFlat;    span.specRedStep = 0;		\
1963      span.specGreen = sgFlat;  span.specGreenStep = 0;		\
1964      span.specBlue = sbFlat;   span.specBlueStep = 0;		\
1965   }								\
1966   rasterize_span(ctx, &span);
1967
1968#include "s_tritemp.h"
1969}
1970
1971
1972/*
1973 * Render a smooth-shaded, textured, RGBA triangle.
1974 * Interpolate S,T,R with perspective correction and compute lambda for
1975 * each fragment.  Lambda is used to determine whether to use the
1976 * minification or magnification filter.  If minification and using
1977 * mipmaps, lambda is also used to select the texture level of detail.
1978 */
1979static void lambda_textured_triangle( GLcontext *ctx,
1980				      const SWvertex *v0,
1981				      const SWvertex *v1,
1982				      const SWvertex *v2 )
1983{
1984#define INTERP_Z 1
1985#define INTERP_FOG 1
1986#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1987#define INTERP_RGB 1
1988#define INTERP_ALPHA 1
1989#define INTERP_TEX 1
1990#define INTERP_LAMBDA 1
1991
1992#define SETUP_CODE							\
1993   const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;	\
1994   const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\
1995   const GLboolean flatShade = (ctx->Light.ShadeModel==GL_FLAT);	\
1996   GLfixed rFlat, gFlat, bFlat, aFlat;					\
1997   GLfixed srFlat, sgFlat, sbFlat;					\
1998   if (flatShade) {							\
1999      rFlat = IntToFixed(v2->color[RCOMP]);				\
2000      gFlat = IntToFixed(v2->color[GCOMP]);				\
2001      bFlat = IntToFixed(v2->color[BCOMP]);				\
2002      aFlat = IntToFixed(v2->color[ACOMP]);				\
2003      srFlat = IntToFixed(v2->specular[RCOMP]);				\
2004      sgFlat = IntToFixed(v2->specular[GCOMP]);				\
2005      sbFlat = IntToFixed(v2->specular[BCOMP]);				\
2006   }									\
2007   span.texWidth[0] = (GLfloat) texImage->Width;			\
2008   span.texHeight[0] = (GLfloat) texImage->Height;			\
2009   (void) fixedToDepthShift;
2010
2011#define RENDER_SPAN( span )					\
2012   if (flatShade) {						\
2013      span.red = rFlat;    span.redStep = 0;			\
2014      span.green = gFlat;  span.greenStep = 0;			\
2015      span.blue = bFlat;   span.blueStep = 0;			\
2016      span.alpha = aFlat;  span.alphaStep = 0;			\
2017      span.specRed = srFlat;    span.specRedStep = 0;		\
2018      span.specGreen = sgFlat;  span.specGreenStep = 0;		\
2019      span.specBlue = sbFlat;   span.specBlueStep = 0;		\
2020   }								\
2021   rasterize_span(ctx, &span);
2022
2023#include "s_tritemp.h"
2024}
2025
2026
2027/*
2028 * Render a smooth-shaded, textured, RGBA triangle with separate specular
2029 * interpolation.
2030 * Interpolate S,T,R with perspective correction and compute lambda for
2031 * each fragment.  Lambda is used to determine whether to use the
2032 * minification or magnification filter.  If minification and using
2033 * mipmaps, lambda is also used to select the texture level of detail.
2034 */
2035static void lambda_textured_spec_triangle( GLcontext *ctx,
2036					   const SWvertex *v0,
2037					   const SWvertex *v1,
2038					   const SWvertex *v2 )
2039{
2040#define INTERP_Z 1
2041#define INTERP_FOG 1
2042#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
2043#define INTERP_RGB 1
2044#define INTERP_SPEC 1
2045#define INTERP_ALPHA 1
2046#define INTERP_TEX 1
2047#define INTERP_LAMBDA 1
2048
2049#define SETUP_CODE							\
2050   const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;	\
2051   const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\
2052   const GLboolean flatShade = (ctx->Light.ShadeModel == GL_FLAT);	\
2053   GLfixed rFlat, gFlat, bFlat, aFlat;					\
2054   GLfixed srFlat, sgFlat, sbFlat;					\
2055   if (flatShade) {							\
2056      rFlat = IntToFixed(v2->color[RCOMP]);				\
2057      gFlat = IntToFixed(v2->color[GCOMP]);				\
2058      bFlat = IntToFixed(v2->color[BCOMP]);				\
2059      aFlat = IntToFixed(v2->color[ACOMP]);				\
2060      srFlat = IntToFixed(v2->specular[RCOMP]);				\
2061      sgFlat = IntToFixed(v2->specular[GCOMP]);				\
2062      sbFlat = IntToFixed(v2->specular[BCOMP]);				\
2063   }									\
2064   span.texWidth[0] = (GLfloat) texImage->Width;			\
2065   span.texHeight[0] = (GLfloat) texImage->Height;			\
2066   (void) fixedToDepthShift;
2067
2068#define RENDER_SPAN( span )					\
2069   if (flatShade) {						\
2070      span.red = rFlat;    span.redStep = 0;			\
2071      span.green = gFlat;  span.greenStep = 0;			\
2072      span.blue = bFlat;   span.blueStep = 0;			\
2073      span.alpha = aFlat;  span.alphaStep = 0;			\
2074      span.specRed = srFlat;    span.specRedStep = 0;		\
2075      span.specGreen = sgFlat;  span.specGreenStep = 0;		\
2076      span.specBlue = sbFlat;   span.specBlueStep = 0;		\
2077   }								\
2078   rasterize_span(ctx, &span);
2079
2080#include "s_tritemp.h"
2081}
2082
2083
2084/*
2085 * This is the big one!
2086 * Interpolate Z, RGB, Alpha, specular, fog, and N sets of texture coordinates
2087 * with lambda (LOD).
2088 * Yup, it's slow.
2089 */
2090static void
2091lambda_multitextured_triangle( GLcontext *ctx,
2092                               const SWvertex *v0,
2093                               const SWvertex *v1,
2094                               const SWvertex *v2 )
2095{
2096
2097#define INTERP_Z 1
2098#define INTERP_FOG 1
2099#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
2100#define INTERP_RGB 1
2101#define INTERP_ALPHA 1
2102#define INTERP_SPEC 1
2103#define INTERP_MULTITEX 1
2104#define INTERP_LAMBDA 1
2105
2106#define SETUP_CODE							\
2107   const GLboolean flatShade = (ctx->Light.ShadeModel == GL_FLAT);	\
2108   GLfixed rFlat, gFlat, bFlat, aFlat;					\
2109   GLfixed srFlat, sgFlat, sbFlat;					\
2110   GLuint u;								\
2111   if (flatShade) {							\
2112      rFlat = IntToFixed(v2->color[RCOMP]);				\
2113      gFlat = IntToFixed(v2->color[GCOMP]);				\
2114      bFlat = IntToFixed(v2->color[BCOMP]);				\
2115      aFlat = IntToFixed(v2->color[ACOMP]);				\
2116      srFlat = IntToFixed(v2->specular[RCOMP]);				\
2117      sgFlat = IntToFixed(v2->specular[GCOMP]);				\
2118      sbFlat = IntToFixed(v2->specular[BCOMP]);				\
2119   }									\
2120   for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {			\
2121      if (ctx->Texture.Unit[u]._ReallyEnabled) {			\
2122         const struct gl_texture_object *texObj;			\
2123         const struct gl_texture_image *texImage;			\
2124         texObj = ctx->Texture.Unit[u]._Current;			\
2125         texImage = texObj->Image[texObj->BaseLevel];			\
2126         span.texWidth[u] = (GLfloat) texImage->Width;			\
2127         span.texHeight[u] = (GLfloat) texImage->Height;		\
2128      }									\
2129   }									\
2130   (void) fixedToDepthShift;
2131
2132#define RENDER_SPAN( span )					\
2133   if (flatShade) {						\
2134      span.red = rFlat;    span.redStep = 0;			\
2135      span.green = gFlat;  span.greenStep = 0;			\
2136      span.blue = bFlat;   span.blueStep = 0;			\
2137      span.alpha = aFlat;  span.alphaStep = 0;			\
2138      span.specRed = srFlat;    span.specRedStep = 0;		\
2139      span.specGreen = sgFlat;  span.specGreenStep = 0;		\
2140      span.specBlue = sbFlat;   span.specBlueStep = 0;		\
2141   }								\
2142   rasterize_span(ctx, &span);
2143
2144#include "s_tritemp.h"
2145
2146}
2147
2148
2149static void occlusion_zless_triangle( GLcontext *ctx,
2150				      const SWvertex *v0,
2151				      const SWvertex *v1,
2152				      const SWvertex *v2 )
2153{
2154   if (ctx->OcclusionResult) {
2155      return;
2156   }
2157
2158#define DO_OCCLUSION_TEST
2159#define INTERP_Z 1
2160#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
2161
2162#define RENDER_SPAN( span )				\
2163   GLuint i;						\
2164   for (i = 0; i < span.count; i++) {			\
2165      GLdepth z = FixedToDepth(span.z);			\
2166      if (z < zRow[i]) {				\
2167         ctx->OcclusionResult = GL_TRUE;		\
2168         return;					\
2169      }							\
2170      span.z += span.zStep;				\
2171   }
2172
2173#include "s_tritemp.h"
2174}
2175
2176static void nodraw_triangle( GLcontext *ctx,
2177			     const SWvertex *v0,
2178			     const SWvertex *v1,
2179			     const SWvertex *v2 )
2180{
2181   (void) (ctx && v0 && v1 && v2);
2182}
2183
2184void _swrast_add_spec_terms_triangle( GLcontext *ctx,
2185				      const SWvertex *v0,
2186				      const SWvertex *v1,
2187				      const SWvertex *v2 )
2188{
2189   SWvertex *ncv0 = (SWvertex *)v0; /* drop const qualifier */
2190   SWvertex *ncv1 = (SWvertex *)v1;
2191   SWvertex *ncv2 = (SWvertex *)v2;
2192   GLchan c[3][4];
2193   COPY_CHAN4( c[0], ncv0->color );
2194   COPY_CHAN4( c[1], ncv1->color );
2195   COPY_CHAN4( c[2], ncv2->color );
2196   ACC_3V( ncv0->color, ncv0->specular );
2197   ACC_3V( ncv1->color, ncv1->specular );
2198   ACC_3V( ncv2->color, ncv2->specular );
2199   SWRAST_CONTEXT(ctx)->SpecTriangle( ctx, ncv0, ncv1, ncv2 );
2200   COPY_CHAN4( ncv0->color, c[0] );
2201   COPY_CHAN4( ncv1->color, c[1] );
2202   COPY_CHAN4( ncv2->color, c[2] );
2203}
2204
2205
2206
2207#ifdef DEBUG
2208
2209/* record the current triangle function name */
2210static const char *triFuncName = NULL;
2211
2212#define USE(triFunc)                   \
2213do {                                   \
2214    triFuncName = #triFunc;            \
2215    /*printf("%s\n", triFuncName);*/   \
2216    swrast->Triangle = triFunc;        \
2217} while (0)
2218
2219#else
2220
2221#define USE(triFunc)  swrast->Triangle = triFunc;
2222
2223#endif
2224
2225
2226
2227
2228/*
2229 * Determine which triangle rendering function to use given the current
2230 * rendering context.
2231 *
2232 * Please update the summary flag _SWRAST_NEW_TRIANGLE if you add or
2233 * remove tests to this code.
2234 */
2235void
2236_swrast_choose_triangle( GLcontext *ctx )
2237{
2238   SWcontext *swrast = SWRAST_CONTEXT(ctx);
2239   const GLboolean rgbmode = ctx->Visual.rgbMode;
2240
2241   if (ctx->Polygon.CullFlag &&
2242       ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) {
2243      USE(nodraw_triangle);
2244      return;
2245   }
2246
2247   if (ctx->RenderMode==GL_RENDER) {
2248
2249      if (ctx->Polygon.SmoothFlag) {
2250         _mesa_set_aa_triangle_function(ctx);
2251         ASSERT(swrast->Triangle);
2252         return;
2253      }
2254
2255      if (ctx->Depth.OcclusionTest &&
2256          ctx->Depth.Test &&
2257          ctx->Depth.Mask == GL_FALSE &&
2258          ctx->Depth.Func == GL_LESS &&
2259          !ctx->Stencil.Enabled) {
2260         if ((rgbmode &&
2261              ctx->Color.ColorMask[0] == 0 &&
2262              ctx->Color.ColorMask[1] == 0 &&
2263              ctx->Color.ColorMask[2] == 0 &&
2264              ctx->Color.ColorMask[3] == 0)
2265             ||
2266             (!rgbmode && ctx->Color.IndexMask == 0)) {
2267            USE(occlusion_zless_triangle);
2268            return;
2269         }
2270      }
2271
2272      if (ctx->Texture._ReallyEnabled) {
2273         /* Ugh, we do a _lot_ of tests to pick the best textured tri func */
2274	 const struct gl_texture_object *texObj2D;
2275         const struct gl_texture_image *texImg;
2276         GLenum minFilter, magFilter, envMode;
2277         GLint format;
2278         texObj2D = ctx->Texture.Unit[0].Current2D;
2279         texImg = texObj2D ? texObj2D->Image[texObj2D->BaseLevel] : NULL;
2280         format = texImg ? texImg->TexFormat->MesaFormat : -1;
2281         minFilter = texObj2D ? texObj2D->MinFilter : (GLenum) 0;
2282         magFilter = texObj2D ? texObj2D->MagFilter : (GLenum) 0;
2283         envMode = ctx->Texture.Unit[0].EnvMode;
2284
2285         /* First see if we can used an optimized 2-D texture function */
2286         if (ctx->Texture._ReallyEnabled==TEXTURE0_2D
2287             && texObj2D->WrapS==GL_REPEAT
2288	     && texObj2D->WrapT==GL_REPEAT
2289             && texImg->Border==0
2290             && (format == MESA_FORMAT_RGB || format == MESA_FORMAT_RGBA)
2291	     && minFilter == magFilter
2292	     && ctx->Light.Model.ColorControl == GL_SINGLE_COLOR
2293	     && ctx->Texture.Unit[0].EnvMode != GL_COMBINE_EXT) {
2294	    if (ctx->Hint.PerspectiveCorrection==GL_FASTEST) {
2295	       if (minFilter == GL_NEAREST
2296		   && format == MESA_FORMAT_RGB
2297		   && (envMode == GL_REPLACE || envMode == GL_DECAL)
2298		   && ((swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)
2299			&& ctx->Depth.Func == GL_LESS
2300			&& ctx->Depth.Mask == GL_TRUE)
2301		       || swrast->_RasterMask == TEXTURE_BIT)
2302		   && ctx->Polygon.StippleFlag == GL_FALSE) {
2303		  if (swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)) {
2304		     USE(simple_z_textured_triangle);
2305		  }
2306		  else {
2307		     USE(simple_textured_triangle);
2308		  }
2309	       }
2310	       else {
2311                  if (ctx->Texture.Unit[0].EnvMode==GL_ADD) {
2312                     USE(general_textured_triangle);
2313                  }
2314                  else {
2315                     USE(affine_textured_triangle);
2316                  }
2317	       }
2318	    }
2319	    else {
2320#if 00 /* XXX these function have problems with texture coord interpolation */
2321	       if (filter==GL_NEAREST) {
2322                  USE(near_persp_textured_triangle);
2323	       }
2324	       else {
2325                  USE(lin_persp_textured_triangle);
2326	       }
2327#endif
2328               USE(general_textured_triangle);
2329	    }
2330	 }
2331         else {
2332            /* More complicated textures (mipmap, multi-tex, sep specular) */
2333            GLboolean needLambda;
2334            /* if mag filter != min filter we need to compute lambda */
2335            const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;
2336            if (obj && obj->MinFilter != obj->MagFilter)
2337               needLambda = GL_TRUE;
2338            else
2339               needLambda = GL_FALSE;
2340            if (swrast->_MultiTextureEnabled) {
2341               USE(lambda_multitextured_triangle);
2342            }
2343            else if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
2344               /* separate specular color interpolation */
2345               if (needLambda) {
2346                  USE(lambda_textured_spec_triangle);
2347	       }
2348               else {
2349                  USE(general_textured_spec_triangle);
2350	       }
2351            }
2352            else {
2353               if (needLambda) {
2354		  USE(lambda_textured_triangle);
2355	       }
2356               else {
2357                  USE(general_textured_triangle);
2358	       }
2359            }
2360         }
2361      }
2362      else {
2363         ASSERT(!ctx->Texture._ReallyEnabled);
2364	 if (ctx->Light.ShadeModel==GL_SMOOTH) {
2365	    /* smooth shaded, no texturing, stippled or some raster ops */
2366            if (rgbmode) {
2367	       USE(smooth_rgba_triangle);
2368            }
2369            else {
2370               USE(smooth_ci_triangle);
2371            }
2372	 }
2373	 else {
2374	    /* flat shaded, no texturing, stippled or some raster ops */
2375            if (rgbmode) {
2376	       USE(flat_rgba_triangle);
2377            }
2378            else {
2379               USE(flat_ci_triangle);
2380            }
2381	 }
2382      }
2383   }
2384   else if (ctx->RenderMode==GL_FEEDBACK) {
2385      USE(_mesa_feedback_triangle);
2386   }
2387   else {
2388      /* GL_SELECT mode */
2389      USE(_mesa_select_triangle);
2390   }
2391}
2392