1 /* $Id: triangle.c,v 1.2 2000/10/27 15:21:40 mholst Exp $ */
2 
3 /*
4  * Mesa 3-D graphics library
5  * Version:  2.2
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  * Triangle rasterizers
25  */
26 
27 
28 #include <assert.h>
29 #include <math.h>
30 #include <stdio.h>
31 #include "depth.h"
32 #include "feedback.h"
33 #include "macros.h"
34 #include "span.h"
35 #include "texture.h"
36 #include "triangle.h"
37 #include "types.h"
38 #include "vb.h"
39 
40 
41 
42 /*
43  * Put triangle in feedback buffer.
44  */
feedback_triangle(GLcontext * ctx,GLuint v0,GLuint v1,GLuint v2,GLuint pv)45 static void feedback_triangle( GLcontext *ctx,
46                                GLuint v0, GLuint v1, GLuint v2, GLuint pv )
47 {
48    struct vertex_buffer *VB = ctx->VB;
49    GLfloat color[4];
50    GLuint i;
51    GLfloat invRedScale   = ctx->Visual->InvRedScale;
52    GLfloat invGreenScale = ctx->Visual->InvGreenScale;
53    GLfloat invBlueScale  = ctx->Visual->InvBlueScale;
54    GLfloat invAlphaScale = ctx->Visual->InvAlphaScale;
55 
56    FEEDBACK_TOKEN( ctx, (GLfloat) GL_POLYGON_TOKEN );
57    FEEDBACK_TOKEN( ctx, (GLfloat) 3 );        /* three vertices */
58 
59    if (ctx->Light.ShadeModel==GL_FLAT) {
60       /* flat shading - same color for each vertex */
61       color[0] = (GLfloat) VB->Color[pv][0] * invRedScale;
62       color[1] = (GLfloat) VB->Color[pv][1] * invGreenScale;
63       color[2] = (GLfloat) VB->Color[pv][2] * invBlueScale;
64       color[3] = (GLfloat) VB->Color[pv][3] * invAlphaScale;
65    }
66 
67    for (i=0;i<3;i++) {
68       GLfloat x, y, z, w;
69       GLfloat tc[4];
70       GLuint v;
71       GLfloat invq;
72 
73       if (i==0)       v = v0;
74       else if (i==1)  v = v1;
75       else            v = v2;
76 
77       x = VB->Win[v][0];
78       y = VB->Win[v][1];
79       z = VB->Win[v][2] / DEPTH_SCALE;
80       w = VB->Clip[v][3];
81 
82       if (ctx->Light.ShadeModel==GL_SMOOTH) {
83          /* smooth shading - different color for each vertex */
84          color[0] = FixedToFloat(VB->Color[v][0]) * invRedScale;
85          color[1] = FixedToFloat(VB->Color[v][1]) * invGreenScale;
86          color[2] = FixedToFloat(VB->Color[v][2]) * invBlueScale;
87          color[3] = FixedToFloat(VB->Color[v][3]) * invAlphaScale;
88       }
89 
90       invq = 1.0F / VB->TexCoord[v][3];
91       tc[0] = VB->TexCoord[v][0] * invq;
92       tc[1] = VB->TexCoord[v][1] * invq;
93       tc[2] = VB->TexCoord[v][2] * invq;
94       tc[3] = VB->TexCoord[v][3];
95 
96       gl_feedback_vertex( ctx, x, y, z, w, color, (GLfloat) VB->Index[v], tc );
97    }
98 }
99 
100 
101 
102 /*
103  * Put triangle in selection buffer.
104  */
select_triangle(GLcontext * ctx,GLuint v0,GLuint v1,GLuint v2,GLuint pv)105 static void select_triangle( GLcontext *ctx,
106                              GLuint v0, GLuint v1, GLuint v2, GLuint pv )
107 {
108    struct vertex_buffer *VB = ctx->VB;
109 
110    gl_update_hitflag( ctx, VB->Win[v0][2] / DEPTH_SCALE );
111    gl_update_hitflag( ctx, VB->Win[v1][2] / DEPTH_SCALE );
112    gl_update_hitflag( ctx, VB->Win[v2][2] / DEPTH_SCALE );
113 }
114 
115 
116 
117 /*
118  * Render a flat-shaded color index triangle.
119  */
flat_ci_triangle(GLcontext * ctx,GLuint v0,GLuint v1,GLuint v2,GLuint pv)120 static void flat_ci_triangle( GLcontext *ctx,
121                               GLuint v0, GLuint v1, GLuint v2, GLuint pv )
122 {
123 #define INTERP_Z 1
124 
125 #define SETUP_CODE				\
126    GLuint index = VB->Index[pv];		\
127    if (!VB->MonoColor) {			\
128       /* set the color index */			\
129       (*ctx->Driver.Index)( ctx, index );	\
130    }
131 
132 #define INNER_LOOP( LEFT, RIGHT, Y )				\
133 	{							\
134 	   GLint i, n = RIGHT-LEFT;				\
135 	   GLdepth zspan[MAX_WIDTH];				\
136 	   if (n>0) {						\
137 	      for (i=0;i<n;i++) {				\
138 		 zspan[i] = FixedToDepth(ffz);			\
139 		 ffz += fdzdx;					\
140 	      }							\
141 	      gl_write_monoindex_span( ctx, n, LEFT, Y,		\
142 	                            zspan, index, GL_POLYGON );	\
143 	   }							\
144 	}
145 
146 #include "tritemp.h"
147 }
148 
149 
150 
151 /*
152  * Render a smooth-shaded color index triangle.
153  */
smooth_ci_triangle(GLcontext * ctx,GLuint v0,GLuint v1,GLuint v2,GLuint pv)154 static void smooth_ci_triangle( GLcontext *ctx,
155                                 GLuint v0, GLuint v1, GLuint v2, GLuint pv )
156 {
157 #define INTERP_Z 1
158 #define INTERP_INDEX 1
159 
160 #define INNER_LOOP( LEFT, RIGHT, Y )				\
161 	{							\
162 	   GLint i, n = RIGHT-LEFT;				\
163 	   GLdepth zspan[MAX_WIDTH];				\
164            GLuint index[MAX_WIDTH];				\
165 	   if (n>0) {						\
166 	      for (i=0;i<n;i++) {				\
167 		 zspan[i] = FixedToDepth(ffz);			\
168                  index[i] = FixedToInt(ffi);			\
169 		 ffz += fdzdx;					\
170 		 ffi += fdidx;					\
171 	      }							\
172 	      gl_write_index_span( ctx, n, LEFT, Y, zspan,	\
173 	                           index, GL_POLYGON );		\
174 	   }							\
175 	}
176 
177 #include "tritemp.h"
178 }
179 
180 
181 
182 /*
183  * Render a flat-shaded RGBA triangle.
184  */
flat_rgba_triangle(GLcontext * ctx,GLuint v0,GLuint v1,GLuint v2,GLuint pv)185 static void flat_rgba_triangle( GLcontext *ctx,
186                                 GLuint v0, GLuint v1, GLuint v2, GLuint pv )
187 {
188 #define INTERP_Z 1
189 
190 #define SETUP_CODE				\
191    if (!VB->MonoColor) {			\
192       /* set the color */			\
193       GLubyte r = VB->Color[pv][0];		\
194       GLubyte g = VB->Color[pv][1];		\
195       GLubyte b = VB->Color[pv][2];		\
196       GLubyte a = VB->Color[pv][3];		\
197       (*ctx->Driver.Color)( ctx, r, g, b, a );	\
198    }
199 
200 #define INNER_LOOP( LEFT, RIGHT, Y )				\
201 	{							\
202 	   GLint i, n = RIGHT-LEFT;				\
203 	   GLdepth zspan[MAX_WIDTH];				\
204 	   if (n>0) {						\
205 	      for (i=0;i<n;i++) {				\
206 		 zspan[i] = FixedToDepth(ffz);			\
207 		 ffz += fdzdx;					\
208 	      }							\
209               gl_write_monocolor_span( ctx, n, LEFT, Y, zspan,	\
210                              VB->Color[pv][0], VB->Color[pv][1],\
211                              VB->Color[pv][2], VB->Color[pv][3],\
212 			     GL_POLYGON );			\
213 	   }							\
214 	}
215 
216 #include "tritemp.h"
217 }
218 
219 
220 
221 /*
222  * Render a smooth-shaded RGBA triangle.
223  */
smooth_rgba_triangle(GLcontext * ctx,GLuint v0,GLuint v1,GLuint v2,GLuint pv)224 static void smooth_rgba_triangle( GLcontext *ctx,
225                                   GLuint v0, GLuint v1, GLuint v2, GLuint pv )
226 {
227 #define INTERP_Z 1
228 #define INTERP_RGB 1
229 #define INTERP_ALPHA 1
230 
231 #define INNER_LOOP( LEFT, RIGHT, Y )				\
232 	{							\
233 	   GLint i, n = RIGHT-LEFT;				\
234 	   GLdepth zspan[MAX_WIDTH];				\
235 	   GLubyte red[MAX_WIDTH], green[MAX_WIDTH];		\
236 	   GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];		\
237 	   if (n>0) {						\
238 	      for (i=0;i<n;i++) {				\
239 		 zspan[i] = FixedToDepth(ffz);			\
240 		 red[i]   = FixedToInt(ffr);			\
241 		 green[i] = FixedToInt(ffg);			\
242 		 blue[i]  = FixedToInt(ffb);			\
243 		 alpha[i] = FixedToInt(ffa);			\
244 		 ffz += fdzdx;					\
245 		 ffr += fdrdx;					\
246 		 ffg += fdgdx;					\
247 		 ffb += fdbdx;					\
248 		 ffa += fdadx;					\
249 	      }							\
250 	      gl_write_color_span( ctx, n, LEFT, Y, zspan,	\
251 	                           red, green, blue, alpha,	\
252 				   GL_POLYGON );		\
253 	   }							\
254 	}
255 
256 #include "tritemp.h"
257 }
258 
259 
260 
261 /*
262  * Render an RGB, GL_DECAL, textured triangle.
263  * Interpolate S,T only w/out mipmapping or perspective correction.
264  */
simple_textured_triangle(GLcontext * ctx,GLuint v0,GLuint v1,GLuint v2,GLuint pv)265 static void simple_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
266                                       GLuint v2, GLuint pv )
267 {
268 #define INTERP_ST 1
269 #define S_SCALE twidth
270 #define T_SCALE theight
271 #define SETUP_CODE							\
272    GLfloat twidth = (GLfloat) ctx->Texture.Current2D->Image[0]->Width;	\
273    GLfloat theight = (GLfloat) ctx->Texture.Current2D->Image[0]->Height;\
274    GLint twidth_log2 = ctx->Texture.Current2D->Image[0]->WidthLog2;	\
275    GLubyte *texture = ctx->Texture.Current2D->Image[0]->Data;		\
276    GLint smask = ctx->Texture.Current2D->Image[0]->Width - 1;		\
277    GLint tmask = ctx->Texture.Current2D->Image[0]->Height - 1;
278 
279 #define INNER_LOOP( LEFT, RIGHT, Y )				\
280 	{							\
281 	   GLint i, n = RIGHT-LEFT;				\
282 	   GLubyte red[MAX_WIDTH], green[MAX_WIDTH];		\
283 	   GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];		\
284 	   if (n>0) {						\
285 	      for (i=0;i<n;i++) {				\
286                  GLint s = FixedToInt(ffs) & smask;		\
287                  GLint t = FixedToInt(fft) & tmask;		\
288                  GLint pos = (t << twidth_log2) + s;		\
289                  pos = pos + pos  + pos;  /* multiply by 3 */	\
290                  red[i]   = texture[pos];			\
291                  green[i] = texture[pos+1];			\
292                  blue[i]  = texture[pos+2];			\
293                  alpha[i] = 255;				\
294 		 ffs += fdsdx;					\
295 		 fft += fdtdx;					\
296 	      }							\
297               (*ctx->Driver.WriteColorSpan)( ctx, n, LEFT, Y,	\
298                              red, green, blue, alpha, NULL );	\
299 	   }							\
300 	}
301 
302 #include "tritemp.h"
303 }
304 
305 
306 
307 /*
308  * Render an RGB, GL_DECAL, textured triangle.
309  * Interpolate S,T, GL_LESS depth test, w/out mipmapping or
310  * perspective correction.
311  */
simple_z_textured_triangle(GLcontext * ctx,GLuint v0,GLuint v1,GLuint v2,GLuint pv)312 static void simple_z_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
313                                       GLuint v2, GLuint pv )
314 {
315 #define INTERP_Z 1
316 #define INTERP_ST 1
317 #define S_SCALE twidth
318 #define T_SCALE theight
319 #define SETUP_CODE							\
320    GLfloat twidth = (GLfloat) ctx->Texture.Current2D->Image[0]->Width;	\
321    GLfloat theight = (GLfloat) ctx->Texture.Current2D->Image[0]->Height;\
322    GLint twidth_log2 = ctx->Texture.Current2D->Image[0]->WidthLog2;	\
323    GLubyte *texture = ctx->Texture.Current2D->Image[0]->Data;		\
324    GLint smask = ctx->Texture.Current2D->Image[0]->Width - 1;		\
325    GLint tmask = ctx->Texture.Current2D->Image[0]->Height - 1;
326 
327 #define INNER_LOOP( LEFT, RIGHT, Y )				\
328 	{							\
329 	   GLint i, n = RIGHT-LEFT;				\
330 	   GLubyte red[MAX_WIDTH], green[MAX_WIDTH];		\
331 	   GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];		\
332            GLubyte mask[MAX_WIDTH];				\
333 	   if (n>0) {						\
334 	      for (i=0;i<n;i++) {				\
335                  GLdepth z = FixedToDepth(ffz);			\
336                  if (z < zRow[i]) {				\
337                     GLint s = FixedToInt(ffs) & smask;		\
338                     GLint t = FixedToInt(fft) & tmask;		\
339                     GLint pos = (t << twidth_log2) + s;		\
340                     pos = pos + pos  + pos;  /* multiply by 3 */\
341                     red[i]   = texture[pos];			\
342                     green[i] = texture[pos+1];			\
343                     blue[i]  = texture[pos+2];			\
344                     alpha[i] = 255;				\
345 		    zRow[i] = z;				\
346                     mask[i] = 1;				\
347                  }						\
348                  else {						\
349                     mask[i] = 0;				\
350                  }						\
351 		 ffz += fdzdx;					\
352 		 ffs += fdsdx;					\
353 		 fft += fdtdx;					\
354 	      }							\
355               (*ctx->Driver.WriteColorSpan)( ctx, n, LEFT, Y,	\
356                              red, green, blue, alpha, mask );	\
357 	   }							\
358 	}
359 
360 #include "tritemp.h"
361 }
362 
363 
364 
365 /*
366  * Render a smooth-shaded, textured, RGBA triangle.
367  * Interpolate S,T,U with perspective correction, w/out mipmapping.
368  * Note: we use texture coordinates S,T,U,V instead of S,T,R,Q because
369  * R is already used for red.
370  */
general_textured_triangle(GLcontext * ctx,GLuint v0,GLuint v1,GLuint v2,GLuint pv)371 static void general_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
372                                        GLuint v2, GLuint pv )
373 {
374 #define INTERP_Z 1
375 #define INTERP_RGB 1
376 #define INTERP_ALPHA 1
377 #define INTERP_STW 1
378 #define INTERP_UV 1
379 #define SETUP_CODE						\
380    GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT);	\
381    GLint r, g, b, a;						\
382    if (flat_shade) {						\
383       r = VB->Color[pv][0];					\
384       g = VB->Color[pv][1];					\
385       b = VB->Color[pv][2];					\
386       a = VB->Color[pv][3];					\
387    }
388 #define INNER_LOOP( LEFT, RIGHT, Y )				\
389 	{							\
390 	   GLint i, n = RIGHT-LEFT;				\
391 	   GLdepth zspan[MAX_WIDTH];				\
392 	   GLubyte red[MAX_WIDTH], green[MAX_WIDTH];		\
393 	   GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];		\
394            GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH];	\
395 	   if (n>0) {						\
396               if (flat_shade) {					\
397                  for (i=0;i<n;i++) {				\
398 		    GLdouble wwvvInv = 1.0 / (ww*vv);		\
399 		    zspan[i] = FixedToDepth(ffz);		\
400 		    red[i]   = r;				\
401 		    green[i] = g;				\
402 		    blue[i]  = b;				\
403 		    alpha[i] = a;				\
404 		    s[i] = ss*wwvvInv;				\
405 		    t[i] = tt*wwvvInv;				\
406 		    u[i] = uu*wwvvInv;				\
407 		    ffz += fdzdx;				\
408 		    ss += dsdx;					\
409 		    tt += dtdx;					\
410 		    uu += dudx;					\
411 		    vv += dvdx;					\
412 		    ww += dwdx;					\
413 		 }						\
414               }							\
415               else {						\
416                  for (i=0;i<n;i++) {				\
417 		    GLdouble wwvvInv = 1.0 / (ww*vv);		\
418 		    zspan[i] = FixedToDepth(ffz);		\
419 		    red[i]   = FixedToInt(ffr);			\
420 		    green[i] = FixedToInt(ffg);			\
421 		    blue[i]  = FixedToInt(ffb);			\
422 		    alpha[i] = FixedToInt(ffa);			\
423 		    s[i] = ss*wwvvInv;				\
424 		    t[i] = tt*wwvvInv;				\
425 		    u[i] = uu*wwvvInv;				\
426 		    ffz += fdzdx;				\
427 		    ffr += fdrdx;				\
428 		    ffg += fdgdx;				\
429 		    ffb += fdbdx;				\
430 		    ffa += fdadx;				\
431 		    ss += dsdx;					\
432 		    tt += dtdx;					\
433 		    uu += dudx;					\
434 		    ww += dwdx;					\
435 		    vv += dvdx;					\
436 		 }						\
437               }							\
438 	      gl_write_texture_span( ctx, n, LEFT, Y, zspan,	\
439                                      s, t, u, NULL, 		\
440 	                             red, green, blue, alpha,	\
441 				     GL_POLYGON );		\
442 	   }							\
443 	}
444 
445 #include "tritemp.h"
446 }
447 
448 
449 
450 /*
451  * Compute the lambda (texture level value) for a fragment.
452  */
compute_lambda(GLfloat s,GLfloat t,GLfloat dsdx,GLfloat dsdy,GLfloat dtdx,GLfloat dtdy,GLfloat w,GLfloat width,GLfloat height)453 static GLfloat compute_lambda( GLfloat s, GLfloat t,
454                                GLfloat dsdx, GLfloat dsdy,
455                                GLfloat dtdx, GLfloat dtdy,
456                                GLfloat w,
457                                GLfloat width, GLfloat height )
458 {
459    /* TODO: this function can probably be optimized a bit */
460    GLfloat invw = 1.0F / w;
461    GLfloat s0, t0, s1, t1, s2, t2;
462    GLfloat dudx, dudy, dvdx, dvdy;
463    GLfloat r1, r2, rho;
464 
465    s0 = s * invw;
466    t0 = t * invw;
467    s1 = (s+dsdx) * invw;
468    t1 = (t+dtdx) * invw;
469    s2 = (s+dsdy) * invw;
470    t2 = (t+dtdy) * invw;
471 
472    dudx = (s1-s0) * width;
473    dudy = (s2-s0) * width;
474    dvdx = (t1-t0) * height;
475    dvdy = (t2-t0) * height;
476 
477    /* r1 = sqrt( dudx * dudx + dvdx * dvdx ); */
478    /* r2 = sqrt( dudy * dudy + dvdy * dvdy ); */
479    if (dudx<0.0F)  dudx = -dudx;
480    if (dudy<0.0F)  dudy = -dudy;
481    if (dvdx<0.0F)  dvdx = -dvdx;
482    if (dvdy<0.0F)  dvdy = -dvdy;
483    r1 = MAX2( dudx, dudy );
484    r2 = MAX2( dvdx, dvdy );
485    rho = MAX2(r1,r2);
486 
487    if (rho<=0.0F) {
488       return 0.0F;
489    }
490    else {
491       /* return log base 2 of rho */
492       return log(rho) * 1.442695;       /* 1.442695 = 1/log(2) */
493    }
494 }
495 
496 
497 
498 /*
499  * Render a smooth-shaded, textured, RGBA triangle.
500  * Interpolate S,T,U with perspective correction and compute lambda for
501  * each fragment.  Lambda is used to determine whether to use the
502  * minification or magnification filter.  If minification and using
503  * mipmaps, lambda is also used to select the texture level of detail.
504  */
lambda_textured_triangle(GLcontext * ctx,GLuint v0,GLuint v1,GLuint v2,GLuint pv)505 static void lambda_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
506                                       GLuint v2, GLuint pv )
507 {
508 #define INTERP_Z 1
509 #define INTERP_RGB 1
510 #define INTERP_ALPHA 1
511 #define INTERP_STW 1
512 #define INTERP_UV 1
513 
514 #define SETUP_CODE							\
515    GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT);		\
516    GLint r, g, b, a;							\
517    GLfloat twidth, theight;						\
518    if (ctx->Texture.Enabled & TEXTURE_3D) {				\
519       twidth = (GLfloat) ctx->Texture.Current3D->Image[0]->Width;	\
520       theight = (GLfloat) ctx->Texture.Current3D->Image[0]->Height;	\
521    }									\
522    else if (ctx->Texture.Enabled & TEXTURE_2D) {			\
523       twidth = (GLfloat) ctx->Texture.Current2D->Image[0]->Width;	\
524       theight = (GLfloat) ctx->Texture.Current2D->Image[0]->Height;	\
525    }									\
526    else {								\
527       twidth = (GLfloat) ctx->Texture.Current1D->Image[0]->Width;	\
528       theight = 1.0;							\
529    }									\
530    if (flat_shade) {							\
531       r = VB->Color[pv][0];						\
532       g = VB->Color[pv][1];						\
533       b = VB->Color[pv][2];						\
534       a = VB->Color[pv][3];						\
535    }
536 
537 #define INNER_LOOP( LEFT, RIGHT, Y )					\
538 	{								\
539 	   GLint i, n = RIGHT-LEFT;					\
540 	   GLdepth zspan[MAX_WIDTH];					\
541 	   GLubyte red[MAX_WIDTH], green[MAX_WIDTH];			\
542 	   GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];			\
543            GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH];		\
544            GLfloat lambda[MAX_WIDTH];					\
545 	   if (n>0) {							\
546 	      if (flat_shade) {						\
547 		 for (i=0;i<n;i++) {					\
548 		    GLdouble wwvvInv = 1.0 / (ww*vv);			\
549 		    zspan[i] = FixedToDepth(ffz);			\
550 		    red[i]   = r;					\
551 		    green[i] = g;					\
552 		    blue[i]  = b;					\
553 		    alpha[i] = a;					\
554 		    s[i] = ss*wwvvInv;					\
555 		    t[i] = tt*wwvvInv;					\
556 		    u[i] = uu*wwvvInv;					\
557 		    lambda[i] = compute_lambda( s[i], t[i],		\
558 						dsdx, dsdy,		\
559 						dtdx, dtdy, ww,		\
560 						twidth, theight );	\
561 		    ffz += fdzdx;					\
562 		    ss += dsdx;						\
563 		    tt += dtdx;						\
564 		    uu += dudx;						\
565 		    vv += dvdx;						\
566 		    ww += dwdx;						\
567 		 }							\
568               }								\
569               else {							\
570 		 for (i=0;i<n;i++) {					\
571 		    GLdouble wwvvInv = 1.0 / (ww*vv);			\
572 		    zspan[i] = FixedToDepth(ffz);			\
573 		    red[i]   = FixedToInt(ffr);				\
574 		    green[i] = FixedToInt(ffg);				\
575 		    blue[i]  = FixedToInt(ffb);				\
576 		    alpha[i] = FixedToInt(ffa);				\
577 		    s[i] = ss*wwvvInv;					\
578 		    t[i] = tt*wwvvInv;					\
579 		    u[i] = uu*wwvvInv;					\
580 		    lambda[i] = compute_lambda( s[i], t[i],		\
581 						dsdx, dsdy,		\
582 						dtdx, dtdy, ww,		\
583 						twidth, theight );	\
584 		    ffz += fdzdx;					\
585 		    ffr += fdrdx;					\
586 		    ffg += fdgdx;					\
587 		    ffb += fdbdx;					\
588 		    ffa += fdadx;					\
589 		    ss += dsdx;						\
590 		    tt += dtdx;						\
591 		    uu += dtdx;						\
592 		    vv += dvdx;						\
593 		    ww += dwdx;						\
594 		 }							\
595               }								\
596 	      gl_write_texture_span( ctx, n, LEFT, Y, zspan,		\
597                                      s, t, u, lambda,	 		\
598 	                             red, green, blue, alpha,		\
599 				     GL_POLYGON );			\
600 	   }								\
601 	}
602 
603 #include "tritemp.h"
604 }
605 
606 
607 
608 /*
609  * Null rasterizer for measuring transformation speed.
610  */
null_triangle(GLcontext * ctx,GLuint v0,GLuint v1,GLuint v2,GLuint pv)611 static void null_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
612                            GLuint v2, GLuint pv )
613 {
614 }
615 
616 
617 
618 /*
619  * Determine which triangle rendering function to use given the current
620  * rendering context.
621  */
gl_set_triangle_function(GLcontext * ctx)622 void gl_set_triangle_function( GLcontext *ctx )
623 {
624    GLboolean rgbmode = ctx->Visual->RGBAflag;
625 
626    if (ctx->RenderMode==GL_RENDER) {
627       if (ctx->NoRaster) {
628          ctx->TriangleFunc = null_triangle;
629          return;
630       }
631       if (ctx->Driver.TriangleFunc) {
632          /* Device driver will draw triangles. */
633          ctx->TriangleFunc = ctx->Driver.TriangleFunc;
634       }
635       else if (gl_texturing_enabled(ctx)) {
636          if (   (ctx->Texture.Enabled==TEXTURE_2D)
637              && ctx->Texture.Current2D->Complete
638              && ctx->Texture.Current2D->MinFilter==GL_NEAREST
639              && ctx->Texture.Current2D->MagFilter==GL_NEAREST
640              && ctx->Texture.Current2D->WrapS==GL_REPEAT
641              && ctx->Texture.Current2D->WrapT==GL_REPEAT
642              && ctx->Texture.Current2D->Image[0]->Format==GL_RGB
643              && ctx->Texture.Current2D->Image[0]->Border==0
644              && (ctx->Texture.EnvMode==GL_DECAL
645                  || ctx->Texture.EnvMode==GL_REPLACE)
646              && ctx->Hint.PerspectiveCorrection==GL_FASTEST
647              && ctx->IdentityTexMat
648              && (ctx->RasterMask==DEPTH_BIT || ctx->RasterMask==0)
649              && ctx->Depth.Func==GL_LESS
650              && ctx->Depth.Mask==GL_TRUE
651              && ctx->Polygon.StippleFlag==GL_FALSE
652              && ctx->Visual->EightBitColor) {
653             if (ctx->RasterMask==DEPTH_BIT) {
654                ctx->TriangleFunc = simple_z_textured_triangle;
655             }
656             else {
657                ctx->TriangleFunc = simple_textured_triangle;
658             }
659          }
660          else {
661             GLboolean needLambda = GL_TRUE;
662             /* if mag filter == min filter we're not mipmapping */
663             if (ctx->Texture.Enabled & TEXTURE_3D) {
664                if (ctx->Texture.Current3D->MinFilter==
665                    ctx->Texture.Current3D->MagFilter) {
666                   needLambda = GL_FALSE;
667                }
668 	    }
669             else if (ctx->Texture.Enabled & TEXTURE_2D) {
670                if (ctx->Texture.Current2D->MinFilter==
671                    ctx->Texture.Current2D->MagFilter) {
672                   needLambda = GL_FALSE;
673                }
674             }
675             else if (ctx->Texture.Enabled & TEXTURE_1D) {
676                if (ctx->Texture.Current1D->MinFilter==
677                    ctx->Texture.Current1D->MagFilter) {
678                   needLambda = GL_FALSE;
679                }
680             }
681             ctx->TriangleFunc = needLambda ? lambda_textured_triangle
682                                            : general_textured_triangle;
683          }
684       }
685       else {
686 	 if (ctx->Light.ShadeModel==GL_SMOOTH) {
687 	    /* smooth shaded, no texturing, stippled or some raster ops */
688 	    ctx->TriangleFunc = rgbmode ? smooth_rgba_triangle
689                                         : smooth_ci_triangle;
690 	 }
691 	 else {
692 	    /* flat shaded, no texturing, stippled or some raster ops */
693 	    ctx->TriangleFunc = rgbmode ? flat_rgba_triangle
694                                         : flat_ci_triangle;
695 	 }
696       }
697    }
698    else if (ctx->RenderMode==GL_FEEDBACK) {
699       ctx->TriangleFunc = feedback_triangle;
700    }
701    else {
702       /* GL_SELECT mode */
703       ctx->TriangleFunc = select_triangle;
704    }
705 }
706 
707