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