xref: /reactos/dll/opengl/mesa/triangle.c (revision 1734f297)
1 /* $Id: triangle.c,v 1.31 1998/02/03 23:46:00 brianp Exp $ */
2 
3 /*
4  * Mesa 3-D graphics library
5  * Version:  2.4
6  * Copyright (C) 1995-1997  Brian Paul
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the Free
20  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22 
23 
24 /*
25  * $Log: triangle.c,v $
26  * Revision 1.31  1998/02/03 23:46:00  brianp
27  * fixed a few problems with condition expressions for Amiga StormC compiler
28  *
29  * Revision 1.30  1997/08/27 01:20:05  brianp
30  * moved texture completeness test out one level (Karl Anders Oygard)
31  *
32  * Revision 1.29  1997/07/24 01:26:05  brianp
33  * changed precompiled header symbol from PCH to PC_HEADER
34  *
35  * Revision 1.28  1997/07/21 22:18:10  brianp
36  * fixed bug in compute_lambda() thanks to Magnus Lundin
37  *
38  * Revision 1.27  1997/06/23 00:40:03  brianp
39  * added a DEFARRAY/UNDEFARRAY for the Mac
40  *
41  * Revision 1.26  1997/06/20 02:51:38  brianp
42  * changed color components from GLfixed to GLubyte
43  *
44  * Revision 1.25  1997/06/03 01:38:22  brianp
45  * fixed divide by zero problem in feedback function (William Mitchell)
46  *
47  * Revision 1.24  1997/05/28 03:26:49  brianp
48  * added precompiled header (PCH) support
49  *
50  * Revision 1.23  1997/05/17 03:40:55  brianp
51  * refined textured triangle selection code (Mats Lofkvist)
52  *
53  * Revision 1.22  1997/05/03 00:51:02  brianp
54  * removed calls to gl_texturing_enabled()
55  *
56  * Revision 1.21  1997/04/14 21:38:15  brianp
57  * fixed a typo (dtdx instead of dudx) in lambda_textured_triangle()
58  *
59  * Revision 1.20  1997/04/14 02:00:39  brianp
60  * #include "texstate.h" instead of "texture.h"
61  *
62  * Revision 1.19  1997/04/12 12:27:16  brianp
63  * replaced ctx->TriangleFunc with ctx->Driver.TriangleFunc
64  *
65  * Revision 1.18  1997/04/02 03:12:06  brianp
66  * replaced ctx->IdentityTexMat with ctx->TextureMatrixType
67  *
68  * Revision 1.17  1997/03/13 03:05:31  brianp
69  * removed unused shift variable in feedback_triangle()
70  *
71  * Revision 1.16  1997/03/08 02:04:27  brianp
72  * better implementation of feedback function
73  *
74  * Revision 1.15  1997/03/04 18:54:13  brianp
75  * renamed mipmap_textured_triangle() to lambda_textured_triangle()
76  * better comments about lambda and mipmapping
77  *
78  * Revision 1.14  1997/02/20 23:47:35  brianp
79  * triangle feedback colors were wrong when using smooth shading
80  *
81  * Revision 1.13  1997/02/19 10:24:26  brianp
82  * use a GLdouble instead of a GLfloat for wwvvInv (perspective correction)
83  *
84  * Revision 1.12  1997/02/09 19:53:43  brianp
85  * now use TEXTURE_xD enable constants
86  *
87  * Revision 1.11  1997/02/09 18:51:02  brianp
88  * added GL_EXT_texture3D support
89  *
90  * Revision 1.10  1997/01/16 03:36:43  brianp
91  * added #include "texture.h"
92  *
93  * Revision 1.9  1997/01/09 19:50:49  brianp
94  * now call gl_texturing_enabled()
95  *
96  * Revision 1.8  1996/12/20 20:23:30  brianp
97  * the test for using general_textured_triangle() was wrong
98  *
99  * Revision 1.7  1996/12/12 22:37:30  brianp
100  * projective textures didn't work right
101  *
102  * Revision 1.6  1996/11/08 02:21:21  brianp
103  * added null drawing function for GL_NO_RASTER
104  *
105  * Revision 1.4  1996/09/27 01:30:37  brianp
106  * removed unneeded INTERP_ALPHA from flat_rgba_triangle()
107  *
108  * Revision 1.3  1996/09/15 14:19:16  brianp
109  * now use GLframebuffer and GLvisual
110  *
111  * Revision 1.2  1996/09/15 01:48:58  brianp
112  * removed #define NULL 0
113  *
114  * Revision 1.1  1996/09/13 01:38:16  brianp
115  * Initial revision
116  *
117  */
118 
119 
120 /*
121  * Triangle rasterizers
122  */
123 
124 
125 #ifdef PC_HEADER
126 #include "all.h"
127 #else
128 #include <assert.h>
129 #include <math.h>
130 #include <stdio.h>
131 #include "depth.h"
132 #include "feedback.h"
133 #include "macros.h"
134 #include "span.h"
135 #include "texstate.h"
136 #include "triangle.h"
137 #include "types.h"
138 #include "vb.h"
139 #endif
140 
141 
142 /*
143  * Put triangle in feedback buffer.
144  */
145 static void feedback_triangle( GLcontext *ctx,
146                                GLuint v0, GLuint v1, GLuint v2, GLuint pv )
147 {
148    struct vertex_buffer *VB = ctx->VB;
149    GLfloat color[4];
150    GLuint i;
151    GLfloat invRedScale   = ctx->Visual->InvRedScale;
152    GLfloat invGreenScale = ctx->Visual->InvGreenScale;
153    GLfloat invBlueScale  = ctx->Visual->InvBlueScale;
154    GLfloat invAlphaScale = ctx->Visual->InvAlphaScale;
155 
156    FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_POLYGON_TOKEN );
157    FEEDBACK_TOKEN( ctx, (GLfloat) 3 );        /* three vertices */
158 
159    if (ctx->Light.ShadeModel==GL_FLAT) {
160       /* flat shading - same color for each vertex */
161       color[0] = (GLfloat) VB->Color[pv][0] * invRedScale;
162       color[1] = (GLfloat) VB->Color[pv][1] * invGreenScale;
163       color[2] = (GLfloat) VB->Color[pv][2] * invBlueScale;
164       color[3] = (GLfloat) VB->Color[pv][3] * invAlphaScale;
165    }
166 
167    for (i=0;i<3;i++) {
168       GLfloat x, y, z, w;
169       GLfloat tc[4];
170       GLuint v;
171       GLfloat invq;
172 
173       if (i==0)       v = v0;
174       else if (i==1)  v = v1;
175       else            v = v2;
176 
177       x = VB->Win[v][0];
178       y = VB->Win[v][1];
179       z = VB->Win[v][2] / DEPTH_SCALE;
180       w = VB->Clip[v][3];
181 
182       if (ctx->Light.ShadeModel==GL_SMOOTH) {
183          /* smooth shading - different color for each vertex */
184          color[0] = VB->Color[v][0] * invRedScale;
185          color[1] = VB->Color[v][1] * invGreenScale;
186          color[2] = VB->Color[v][2] * invBlueScale;
187          color[3] = VB->Color[v][3] * invAlphaScale;
188       }
189 
190       invq = (VB->TexCoord[v][3]==0.0) ? 1.0 : (1.0F / VB->TexCoord[v][3]);
191       tc[0] = VB->TexCoord[v][0] * invq;
192       tc[1] = VB->TexCoord[v][1] * invq;
193       tc[2] = VB->TexCoord[v][2] * invq;
194       tc[3] = VB->TexCoord[v][3];
195 
196       gl_feedback_vertex( ctx, x, y, z, w, color, (GLfloat) VB->Index[v], tc );
197    }
198 }
199 
200 
201 
202 /*
203  * Put triangle in selection buffer.
204  */
205 static void select_triangle( GLcontext *ctx,
206                              GLuint v0, GLuint v1, GLuint v2, GLuint pv )
207 {
208    struct vertex_buffer *VB = ctx->VB;
209 
210    gl_update_hitflag( ctx, VB->Win[v0][2] / DEPTH_SCALE );
211    gl_update_hitflag( ctx, VB->Win[v1][2] / DEPTH_SCALE );
212    gl_update_hitflag( ctx, VB->Win[v2][2] / DEPTH_SCALE );
213 }
214 
215 
216 
217 /*
218  * Render a flat-shaded color index triangle.
219  */
220 static void flat_ci_triangle( GLcontext *ctx,
221                               GLuint v0, GLuint v1, GLuint v2, GLuint pv )
222 {
223 #define INTERP_Z 1
224 
225 #define SETUP_CODE				\
226    GLuint index = VB->Index[pv];		\
227    if (!VB->MonoColor) {			\
228       /* set the color index */			\
229       (*ctx->Driver.Index)( ctx, index );	\
230    }
231 
232 #define INNER_LOOP( LEFT, RIGHT, Y )				\
233 	{							\
234 	   GLint i, n = RIGHT-LEFT;				\
235 	   GLdepth zspan[MAX_WIDTH];				\
236 	   if (n>0) {						\
237 	      for (i=0;i<n;i++) {				\
238 		 zspan[i] = ffz;			    \
239 		 ffz += fdzdx;					\
240 	      }							\
241 	      gl_write_monoindex_span( ctx, n, LEFT, Y,		\
242 	                            zspan, index, GL_POLYGON );	\
243 	   }							\
244 	}
245 
246 #include "tritemp.h"
247 }
248 
249 
250 
251 /*
252  * Render a smooth-shaded color index triangle.
253  */
254 static void smooth_ci_triangle( GLcontext *ctx,
255                                 GLuint v0, GLuint v1, GLuint v2, GLuint pv )
256 {
257 #define INTERP_Z 1
258 #define INTERP_INDEX 1
259 
260 #define INNER_LOOP( LEFT, RIGHT, Y )				\
261 	{							\
262 	   GLint i, n = RIGHT-LEFT;				\
263 	   GLdepth zspan[MAX_WIDTH];				\
264            GLuint index[MAX_WIDTH];				\
265 	   if (n>0) {						\
266 	      for (i=0;i<n;i++) {				\
267 		 zspan[i] = ffz;                    \
268                  index[i] = FixedToInt(ffi);			\
269 		 ffz += fdzdx;					\
270 		 ffi += fdidx;					\
271 	      }							\
272 	      gl_write_index_span( ctx, n, LEFT, Y, zspan,	\
273 	                           index, GL_POLYGON );		\
274 	   }							\
275 	}
276 
277 #include "tritemp.h"
278 }
279 
280 
281 
282 /*
283  * Render a flat-shaded RGBA triangle.
284  */
285 static void flat_rgba_triangle( GLcontext *ctx,
286                                 GLuint v0, GLuint v1, GLuint v2, GLuint pv )
287 {
288 #define INTERP_Z 1
289 
290 #define SETUP_CODE				\
291    if (!VB->MonoColor) {			\
292       /* set the color */			\
293       GLubyte r = VB->Color[pv][0];		\
294       GLubyte g = VB->Color[pv][1];		\
295       GLubyte b = VB->Color[pv][2];		\
296       GLubyte a = VB->Color[pv][3];		\
297       (*ctx->Driver.Color)( ctx, r, g, b, a );	\
298    }
299 
300 #define INNER_LOOP( LEFT, RIGHT, Y )				\
301 	{							\
302 	   GLint i, n = RIGHT-LEFT;				\
303 	   GLdepth zspan[MAX_WIDTH];				\
304 	   if (n>0) {						\
305 	      for (i=0;i<n;i++) {				\
306 		 zspan[i] = ffz;                \
307 		 ffz += fdzdx;					\
308 	      }							\
309               gl_write_monocolor_span( ctx, n, LEFT, Y, zspan,	\
310                              VB->Color[pv][0], VB->Color[pv][1],\
311                              VB->Color[pv][2], VB->Color[pv][3],\
312 			     GL_POLYGON );			\
313 	   }							\
314 	}
315 
316 #include "tritemp.h"
317 }
318 
319 
320 
321 /*
322  * Render a smooth-shaded RGBA triangle.
323  */
324 static void smooth_rgba_triangle( GLcontext *ctx,
325                                   GLuint v0, GLuint v1, GLuint v2, GLuint pv )
326 {
327 #define INTERP_Z 1
328 #define INTERP_RGB 1
329 #define INTERP_ALPHA 1
330 
331 #define INNER_LOOP( LEFT, RIGHT, Y )				\
332 	{							\
333 	   GLint i, n = RIGHT-LEFT;				\
334 	   GLdepth zspan[MAX_WIDTH];				\
335 	   GLubyte red[MAX_WIDTH], green[MAX_WIDTH];		\
336 	   GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];		\
337 	   if (n>0) {						\
338 	      for (i=0;i<n;i++) {				\
339 		 zspan[i] = ffz;			            \
340 		 red[i]   = FixedToInt(ffr);			\
341 		 green[i] = FixedToInt(ffg);			\
342 		 blue[i]  = FixedToInt(ffb);			\
343 		 alpha[i] = FixedToInt(ffa);			\
344 		 ffz += fdzdx;					\
345 		 ffr += fdrdx;					\
346 		 ffg += fdgdx;					\
347 		 ffb += fdbdx;					\
348 		 ffa += fdadx;					\
349 	      }							\
350 	      gl_write_color_span( ctx, n, LEFT, Y, zspan,	\
351 	                           red, green, blue, alpha,	\
352 				   GL_POLYGON );		\
353 	   }							\
354 	}
355 
356 #include "tritemp.h"
357 }
358 
359 
360 
361 /*
362  * Render an RGB, GL_DECAL, textured triangle.
363  * Interpolate S,T only w/out mipmapping or perspective correction.
364  */
365 static void simple_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
366                                       GLuint v2, GLuint pv )
367 {
368 #define INTERP_ST 1
369 #define S_SCALE twidth
370 #define T_SCALE theight
371 #define SETUP_CODE							\
372    GLfloat twidth = (GLfloat) ctx->Texture.Current2D->Image[0]->Width;	\
373    GLfloat theight = (GLfloat) ctx->Texture.Current2D->Image[0]->Height;\
374    GLint twidth_log2 = ctx->Texture.Current2D->Image[0]->WidthLog2;	\
375    GLubyte *texture = ctx->Texture.Current2D->Image[0]->Data;		\
376    GLint smask = ctx->Texture.Current2D->Image[0]->Width - 1;		\
377    GLint tmask = ctx->Texture.Current2D->Image[0]->Height - 1;
378 
379 #define INNER_LOOP( LEFT, RIGHT, Y )				\
380 	{							\
381 	   GLint i, n = RIGHT-LEFT;				\
382 	   GLubyte red[MAX_WIDTH], green[MAX_WIDTH];		\
383 	   GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];		\
384 	   if (n>0) {						\
385 	      for (i=0;i<n;i++) {				\
386                  GLint s = FixedToInt(ffs) & smask;		\
387                  GLint t = FixedToInt(fft) & tmask;		\
388                  GLint pos = (t << twidth_log2) + s;		\
389                  pos = pos + pos  + pos;  /* multiply by 3 */	\
390                  red[i]   = texture[pos];			\
391                  green[i] = texture[pos+1];			\
392                  blue[i]  = texture[pos+2];			\
393                  alpha[i] = 255;				\
394 		 ffs += fdsdx;					\
395 		 fft += fdtdx;					\
396 	      }							\
397               (*ctx->Driver.WriteColorSpan)( ctx, n, LEFT, Y,	\
398                              red, green, blue, alpha, NULL );	\
399 	   }							\
400 	}
401 
402 #include "tritemp.h"
403 }
404 
405 
406 
407 /*
408  * Render an RGB, GL_DECAL, textured triangle.
409  * Interpolate S,T, GL_LESS depth test, w/out mipmapping or
410  * perspective correction.
411  */
412 static void simple_z_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
413                                       GLuint v2, GLuint pv )
414 {
415 #define INTERP_Z 1
416 #define INTERP_ST 1
417 #define S_SCALE twidth
418 #define T_SCALE theight
419 #define SETUP_CODE							\
420    GLfloat twidth = (GLfloat) ctx->Texture.Current2D->Image[0]->Width;	\
421    GLfloat theight = (GLfloat) ctx->Texture.Current2D->Image[0]->Height;\
422    GLint twidth_log2 = ctx->Texture.Current2D->Image[0]->WidthLog2;	\
423    GLubyte *texture = ctx->Texture.Current2D->Image[0]->Data;		\
424    GLint smask = ctx->Texture.Current2D->Image[0]->Width - 1;		\
425    GLint tmask = ctx->Texture.Current2D->Image[0]->Height - 1;
426 
427 #define INNER_LOOP( LEFT, RIGHT, Y )				\
428 	{							\
429 	   GLint i, n = RIGHT-LEFT;				\
430 	   GLubyte red[MAX_WIDTH], green[MAX_WIDTH];		\
431 	   GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];		\
432            GLubyte mask[MAX_WIDTH];				\
433 	   if (n>0) {						\
434 	      for (i=0;i<n;i++) {				\
435                  GLdepth z = ffz;           \
436                  if (z < zRow[i]) {				\
437                     GLint s = FixedToInt(ffs) & smask;		\
438                     GLint t = FixedToInt(fft) & tmask;		\
439                     GLint pos = (t << twidth_log2) + s;		\
440                     pos = pos + pos  + pos;  /* multiply by 3 */\
441                     red[i]   = texture[pos];			\
442                     green[i] = texture[pos+1];			\
443                     blue[i]  = texture[pos+2];			\
444                     alpha[i] = 255;				\
445                     zRow[i] = z;				\
446                     mask[i] = 1;				\
447                  }						\
448                  else {						\
449                     mask[i] = 0;				\
450                  }						\
451 		 ffz += fdzdx;					\
452 		 ffs += fdsdx;					\
453 		 fft += fdtdx;					\
454 	      }							\
455               (*ctx->Driver.WriteColorSpan)( ctx, n, LEFT, Y,	\
456                              red, green, blue, alpha, mask );	\
457 	   }							\
458 	}
459 
460 #include "tritemp.h"
461 }
462 
463 
464 
465 /*
466  * Render a smooth-shaded, textured, RGBA triangle.
467  * Interpolate S,T,U with perspective correction, w/out mipmapping.
468  * Note: we use texture coordinates S,T,U,V instead of S,T,R,Q because
469  * R is already used for red.
470  */
471 static void general_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
472                                        GLuint v2, GLuint pv )
473 {
474 #define INTERP_Z 1
475 #define INTERP_RGB 1
476 #define INTERP_ALPHA 1
477 #define INTERP_STW 1
478 #define INTERP_UV 1
479 #define SETUP_CODE						\
480    GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT);	\
481    GLint r, g, b, a;						\
482    if (flat_shade) {						\
483       r = VB->Color[pv][0];					\
484       g = VB->Color[pv][1];					\
485       b = VB->Color[pv][2];					\
486       a = VB->Color[pv][3];					\
487    }
488 #define INNER_LOOP( LEFT, RIGHT, Y )				\
489 	{							\
490 	   GLint i, n = RIGHT-LEFT;				\
491 	   GLdepth zspan[MAX_WIDTH];				\
492 	   GLubyte red[MAX_WIDTH], green[MAX_WIDTH];		\
493 	   GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];		\
494            GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH];	\
495 	   if (n>0) {						\
496               if (flat_shade) {					\
497                  for (i=0;i<n;i++) {				\
498 		    GLdouble wwvvInv = 1.0 / (ww*vv);		\
499 		    zspan[i] = ffz;		        \
500 		    red[i]   = r;				\
501 		    green[i] = g;				\
502 		    blue[i]  = b;				\
503 		    alpha[i] = a;				\
504 		    s[i] = ss*wwvvInv;				\
505 		    t[i] = tt*wwvvInv;				\
506 		    u[i] = uu*wwvvInv;				\
507 		    ffz += fdzdx;				\
508 		    ss += dsdx;					\
509 		    tt += dtdx;					\
510 		    uu += dudx;					\
511 		    vv += dvdx;					\
512 		    ww += dwdx;					\
513 		 }						\
514               }							\
515               else {						\
516                  for (i=0;i<n;i++) {				\
517 		    GLdouble wwvvInv = 1.0 / (ww*vv);		\
518 		    zspan[i] = ffz;	                    \
519 		    red[i]   = FixedToInt(ffr);			\
520 		    green[i] = FixedToInt(ffg);			\
521 		    blue[i]  = FixedToInt(ffb);			\
522 		    alpha[i] = FixedToInt(ffa);			\
523 		    s[i] = ss*wwvvInv;				\
524 		    t[i] = tt*wwvvInv;				\
525 		    u[i] = uu*wwvvInv;				\
526 		    ffz += fdzdx;				\
527 		    ffr += fdrdx;				\
528 		    ffg += fdgdx;				\
529 		    ffb += fdbdx;				\
530 		    ffa += fdadx;				\
531 		    ss += dsdx;					\
532 		    tt += dtdx;					\
533 		    uu += dudx;					\
534 		    ww += dwdx;					\
535 		    vv += dvdx;					\
536 		 }						\
537               }							\
538 	      gl_write_texture_span( ctx, n, LEFT, Y, zspan,	\
539                                      s, t, u, NULL, 		\
540 	                             red, green, blue, alpha,	\
541 				     GL_POLYGON );		\
542 	   }							\
543 	}
544 
545 #include "tritemp.h"
546 }
547 
548 
549 
550 /*
551  * Compute the lambda value (texture level value) for a fragment.
552  */
553 static GLfloat compute_lambda( GLfloat s, GLfloat t,
554                                GLfloat dsdx, GLfloat dsdy,
555                                GLfloat dtdx, GLfloat dtdy,
556                                GLfloat w, GLfloat dwdx, GLfloat dwdy,
557                                GLfloat width, GLfloat height )
558 {
559    /* TODO: this function can probably be optimized a bit */
560    GLfloat invw = 1.0 / w;
561    GLfloat dudx, dudy, dvdx, dvdy;
562    GLfloat r1, r2, rho2;
563 
564    dudx = (dsdx - s*dwdx) * invw * width;
565    dudy = (dsdy - s*dwdy) * invw * width;
566    dvdx = (dtdx - t*dwdx) * invw * height;
567    dvdy = (dtdy - t*dwdy) * invw * height;
568 
569    r1 = dudx * dudx + dudy * dudy;
570    r2 = dvdx * dvdx + dvdy * dvdy;
571 
572    /* rho2 = MAX2(r1,r2); */
573    rho2 = r1 + r2;
574    if (rho2 <= 0.0F) {
575       return 0.0F;
576    }
577    else {
578       /* return log base 2 of rho */
579       return log(rho2) * 1.442695 * 0.5;       /* 1.442695 = 1/log(2) */
580    }
581 }
582 
583 
584 
585 /*
586  * Render a smooth-shaded, textured, RGBA triangle.
587  * Interpolate S,T,U with perspective correction and compute lambda for
588  * each fragment.  Lambda is used to determine whether to use the
589  * minification or magnification filter.  If minification and using
590  * mipmaps, lambda is also used to select the texture level of detail.
591  */
592 static void lambda_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
593                                       GLuint v2, GLuint pv )
594 {
595 #define INTERP_Z 1
596 #define INTERP_RGB 1
597 #define INTERP_ALPHA 1
598 #define INTERP_STW 1
599 #define INTERP_UV 1
600 
601 #define SETUP_CODE							\
602    GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT);		\
603    GLint r, g, b, a;							\
604    GLfloat twidth, theight;						\
605    if (ctx->Texture.Enabled & TEXTURE_2D) {			\
606       twidth = (GLfloat) ctx->Texture.Current2D->Image[0]->Width;	\
607       theight = (GLfloat) ctx->Texture.Current2D->Image[0]->Height;	\
608    }									\
609    else {								\
610       twidth = (GLfloat) ctx->Texture.Current1D->Image[0]->Width;	\
611       theight = 1.0;							\
612    }									\
613    if (flat_shade) {							\
614       r = VB->Color[pv][0];						\
615       g = VB->Color[pv][1];						\
616       b = VB->Color[pv][2];						\
617       a = VB->Color[pv][3];						\
618    }
619 
620 #define INNER_LOOP( LEFT, RIGHT, Y )					\
621 	{								\
622 	   GLint i, n = RIGHT-LEFT;					\
623 	   GLdepth zspan[MAX_WIDTH];					\
624 	   GLubyte red[MAX_WIDTH], green[MAX_WIDTH];			\
625 	   GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];			\
626            GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH];		\
627 	   DEFARRAY(GLfloat,lambda,MAX_WIDTH);				\
628 	   if (n>0) {							\
629 	      if (flat_shade) {						\
630 		 for (i=0;i<n;i++) {					\
631 		    GLdouble wwvvInv = 1.0 / (ww*vv);			\
632 		    zspan[i] = ffz;			        \
633 		    red[i]   = r;					\
634 		    green[i] = g;					\
635 		    blue[i]  = b;					\
636 		    alpha[i] = a;					\
637 		    s[i] = ss*wwvvInv;					\
638 		    t[i] = tt*wwvvInv;					\
639 		    u[i] = uu*wwvvInv;					\
640 		    lambda[i] = compute_lambda( s[i], t[i],		\
641 						dsdx, dsdy,		\
642 						dtdx, dtdy, ww,		\
643 						dwdx, dwdy,		\
644 						twidth, theight );	\
645 		    ffz += fdzdx;					\
646 		    ss += dsdx;						\
647 		    tt += dtdx;						\
648 		    uu += dudx;						\
649 		    vv += dvdx;						\
650 		    ww += dwdx;						\
651 		 }							\
652               }								\
653               else {							\
654 		 for (i=0;i<n;i++) {					\
655 		    GLdouble wwvvInv = 1.0 / (ww*vv);			\
656 		    zspan[i] = ffz;			                \
657 		    red[i]   = FixedToInt(ffr);				\
658 		    green[i] = FixedToInt(ffg);				\
659 		    blue[i]  = FixedToInt(ffb);				\
660 		    alpha[i] = FixedToInt(ffa);				\
661 		    s[i] = ss*wwvvInv;					\
662 		    t[i] = tt*wwvvInv;					\
663 		    u[i] = uu*wwvvInv;					\
664 		    lambda[i] = compute_lambda( s[i], t[i],		\
665 						dsdx, dsdy,		\
666 						dtdx, dtdy, ww,		\
667 						dwdx, dwdy,		\
668 						twidth, theight );	\
669 		    ffz += fdzdx;					\
670 		    ffr += fdrdx;					\
671 		    ffg += fdgdx;					\
672 		    ffb += fdbdx;					\
673 		    ffa += fdadx;					\
674 		    ss += dsdx;						\
675 		    tt += dtdx;						\
676 		    uu += dudx;						\
677 		    vv += dvdx;						\
678 		    ww += dwdx;						\
679 		 }							\
680               }								\
681 	      gl_write_texture_span( ctx, n, LEFT, Y, zspan,		\
682                                      s, t, u, lambda,	 		\
683 	                             red, green, blue, alpha,		\
684 				     GL_POLYGON );			\
685 	   }								\
686 	   UNDEFARRAY(lambda);						\
687 	}
688 
689 #include "tritemp.h"
690 }
691 
692 
693 
694 /*
695  * Null rasterizer for measuring transformation speed.
696  */
697 static void null_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
698                            GLuint v2, GLuint pv )
699 {
700 }
701 
702 
703 
704 /*
705  * Determine which triangle rendering function to use given the current
706  * rendering context.
707  */
708 void gl_set_triangle_function( GLcontext *ctx )
709 {
710    GLboolean rgbmode = ctx->Visual->RGBAflag;
711 
712    if (ctx->RenderMode==GL_RENDER) {
713       if (ctx->NoRaster) {
714          ctx->Driver.TriangleFunc = null_triangle;
715          return;
716       }
717       if (ctx->Driver.TriangleFunc) {
718          /* Device driver will draw triangles. */
719       }
720       else if (ctx->Texture.Enabled
721                && ctx->Texture.Current
722                && ctx->Texture.Current->Complete) {
723          if (   (ctx->Texture.Enabled==TEXTURE_2D)
724              && ctx->Texture.Current2D->MinFilter==GL_NEAREST
725              && ctx->Texture.Current2D->MagFilter==GL_NEAREST
726              && ctx->Texture.Current2D->WrapS==GL_REPEAT
727              && ctx->Texture.Current2D->WrapT==GL_REPEAT
728              && ctx->Texture.Current2D->Image[0]->Format==GL_RGB
729              && ctx->Texture.Current2D->Image[0]->Border==0
730              && (ctx->Texture.EnvMode==GL_DECAL
731                  || ctx->Texture.EnvMode==GL_REPLACE)
732              && ctx->Hint.PerspectiveCorrection==GL_FASTEST
733              && ctx->TextureMatrixType==MATRIX_IDENTITY
734              && ((ctx->RasterMask==DEPTH_BIT
735                   && ctx->Depth.Func==GL_LESS
736                   && ctx->Depth.Mask==GL_TRUE)
737                  || ctx->RasterMask==0)
738              && ctx->Polygon.StippleFlag==GL_FALSE
739              && ctx->Visual->EightBitColor) {
740             if (ctx->RasterMask==DEPTH_BIT) {
741                ctx->Driver.TriangleFunc = simple_z_textured_triangle;
742             }
743             else {
744                ctx->Driver.TriangleFunc = simple_textured_triangle;
745             }
746          }
747          else {
748             GLboolean needLambda = GL_TRUE;
749             /* if mag filter == min filter we're not mipmapping */
750             if (ctx->Texture.Enabled & TEXTURE_2D) {
751                if (ctx->Texture.Current2D->MinFilter==
752                    ctx->Texture.Current2D->MagFilter) {
753                   needLambda = GL_FALSE;
754                }
755             }
756             else if (ctx->Texture.Enabled & TEXTURE_1D) {
757                if (ctx->Texture.Current1D->MinFilter==
758                    ctx->Texture.Current1D->MagFilter) {
759                   needLambda = GL_FALSE;
760                }
761             }
762             if (needLambda)
763                ctx->Driver.TriangleFunc = lambda_textured_triangle;
764             else
765                ctx->Driver.TriangleFunc = general_textured_triangle;
766          }
767       }
768       else {
769 	 if (ctx->Light.ShadeModel==GL_SMOOTH) {
770 	    /* smooth shaded, no texturing, stippled or some raster ops */
771             if (rgbmode)
772                ctx->Driver.TriangleFunc = smooth_rgba_triangle;
773             else
774                ctx->Driver.TriangleFunc = smooth_ci_triangle;
775 	 }
776 	 else {
777 	    /* flat shaded, no texturing, stippled or some raster ops */
778             if (rgbmode)
779                ctx->Driver.TriangleFunc = flat_rgba_triangle;
780             else
781                ctx->Driver.TriangleFunc = flat_ci_triangle;
782 	 }
783       }
784    }
785    else if (ctx->RenderMode==GL_FEEDBACK) {
786       ctx->Driver.TriangleFunc = feedback_triangle;
787    }
788    else {
789       /* GL_SELECT mode */
790       ctx->Driver.TriangleFunc = select_triangle;
791    }
792 }
793 
794