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