s_triangle.c revision 709892459922a32096fe9dd8261d0d92337bb02f
1/* $Id: s_triangle.c,v 1.20 2001/03/19 02:25:36 keithw Exp $ */ 2 3/* 4 * Mesa 3-D graphics library 5 * Version: 3.5 6 * 7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a 10 * copy of this software and associated documentation files (the "Software"), 11 * to deal in the Software without restriction, including without limitation 12 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 * and/or sell copies of the Software, and to permit persons to whom the 14 * Software is furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included 17 * in all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 */ 26 27 28/* 29 * When the device driver doesn't implement triangle rasterization it 30 * can hook in _swrast_Triangle, which eventually calls one of these 31 * functions to draw triangles. 32 */ 33 34#include "glheader.h" 35#include "context.h" 36#include "colormac.h" 37#include "macros.h" 38#include "mem.h" 39#include "mmath.h" 40#include "teximage.h" 41#include "texstate.h" 42 43#include "s_aatriangle.h" 44#include "s_context.h" 45#include "s_depth.h" 46#include "s_feedback.h" 47#include "s_span.h" 48#include "s_triangle.h" 49 50GLboolean _mesa_cull_triangle( GLcontext *ctx, 51 const SWvertex *v0, 52 const SWvertex *v1, 53 const SWvertex *v2 ) 54{ 55 GLfloat ex = v1->win[0] - v0->win[0]; 56 GLfloat ey = v1->win[1] - v0->win[1]; 57 GLfloat fx = v2->win[0] - v0->win[0]; 58 GLfloat fy = v2->win[1] - v0->win[1]; 59 GLfloat c = ex*fy-ey*fx; 60 61 if (c * SWRAST_CONTEXT(ctx)->_backface_sign > 0) 62 return 0; 63 64 return 1; 65} 66 67 68 69/* 70 * Render a flat-shaded color index triangle. 71 */ 72static void flat_ci_triangle( GLcontext *ctx, 73 const SWvertex *v0, 74 const SWvertex *v1, 75 const SWvertex *v2 ) 76{ 77#define INTERP_Z 1 78#define INTERP_FOG 1 79 80#define INNER_LOOP( LEFT, RIGHT, Y ) \ 81 { \ 82 const GLint n = RIGHT-LEFT; \ 83 GLint i; \ 84 GLdepth zspan[MAX_WIDTH]; \ 85 GLfixed fogspan[MAX_WIDTH]; \ 86 if (n>0) { \ 87 for (i=0;i<n;i++) { \ 88 zspan[i] = FixedToDepth(ffz); \ 89 ffz += fdzdx; \ 90 fogspan[i] = fffog / 256; \ 91 fffog += fdfogdx; \ 92 } \ 93 _mesa_write_monoindex_span( ctx, n, LEFT, Y, zspan, \ 94 fogspan, v0->index, GL_POLYGON ); \ 95 } \ 96 } 97 98#include "s_tritemp.h" 99} 100 101 102 103/* 104 * Render a smooth-shaded color index triangle. 105 */ 106static void smooth_ci_triangle( GLcontext *ctx, 107 const SWvertex *v0, 108 const SWvertex *v1, 109 const SWvertex *v2 ) 110{ 111#define INTERP_Z 1 112#define INTERP_FOG 1 113#define INTERP_INDEX 1 114 115#define INNER_LOOP( LEFT, RIGHT, Y ) \ 116 { \ 117 const GLint n = RIGHT-LEFT; \ 118 GLint i; \ 119 GLdepth zspan[MAX_WIDTH]; \ 120 GLfixed fogspan[MAX_WIDTH]; \ 121 GLuint index[MAX_WIDTH]; \ 122 if (n>0) { \ 123 for (i=0;i<n;i++) { \ 124 zspan[i] = FixedToDepth(ffz); \ 125 ffz += fdzdx; \ 126 index[i] = FixedToInt(ffi); \ 127 ffi += fdidx; \ 128 fogspan[i] = fffog / 256; \ 129 fffog += fdfogdx; \ 130 } \ 131 _mesa_write_index_span( ctx, n, LEFT, Y, zspan, fogspan, \ 132 index, GL_POLYGON ); \ 133 } \ 134 } 135 136#include "s_tritemp.h" 137} 138 139 140 141/* 142 * Render a flat-shaded RGBA triangle. 143 */ 144static void flat_rgba_triangle( GLcontext *ctx, 145 const SWvertex *v0, 146 const SWvertex *v1, 147 const SWvertex *v2 ) 148{ 149#define INTERP_Z 1 150#define INTERP_FOG 1 151#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 152 153#define INNER_LOOP( LEFT, RIGHT, Y ) \ 154 { \ 155 const GLint n = RIGHT-LEFT; \ 156 GLint i; \ 157 GLdepth zspan[MAX_WIDTH]; \ 158 GLfixed fogspan[MAX_WIDTH]; \ 159 if (n>0) { \ 160 for (i=0;i<n;i++) { \ 161 zspan[i] = FixedToDepth(ffz); \ 162 ffz += fdzdx; \ 163 fogspan[i] = fffog / 256; \ 164 fffog += fdfogdx; \ 165 } \ 166 _mesa_write_monocolor_span( ctx, n, LEFT, Y, zspan, \ 167 fogspan, v2->color, \ 168 GL_POLYGON ); \ 169 } \ 170 } 171 172#include "s_tritemp.h" 173 174 ASSERT(!ctx->Texture._ReallyEnabled); /* texturing must be off */ 175 ASSERT(ctx->Light.ShadeModel==GL_FLAT); 176} 177 178 179 180/* 181 * Render a smooth-shaded RGBA triangle. 182 */ 183static void smooth_rgba_triangle( GLcontext *ctx, 184 const SWvertex *v0, 185 const SWvertex *v1, 186 const SWvertex *v2 ) 187{ 188 189#define INTERP_Z 1 190#define INTERP_FOG 1 191#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 192#define INTERP_RGB 1 193#define INTERP_ALPHA 1 194 195#define INNER_LOOP( LEFT, RIGHT, Y ) \ 196 { \ 197 const GLint n = RIGHT-LEFT; \ 198 GLint i; \ 199 GLdepth zspan[MAX_WIDTH]; \ 200 GLchan rgba[MAX_WIDTH][4]; \ 201 GLfixed fogspan[MAX_WIDTH]; \ 202 if (n>0) { \ 203 for (i=0;i<n;i++) { \ 204 zspan[i] = FixedToDepth(ffz); \ 205 rgba[i][RCOMP] = FixedToInt(ffr); \ 206 rgba[i][GCOMP] = FixedToInt(ffg); \ 207 rgba[i][BCOMP] = FixedToInt(ffb); \ 208 rgba[i][ACOMP] = FixedToInt(ffa); \ 209 fogspan[i] = fffog / 256; \ 210 fffog += fdfogdx; \ 211 ffz += fdzdx; \ 212 ffr += fdrdx; \ 213 ffg += fdgdx; \ 214 ffb += fdbdx; \ 215 ffa += fdadx; \ 216 } \ 217 _mesa_write_rgba_span( ctx, n, LEFT, Y, \ 218 (CONST GLdepth *) zspan, \ 219 fogspan, \ 220 rgba, GL_POLYGON ); \ 221 } \ 222 } 223 224#include "s_tritemp.h" 225 226 ASSERT(!ctx->Texture._ReallyEnabled); /* texturing must be off */ 227 ASSERT(ctx->Light.ShadeModel==GL_SMOOTH); 228} 229 230 231/* 232 * Render an RGB, GL_DECAL, textured triangle. 233 * Interpolate S,T only w/out mipmapping or perspective correction. 234 * 235 * No fog. 236 */ 237static void simple_textured_triangle( GLcontext *ctx, 238 const SWvertex *v0, 239 const SWvertex *v1, 240 const SWvertex *v2 ) 241{ 242#define INTERP_INT_TEX 1 243#define S_SCALE twidth 244#define T_SCALE theight 245#define SETUP_CODE \ 246 SWcontext *swrast = SWRAST_CONTEXT(ctx); \ 247 struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \ 248 GLint b = obj->BaseLevel; \ 249 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ 250 GLfloat theight = (GLfloat) obj->Image[b]->Height; \ 251 GLint twidth_log2 = obj->Image[b]->WidthLog2; \ 252 const GLchan *texture = (const GLchan *) obj->Image[b]->Data; \ 253 GLint smask = obj->Image[b]->Width - 1; \ 254 GLint tmask = obj->Image[b]->Height - 1; \ 255 if (!texture) { \ 256 /* this shouldn't happen */ \ 257 return; \ 258 } 259 260#define INNER_LOOP( LEFT, RIGHT, Y ) \ 261 { \ 262 CONST GLint n = RIGHT-LEFT; \ 263 GLint i; \ 264 GLchan rgb[MAX_WIDTH][3]; \ 265 if (n>0) { \ 266 ffs -= FIXED_HALF; /* off-by-one error? */ \ 267 fft -= FIXED_HALF; \ 268 for (i=0;i<n;i++) { \ 269 GLint s = FixedToInt(ffs) & smask; \ 270 GLint t = FixedToInt(fft) & tmask; \ 271 GLint pos = (t << twidth_log2) + s; \ 272 pos = pos + pos + pos; /* multiply by 3 */ \ 273 rgb[i][RCOMP] = texture[pos]; \ 274 rgb[i][GCOMP] = texture[pos+1]; \ 275 rgb[i][BCOMP] = texture[pos+2]; \ 276 ffs += fdsdx; \ 277 fft += fdtdx; \ 278 } \ 279 (*swrast->Driver.WriteRGBSpan)( ctx, n, LEFT, Y, \ 280 (CONST GLchan (*)[3]) rgb, NULL ); \ 281 } \ 282 } 283 284#include "s_tritemp.h" 285} 286 287 288/* 289 * Render an RGB, GL_DECAL, textured triangle. 290 * Interpolate S,T, GL_LESS depth test, w/out mipmapping or 291 * perspective correction. 292 * 293 * No fog. 294 */ 295static void simple_z_textured_triangle( GLcontext *ctx, 296 const SWvertex *v0, 297 const SWvertex *v1, 298 const SWvertex *v2 ) 299{ 300#define INTERP_Z 1 301#define INTERP_FOG 1 302#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 303#define INTERP_INT_TEX 1 304#define S_SCALE twidth 305#define T_SCALE theight 306#define SETUP_CODE \ 307 SWcontext *swrast = SWRAST_CONTEXT(ctx); \ 308 struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \ 309 GLint b = obj->BaseLevel; \ 310 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ 311 GLfloat theight = (GLfloat) obj->Image[b]->Height; \ 312 GLint twidth_log2 = obj->Image[b]->WidthLog2; \ 313 const GLchan *texture = (const GLchan *) obj->Image[b]->Data; \ 314 GLint smask = obj->Image[b]->Width - 1; \ 315 GLint tmask = obj->Image[b]->Height - 1; \ 316 if (!texture) { \ 317 /* this shouldn't happen */ \ 318 return; \ 319 } 320 321#define INNER_LOOP( LEFT, RIGHT, Y ) \ 322 { \ 323 CONST GLint n = RIGHT-LEFT; \ 324 GLint i; \ 325 GLchan rgb[MAX_WIDTH][3]; \ 326 GLubyte mask[MAX_WIDTH]; \ 327 (void) fffog; \ 328 if (n>0) { \ 329 ffs -= FIXED_HALF; /* off-by-one error? */ \ 330 fft -= FIXED_HALF; \ 331 for (i=0;i<n;i++) { \ 332 GLdepth z = FixedToDepth(ffz); \ 333 if (z < zRow[i]) { \ 334 GLint s = FixedToInt(ffs) & smask; \ 335 GLint t = FixedToInt(fft) & tmask; \ 336 GLint pos = (t << twidth_log2) + s; \ 337 pos = pos + pos + pos; /* multiply by 3 */ \ 338 rgb[i][RCOMP] = texture[pos]; \ 339 rgb[i][GCOMP] = texture[pos+1]; \ 340 rgb[i][BCOMP] = texture[pos+2]; \ 341 zRow[i] = z; \ 342 mask[i] = 1; \ 343 } \ 344 else { \ 345 mask[i] = 0; \ 346 } \ 347 ffz += fdzdx; \ 348 ffs += fdsdx; \ 349 fft += fdtdx; \ 350 } \ 351 (*swrast->Driver.WriteRGBSpan)( ctx, n, LEFT, Y, \ 352 (CONST GLchan (*)[3]) rgb, mask ); \ 353 } \ 354 } 355 356#include "s_tritemp.h" 357} 358 359 360 361/* 362 * Render an RGB/RGBA textured triangle without perspective correction. 363 */ 364static void affine_textured_triangle( GLcontext *ctx, 365 const SWvertex *v0, 366 const SWvertex *v1, 367 const SWvertex *v2 ) 368{ 369#define INTERP_Z 1 370#define INTERP_FOG 1 371#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 372#define INTERP_RGB 1 373#define INTERP_ALPHA 1 374#define INTERP_INT_TEX 1 375#define S_SCALE twidth 376#define T_SCALE theight 377#define SETUP_CODE \ 378 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \ 379 struct gl_texture_object *obj = unit->Current2D; \ 380 GLint b = obj->BaseLevel; \ 381 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ 382 GLfloat theight = (GLfloat) obj->Image[b]->Height; \ 383 GLint twidth_log2 = obj->Image[b]->WidthLog2; \ 384 const GLchan *texture = (const GLchan *) obj->Image[b]->Data; \ 385 GLint smask = obj->Image[b]->Width - 1; \ 386 GLint tmask = obj->Image[b]->Height - 1; \ 387 GLint format = obj->Image[b]->Format; \ 388 GLint filter = obj->MinFilter; \ 389 GLint envmode = unit->EnvMode; \ 390 GLint comp, tbytesline, tsize; \ 391 GLfixed er, eg, eb, ea; \ 392 GLint tr, tg, tb, ta; \ 393 if (!texture) { \ 394 /* this shouldn't happen */ \ 395 return; \ 396 } \ 397 if (envmode == GL_BLEND || envmode == GL_ADD) { \ 398 /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \ 399 er = FloatToFixed(unit->EnvColor[RCOMP]); \ 400 eg = FloatToFixed(unit->EnvColor[GCOMP]); \ 401 eb = FloatToFixed(unit->EnvColor[BCOMP]); \ 402 ea = FloatToFixed(unit->EnvColor[ACOMP]); \ 403 } \ 404 switch (format) { \ 405 case GL_ALPHA: \ 406 case GL_LUMINANCE: \ 407 case GL_INTENSITY: \ 408 comp = 1; \ 409 break; \ 410 case GL_LUMINANCE_ALPHA: \ 411 comp = 2; \ 412 break; \ 413 case GL_RGB: \ 414 comp = 3; \ 415 break; \ 416 case GL_RGBA: \ 417 comp = 4; \ 418 break; \ 419 default: \ 420 _mesa_problem(NULL, "Bad texture format in affine_texture_triangle");\ 421 return; \ 422 } \ 423 tbytesline = obj->Image[b]->Width * comp; \ 424 tsize = obj->Image[b]->Height * tbytesline; 425 426 427 /* Instead of defining a function for each mode, a test is done 428 * between the outer and inner loops. This is to reduce code size 429 * and complexity. Observe that an optimizing compiler kills 430 * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST). 431 */ 432 433#define NEAREST_RGB \ 434 tr = tex00[RCOMP]; \ 435 tg = tex00[GCOMP]; \ 436 tb = tex00[BCOMP]; \ 437 ta = 0xff 438 439#define LINEAR_RGB \ 440 tr = (ti * (si * tex00[0] + sf * tex01[0]) + \ 441 tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \ 442 tg = (ti * (si * tex00[1] + sf * tex01[1]) + \ 443 tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \ 444 tb = (ti * (si * tex00[2] + sf * tex01[2]) + \ 445 tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \ 446 ta = 0xff 447 448#define NEAREST_RGBA \ 449 tr = tex00[RCOMP]; \ 450 tg = tex00[GCOMP]; \ 451 tb = tex00[BCOMP]; \ 452 ta = tex00[ACOMP] 453 454#define LINEAR_RGBA \ 455 tr = (ti * (si * tex00[0] + sf * tex01[0]) + \ 456 tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \ 457 tg = (ti * (si * tex00[1] + sf * tex01[1]) + \ 458 tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \ 459 tb = (ti * (si * tex00[2] + sf * tex01[2]) + \ 460 tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \ 461 ta = (ti * (si * tex00[3] + sf * tex01[3]) + \ 462 tf * (si * tex10[3] + sf * tex11[3])) >> 2 * FIXED_SHIFT 463 464#define MODULATE \ 465 dest[RCOMP] = ffr * (tr + 1) >> (FIXED_SHIFT + 8); \ 466 dest[GCOMP] = ffg * (tg + 1) >> (FIXED_SHIFT + 8); \ 467 dest[BCOMP] = ffb * (tb + 1) >> (FIXED_SHIFT + 8); \ 468 dest[ACOMP] = ffa * (ta + 1) >> (FIXED_SHIFT + 8) 469 470#define DECAL \ 471 dest[RCOMP] = ((0xff - ta) * ffr + ((ta + 1) * tr << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \ 472 dest[GCOMP] = ((0xff - ta) * ffg + ((ta + 1) * tg << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \ 473 dest[BCOMP] = ((0xff - ta) * ffb + ((ta + 1) * tb << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \ 474 dest[ACOMP] = FixedToInt(ffa) 475 476#define BLEND \ 477 dest[RCOMP] = ((0xff - tr) * ffr + (tr + 1) * er) >> (FIXED_SHIFT + 8); \ 478 dest[GCOMP] = ((0xff - tg) * ffg + (tg + 1) * eg) >> (FIXED_SHIFT + 8); \ 479 dest[BCOMP] = ((0xff - tb) * ffb + (tb + 1) * eb) >> (FIXED_SHIFT + 8); \ 480 dest[ACOMP] = ffa * (ta + 1) >> (FIXED_SHIFT + 8) 481 482#define REPLACE \ 483 dest[RCOMP] = tr; \ 484 dest[GCOMP] = tg; \ 485 dest[BCOMP] = tb; \ 486 dest[ACOMP] = ta 487 488#define ADD \ 489 dest[RCOMP] = ((ffr << 8) + (tr + 1) * er) >> (FIXED_SHIFT + 8); \ 490 dest[GCOMP] = ((ffg << 8) + (tg + 1) * eg) >> (FIXED_SHIFT + 8); \ 491 dest[BCOMP] = ((ffb << 8) + (tb + 1) * eb) >> (FIXED_SHIFT + 8); \ 492 dest[ACOMP] = ffa * (ta + 1) >> (FIXED_SHIFT + 8) 493 494/* shortcuts */ 495 496#define NEAREST_RGB_REPLACE NEAREST_RGB;REPLACE 497 498#define NEAREST_RGBA_REPLACE *(GLint *)dest = *(GLint *)tex00 499 500#define SPAN1(DO_TEX,COMP) \ 501 for (i=0;i<n;i++) { \ 502 GLint s = FixedToInt(ffs) & smask; \ 503 GLint t = FixedToInt(fft) & tmask; \ 504 GLint pos = (t << twidth_log2) + s; \ 505 const GLchan *tex00 = texture + COMP * pos; \ 506 zspan[i] = FixedToDepth(ffz); \ 507 fogspan[i] = fffog / 256; \ 508 DO_TEX; \ 509 fffog += fdfogdx; \ 510 ffz += fdzdx; \ 511 ffr += fdrdx; \ 512 ffg += fdgdx; \ 513 ffb += fdbdx; \ 514 ffa += fdadx; \ 515 ffs += fdsdx; \ 516 fft += fdtdx; \ 517 dest += 4; \ 518 } 519 520#define SPAN2(DO_TEX,COMP) \ 521 for (i=0;i<n;i++) { \ 522 GLint s = FixedToInt(ffs) & smask; \ 523 GLint t = FixedToInt(fft) & tmask; \ 524 GLint sf = ffs & FIXED_FRAC_MASK; \ 525 GLint tf = fft & FIXED_FRAC_MASK; \ 526 GLint si = FIXED_FRAC_MASK - sf; \ 527 GLint ti = FIXED_FRAC_MASK - tf; \ 528 GLint pos = (t << twidth_log2) + s; \ 529 const GLchan *tex00 = texture + COMP * pos; \ 530 const GLchan *tex10 = tex00 + tbytesline; \ 531 const GLchan *tex01 = tex00 + COMP; \ 532 const GLchan *tex11 = tex10 + COMP; \ 533 if (t == tmask) { \ 534 tex10 -= tsize; \ 535 tex11 -= tsize; \ 536 } \ 537 if (s == smask) { \ 538 tex01 -= tbytesline; \ 539 tex11 -= tbytesline; \ 540 } \ 541 zspan[i] = FixedToDepth(ffz); \ 542 fogspan[i] = fffog / 256; \ 543 DO_TEX; \ 544 fffog += fdfogdx; \ 545 ffz += fdzdx; \ 546 ffr += fdrdx; \ 547 ffg += fdgdx; \ 548 ffb += fdbdx; \ 549 ffa += fdadx; \ 550 ffs += fdsdx; \ 551 fft += fdtdx; \ 552 dest += 4; \ 553 } 554 555/* here comes the heavy part.. (something for the compiler to chew on) */ 556#define INNER_LOOP( LEFT, RIGHT, Y ) \ 557 { \ 558 CONST GLint n = RIGHT-LEFT; \ 559 GLint i; \ 560 GLdepth zspan[MAX_WIDTH]; \ 561 GLfixed fogspan[MAX_WIDTH]; \ 562 GLchan rgba[MAX_WIDTH][4]; \ 563 if (n>0) { \ 564 GLchan *dest = rgba[0]; \ 565 ffs -= FIXED_HALF; /* off-by-one error? */ \ 566 fft -= FIXED_HALF; \ 567 switch (filter) { \ 568 case GL_NEAREST: \ 569 switch (format) { \ 570 case GL_RGB: \ 571 switch (envmode) { \ 572 case GL_MODULATE: \ 573 SPAN1(NEAREST_RGB;MODULATE,3); \ 574 break; \ 575 case GL_DECAL: \ 576 case GL_REPLACE: \ 577 SPAN1(NEAREST_RGB_REPLACE,3); \ 578 break; \ 579 case GL_BLEND: \ 580 SPAN1(NEAREST_RGB;BLEND,3); \ 581 break; \ 582 case GL_ADD: \ 583 SPAN1(NEAREST_RGB;ADD,3); \ 584 break; \ 585 default: /* unexpected env mode */ \ 586 abort(); \ 587 } \ 588 break; \ 589 case GL_RGBA: \ 590 switch(envmode) { \ 591 case GL_MODULATE: \ 592 SPAN1(NEAREST_RGBA;MODULATE,4); \ 593 break; \ 594 case GL_DECAL: \ 595 SPAN1(NEAREST_RGBA;DECAL,4); \ 596 break; \ 597 case GL_BLEND: \ 598 SPAN1(NEAREST_RGBA;BLEND,4); \ 599 break; \ 600 case GL_ADD: \ 601 SPAN1(NEAREST_RGBA;ADD,4); \ 602 break; \ 603 case GL_REPLACE: \ 604 SPAN1(NEAREST_RGBA_REPLACE,4); \ 605 break; \ 606 default: /* unexpected env mode */ \ 607 abort(); \ 608 } \ 609 break; \ 610 } \ 611 break; \ 612 case GL_LINEAR: \ 613 ffs -= FIXED_HALF; \ 614 fft -= FIXED_HALF; \ 615 switch (format) { \ 616 case GL_RGB: \ 617 switch (envmode) { \ 618 case GL_MODULATE: \ 619 SPAN2(LINEAR_RGB;MODULATE,3); \ 620 break; \ 621 case GL_DECAL: \ 622 case GL_REPLACE: \ 623 SPAN2(LINEAR_RGB;REPLACE,3); \ 624 break; \ 625 case GL_BLEND: \ 626 SPAN2(LINEAR_RGB;BLEND,3); \ 627 break; \ 628 case GL_ADD: \ 629 SPAN2(LINEAR_RGB;ADD,3); \ 630 break; \ 631 default: /* unexpected env mode */ \ 632 abort(); \ 633 } \ 634 break; \ 635 case GL_RGBA: \ 636 switch (envmode) { \ 637 case GL_MODULATE: \ 638 SPAN2(LINEAR_RGBA;MODULATE,4); \ 639 break; \ 640 case GL_DECAL: \ 641 SPAN2(LINEAR_RGBA;DECAL,4); \ 642 break; \ 643 case GL_BLEND: \ 644 SPAN2(LINEAR_RGBA;BLEND,4); \ 645 break; \ 646 case GL_ADD: \ 647 SPAN2(LINEAR_RGBA;ADD,4); \ 648 break; \ 649 case GL_REPLACE: \ 650 SPAN2(LINEAR_RGBA;REPLACE,4); \ 651 break; \ 652 default: /* unexpected env mode */ \ 653 abort(); \ 654 } \ 655 break; \ 656 } \ 657 break; \ 658 } \ 659 _mesa_write_rgba_span(ctx, n, LEFT, Y, zspan, \ 660 fogspan, \ 661 rgba, GL_POLYGON); \ 662 /* explicit kill of variables: */ \ 663 ffr = ffg = ffb = ffa = 0; \ 664 } \ 665 } 666 667#include "s_tritemp.h" 668#undef SPAN1 669#undef SPAN2 670} 671 672 673 674/* 675 * Render an perspective corrected RGB/RGBA textured triangle. 676 * The Q (aka V in Mesa) coordinate must be zero such that the divide 677 * by interpolated Q/W comes out right. 678 * 679 * This function only renders textured triangles that use GL_NEAREST. 680 * Perspective correction works right. 681 * 682 * This function written by Klaus Niederkrueger <klaus@math.leidenuniv.nl> 683 * Send all questions and bug reports to him. 684 */ 685#if 0 /* XXX disabled because of texcoord interpolation errors */ 686static void near_persp_textured_triangle(GLcontext *ctx, 687 const SWvertex *v0, 688 const SWvertex *v1, 689 const SWvertex *v2 ) 690{ 691/* The BIAS value is used to shift negative values into positive values. 692 * Without this, negative texture values don't GL_REPEAT correctly at just 693 * below zero, because (int)-0.5 = 0 = (int)0.5. We're not going to worry 694 * about texture coords less than -BIAS. This could be fixed by using 695 * FLOORF etc. instead, but this is slower... 696 */ 697#define BIAS 4096.0F 698 699#define INTERP_Z 1 700#define INTERP_FOG 1 701#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 702#define INTERP_RGB 1 703#define INTERP_ALPHA 1 704#define INTERP_TEX 1 705#define SETUP_CODE \ 706 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \ 707 struct gl_texture_object *obj = unit->Current2D; \ 708 const GLint b = obj->BaseLevel; \ 709 const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ 710 const GLfloat theight = (GLfloat) obj->Image[b]->Height; \ 711 const GLint twidth_log2 = obj->Image[b]->WidthLog2; \ 712 const GLchan *texture = (const GLchan *) obj->Image[b]->Data; \ 713 const GLint smask = (obj->Image[b]->Width - 1); \ 714 const GLint tmask = (obj->Image[b]->Height - 1); \ 715 const GLint format = obj->Image[b]->Format; \ 716 const GLint envmode = unit->EnvMode; \ 717 GLfloat sscale, tscale; \ 718 GLfixed er, eg, eb, ea; \ 719 GLint tr, tg, tb, ta; \ 720 if (!texture) { \ 721 /* this shouldn't happen */ \ 722 return; \ 723 } \ 724 if (envmode == GL_BLEND || envmode == GL_ADD) { \ 725 er = FloatToFixed(unit->EnvColor[RCOMP]); \ 726 eg = FloatToFixed(unit->EnvColor[GCOMP]); \ 727 eb = FloatToFixed(unit->EnvColor[BCOMP]); \ 728 ea = FloatToFixed(unit->EnvColor[ACOMP]); \ 729 } \ 730 sscale = twidth; \ 731 tscale = theight; \ 732 733 734#define OLD_SPAN(DO_TEX,COMP) \ 735 for (i=0;i<n;i++) { \ 736 GLfloat invQ = 1.0f / vv; \ 737 GLint s = (int)(SS * invQ + BIAS) & smask; \ 738 GLint t = (int)(TT * invQ + BIAS) & tmask; \ 739 GLint pos = COMP * ((t << twidth_log2) + s); \ 740 const GLchan *tex00 = texture + pos; \ 741 zspan[i] = FixedToDepth(ffz); \ 742 fogspan[i] = fffog / 256; \ 743 DO_TEX; \ 744 fffog += fdfogdx; \ 745 ffz += fdzdx; \ 746 ffr += fdrdx; \ 747 ffg += fdgdx; \ 748 ffb += fdbdx; \ 749 ffa += fdadx; \ 750 SS += dSdx; \ 751 TT += dTdx; \ 752 vv += dvdx; \ 753 dest += 4; \ 754 } 755 756#define X_Y_TEX_COORD(X, Y) ((((int)(X) & tmask) << twidth_log2) + ((int)(Y) & smask)) 757#define Y_X_TEX_COORD(X, Y) ((((int)(Y) & tmask) << twidth_log2) + ((int)(X) & smask)) 758 759#define SPAN1(DO_TEX, COMP, TEX_COORD) { \ 760 GLfloat x_max = CEILF(x_tex); \ 761 GLfloat y_max = y_tex + (x_max - x_tex) * dy_dx; \ 762 GLint j, x_m = (int)x_max; \ 763 GLint pos; \ 764 if ((int)y_max != (int)y_tex) { \ 765 GLfloat x_mid = x_tex + (CEILF(y_tex)-y_tex) * dx_dy; \ 766 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \ 767 pos = COMP * TEX_COORD(x_tex, y_tex); \ 768 DRAW_LINE (DO_TEX); \ 769 y_tex = y_max; \ 770 } \ 771 nominator += vv * x_max; \ 772 denominator -= dvdx * x_max; \ 773 j = nominator / denominator; \ 774 pos = COMP * TEX_COORD(x_tex, y_tex); \ 775 DRAW_LINE (DO_TEX); \ 776 while (i<n) { \ 777 y_tex = y_max; \ 778 y_max += dy_dx; \ 779 if ((int)y_max != (int)y_tex) { \ 780 GLfloat x_mid = (CEILF(y_tex)-y_tex) * dx_dy; \ 781 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \ 782 pos = COMP * TEX_COORD(x_m, y_tex); \ 783 DRAW_LINE (DO_TEX); \ 784 y_tex = y_max; \ 785 } \ 786 nominator += vv; \ 787 denominator -= dvdx; \ 788 j = nominator/denominator; \ 789 pos = COMP * TEX_COORD(x_m, y_tex); \ 790 DRAW_LINE (DO_TEX); \ 791 x_m ++; \ 792 } \ 793} 794 795#define SPAN2(DO_TEX, COMP, TEX_COORD) { \ 796 GLfloat x_max = CEILF (x_tex); \ 797 GLfloat y_max = y_tex + (x_max - x_tex) * dy_dx; \ 798 GLint j, x_m = (int) x_max; \ 799 GLint pos; \ 800 if ((int)y_max != (int)y_tex) { \ 801 GLfloat x_mid = x_tex + (FLOORF(y_tex)-y_tex) * dx_dy; \ 802 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \ 803 pos = COMP * TEX_COORD(x_tex, y_tex); \ 804 DRAW_LINE (DO_TEX); \ 805 y_tex = y_max; \ 806 } \ 807 nominator += vv * x_max; \ 808 denominator -= dvdx * x_max; \ 809 j = nominator / denominator; \ 810 pos = COMP * TEX_COORD(x_tex, y_tex); \ 811 DRAW_LINE (DO_TEX); \ 812 while (i<n) { \ 813 y_tex = y_max; \ 814 y_max += dy_dx; \ 815 if ((int)y_max != (int)y_tex) { \ 816 GLfloat x_mid = (FLOORF(y_tex)-y_tex) * dx_dy; \ 817 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid);\ 818 pos = COMP * TEX_COORD(x_m, y_tex); \ 819 DRAW_LINE (DO_TEX); \ 820 y_tex = y_max; \ 821 } \ 822 nominator += vv; \ 823 denominator -= dvdx; \ 824 j = nominator/denominator; \ 825 pos = COMP * TEX_COORD(x_m, y_tex); \ 826 DRAW_LINE (DO_TEX); \ 827 x_m ++; \ 828 } \ 829} 830 831#define SPAN3(DO_TEX, COMP, TEX_COORD) { \ 832 GLfloat x_min = FLOORF (x_tex); \ 833 GLfloat y_min = y_tex + (x_min - x_tex) * dy_dx; \ 834 GLint j, x_m = (int)x_min; \ 835 GLint pos; \ 836 if ((int)y_min != (int)y_tex) { \ 837 GLfloat x_mid = x_tex + (CEILF(y_tex)-y_tex) * dx_dy; \ 838 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \ 839 pos = COMP * TEX_COORD(x_m, y_tex); \ 840 DRAW_LINE (DO_TEX); \ 841 y_tex = y_min; \ 842 } \ 843 nominator += vv*x_min; \ 844 denominator -= dvdx*x_min; \ 845 j = nominator / denominator; \ 846 pos = COMP * TEX_COORD(x_m, y_tex); \ 847 DRAW_LINE (DO_TEX); \ 848 while (i<n) { \ 849 x_m --; \ 850 y_tex = y_min; \ 851 y_min -= dy_dx; \ 852 if ((int)y_min != (int)y_tex) { \ 853 GLfloat x_mid = (CEILF(y_tex)-y_tex) * dx_dy; \ 854 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \ 855 pos = COMP * TEX_COORD(x_m, y_tex); \ 856 DRAW_LINE (DO_TEX); \ 857 y_tex = y_min; \ 858 } \ 859 nominator -= vv; \ 860 denominator += dvdx; \ 861 j = nominator/denominator; \ 862 pos = COMP * TEX_COORD(x_m, y_tex); \ 863 DRAW_LINE (DO_TEX); \ 864 } \ 865} 866 867#define SPAN4(DO_TEX, COMP, TEX_COORD) \ 868{ \ 869 GLfloat x_min = FLOORF(x_tex); \ 870 GLint x_m = (int)x_min; \ 871 GLfloat y_min = y_tex + (x_min - x_tex) * dy_dx; \ 872 GLint j; \ 873 GLint pos; \ 874 if ((int)y_min != (int)y_tex) { \ 875 GLfloat x_mid = x_tex + (FLOORF(y_tex)-y_tex) * dx_dy; \ 876 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \ 877 pos = COMP * TEX_COORD(x_m, y_tex); \ 878 DRAW_LINE (DO_TEX); \ 879 y_tex = y_min; \ 880 } \ 881 nominator += vv * x_min; \ 882 denominator -= dvdx * x_min; \ 883 j = nominator / denominator; \ 884 pos = COMP * TEX_COORD(x_m, y_tex); \ 885 DRAW_LINE (DO_TEX); \ 886 while (i<n) { \ 887 x_m --; \ 888 y_tex = y_min; \ 889 y_min -= dy_dx; \ 890 if ((int)y_min != (int)y_tex) { \ 891 GLfloat x_mid = (FLOORF(y_tex)-y_tex) * dx_dy; \ 892 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \ 893 pos = COMP * TEX_COORD(x_m, (y_tex)); \ 894 DRAW_LINE (DO_TEX); \ 895 y_tex = y_min; \ 896 } \ 897 nominator -= vv; \ 898 denominator += dvdx; \ 899 j = nominator/denominator; \ 900 pos = COMP * TEX_COORD(x_m, y_tex); \ 901 DRAW_LINE (DO_TEX); \ 902 } \ 903} 904 905#define DRAW_LINE(DO_TEX) \ 906 { \ 907 GLchan *tex00 = texture + pos; \ 908 if (j>n || j<-100000) \ 909 j = n; \ 910 while (i<j) { \ 911 zspan[i] = FixedToDepth(ffz); \ 912 fogspan[i] = fffog / 256; \ 913 DO_TEX; \ 914 fffog += fdfogdx; \ 915 ffz += fdzdx; \ 916 ffr += fdrdx; \ 917 ffg += fdgdx; \ 918 ffb += fdbdx; \ 919 ffa += fdadx; \ 920 dest += 4; \ 921 i++; \ 922 } \ 923 } 924 925#define INNER_LOOP( LEFT, RIGHT, Y ) \ 926 { \ 927 GLint i = 0; \ 928 const GLint n = RIGHT-LEFT; \ 929 GLdepth zspan[MAX_WIDTH]; \ 930 GLfixed fogspan[MAX_WIDTH]; \ 931 GLchan rgba[MAX_WIDTH][4]; \ 932 (void)uu; /* please GCC */ \ 933 if (n > 0) { \ 934 GLchan *dest = rgba[0]; \ 935 GLfloat SS = ss * sscale; \ 936 GLfloat TT = tt * tscale; \ 937 GLfloat dSdx = dsdx * sscale; \ 938 GLfloat dTdx = dtdx * tscale; \ 939 GLfloat x_tex; \ 940 GLfloat y_tex; \ 941 GLfloat dx_tex; \ 942 GLfloat dy_tex; \ 943 if (n<5) /* When line very short, setup-time > speed-gain. */ \ 944 goto old_span; /* So: take old method */ \ 945 x_tex = SS / vv, \ 946 y_tex = TT / vv; \ 947 dx_tex = (SS + n * dSdx) / (vv + n * dvdx) - x_tex, \ 948 dy_tex = (TT + n * dTdx) / (vv + n * dvdx) - y_tex; \ 949 /* Choose between walking over texture or over pixelline: */ \ 950 /* If there are few texels, walk over texture otherwise */ \ 951 /* walk over pixelarray. The quotient on the right side */ \ 952 /* should give the timeratio needed to draw one texel in */ \ 953 /* comparison to one pixel. Depends on CPU. */ \ 954 if (dx_tex*dx_tex + dy_tex*dy_tex < (n*n)/16) { \ 955 x_tex += BIAS; \ 956 y_tex += BIAS; \ 957 if (dx_tex*dx_tex > dy_tex*dy_tex) { \ 958 /* if (FABSF(dx_tex) > FABSF(dy_tex)) */ \ 959 GLfloat nominator = - SS - vv * BIAS; \ 960 GLfloat denominator = dvdx * BIAS + dSdx; \ 961 GLfloat dy_dx; \ 962 GLfloat dx_dy; \ 963 if (dy_tex != 0.0f) { \ 964 dy_dx = dy_tex / dx_tex; \ 965 dx_dy = 1.0f/dy_dx; \ 966 } \ 967 else \ 968 dy_dx = 0.0f; \ 969 if (dx_tex > 0.0f) { \ 970 if (dy_tex > 0.0f) { \ 971 switch (format) { \ 972 case GL_RGB: \ 973 switch (envmode) { \ 974 case GL_MODULATE: \ 975 SPAN1(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\ 976 break; \ 977 case GL_DECAL: \ 978 case GL_REPLACE: \ 979 SPAN1(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \ 980 break; \ 981 case GL_BLEND: \ 982 SPAN1(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \ 983 break; \ 984 case GL_ADD: \ 985 SPAN1(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \ 986 break; \ 987 default: /* unexpected env mode */ \ 988 abort(); \ 989 } \ 990 break; \ 991 case GL_RGBA: \ 992 switch(envmode) { \ 993 case GL_MODULATE: \ 994 SPAN1(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\ 995 break; \ 996 case GL_DECAL: \ 997 SPAN1(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \ 998 break; \ 999 case GL_BLEND: \ 1000 SPAN1(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \ 1001 break; \ 1002 case GL_ADD: \ 1003 SPAN1(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \ 1004 break; \ 1005 case GL_REPLACE: \ 1006 SPAN1(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\ 1007 break; \ 1008 default: /* unexpected env mode */ \ 1009 abort(); \ 1010 } \ 1011 break; \ 1012 } \ 1013 } \ 1014 else { /* dy_tex <= 0.0f */ \ 1015 switch (format) { \ 1016 case GL_RGB: \ 1017 switch (envmode) { \ 1018 case GL_MODULATE: \ 1019 SPAN2(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\ 1020 break; \ 1021 case GL_DECAL: \ 1022 case GL_REPLACE: \ 1023 SPAN2(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \ 1024 break; \ 1025 case GL_BLEND: \ 1026 SPAN2(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \ 1027 break; \ 1028 case GL_ADD: \ 1029 SPAN2(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \ 1030 break; \ 1031 default: /* unexpected env mode */ \ 1032 abort(); \ 1033 } \ 1034 break; \ 1035 case GL_RGBA: \ 1036 switch(envmode) { \ 1037 case GL_MODULATE: \ 1038 SPAN2(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\ 1039 break; \ 1040 case GL_DECAL: \ 1041 SPAN2(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \ 1042 break; \ 1043 case GL_BLEND: \ 1044 SPAN2(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \ 1045 break; \ 1046 case GL_ADD: \ 1047 SPAN2(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \ 1048 break; \ 1049 case GL_REPLACE: \ 1050 SPAN2(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\ 1051 break; \ 1052 default: /* unexpected env mode */ \ 1053 abort(); \ 1054 } \ 1055 break; \ 1056 } \ 1057 } \ 1058 } \ 1059 else { /* dx_tex < 0.0f */ \ 1060 if (dy_tex > 0.0f) { \ 1061 switch (format) { \ 1062 case GL_RGB: \ 1063 switch (envmode) { \ 1064 case GL_MODULATE: \ 1065 SPAN3(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\ 1066 break; \ 1067 case GL_DECAL: \ 1068 case GL_REPLACE: \ 1069 SPAN3(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \ 1070 break; \ 1071 case GL_BLEND: \ 1072 SPAN3(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \ 1073 break; \ 1074 case GL_ADD: \ 1075 SPAN3(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \ 1076 break; \ 1077 default: /* unexpected env mode */ \ 1078 abort(); \ 1079 } \ 1080 break; \ 1081 case GL_RGBA: \ 1082 switch(envmode) { \ 1083 case GL_MODULATE: \ 1084 SPAN3(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\ 1085 break; \ 1086 case GL_DECAL: \ 1087 SPAN3(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \ 1088 break; \ 1089 case GL_BLEND: \ 1090 SPAN3(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \ 1091 break; \ 1092 case GL_ADD: \ 1093 SPAN3(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \ 1094 break; \ 1095 case GL_REPLACE: \ 1096 SPAN3(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\ 1097 break; \ 1098 default: /* unexpected env mode */ \ 1099 abort(); \ 1100 } \ 1101 break; \ 1102 } \ 1103 } \ 1104 else { /* dy_tex <= 0.0f */ \ 1105 switch (format) { \ 1106 case GL_RGB: \ 1107 switch (envmode) { \ 1108 case GL_MODULATE: \ 1109 SPAN4(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\ 1110 break; \ 1111 case GL_DECAL: \ 1112 case GL_REPLACE: \ 1113 SPAN4(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \ 1114 break; \ 1115 case GL_BLEND: \ 1116 SPAN4(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \ 1117 break; \ 1118 case GL_ADD: \ 1119 SPAN4(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \ 1120 break; \ 1121 default: \ 1122 abort(); \ 1123 } \ 1124 break; \ 1125 case GL_RGBA: \ 1126 switch(envmode) { \ 1127 case GL_MODULATE: \ 1128 SPAN4(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\ 1129 break; \ 1130 case GL_DECAL: \ 1131 SPAN4(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \ 1132 break; \ 1133 case GL_BLEND: \ 1134 SPAN4(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \ 1135 break; \ 1136 case GL_ADD: \ 1137 SPAN4(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \ 1138 break; \ 1139 case GL_REPLACE: \ 1140 SPAN4(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\ 1141 break; \ 1142 default: /* unexpected env mode */ \ 1143 abort(); \ 1144 } \ 1145 break; \ 1146 } \ 1147 } \ 1148 } \ 1149 } \ 1150 else { /* FABSF(dx_tex) > FABSF(dy_tex) */ \ 1151 GLfloat swap; \ 1152 GLfloat dy_dx; \ 1153 GLfloat dx_dy; \ 1154 GLfloat nominator, denominator; \ 1155 if (dx_tex == 0.0f /* && dy_tex == 0.0f*/) \ 1156 goto old_span; /* case so special, that use old */ \ 1157 /* swap some x-values and y-values */ \ 1158 SS = TT; \ 1159 dSdx = dTdx; \ 1160 swap = x_tex, x_tex = y_tex, y_tex = swap; \ 1161 swap = dx_tex, dx_tex = dy_tex, dy_tex = swap; \ 1162 nominator = - SS - vv * BIAS; \ 1163 denominator = dvdx * BIAS + dSdx; \ 1164 if (dy_tex != 0.0f) { \ 1165 dy_dx = dy_tex / dx_tex; \ 1166 dx_dy = 1.0f/dy_dx; \ 1167 } \ 1168 else \ 1169 dy_dx = 0.0f; \ 1170 if (dx_tex > 0.0f) { \ 1171 if (dy_tex > 0.0f) { \ 1172 switch (format) { \ 1173 case GL_RGB: \ 1174 switch (envmode) { \ 1175 case GL_MODULATE: \ 1176 SPAN1(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\ 1177 break; \ 1178 case GL_DECAL: \ 1179 case GL_REPLACE: \ 1180 SPAN1(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \ 1181 break; \ 1182 case GL_BLEND: \ 1183 SPAN1(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \ 1184 break; \ 1185 case GL_ADD: \ 1186 SPAN1(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \ 1187 break; \ 1188 default: /* unexpected env mode */ \ 1189 abort(); \ 1190 } \ 1191 break; \ 1192 case GL_RGBA: \ 1193 switch(envmode) { \ 1194 case GL_MODULATE: \ 1195 SPAN1(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\ 1196 break; \ 1197 case GL_DECAL: \ 1198 SPAN1(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \ 1199 break; \ 1200 case GL_BLEND: \ 1201 SPAN1(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \ 1202 break; \ 1203 case GL_ADD: \ 1204 SPAN1(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \ 1205 break; \ 1206 case GL_REPLACE: \ 1207 SPAN1(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\ 1208 break; \ 1209 default: \ 1210 abort(); \ 1211 } \ 1212 break; \ 1213 } \ 1214 } \ 1215 else { /* dy_tex <= 0.0f */ \ 1216 switch (format) { \ 1217 case GL_RGB: \ 1218 switch (envmode) { \ 1219 case GL_MODULATE: \ 1220 SPAN2(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\ 1221 break; \ 1222 case GL_DECAL: \ 1223 case GL_REPLACE: \ 1224 SPAN2(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \ 1225 break; \ 1226 case GL_BLEND: \ 1227 SPAN2(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \ 1228 break; \ 1229 case GL_ADD: \ 1230 SPAN2(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \ 1231 break; \ 1232 default: \ 1233 abort(); \ 1234 } \ 1235 break; \ 1236 case GL_RGBA: \ 1237 switch(envmode) { \ 1238 case GL_MODULATE: \ 1239 SPAN2(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\ 1240 break; \ 1241 case GL_DECAL: \ 1242 SPAN2(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \ 1243 break; \ 1244 case GL_BLEND: \ 1245 SPAN2(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \ 1246 break; \ 1247 case GL_ADD: \ 1248 SPAN2(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \ 1249 break; \ 1250 case GL_REPLACE: \ 1251 SPAN2(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\ 1252 break; \ 1253 default: \ 1254 abort(); \ 1255 } \ 1256 break; \ 1257 } \ 1258 } \ 1259 } \ 1260 else { /* dx_tex < 0.0f */ \ 1261 if (dy_tex > 0.0f) { \ 1262 switch (format) { \ 1263 case GL_RGB: \ 1264 switch (envmode) { \ 1265 case GL_MODULATE: \ 1266 SPAN3(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\ 1267 break; \ 1268 case GL_DECAL: \ 1269 case GL_REPLACE: \ 1270 SPAN3(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \ 1271 break; \ 1272 case GL_BLEND: \ 1273 SPAN3(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \ 1274 break; \ 1275 case GL_ADD: \ 1276 SPAN3(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \ 1277 break; \ 1278 default: \ 1279 abort(); \ 1280 } \ 1281 break; \ 1282 case GL_RGBA: \ 1283 switch(envmode) { \ 1284 case GL_MODULATE: \ 1285 SPAN3(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\ 1286 break; \ 1287 case GL_DECAL: \ 1288 SPAN3(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \ 1289 break; \ 1290 case GL_BLEND: \ 1291 SPAN3(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \ 1292 break; \ 1293 case GL_ADD: \ 1294 SPAN3(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \ 1295 break; \ 1296 case GL_REPLACE: \ 1297 SPAN3(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\ 1298 break; \ 1299 default: \ 1300 abort(); \ 1301 } \ 1302 break; \ 1303 } \ 1304 } \ 1305 else { /* dy_tex <= 0.0f */ \ 1306 switch (format) { \ 1307 case GL_RGB: \ 1308 switch (envmode) { \ 1309 case GL_MODULATE: \ 1310 SPAN4(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\ 1311 break; \ 1312 case GL_DECAL: \ 1313 case GL_REPLACE: \ 1314 SPAN4(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \ 1315 break; \ 1316 case GL_BLEND: \ 1317 SPAN4(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \ 1318 break; \ 1319 case GL_ADD: \ 1320 SPAN4(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \ 1321 break; \ 1322 default: \ 1323 abort(); \ 1324 } \ 1325 break; \ 1326 case GL_RGBA: \ 1327 switch(envmode) { \ 1328 case GL_MODULATE: \ 1329 SPAN4(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\ 1330 break; \ 1331 case GL_DECAL: \ 1332 SPAN4(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \ 1333 break; \ 1334 case GL_BLEND: \ 1335 SPAN4(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \ 1336 break; \ 1337 case GL_ADD: \ 1338 SPAN4(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \ 1339 break; \ 1340 case GL_REPLACE: \ 1341 SPAN4(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\ 1342 break; \ 1343 default: \ 1344 abort(); \ 1345 } \ 1346 break; \ 1347 } \ 1348 } \ 1349 } \ 1350 } \ 1351 } \ 1352 else { \ 1353 old_span: \ 1354 switch (format) { \ 1355 case GL_RGB: \ 1356 switch (envmode) { \ 1357 case GL_MODULATE: \ 1358 OLD_SPAN(NEAREST_RGB;MODULATE,3); \ 1359 break; \ 1360 case GL_DECAL: \ 1361 case GL_REPLACE: \ 1362 OLD_SPAN(NEAREST_RGB_REPLACE,3); \ 1363 break; \ 1364 case GL_BLEND: \ 1365 OLD_SPAN(NEAREST_RGB;BLEND,3); \ 1366 break; \ 1367 case GL_ADD: \ 1368 OLD_SPAN(NEAREST_RGB;ADD,3); \ 1369 break; \ 1370 default: \ 1371 abort(); \ 1372 } \ 1373 break; \ 1374 case GL_RGBA: \ 1375 switch(envmode) { \ 1376 case GL_MODULATE: \ 1377 OLD_SPAN(NEAREST_RGBA;MODULATE,4); \ 1378 break; \ 1379 case GL_DECAL: \ 1380 OLD_SPAN(NEAREST_RGBA;DECAL,4); \ 1381 break; \ 1382 case GL_BLEND: \ 1383 OLD_SPAN(NEAREST_RGBA;BLEND,4); \ 1384 break; \ 1385 case GL_ADD: \ 1386 OLD_SPAN(NEAREST_RGBA;ADD,4); \ 1387 break; \ 1388 case GL_REPLACE: \ 1389 OLD_SPAN(NEAREST_RGBA_REPLACE,4); \ 1390 break; \ 1391 default: \ 1392 abort(); \ 1393 } \ 1394 break; \ 1395 } \ 1396 } \ 1397 _mesa_write_rgba_span( ctx, n, LEFT, Y, zspan, \ 1398 fogspan, rgba, GL_POLYGON); \ 1399 ffr = ffg = ffb = ffa = 0; \ 1400 } \ 1401 } \ 1402 1403#include "s_tritemp.h" 1404#undef OLD_SPAN 1405#undef SPAN1 1406#undef SPAN2 1407#undef SPAN3 1408#undef SPAN4 1409#undef X_Y_TEX_COORD 1410#undef Y_X_TEX_COORD 1411#undef DRAW_LINE 1412#undef BIAS 1413} 1414#endif 1415 1416 1417/* 1418 * Render an perspective corrected RGB/RGBA textured triangle. 1419 * The Q (aka V in Mesa) coordinate must be zero such that the divide 1420 * by interpolated Q/W comes out right. 1421 * 1422 * This function written by Klaus Niederkrueger <klaus@math.leidenuniv.nl> 1423 * Send all questions and bug reports to him. 1424 */ 1425#if 0 /* XXX disabled because of texcoord interpolation errors */ 1426static void lin_persp_textured_triangle( GLcontext *ctx, 1427 const SWvertex *v0, 1428 const SWvertex *v1, 1429 const SWvertex *v2 ) 1430{ 1431#define INTERP_Z 1 1432#define INTERP_FOG 1 1433#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1434#define INTERP_RGB 1 1435#define INTERP_ALPHA 1 1436#define INTERP_TEX 1 1437#define SETUP_CODE \ 1438 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \ 1439 struct gl_texture_object *obj = unit->Current2D; \ 1440 const GLint b = obj->BaseLevel; \ 1441 const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ 1442 const GLfloat theight = (GLfloat) obj->Image[b]->Height; \ 1443 const GLint twidth_log2 = obj->Image[b]->WidthLog2; \ 1444 GLchan *texture = obj->Image[b]->Data; \ 1445 const GLint smask = (obj->Image[b]->Width - 1); \ 1446 const GLint tmask = (obj->Image[b]->Height - 1); \ 1447 const GLint format = obj->Image[b]->Format; \ 1448 const GLint envmode = unit->EnvMode; \ 1449 GLfloat sscale, tscale; \ 1450 GLint comp, tbytesline, tsize; \ 1451 GLfixed er, eg, eb, ea; \ 1452 GLint tr, tg, tb, ta; \ 1453 if (!texture) { \ 1454 return; \ 1455 } \ 1456 if (envmode == GL_BLEND || envmode == GL_ADD) { \ 1457 er = FloatToFixed(unit->EnvColor[RCOMP]); \ 1458 eg = FloatToFixed(unit->EnvColor[GCOMP]); \ 1459 eb = FloatToFixed(unit->EnvColor[BCOMP]); \ 1460 ea = FloatToFixed(unit->EnvColor[ACOMP]); \ 1461 } \ 1462 switch (format) { \ 1463 case GL_ALPHA: \ 1464 case GL_LUMINANCE: \ 1465 case GL_INTENSITY: \ 1466 comp = 1; \ 1467 break; \ 1468 case GL_LUMINANCE_ALPHA: \ 1469 comp = 2; \ 1470 break; \ 1471 case GL_RGB: \ 1472 comp = 3; \ 1473 break; \ 1474 case GL_RGBA: \ 1475 comp = 4; \ 1476 break; \ 1477 default: \ 1478 _mesa_problem(NULL, "Bad texture format in lin_persp_texture_triangle"); \ 1479 return; \ 1480 } \ 1481 sscale = FIXED_SCALE * twidth; \ 1482 tscale = FIXED_SCALE * theight; \ 1483 tbytesline = obj->Image[b]->Width * comp; \ 1484 tsize = theight * tbytesline; 1485 1486 1487#define SPAN(DO_TEX,COMP) \ 1488 for (i=0;i<n;i++) { \ 1489 GLfloat invQ = 1.0f / vv; \ 1490 GLfixed ffs = (int)(SS * invQ); \ 1491 GLfixed fft = (int)(TT * invQ); \ 1492 GLint s = FixedToInt(ffs) & smask; \ 1493 GLint t = FixedToInt(fft) & tmask; \ 1494 GLint sf = ffs & FIXED_FRAC_MASK; \ 1495 GLint tf = fft & FIXED_FRAC_MASK; \ 1496 GLint si = FIXED_FRAC_MASK - sf; \ 1497 GLint ti = FIXED_FRAC_MASK - tf; \ 1498 GLint pos = COMP * ((t << twidth_log2) + s); \ 1499 GLchan *tex00 = texture + pos; \ 1500 GLchan *tex10 = tex00 + tbytesline; \ 1501 GLchan *tex01 = tex00 + COMP; \ 1502 GLchan *tex11 = tex10 + COMP; \ 1503 if (t == tmask) { \ 1504 tex10 -= tsize; \ 1505 tex11 -= tsize; \ 1506 } \ 1507 if (s == smask) { \ 1508 tex01 -= tbytesline; \ 1509 tex11 -= tbytesline; \ 1510 } \ 1511 zspan[i] = FixedToDepth(ffz); \ 1512 fogspan[i] = fffog / 256; \ 1513 DO_TEX; \ 1514 fffog += fdfogdx; \ 1515 ffz += fdzdx; \ 1516 ffr += fdrdx; \ 1517 ffg += fdgdx; \ 1518 ffb += fdbdx; \ 1519 ffa += fdadx; \ 1520 SS += dSdx; \ 1521 TT += dTdx; \ 1522 vv += dvdx; \ 1523 dest += 4; \ 1524 } 1525 1526#define INNER_LOOP( LEFT, RIGHT, Y ) \ 1527 { \ 1528 GLint i; \ 1529 const GLint n = RIGHT-LEFT; \ 1530 GLdepth zspan[MAX_WIDTH]; \ 1531 GLfixed fogspan[MAX_WIDTH]; \ 1532 GLchan rgba[MAX_WIDTH][4]; \ 1533 (void) uu; /* please GCC */ \ 1534 if (n > 0) { \ 1535 GLfloat SS = ss * sscale; \ 1536 GLfloat TT = tt * tscale; \ 1537 GLfloat dSdx = dsdx * sscale; \ 1538 GLfloat dTdx = dtdx * tscale; \ 1539 GLchan *dest = rgba[0]; \ 1540 SS -= 0.5f * FIXED_SCALE * vv; \ 1541 TT -= 0.5f * FIXED_SCALE * vv; \ 1542 switch (format) { \ 1543 case GL_RGB: \ 1544 switch (envmode) { \ 1545 case GL_MODULATE: \ 1546 SPAN(LINEAR_RGB;MODULATE,3); \ 1547 break; \ 1548 case GL_DECAL: \ 1549 case GL_REPLACE: \ 1550 SPAN(LINEAR_RGB;REPLACE,3); \ 1551 break; \ 1552 case GL_BLEND: \ 1553 SPAN(LINEAR_RGB;BLEND,3); \ 1554 break; \ 1555 case GL_ADD: \ 1556 SPAN(LINEAR_RGB;ADD,3); \ 1557 break; \ 1558 default: \ 1559 abort(); \ 1560 } \ 1561 break; \ 1562 case GL_RGBA: \ 1563 switch (envmode) { \ 1564 case GL_MODULATE: \ 1565 SPAN(LINEAR_RGBA;MODULATE,4); \ 1566 break; \ 1567 case GL_DECAL: \ 1568 SPAN(LINEAR_RGBA;DECAL,4); \ 1569 break; \ 1570 case GL_BLEND: \ 1571 SPAN(LINEAR_RGBA;BLEND,4); \ 1572 break; \ 1573 case GL_REPLACE: \ 1574 SPAN(LINEAR_RGBA;REPLACE,4); \ 1575 break; \ 1576 case GL_ADD: \ 1577 SPAN(LINEAR_RGBA;ADD,4); \ 1578 break; \ 1579 default: /* unexpected env mode */ \ 1580 abort(); \ 1581 } \ 1582 } \ 1583 _mesa_write_rgba_span( ctx, n, LEFT, Y, zspan, \ 1584 fogspan, \ 1585 rgba, GL_POLYGON ); \ 1586 ffr = ffg = ffb = ffa = 0; \ 1587 } \ 1588 } 1589 1590#include "s_tritemp.h" 1591#undef SPAN 1592} 1593#endif 1594 1595 1596/* 1597 * Render a smooth-shaded, textured, RGBA triangle. 1598 * Interpolate S,T,U with perspective correction, w/out mipmapping. 1599 * Note: we use texture coordinates S,T,U,V instead of S,T,R,Q because 1600 * R is already used for red. 1601 */ 1602static void general_textured_triangle( GLcontext *ctx, 1603 const SWvertex *v0, 1604 const SWvertex *v1, 1605 const SWvertex *v2 ) 1606{ 1607#define INTERP_Z 1 1608#define INTERP_FOG 1 1609#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1610#define INTERP_RGB 1 1611#define INTERP_ALPHA 1 1612#define INTERP_TEX 1 1613#define SETUP_CODE \ 1614 GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \ 1615 GLint r, g, b, a; \ 1616 if (flat_shade) { \ 1617 r = v2->color[RCOMP]; \ 1618 g = v2->color[GCOMP]; \ 1619 b = v2->color[BCOMP]; \ 1620 a = v2->color[ACOMP]; \ 1621 } 1622#define INNER_LOOP( LEFT, RIGHT, Y ) \ 1623 { \ 1624 GLint i; \ 1625 const GLint n = RIGHT-LEFT; \ 1626 GLdepth zspan[MAX_WIDTH]; \ 1627 GLfixed fogspan[MAX_WIDTH]; \ 1628 GLchan rgba[MAX_WIDTH][4]; \ 1629 GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH]; \ 1630 if (n>0) { \ 1631 if (flat_shade) { \ 1632 for (i=0;i<n;i++) { \ 1633 GLdouble invQ = vv ? (1.0 / vv) : 1.0; \ 1634 zspan[i] = FixedToDepth(ffz); \ 1635 fogspan[i] = fffog / 256; \ 1636 rgba[i][RCOMP] = r; \ 1637 rgba[i][GCOMP] = g; \ 1638 rgba[i][BCOMP] = b; \ 1639 rgba[i][ACOMP] = a; \ 1640 s[i] = ss*invQ; \ 1641 t[i] = tt*invQ; \ 1642 u[i] = uu*invQ; \ 1643 fffog += fdfogdx; \ 1644 ffz += fdzdx; \ 1645 ss += dsdx; \ 1646 tt += dtdx; \ 1647 uu += dudx; \ 1648 vv += dvdx; \ 1649 } \ 1650 } \ 1651 else { \ 1652 for (i=0;i<n;i++) { \ 1653 GLdouble invQ = vv ? (1.0 / vv) : 1.0; \ 1654 zspan[i] = FixedToDepth(ffz); \ 1655 rgba[i][RCOMP] = FixedToInt(ffr); \ 1656 rgba[i][GCOMP] = FixedToInt(ffg); \ 1657 rgba[i][BCOMP] = FixedToInt(ffb); \ 1658 rgba[i][ACOMP] = FixedToInt(ffa); \ 1659 fogspan[i] = fffog / 256; \ 1660 s[i] = ss*invQ; \ 1661 t[i] = tt*invQ; \ 1662 u[i] = uu*invQ; \ 1663 fffog += fdfogdx; \ 1664 ffz += fdzdx; \ 1665 ffr += fdrdx; \ 1666 ffg += fdgdx; \ 1667 ffb += fdbdx; \ 1668 ffa += fdadx; \ 1669 ss += dsdx; \ 1670 tt += dtdx; \ 1671 uu += dudx; \ 1672 vv += dvdx; \ 1673 } \ 1674 } \ 1675 _mesa_write_texture_span( ctx, n, LEFT, Y, zspan, fogspan, \ 1676 s, t, u, NULL, \ 1677 rgba, \ 1678 NULL, GL_POLYGON ); \ 1679 } \ 1680 } 1681 1682#include "s_tritemp.h" 1683} 1684 1685 1686/* 1687 * Render a smooth-shaded, textured, RGBA triangle with separate specular 1688 * color interpolation. 1689 * Interpolate S,T,U with perspective correction, w/out mipmapping. 1690 * Note: we use texture coordinates S,T,U,V instead of S,T,R,Q because 1691 * R is already used for red. 1692 */ 1693static void general_textured_spec_triangle1( GLcontext *ctx, 1694 const SWvertex *v0, 1695 const SWvertex *v1, 1696 const SWvertex *v2, 1697 GLdepth zspan[MAX_WIDTH], 1698 GLfixed fogspan[MAX_WIDTH], 1699 GLchan rgba[MAX_WIDTH][4], 1700 GLchan spec[MAX_WIDTH][4] ) 1701{ 1702#define INTERP_Z 1 1703#define INTERP_FOG 1 1704#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1705#define INTERP_RGB 1 1706#define INTERP_SPEC 1 1707#define INTERP_ALPHA 1 1708#define INTERP_TEX 1 1709#define SETUP_CODE \ 1710 GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \ 1711 GLint r, g, b, a, sr, sg, sb; \ 1712 if (flat_shade) { \ 1713 r = v2->color[RCOMP]; \ 1714 g = v2->color[GCOMP]; \ 1715 b = v2->color[BCOMP]; \ 1716 a = v2->color[ACOMP]; \ 1717 sr = v2->specular[RCOMP]; \ 1718 sg = v2->specular[GCOMP]; \ 1719 sb = v2->specular[BCOMP]; \ 1720 } 1721#define INNER_LOOP( LEFT, RIGHT, Y ) \ 1722 { \ 1723 GLint i; \ 1724 const GLint n = RIGHT-LEFT; \ 1725 GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH]; \ 1726 if (n>0) { \ 1727 if (flat_shade) { \ 1728 for (i=0;i<n;i++) { \ 1729 GLdouble invQ = vv ? (1.0 / vv) : 1.0; \ 1730 zspan[i] = FixedToDepth(ffz); \ 1731 fogspan[i] = fffog / 256; \ 1732 rgba[i][RCOMP] = r; \ 1733 rgba[i][GCOMP] = g; \ 1734 rgba[i][BCOMP] = b; \ 1735 rgba[i][ACOMP] = a; \ 1736 spec[i][RCOMP] = sr; \ 1737 spec[i][GCOMP] = sg; \ 1738 spec[i][BCOMP] = sb; \ 1739 s[i] = ss*invQ; \ 1740 t[i] = tt*invQ; \ 1741 u[i] = uu*invQ; \ 1742 fffog += fdfogdx; \ 1743 ffz += fdzdx; \ 1744 ss += dsdx; \ 1745 tt += dtdx; \ 1746 uu += dudx; \ 1747 vv += dvdx; \ 1748 } \ 1749 } \ 1750 else { \ 1751 for (i=0;i<n;i++) { \ 1752 GLdouble invQ = vv ? (1.0 / vv) : 1.0; \ 1753 zspan[i] = FixedToDepth(ffz); \ 1754 fogspan[i] = fffog / 256; \ 1755 rgba[i][RCOMP] = FixedToInt(ffr); \ 1756 rgba[i][GCOMP] = FixedToInt(ffg); \ 1757 rgba[i][BCOMP] = FixedToInt(ffb); \ 1758 rgba[i][ACOMP] = FixedToInt(ffa); \ 1759 spec[i][RCOMP] = FixedToInt(ffsr); \ 1760 spec[i][GCOMP] = FixedToInt(ffsg); \ 1761 spec[i][BCOMP] = FixedToInt(ffsb); \ 1762 s[i] = ss*invQ; \ 1763 t[i] = tt*invQ; \ 1764 u[i] = uu*invQ; \ 1765 fffog += fdfogdx; \ 1766 ffz += fdzdx; \ 1767 ffr += fdrdx; \ 1768 ffg += fdgdx; \ 1769 ffb += fdbdx; \ 1770 ffa += fdadx; \ 1771 ffsr += fdsrdx; \ 1772 ffsg += fdsgdx; \ 1773 ffsb += fdsbdx; \ 1774 ss += dsdx; \ 1775 tt += dtdx; \ 1776 uu += dudx; \ 1777 vv += dvdx; \ 1778 } \ 1779 } \ 1780 _mesa_write_texture_span( ctx, n, LEFT, Y, zspan, \ 1781 fogspan, \ 1782 s, t, u, NULL, rgba, \ 1783 (CONST GLchan (*)[4]) spec, \ 1784 GL_POLYGON ); \ 1785 } \ 1786 } 1787 1788#include "s_tritemp.h" 1789} 1790 1791 1792/* 1793 * Render a smooth-shaded, textured, RGBA triangle. 1794 * Interpolate S,T,U with perspective correction and compute lambda for 1795 * each fragment. Lambda is used to determine whether to use the 1796 * minification or magnification filter. If minification and using 1797 * mipmaps, lambda is also used to select the texture level of detail. 1798 */ 1799static void lambda_textured_triangle1( GLcontext *ctx, 1800 const SWvertex *v0, 1801 const SWvertex *v1, 1802 const SWvertex *v2, 1803 GLfloat s[MAX_WIDTH], 1804 GLfloat t[MAX_WIDTH], 1805 GLfloat u[MAX_WIDTH] ) 1806{ 1807#define INTERP_Z 1 1808#define INTERP_FOG 1 1809#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1810#define INTERP_RGB 1 1811#define INTERP_ALPHA 1 1812#define INTERP_LAMBDA 1 1813#define INTERP_TEX 1 1814 1815#define SETUP_CODE \ 1816 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \ 1817 const GLint baseLevel = obj->BaseLevel; \ 1818 const struct gl_texture_image *texImage = obj->Image[baseLevel]; \ 1819 const GLfloat twidth = (GLfloat) texImage->Width; \ 1820 const GLfloat theight = (GLfloat) texImage->Height; \ 1821 const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \ 1822 GLint r, g, b, a; \ 1823 if (flat_shade) { \ 1824 r = v2->color[RCOMP]; \ 1825 g = v2->color[GCOMP]; \ 1826 b = v2->color[BCOMP]; \ 1827 a = v2->color[ACOMP]; \ 1828 } 1829 1830#define INNER_LOOP( LEFT, RIGHT, Y ) \ 1831 { \ 1832 GLint i; \ 1833 const GLint n = RIGHT-LEFT; \ 1834 GLdepth zspan[MAX_WIDTH]; \ 1835 GLfixed fogspan[MAX_WIDTH]; \ 1836 GLchan rgba[MAX_WIDTH][4]; \ 1837 GLfloat lambda[MAX_WIDTH]; \ 1838 if (n>0) { \ 1839 if (flat_shade) { \ 1840 for (i=0;i<n;i++) { \ 1841 GLdouble invQ = vv ? (1.0 / vv) : 1.0; \ 1842 zspan[i] = FixedToDepth(ffz); \ 1843 fogspan[i] = fffog / 256; \ 1844 rgba[i][RCOMP] = r; \ 1845 rgba[i][GCOMP] = g; \ 1846 rgba[i][BCOMP] = b; \ 1847 rgba[i][ACOMP] = a; \ 1848 s[i] = ss*invQ; \ 1849 t[i] = tt*invQ; \ 1850 u[i] = uu*invQ; \ 1851 COMPUTE_LAMBDA(lambda[i], invQ); \ 1852 ffz += fdzdx; \ 1853 fffog += fdfogdx; \ 1854 ss += dsdx; \ 1855 tt += dtdx; \ 1856 uu += dudx; \ 1857 vv += dvdx; \ 1858 } \ 1859 } \ 1860 else { \ 1861 for (i=0;i<n;i++) { \ 1862 GLdouble invQ = vv ? (1.0 / vv) : 1.0; \ 1863 zspan[i] = FixedToDepth(ffz); \ 1864 fogspan[i] = fffog / 256; \ 1865 rgba[i][RCOMP] = FixedToInt(ffr); \ 1866 rgba[i][GCOMP] = FixedToInt(ffg); \ 1867 rgba[i][BCOMP] = FixedToInt(ffb); \ 1868 rgba[i][ACOMP] = FixedToInt(ffa); \ 1869 s[i] = ss*invQ; \ 1870 t[i] = tt*invQ; \ 1871 u[i] = uu*invQ; \ 1872 COMPUTE_LAMBDA(lambda[i], invQ); \ 1873 ffz += fdzdx; \ 1874 fffog += fdfogdx; \ 1875 ffr += fdrdx; \ 1876 ffg += fdgdx; \ 1877 ffb += fdbdx; \ 1878 ffa += fdadx; \ 1879 ss += dsdx; \ 1880 tt += dtdx; \ 1881 uu += dudx; \ 1882 vv += dvdx; \ 1883 } \ 1884 } \ 1885 _mesa_write_texture_span( ctx, n, LEFT, Y, zspan, fogspan, \ 1886 s, t, u, lambda, \ 1887 rgba, NULL, GL_POLYGON ); \ 1888 } \ 1889 } 1890 1891#include "s_tritemp.h" 1892} 1893 1894 1895/* 1896 * Render a smooth-shaded, textured, RGBA triangle with separate specular 1897 * interpolation. 1898 * Interpolate S,T,U with perspective correction and compute lambda for 1899 * each fragment. Lambda is used to determine whether to use the 1900 * minification or magnification filter. If minification and using 1901 * mipmaps, lambda is also used to select the texture level of detail. 1902 */ 1903static void lambda_textured_spec_triangle1( GLcontext *ctx, 1904 const SWvertex *v0, 1905 const SWvertex *v1, 1906 const SWvertex *v2, 1907 GLfloat s[MAX_WIDTH], 1908 GLfloat t[MAX_WIDTH], 1909 GLfloat u[MAX_WIDTH] ) 1910{ 1911#define INTERP_Z 1 1912#define INTERP_FOG 1 1913#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1914#define INTERP_RGB 1 1915#define INTERP_SPEC 1 1916#define INTERP_ALPHA 1 1917#define INTERP_TEX 1 1918#define INTERP_LAMBDA 1 1919 1920#define SETUP_CODE \ 1921 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \ 1922 const GLint baseLevel = obj->BaseLevel; \ 1923 const struct gl_texture_image *texImage = obj->Image[baseLevel]; \ 1924 const GLfloat twidth = (GLfloat) texImage->Width; \ 1925 const GLfloat theight = (GLfloat) texImage->Height; \ 1926 const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \ 1927 GLint r, g, b, a, sr, sg, sb; \ 1928 if (flat_shade) { \ 1929 r = v2->color[RCOMP]; \ 1930 g = v2->color[GCOMP]; \ 1931 b = v2->color[BCOMP]; \ 1932 a = v2->color[ACOMP]; \ 1933 sr = v2->specular[RCOMP]; \ 1934 sg = v2->specular[GCOMP]; \ 1935 sb = v2->specular[BCOMP]; \ 1936 } 1937 1938#define INNER_LOOP( LEFT, RIGHT, Y ) \ 1939 { \ 1940 GLint i; \ 1941 const GLint n = RIGHT-LEFT; \ 1942 GLdepth zspan[MAX_WIDTH]; \ 1943 GLfixed fogspan[MAX_WIDTH]; \ 1944 GLchan spec[MAX_WIDTH][4]; \ 1945 GLchan rgba[MAX_WIDTH][4]; \ 1946 GLfloat lambda[MAX_WIDTH]; \ 1947 if (n>0) { \ 1948 if (flat_shade) { \ 1949 for (i=0;i<n;i++) { \ 1950 GLdouble invQ = vv ? (1.0 / vv) : 1.0; \ 1951 zspan[i] = FixedToDepth(ffz); \ 1952 fogspan[i] = fffog / 256; \ 1953 rgba[i][RCOMP] = r; \ 1954 rgba[i][GCOMP] = g; \ 1955 rgba[i][BCOMP] = b; \ 1956 rgba[i][ACOMP] = a; \ 1957 spec[i][RCOMP] = sr; \ 1958 spec[i][GCOMP] = sg; \ 1959 spec[i][BCOMP] = sb; \ 1960 s[i] = ss*invQ; \ 1961 t[i] = tt*invQ; \ 1962 u[i] = uu*invQ; \ 1963 COMPUTE_LAMBDA(lambda[i], invQ); \ 1964 fffog += fdfogdx; \ 1965 ffz += fdzdx; \ 1966 ss += dsdx; \ 1967 tt += dtdx; \ 1968 uu += dudx; \ 1969 vv += dvdx; \ 1970 } \ 1971 } \ 1972 else { \ 1973 for (i=0;i<n;i++) { \ 1974 GLdouble invQ = vv ? (1.0 / vv) : 1.0; \ 1975 zspan[i] = FixedToDepth(ffz); \ 1976 fogspan[i] = fffog / 256; \ 1977 rgba[i][RCOMP] = FixedToInt(ffr); \ 1978 rgba[i][GCOMP] = FixedToInt(ffg); \ 1979 rgba[i][BCOMP] = FixedToInt(ffb); \ 1980 rgba[i][ACOMP] = FixedToInt(ffa); \ 1981 spec[i][RCOMP] = FixedToInt(ffsr); \ 1982 spec[i][GCOMP] = FixedToInt(ffsg); \ 1983 spec[i][BCOMP] = FixedToInt(ffsb); \ 1984 s[i] = ss*invQ; \ 1985 t[i] = tt*invQ; \ 1986 u[i] = uu*invQ; \ 1987 COMPUTE_LAMBDA(lambda[i], invQ); \ 1988 fffog += fdfogdx; \ 1989 ffz += fdzdx; \ 1990 ffr += fdrdx; \ 1991 ffg += fdgdx; \ 1992 ffb += fdbdx; \ 1993 ffa += fdadx; \ 1994 ffsr += fdsrdx; \ 1995 ffsg += fdsgdx; \ 1996 ffsb += fdsbdx; \ 1997 ss += dsdx; \ 1998 tt += dtdx; \ 1999 uu += dudx; \ 2000 vv += dvdx; \ 2001 } \ 2002 } \ 2003 _mesa_write_texture_span( ctx, n, LEFT, Y, zspan, fogspan, \ 2004 s, t, u, lambda, \ 2005 rgba, (CONST GLchan (*)[4]) spec, \ 2006 GL_POLYGON ); \ 2007 } \ 2008 } 2009 2010#include "s_tritemp.h" 2011} 2012 2013 2014/* 2015 * This is the big one! 2016 * Interpolate Z, RGB, Alpha, and two sets of texture coordinates. 2017 * Yup, it's slow. 2018 */ 2019static void 2020lambda_multitextured_triangle1( GLcontext *ctx, 2021 const SWvertex *v0, 2022 const SWvertex *v1, 2023 const SWvertex *v2, 2024 GLfloat s[MAX_TEXTURE_UNITS][MAX_WIDTH], 2025 GLfloat t[MAX_TEXTURE_UNITS][MAX_WIDTH], 2026 GLfloat u[MAX_TEXTURE_UNITS][MAX_WIDTH]) 2027{ 2028#define INTERP_Z 1 2029#define INTERP_FOG 1 2030#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 2031#define INTERP_RGB 1 2032#define INTERP_ALPHA 1 2033#define INTERP_MULTITEX 1 2034#define INTERP_MULTILAMBDA 1 2035 2036#define SETUP_CODE \ 2037 GLchan rgba[MAX_WIDTH][4]; \ 2038 const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \ 2039 GLfloat twidth[MAX_TEXTURE_UNITS], theight[MAX_TEXTURE_UNITS]; \ 2040 GLint r, g, b, a; \ 2041 if (flat_shade) { \ 2042 r = v2->color[0]; \ 2043 g = v2->color[1]; \ 2044 b = v2->color[2]; \ 2045 a = v2->color[3]; \ 2046 } \ 2047 { \ 2048 GLuint unit; \ 2049 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { \ 2050 if (ctx->Texture.Unit[unit]._ReallyEnabled) { \ 2051 const struct gl_texture_object *obj = ctx->Texture.Unit[unit]._Current; \ 2052 const GLint baseLevel = obj->BaseLevel; \ 2053 const struct gl_texture_image *texImage = obj->Image[baseLevel];\ 2054 twidth[unit] = (GLfloat) texImage->Width; \ 2055 theight[unit] = (GLfloat) texImage->Height; \ 2056 } \ 2057 } \ 2058 } 2059 2060#define INNER_LOOP( LEFT, RIGHT, Y ) \ 2061 { \ 2062 GLint i; \ 2063 const GLint n = RIGHT-LEFT; \ 2064 GLdepth zspan[MAX_WIDTH]; \ 2065 GLfixed fogspan[MAX_WIDTH]; \ 2066 GLfloat lambda[MAX_TEXTURE_UNITS][MAX_WIDTH]; \ 2067 if (n > 0) { \ 2068 if (flat_shade) { \ 2069 for (i=0;i<n;i++) { \ 2070 GLuint unit; \ 2071 zspan[i] = FixedToDepth(ffz); \ 2072 fogspan[i] = fffog / 256; \ 2073 fffog += fdfogdx; \ 2074 ffz += fdzdx; \ 2075 rgba[i][RCOMP] = r; \ 2076 rgba[i][GCOMP] = g; \ 2077 rgba[i][BCOMP] = b; \ 2078 rgba[i][ACOMP] = a; \ 2079 for (unit=0; unit < ctx->Const.MaxTextureUnits; unit++) {\ 2080 if (ctx->Texture.Unit[unit]._ReallyEnabled) { \ 2081 GLdouble invQ = 1.0 / vv[unit]; \ 2082 s[unit][i] = ss[unit] * invQ; \ 2083 t[unit][i] = tt[unit] * invQ; \ 2084 u[unit][i] = uu[unit] * invQ; \ 2085 COMPUTE_MULTILAMBDA(lambda[unit][i], invQ, unit); \ 2086 ss[unit] += dsdx[unit]; \ 2087 tt[unit] += dtdx[unit]; \ 2088 uu[unit] += dudx[unit]; \ 2089 vv[unit] += dvdx[unit]; \ 2090 } \ 2091 } \ 2092 } \ 2093 } \ 2094 else { /* smooth shade */ \ 2095 for (i=0;i<n;i++) { \ 2096 GLuint unit; \ 2097 zspan[i] = FixedToDepth(ffz); \ 2098 fogspan[i] = fffog / 256; \ 2099 ffz += fdzdx; \ 2100 fffog += fdfogdx; \ 2101 rgba[i][RCOMP] = FixedToInt(ffr); \ 2102 rgba[i][GCOMP] = FixedToInt(ffg); \ 2103 rgba[i][BCOMP] = FixedToInt(ffb); \ 2104 rgba[i][ACOMP] = FixedToInt(ffa); \ 2105 ffr += fdrdx; \ 2106 ffg += fdgdx; \ 2107 ffb += fdbdx; \ 2108 ffa += fdadx; \ 2109 for (unit=0; unit < ctx->Const.MaxTextureUnits; unit++) {\ 2110 if (ctx->Texture.Unit[unit]._ReallyEnabled) { \ 2111 GLdouble invQ = 1.0 / vv[unit]; \ 2112 s[unit][i] = ss[unit] * invQ; \ 2113 t[unit][i] = tt[unit] * invQ; \ 2114 u[unit][i] = uu[unit] * invQ; \ 2115 COMPUTE_MULTILAMBDA(lambda[unit][i], invQ, unit); \ 2116 ss[unit] += dsdx[unit]; \ 2117 tt[unit] += dtdx[unit]; \ 2118 uu[unit] += dudx[unit]; \ 2119 vv[unit] += dvdx[unit]; \ 2120 } \ 2121 } \ 2122 } \ 2123 } \ 2124 _mesa_write_multitexture_span(ctx, n, LEFT, Y, zspan, fogspan, \ 2125 (const GLfloat (*)[MAX_WIDTH]) s,\ 2126 (const GLfloat (*)[MAX_WIDTH]) t,\ 2127 (const GLfloat (*)[MAX_WIDTH]) u,\ 2128 (GLfloat (*)[MAX_WIDTH]) lambda, \ 2129 rgba, NULL, GL_POLYGON ); \ 2130 } \ 2131 } 2132 2133#include "s_tritemp.h" 2134} 2135 2136 2137/* 2138 * These wrappers are needed to deal with the 32KB / stack frame limit 2139 * on Mac / PowerPC systems. 2140 */ 2141 2142static void general_textured_spec_triangle(GLcontext *ctx, 2143 const SWvertex *v0, 2144 const SWvertex *v1, 2145 const SWvertex *v2 ) 2146{ 2147 GLdepth zspan[MAX_WIDTH]; 2148 GLfixed fogspan[MAX_WIDTH]; 2149 GLchan rgba[MAX_WIDTH][4], spec[MAX_WIDTH][4]; 2150 general_textured_spec_triangle1(ctx,v0,v1,v2,zspan,fogspan,rgba,spec); 2151} 2152 2153static void lambda_textured_triangle( GLcontext *ctx, 2154 const SWvertex *v0, 2155 const SWvertex *v1, 2156 const SWvertex *v2 ) 2157{ 2158 GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH]; 2159 lambda_textured_triangle1(ctx,v0,v1,v2,s,t,u); 2160} 2161 2162static void lambda_textured_spec_triangle( GLcontext *ctx, 2163 const SWvertex *v0, 2164 const SWvertex *v1, 2165 const SWvertex *v2 ) 2166{ 2167 GLfloat s[MAX_WIDTH]; 2168 GLfloat t[MAX_WIDTH]; 2169 GLfloat u[MAX_WIDTH]; 2170 lambda_textured_spec_triangle1(ctx,v0,v1,v2,s,t,u); 2171} 2172 2173 2174static void lambda_multitextured_triangle( GLcontext *ctx, 2175 const SWvertex *v0, 2176 const SWvertex *v1, 2177 const SWvertex *v2 ) 2178{ 2179 2180 GLfloat s[MAX_TEXTURE_UNITS][MAX_WIDTH]; 2181 GLfloat t[MAX_TEXTURE_UNITS][MAX_WIDTH]; 2182 DEFMARRAY(GLfloat,u,MAX_TEXTURE_UNITS,MAX_WIDTH); 2183 CHECKARRAY(u,return); 2184 2185 lambda_multitextured_triangle1(ctx,v0,v1,v2,s,t,u); 2186 2187 UNDEFARRAY(u); 2188} 2189 2190 2191 2192static void occlusion_zless_triangle( GLcontext *ctx, 2193 const SWvertex *v0, 2194 const SWvertex *v1, 2195 const SWvertex *v2 ) 2196{ 2197 if (ctx->OcclusionResult) { 2198 return; 2199 } 2200 2201#define DO_OCCLUSION_TEST 2202#define INTERP_Z 1 2203#define INTERP_FOG 1 2204#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 2205#define INNER_LOOP( LEFT, RIGHT, Y ) \ 2206 { \ 2207 GLint i; \ 2208 const GLint len = RIGHT-LEFT; \ 2209 for (i=0;i<len;i++) { \ 2210 GLdepth z = FixedToDepth(ffz); \ 2211 (void) fffog; \ 2212 if (z < zRow[i]) { \ 2213 ctx->OcclusionResult = GL_TRUE; \ 2214 return; \ 2215 } \ 2216 ffz += fdzdx; \ 2217 } \ 2218 } 2219#include "s_tritemp.h" 2220} 2221 2222static void nodraw_triangle( GLcontext *ctx, 2223 const SWvertex *v0, 2224 const SWvertex *v1, 2225 const SWvertex *v2 ) 2226{ 2227 (void) (ctx && v0 && v1 && v2); 2228} 2229 2230void _swrast_add_spec_terms_triangle( GLcontext *ctx, 2231 const SWvertex *v0, 2232 const SWvertex *v1, 2233 const SWvertex *v2 ) 2234{ 2235 SWvertex *ncv0 = (SWvertex *)v0; /* drop const qualifier */ 2236 SWvertex *ncv1 = (SWvertex *)v1; 2237 SWvertex *ncv2 = (SWvertex *)v2; 2238 GLchan c[3][4]; 2239 COPY_CHAN4( c[0], ncv0->color ); 2240 COPY_CHAN4( c[1], ncv1->color ); 2241 COPY_CHAN4( c[2], ncv2->color ); 2242 ACC_3V( ncv0->color, ncv0->specular ); 2243 ACC_3V( ncv1->color, ncv1->specular ); 2244 ACC_3V( ncv2->color, ncv2->specular ); 2245 SWRAST_CONTEXT(ctx)->SpecTriangle( ctx, ncv0, ncv1, ncv2 ); 2246 COPY_CHAN4( ncv0->color, c[0] ); 2247 COPY_CHAN4( ncv1->color, c[1] ); 2248 COPY_CHAN4( ncv2->color, c[2] ); 2249} 2250 2251 2252 2253#if 0 2254# define dputs(s) puts(s) 2255#else 2256# define dputs(s) 2257#endif 2258 2259 2260 2261/* 2262 * Determine which triangle rendering function to use given the current 2263 * rendering context. 2264 * 2265 * Please update the summary flag _SWRAST_NEW_TRIANGLE if you add or 2266 * remove tests to this code. 2267 */ 2268void 2269_swrast_choose_triangle( GLcontext *ctx ) 2270{ 2271 SWcontext *swrast = SWRAST_CONTEXT(ctx); 2272 const GLboolean rgbmode = ctx->Visual.rgbMode; 2273 2274 if (ctx->Polygon.CullFlag && 2275 ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) { 2276 dputs("nodraw_triangle"); 2277 swrast->Triangle = nodraw_triangle; 2278 return; 2279 } 2280 2281 2282 2283 if (ctx->RenderMode==GL_RENDER) { 2284 2285 if (ctx->Polygon.SmoothFlag) { 2286 _mesa_set_aa_triangle_function(ctx); 2287 ASSERT(swrast->Triangle); 2288 return; 2289 } 2290 2291 if (ctx->Depth.OcclusionTest && 2292 ctx->Depth.Test && 2293 ctx->Depth.Mask == GL_FALSE && 2294 ctx->Depth.Func == GL_LESS && 2295 !ctx->Stencil.Enabled) { 2296 if ((rgbmode && 2297 ctx->Color.ColorMask[0] == 0 && 2298 ctx->Color.ColorMask[1] == 0 && 2299 ctx->Color.ColorMask[2] == 0 && 2300 ctx->Color.ColorMask[3] == 0) 2301 || 2302 (!rgbmode && ctx->Color.IndexMask == 0)) { 2303 dputs("occlusion_test_triangle"); 2304 swrast->Triangle = occlusion_zless_triangle; 2305 return; 2306 } 2307 } 2308 2309 if (ctx->Texture._ReallyEnabled) { 2310 /* Ugh, we do a _lot_ of tests to pick the best textured tri func */ 2311 GLint format, filter; 2312 const struct gl_texture_object *current2Dtex = ctx->Texture.Unit[0].Current2D; 2313 const struct gl_texture_image *image; 2314 /* First see if we can used an optimized 2-D texture function */ 2315 if (ctx->Texture._ReallyEnabled==TEXTURE0_2D 2316 && current2Dtex->WrapS==GL_REPEAT 2317 && current2Dtex->WrapT==GL_REPEAT 2318 && ((image = current2Dtex->Image[current2Dtex->BaseLevel]) != 0) /* correct! */ 2319 && image->Border==0 2320 && ((format = image->Format)==GL_RGB || format==GL_RGBA) 2321 && image->Type == CHAN_TYPE 2322 && (filter = current2Dtex->MinFilter)==current2Dtex->MagFilter 2323 /* ==> current2Dtex->MinFilter != GL_XXX_MIPMAP_XXX */ 2324 && ctx->Light.Model.ColorControl==GL_SINGLE_COLOR 2325 && ctx->Texture.Unit[0].EnvMode!=GL_COMBINE_EXT) { 2326 2327 if (ctx->Hint.PerspectiveCorrection==GL_FASTEST) { 2328 2329 if (filter==GL_NEAREST 2330 && format==GL_RGB 2331 && (ctx->Texture.Unit[0].EnvMode==GL_REPLACE 2332 || ctx->Texture.Unit[0].EnvMode==GL_DECAL) 2333 && ((swrast->_RasterMask==DEPTH_BIT 2334 && ctx->Depth.Func==GL_LESS 2335 && ctx->Depth.Mask==GL_TRUE) 2336 || swrast->_RasterMask==0) 2337 && ctx->Polygon.StippleFlag==GL_FALSE) { 2338 2339 if (swrast->_RasterMask==DEPTH_BIT) { 2340 swrast->Triangle = simple_z_textured_triangle; 2341 dputs("simple_z_textured_triangle"); 2342 } 2343 else { 2344 swrast->Triangle = simple_textured_triangle; 2345 dputs("simple_textured_triangle"); 2346 } 2347 } 2348 else { 2349 if (ctx->Texture.Unit[0].EnvMode==GL_ADD) { 2350 swrast->Triangle = general_textured_triangle; 2351 dputs("general_textured_triangle"); 2352 } 2353 else { 2354 swrast->Triangle = affine_textured_triangle; 2355 dputs("affine_textured_triangle"); 2356 } 2357 } 2358 } 2359 else { 2360#if 00 /* XXX these function have problems with texture coord interpolation */ 2361 if (filter==GL_NEAREST) { 2362 swrast->Triangle = near_persp_textured_triangle; 2363 dputs("near_persp_textured_triangle"); 2364 } 2365 else { 2366 swrast->Triangle = lin_persp_textured_triangle; 2367 dputs("lin_persp_textured_triangle"); 2368 } 2369#endif 2370 swrast->Triangle = general_textured_triangle; 2371 } 2372 } 2373 else { 2374 /* More complicated textures (mipmap, multi-tex, sep specular) */ 2375 GLboolean needLambda; 2376 /* if mag filter != min filter we need to compute lambda */ 2377 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; 2378 if (obj && obj->MinFilter != obj->MagFilter) 2379 needLambda = GL_TRUE; 2380 else 2381 needLambda = GL_FALSE; 2382 if (swrast->_MultiTextureEnabled) { 2383 swrast->Triangle = lambda_multitextured_triangle; 2384 dputs("lambda_multitextured_triangle"); 2385 } 2386 else if (ctx->_TriangleCaps & DD_SEPERATE_SPECULAR) { 2387 /* separate specular color interpolation */ 2388 if (needLambda) { 2389 swrast->Triangle = lambda_textured_spec_triangle; 2390 dputs("lambda_textured_spec_triangle"); 2391 } 2392 else { 2393 swrast->Triangle = general_textured_spec_triangle; 2394 dputs("general_textured_spec_triangle"); 2395 } 2396 } 2397 else { 2398 if (needLambda) { 2399 swrast->Triangle = lambda_textured_triangle; 2400 dputs("lambda_textured_triangle"); 2401 } 2402 else { 2403 swrast->Triangle = general_textured_triangle; 2404 dputs("general_textured_triangle"); 2405 } 2406 } 2407 } 2408 } 2409 else { 2410 if (ctx->Light.ShadeModel==GL_SMOOTH) { 2411 /* smooth shaded, no texturing, stippled or some raster ops */ 2412 if (rgbmode) { 2413 dputs("smooth_rgba_triangle"); 2414 swrast->Triangle = smooth_rgba_triangle; 2415 } 2416 else { 2417 dputs("smooth_ci_triangle"); 2418 swrast->Triangle = smooth_ci_triangle; 2419 } 2420 } 2421 else { 2422 /* flat shaded, no texturing, stippled or some raster ops */ 2423 if (rgbmode) { 2424 dputs("flat_rgba_triangle"); 2425 swrast->Triangle = flat_rgba_triangle; 2426 } 2427 else { 2428 dputs("flat_ci_triangle"); 2429 swrast->Triangle = flat_ci_triangle; 2430 } 2431 } 2432 } 2433 } 2434 else if (ctx->RenderMode==GL_FEEDBACK) { 2435 swrast->Triangle = _mesa_feedback_triangle; 2436 } 2437 else { 2438 /* GL_SELECT mode */ 2439 swrast->Triangle = _mesa_select_triangle; 2440 } 2441} 2442