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