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