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