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