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