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 */
feedback_triangle(GLcontext * ctx,GLuint v0,GLuint v1,GLuint v2,GLuint pv)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 */
select_triangle(GLcontext * ctx,GLuint v0,GLuint v1,GLuint v2,GLuint pv)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 */
flat_ci_triangle(GLcontext * ctx,GLuint v0,GLuint v1,GLuint v2,GLuint pv)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 */
smooth_ci_triangle(GLcontext * ctx,GLuint v0,GLuint v1,GLuint v2,GLuint pv)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 */
flat_rgba_triangle(GLcontext * ctx,GLuint v0,GLuint v1,GLuint v2,GLuint pv)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 */
smooth_rgba_triangle(GLcontext * ctx,GLuint v0,GLuint v1,GLuint v2,GLuint pv)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 */
simple_textured_triangle(GLcontext * ctx,GLuint v0,GLuint v1,GLuint v2,GLuint pv)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 */
simple_z_textured_triangle(GLcontext * ctx,GLuint v0,GLuint v1,GLuint v2,GLuint pv)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 */
general_textured_triangle(GLcontext * ctx,GLuint v0,GLuint v1,GLuint v2,GLuint pv)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 */
compute_lambda(GLfloat s,GLfloat t,GLfloat dsdx,GLfloat dsdy,GLfloat dtdx,GLfloat dtdy,GLfloat w,GLfloat dwdx,GLfloat dwdy,GLfloat width,GLfloat height)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 */
lambda_textured_triangle(GLcontext * ctx,GLuint v0,GLuint v1,GLuint v2,GLuint pv)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 */
null_triangle(GLcontext * ctx,GLuint v0,GLuint v1,GLuint v2,GLuint pv)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 */
gl_set_triangle_function(GLcontext * ctx)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