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