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