s_triangle.c revision a852378a6289d154364dde440f89a39bbfc33e2d
1/* $Id: s_triangle.c,v 1.5 2000/11/19 23:10:26 brianp 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#define SETUP_CODE 78 79#define INNER_LOOP( LEFT, RIGHT, Y ) \ 80 { \ 81 const GLint n = RIGHT-LEFT; \ 82 GLint i; \ 83 GLdepth zspan[MAX_WIDTH]; \ 84 GLfixed fogspan[MAX_WIDTH]; \ 85 if (n>0) { \ 86 for (i=0;i<n;i++) { \ 87 zspan[i] = FixedToDepth(ffz); \ 88 ffz += fdzdx; \ 89 fogspan[i] = fffog / 256; \ 90 fffog += fdfogdx; \ 91 } \ 92 gl_write_monoindex_span( ctx, n, LEFT, Y, zspan, \ 93 fogspan, v0->index, GL_POLYGON ); \ 94 } \ 95 } 96 97#include "s_tritemp.h" 98} 99 100 101 102/* 103 * Render a smooth-shaded color index triangle. 104 */ 105static void smooth_ci_triangle( GLcontext *ctx, 106 const SWvertex *v0, 107 const SWvertex *v1, 108 const SWvertex *v2 ) 109{ 110#define INTERP_Z 1 111#define INTERP_INDEX 1 112 113#define INNER_LOOP( LEFT, RIGHT, Y ) \ 114 { \ 115 const GLint n = RIGHT-LEFT; \ 116 GLint i; \ 117 GLdepth zspan[MAX_WIDTH]; \ 118 GLfixed fogspan[MAX_WIDTH]; \ 119 GLuint index[MAX_WIDTH]; \ 120 if (n>0) { \ 121 for (i=0;i<n;i++) { \ 122 zspan[i] = FixedToDepth(ffz); \ 123 ffz += fdzdx; \ 124 index[i] = FixedToInt(ffi); \ 125 ffi += fdidx; \ 126 fogspan[i] = fffog / 256; \ 127 fffog += fdfogdx; \ 128 } \ 129 gl_write_index_span( ctx, n, LEFT, Y, zspan, fogspan, \ 130 index, GL_POLYGON ); \ 131 } \ 132 } 133 134#include "s_tritemp.h" 135} 136 137 138 139/* 140 * Render a flat-shaded RGBA triangle. 141 */ 142static void flat_rgba_triangle( GLcontext *ctx, 143 const SWvertex *v0, 144 const SWvertex *v1, 145 const SWvertex *v2 ) 146{ 147#define INTERP_Z 1 148#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 149 150#define SETUP_CODE 151 152#define INNER_LOOP( LEFT, RIGHT, Y ) \ 153 { \ 154 const GLint n = RIGHT-LEFT; \ 155 GLint i; \ 156 GLdepth zspan[MAX_WIDTH]; \ 157 GLfixed fogspan[MAX_WIDTH]; \ 158 if (n>0) { \ 159 for (i=0;i<n;i++) { \ 160 zspan[i] = FixedToDepth(ffz); \ 161 ffz += fdzdx; \ 162 fogspan[i] = fffog / 256; \ 163 fffog += fdfogdx; \ 164 } \ 165 gl_write_monocolor_span( ctx, n, LEFT, Y, zspan, \ 166 fogspan, v0->color, \ 167 GL_POLYGON ); \ 168 } \ 169 } 170 171#include "s_tritemp.h" 172 173 ASSERT(!ctx->Texture._ReallyEnabled); /* texturing must be off */ 174 ASSERT(ctx->Light.ShadeModel==GL_FLAT); 175} 176 177 178 179/* 180 * Render a smooth-shaded RGBA triangle. 181 */ 182static void smooth_rgba_triangle( GLcontext *ctx, 183 const SWvertex *v0, 184 const SWvertex *v1, 185 const SWvertex *v2 ) 186{ 187 188#define INTERP_Z 1 189#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 190#define INTERP_RGB 1 191#define INTERP_ALPHA 1 192 193#define INNER_LOOP( LEFT, RIGHT, Y ) \ 194 { \ 195 const GLint n = RIGHT-LEFT; \ 196 GLint i; \ 197 GLdepth zspan[MAX_WIDTH]; \ 198 GLchan rgba[MAX_WIDTH][4]; \ 199 GLfixed fogspan[MAX_WIDTH]; \ 200 if (n>0) { \ 201 for (i=0;i<n;i++) { \ 202 zspan[i] = FixedToDepth(ffz); \ 203 rgba[i][RCOMP] = FixedToInt(ffr); \ 204 rgba[i][GCOMP] = FixedToInt(ffg); \ 205 rgba[i][BCOMP] = FixedToInt(ffb); \ 206 rgba[i][ACOMP] = FixedToInt(ffa); \ 207 fogspan[i] = fffog / 256; \ 208 fffog += fdfogdx; \ 209 ffz += fdzdx; \ 210 ffr += fdrdx; \ 211 ffg += fdgdx; \ 212 ffb += fdbdx; \ 213 ffa += fdadx; \ 214 } \ 215 gl_write_rgba_span( ctx, n, LEFT, Y, \ 216 (CONST GLdepth *) zspan, \ 217 fogspan, \ 218 rgba, GL_POLYGON ); \ 219 } \ 220 } 221 222#include "s_tritemp.h" 223 224 ASSERT(!ctx->Texture._ReallyEnabled); /* texturing must be off */ 225 ASSERT(ctx->Light.ShadeModel==GL_SMOOTH); 226} 227 228 229/* 230 * Render an RGB, GL_DECAL, textured triangle. 231 * Interpolate S,T only w/out mipmapping or perspective correction. 232 * 233 * No fog. 234 */ 235static void simple_textured_triangle( GLcontext *ctx, 236 const SWvertex *v0, 237 const SWvertex *v1, 238 const SWvertex *v2 ) 239{ 240#define INTERP_INT_TEX 1 241#define S_SCALE twidth 242#define T_SCALE theight 243#define SETUP_CODE \ 244 struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \ 245 GLint b = obj->BaseLevel; \ 246 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ 247 GLfloat theight = (GLfloat) obj->Image[b]->Height; \ 248 GLint twidth_log2 = obj->Image[b]->WidthLog2; \ 249 GLchan *texture = obj->Image[b]->Data; \ 250 GLint smask = obj->Image[b]->Width - 1; \ 251 GLint tmask = obj->Image[b]->Height - 1; \ 252 if (!texture) { \ 253 if (!_mesa_get_teximages_from_driver(ctx, obj)) \ 254 return; \ 255 texture = obj->Image[b]->Data; \ 256 ASSERT(texture); \ 257 } 258 259#define INNER_LOOP( LEFT, RIGHT, Y ) \ 260 { \ 261 CONST GLint n = RIGHT-LEFT; \ 262 GLint i; \ 263 GLchan rgb[MAX_WIDTH][3]; \ 264 if (n>0) { \ 265 ffs -= FIXED_HALF; /* off-by-one error? */ \ 266 fft -= FIXED_HALF; \ 267 for (i=0;i<n;i++) { \ 268 GLint s = FixedToInt(ffs) & smask; \ 269 GLint t = FixedToInt(fft) & tmask; \ 270 GLint pos = (t << twidth_log2) + s; \ 271 pos = pos + pos + pos; /* multiply by 3 */ \ 272 rgb[i][RCOMP] = texture[pos]; \ 273 rgb[i][GCOMP] = texture[pos+1]; \ 274 rgb[i][BCOMP] = texture[pos+2]; \ 275 ffs += fdsdx; \ 276 fft += fdtdx; \ 277 } \ 278 (*ctx->Driver.WriteRGBSpan)( ctx, n, LEFT, Y, \ 279 (CONST GLchan (*)[3]) rgb, NULL ); \ 280 } \ 281 } 282 283#include "s_tritemp.h" 284} 285 286 287/* 288 * Render an RGB, GL_DECAL, textured triangle. 289 * Interpolate S,T, GL_LESS depth test, w/out mipmapping or 290 * perspective correction. 291 * 292 * No fog. 293 */ 294static void simple_z_textured_triangle( GLcontext *ctx, 295 const SWvertex *v0, 296 const SWvertex *v1, 297 const SWvertex *v2 ) 298{ 299#define INTERP_Z 1 300#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 301#define INTERP_INT_TEX 1 302#define S_SCALE twidth 303#define T_SCALE theight 304#define SETUP_CODE \ 305 struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \ 306 GLint b = obj->BaseLevel; \ 307 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ 308 GLfloat theight = (GLfloat) obj->Image[b]->Height; \ 309 GLint twidth_log2 = obj->Image[b]->WidthLog2; \ 310 GLchan *texture = obj->Image[b]->Data; \ 311 GLint smask = obj->Image[b]->Width - 1; \ 312 GLint tmask = obj->Image[b]->Height - 1; \ 313 if (!texture) { \ 314 if (!_mesa_get_teximages_from_driver(ctx, obj)) \ 315 return; \ 316 texture = obj->Image[b]->Data; \ 317 ASSERT(texture); \ 318 } 319 320#define INNER_LOOP( LEFT, RIGHT, Y ) \ 321 { \ 322 CONST GLint n = RIGHT-LEFT; \ 323 GLint i; \ 324 GLchan rgb[MAX_WIDTH][3]; \ 325 GLubyte mask[MAX_WIDTH]; \ 326 (void) fffog; \ 327 if (n>0) { \ 328 ffs -= FIXED_HALF; /* off-by-one error? */ \ 329 fft -= FIXED_HALF; \ 330 for (i=0;i<n;i++) { \ 331 GLdepth z = FixedToDepth(ffz); \ 332 if (z < zRow[i]) { \ 333 GLint s = FixedToInt(ffs) & smask; \ 334 GLint t = FixedToInt(fft) & tmask; \ 335 GLint pos = (t << twidth_log2) + s; \ 336 pos = pos + pos + pos; /* multiply by 3 */ \ 337 rgb[i][RCOMP] = texture[pos]; \ 338 rgb[i][GCOMP] = texture[pos+1]; \ 339 rgb[i][BCOMP] = texture[pos+2]; \ 340 zRow[i] = z; \ 341 mask[i] = 1; \ 342 } \ 343 else { \ 344 mask[i] = 0; \ 345 } \ 346 ffz += fdzdx; \ 347 ffs += fdsdx; \ 348 fft += fdtdx; \ 349 } \ 350 (*ctx->Driver.WriteRGBSpan)( ctx, n, LEFT, Y, \ 351 (CONST GLchan (*)[3]) rgb, mask ); \ 352 } \ 353 } 354 355#include "s_tritemp.h" 356} 357 358 359 360/* 361 * Render an RGB/RGBA textured triangle without perspective correction. 362 */ 363static void affine_textured_triangle( GLcontext *ctx, 364 const SWvertex *v0, 365 const SWvertex *v1, 366 const SWvertex *v2 ) 367{ 368#define INTERP_Z 1 369#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 370#define INTERP_RGB 1 371#define INTERP_ALPHA 1 372#define INTERP_INT_TEX 1 373#define S_SCALE twidth 374#define T_SCALE theight 375#define SETUP_CODE \ 376 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \ 377 struct gl_texture_object *obj = unit->Current2D; \ 378 GLint b = obj->BaseLevel; \ 379 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ 380 GLfloat theight = (GLfloat) obj->Image[b]->Height; \ 381 GLint twidth_log2 = obj->Image[b]->WidthLog2; \ 382 GLchan *texture = obj->Image[b]->Data; \ 383 GLint smask = obj->Image[b]->Width - 1; \ 384 GLint tmask = obj->Image[b]->Height - 1; \ 385 GLint format = obj->Image[b]->Format; \ 386 GLint filter = obj->MinFilter; \ 387 GLint envmode = unit->EnvMode; \ 388 GLint comp, tbytesline, tsize; \ 389 GLfixed er, eg, eb, ea; \ 390 GLint tr, tg, tb, ta; \ 391 if (!texture) { \ 392 if (!_mesa_get_teximages_from_driver(ctx, obj)) \ 393 return; \ 394 texture = obj->Image[b]->Data; \ 395 ASSERT(texture); \ 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[0]); \ 400 eg = FloatToFixed(unit->EnvColor[1]); \ 401 eb = FloatToFixed(unit->EnvColor[2]); \ 402 ea = FloatToFixed(unit->EnvColor[3]); \ 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 gl_problem(NULL, "Bad texture format in affine_texture_triangle");\ 421 return; \ 422 } \ 423 tbytesline = obj->Image[b]->Width * comp; \ 424 tsize = theight * 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[0]; \ 435 tg = tex00[1]; \ 436 tb = tex00[2]; \ 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[0]; \ 450 tg = tex00[1]; \ 451 tb = tex00[2]; \ 452 ta = tex00[3] 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[0] = ffr * (tr + 1) >> (FIXED_SHIFT + 8); \ 466 dest[1] = ffg * (tg + 1) >> (FIXED_SHIFT + 8); \ 467 dest[2] = ffb * (tb + 1) >> (FIXED_SHIFT + 8); \ 468 dest[3] = ffa * (ta + 1) >> (FIXED_SHIFT + 8) 469 470#define DECAL \ 471 dest[0] = ((0xff - ta) * ffr + ((ta + 1) * tr << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \ 472 dest[1] = ((0xff - ta) * ffg + ((ta + 1) * tg << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \ 473 dest[2] = ((0xff - ta) * ffb + ((ta + 1) * tb << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \ 474 dest[3] = FixedToInt(ffa) 475 476#define BLEND \ 477 dest[0] = ((0xff - tr) * ffr + (tr + 1) * er) >> (FIXED_SHIFT + 8); \ 478 dest[1] = ((0xff - tg) * ffg + (tg + 1) * eg) >> (FIXED_SHIFT + 8); \ 479 dest[2] = ((0xff - tb) * ffb + (tb + 1) * eb) >> (FIXED_SHIFT + 8); \ 480 dest[3] = ffa * (ta + 1) >> (FIXED_SHIFT + 8) 481 482#define REPLACE \ 483 dest[0] = tr; \ 484 dest[1] = tg; \ 485 dest[2] = tb; \ 486 dest[3] = ta 487 488#define ADD \ 489 dest[0] = ((ffr << 8) + (tr + 1) * er) >> (FIXED_SHIFT + 8); \ 490 dest[1] = ((ffg << 8) + (tg + 1) * eg) >> (FIXED_SHIFT + 8); \ 491 dest[2] = ((ffb << 8) + (tb + 1) * eb) >> (FIXED_SHIFT + 8); \ 492 dest[3] = 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 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 GLchan *tex00 = texture + COMP * pos; \ 530 GLchan *tex10 = tex00 + tbytesline; \ 531 GLchan *tex01 = tex00 + COMP; \ 532 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 gl_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 */ 685static void near_persp_textured_triangle(GLcontext *ctx, 686 const SWvertex *v0, 687 const SWvertex *v1, 688 const SWvertex *v2 ) 689{ 690/* The BIAS value is used to shift negative values into positive values. 691 * Without this, negative texture values don't GL_REPEAT correctly at just 692 * below zero, because (int)-0.5 = 0 = (int)0.5. We're not going to worry 693 * about texture coords less than -BIAS. This could be fixed by using 694 * FLOORF etc. instead, but this is slower... 695 */ 696#define BIAS 4096.0F 697 698#define INTERP_Z 1 699#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 700#define INTERP_RGB 1 701#define INTERP_ALPHA 1 702#define INTERP_TEX 1 703#define SETUP_CODE \ 704 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \ 705 struct gl_texture_object *obj = unit->Current2D; \ 706 const GLint b = obj->BaseLevel; \ 707 const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ 708 const GLfloat theight = (GLfloat) obj->Image[b]->Height; \ 709 const GLint twidth_log2 = obj->Image[b]->WidthLog2; \ 710 GLchan *texture = obj->Image[b]->Data; \ 711 const GLint smask = (obj->Image[b]->Width - 1); \ 712 const GLint tmask = (obj->Image[b]->Height - 1); \ 713 const GLint format = obj->Image[b]->Format; \ 714 const GLint envmode = unit->EnvMode; \ 715 GLfloat sscale, tscale; \ 716 GLfixed er, eg, eb, ea; \ 717 GLint tr, tg, tb, ta; \ 718 if (!texture) { \ 719 if (!_mesa_get_teximages_from_driver(ctx, obj)) \ 720 return; \ 721 texture = obj->Image[b]->Data; \ 722 ASSERT(texture); \ 723 } \ 724 if (envmode == GL_BLEND || envmode == GL_ADD) { \ 725 er = FloatToFixed(unit->EnvColor[0]); \ 726 eg = FloatToFixed(unit->EnvColor[1]); \ 727 eb = FloatToFixed(unit->EnvColor[2]); \ 728 ea = FloatToFixed(unit->EnvColor[3]); \ 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 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 gl_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 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 */ 1425static void lin_persp_textured_triangle( GLcontext *ctx, 1426 const SWvertex *v0, 1427 const SWvertex *v1, 1428 const SWvertex *v2 ) 1429{ 1430#define INTERP_Z 1 1431#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1432#define INTERP_RGB 1 1433#define INTERP_ALPHA 1 1434#define INTERP_TEX 1 1435#define SETUP_CODE \ 1436 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \ 1437 struct gl_texture_object *obj = unit->Current2D; \ 1438 const GLint b = obj->BaseLevel; \ 1439 const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ 1440 const GLfloat theight = (GLfloat) obj->Image[b]->Height; \ 1441 const GLint twidth_log2 = obj->Image[b]->WidthLog2; \ 1442 GLchan *texture = obj->Image[b]->Data; \ 1443 const GLint smask = (obj->Image[b]->Width - 1); \ 1444 const GLint tmask = (obj->Image[b]->Height - 1); \ 1445 const GLint format = obj->Image[b]->Format; \ 1446 const GLint envmode = unit->EnvMode; \ 1447 GLfloat sscale, tscale; \ 1448 GLint comp, tbytesline, tsize; \ 1449 GLfixed er, eg, eb, ea; \ 1450 GLint tr, tg, tb, ta; \ 1451 if (!texture) { \ 1452 if (!_mesa_get_teximages_from_driver(ctx, obj)) \ 1453 return; \ 1454 texture = obj->Image[b]->Data; \ 1455 ASSERT(texture); \ 1456 } \ 1457 if (envmode == GL_BLEND || envmode == GL_ADD) { \ 1458 er = FloatToFixed(unit->EnvColor[0]); \ 1459 eg = FloatToFixed(unit->EnvColor[1]); \ 1460 eb = FloatToFixed(unit->EnvColor[2]); \ 1461 ea = FloatToFixed(unit->EnvColor[3]); \ 1462 } \ 1463 switch (format) { \ 1464 case GL_ALPHA: \ 1465 case GL_LUMINANCE: \ 1466 case GL_INTENSITY: \ 1467 comp = 1; \ 1468 break; \ 1469 case GL_LUMINANCE_ALPHA: \ 1470 comp = 2; \ 1471 break; \ 1472 case GL_RGB: \ 1473 comp = 3; \ 1474 break; \ 1475 case GL_RGBA: \ 1476 comp = 4; \ 1477 break; \ 1478 default: \ 1479 gl_problem(NULL, "Bad texture format in lin_persp_texture_triangle"); \ 1480 return; \ 1481 } \ 1482 sscale = FIXED_SCALE * twidth; \ 1483 tscale = FIXED_SCALE * theight; \ 1484 tbytesline = obj->Image[b]->Width * comp; \ 1485 tsize = theight * tbytesline; 1486 1487 1488#define SPAN(DO_TEX,COMP) \ 1489 for (i=0;i<n;i++) { \ 1490 GLfloat invQ = 1.0f / vv; \ 1491 GLfixed ffs = (int)(SS * invQ); \ 1492 GLfixed fft = (int)(TT * invQ); \ 1493 GLint s = FixedToInt(ffs) & smask; \ 1494 GLint t = FixedToInt(fft) & tmask; \ 1495 GLint sf = ffs & FIXED_FRAC_MASK; \ 1496 GLint tf = fft & FIXED_FRAC_MASK; \ 1497 GLint si = FIXED_FRAC_MASK - sf; \ 1498 GLint ti = FIXED_FRAC_MASK - tf; \ 1499 GLint pos = COMP * ((t << twidth_log2) + s); \ 1500 GLchan *tex00 = texture + pos; \ 1501 GLchan *tex10 = tex00 + tbytesline; \ 1502 GLchan *tex01 = tex00 + COMP; \ 1503 GLchan *tex11 = tex10 + COMP; \ 1504 if (t == tmask) { \ 1505 tex10 -= tsize; \ 1506 tex11 -= tsize; \ 1507 } \ 1508 if (s == smask) { \ 1509 tex01 -= tbytesline; \ 1510 tex11 -= tbytesline; \ 1511 } \ 1512 zspan[i] = FixedToDepth(ffz); \ 1513 fogspan[i] = fffog / 256; \ 1514 DO_TEX; \ 1515 fffog += fdfogdx; \ 1516 ffz += fdzdx; \ 1517 ffr += fdrdx; \ 1518 ffg += fdgdx; \ 1519 ffb += fdbdx; \ 1520 ffa += fdadx; \ 1521 SS += dSdx; \ 1522 TT += dTdx; \ 1523 vv += dvdx; \ 1524 dest += 4; \ 1525 } 1526 1527#define INNER_LOOP( LEFT, RIGHT, Y ) \ 1528 { \ 1529 GLint i; \ 1530 const GLint n = RIGHT-LEFT; \ 1531 GLdepth zspan[MAX_WIDTH]; \ 1532 GLfixed fogspan[MAX_WIDTH]; \ 1533 GLchan rgba[MAX_WIDTH][4]; \ 1534 (void) uu; /* please GCC */ \ 1535 if (n > 0) { \ 1536 GLfloat SS = ss * sscale; \ 1537 GLfloat TT = tt * tscale; \ 1538 GLfloat dSdx = dsdx * sscale; \ 1539 GLfloat dTdx = dtdx * tscale; \ 1540 GLchan *dest = rgba[0]; \ 1541 SS -= 0.5f * FIXED_SCALE * vv; \ 1542 TT -= 0.5f * FIXED_SCALE * vv; \ 1543 switch (format) { \ 1544 case GL_RGB: \ 1545 switch (envmode) { \ 1546 case GL_MODULATE: \ 1547 SPAN(LINEAR_RGB;MODULATE,3); \ 1548 break; \ 1549 case GL_DECAL: \ 1550 case GL_REPLACE: \ 1551 SPAN(LINEAR_RGB;REPLACE,3); \ 1552 break; \ 1553 case GL_BLEND: \ 1554 SPAN(LINEAR_RGB;BLEND,3); \ 1555 break; \ 1556 case GL_ADD: \ 1557 SPAN(LINEAR_RGB;ADD,3); \ 1558 break; \ 1559 default: \ 1560 abort(); \ 1561 } \ 1562 break; \ 1563 case GL_RGBA: \ 1564 switch (envmode) { \ 1565 case GL_MODULATE: \ 1566 SPAN(LINEAR_RGBA;MODULATE,4); \ 1567 break; \ 1568 case GL_DECAL: \ 1569 SPAN(LINEAR_RGBA;DECAL,4); \ 1570 break; \ 1571 case GL_BLEND: \ 1572 SPAN(LINEAR_RGBA;BLEND,4); \ 1573 break; \ 1574 case GL_REPLACE: \ 1575 SPAN(LINEAR_RGBA;REPLACE,4); \ 1576 break; \ 1577 case GL_ADD: \ 1578 SPAN(LINEAR_RGBA;ADD,4); \ 1579 break; \ 1580 default: /* unexpected env mode */ \ 1581 abort(); \ 1582 } \ 1583 } \ 1584 gl_write_rgba_span( ctx, n, LEFT, Y, zspan, \ 1585 fogspan, \ 1586 rgba, GL_POLYGON ); \ 1587 ffr = ffg = ffb = ffa = 0; \ 1588 } \ 1589 } 1590 1591 1592#include "s_tritemp.h" 1593#undef SPAN 1594} 1595 1596 1597 1598/* 1599 * Render a smooth-shaded, textured, RGBA triangle. 1600 * Interpolate S,T,U with perspective correction, w/out mipmapping. 1601 * Note: we use texture coordinates S,T,U,V instead of S,T,R,Q because 1602 * R is already used for red. 1603 */ 1604static void general_textured_triangle( GLcontext *ctx, 1605 const SWvertex *v0, 1606 const SWvertex *v1, 1607 const SWvertex *v2 ) 1608{ 1609#define INTERP_Z 1 1610#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1611#define INTERP_RGB 1 1612#define INTERP_ALPHA 1 1613#define INTERP_TEX 1 1614#define SETUP_CODE \ 1615 GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \ 1616 GLint r, g, b, a; \ 1617 if (flat_shade) { \ 1618 r = v0->color[0]; \ 1619 g = v0->color[1]; \ 1620 b = v0->color[2]; \ 1621 a = v0->color[3]; \ 1622 } 1623#define INNER_LOOP( LEFT, RIGHT, Y ) \ 1624 { \ 1625 GLint i; \ 1626 const GLint n = RIGHT-LEFT; \ 1627 GLdepth zspan[MAX_WIDTH]; \ 1628 GLfixed fogspan[MAX_WIDTH]; \ 1629 GLchan rgba[MAX_WIDTH][4]; \ 1630 GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH]; \ 1631 if (n>0) { \ 1632 if (flat_shade) { \ 1633 for (i=0;i<n;i++) { \ 1634 GLdouble invQ = 1.0 / vv; \ 1635 zspan[i] = FixedToDepth(ffz); \ 1636 fogspan[i] = fffog / 256; \ 1637 rgba[i][RCOMP] = r; \ 1638 rgba[i][GCOMP] = g; \ 1639 rgba[i][BCOMP] = b; \ 1640 rgba[i][ACOMP] = a; \ 1641 s[i] = ss*invQ; \ 1642 t[i] = tt*invQ; \ 1643 u[i] = uu*invQ; \ 1644 fffog += fdfogdx; \ 1645 ffz += fdzdx; \ 1646 ss += dsdx; \ 1647 tt += dtdx; \ 1648 uu += dudx; \ 1649 vv += dvdx; \ 1650 } \ 1651 } \ 1652 else { \ 1653 for (i=0;i<n;i++) { \ 1654 GLdouble invQ = 1.0 / vv; \ 1655 zspan[i] = FixedToDepth(ffz); \ 1656 rgba[i][RCOMP] = FixedToInt(ffr); \ 1657 rgba[i][GCOMP] = FixedToInt(ffg); \ 1658 rgba[i][BCOMP] = FixedToInt(ffb); \ 1659 rgba[i][ACOMP] = FixedToInt(ffa); \ 1660 fogspan[i] = fffog / 256; \ 1661 s[i] = ss*invQ; \ 1662 t[i] = tt*invQ; \ 1663 u[i] = uu*invQ; \ 1664 fffog += fdfogdx; \ 1665 ffz += fdzdx; \ 1666 ffr += fdrdx; \ 1667 ffg += fdgdx; \ 1668 ffb += fdbdx; \ 1669 ffa += fdadx; \ 1670 ss += dsdx; \ 1671 tt += dtdx; \ 1672 uu += dudx; \ 1673 vv += dvdx; \ 1674 } \ 1675 } \ 1676 gl_write_texture_span( ctx, n, LEFT, Y, zspan, fogspan, \ 1677 s, t, u, NULL, \ 1678 rgba, \ 1679 NULL, GL_POLYGON ); \ 1680 } \ 1681 } 1682 1683#include "s_tritemp.h" 1684} 1685 1686 1687/* 1688 * Render a smooth-shaded, textured, RGBA triangle with separate specular 1689 * color interpolation. 1690 * Interpolate S,T,U with perspective correction, w/out mipmapping. 1691 * Note: we use texture coordinates S,T,U,V instead of S,T,R,Q because 1692 * R is already used for red. 1693 */ 1694static void general_textured_spec_triangle1( GLcontext *ctx, 1695 const SWvertex *v0, 1696 const SWvertex *v1, 1697 const SWvertex *v2, 1698 GLdepth zspan[MAX_WIDTH], 1699 GLfixed fogspan[MAX_WIDTH], 1700 GLchan rgba[MAX_WIDTH][4], 1701 GLchan spec[MAX_WIDTH][4] ) 1702{ 1703#define INTERP_Z 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 = v0->color[0]; \ 1714 g = v0->color[1]; \ 1715 b = v0->color[2]; \ 1716 a = v0->color[3]; \ 1717 sr = v0->specular[0]; \ 1718 sg = v0->specular[1]; \ 1719 sb = v0->specular[2]; \ 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 = 1.0 / vv; \ 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 = 1.0 / vv; \ 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 gl_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/* 1794 * Compute the lambda value for a fragment. (texture level of detail) 1795 */ 1796static INLINE GLfloat 1797compute_lambda( GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy, 1798 GLfloat invQ, GLfloat width, GLfloat height ) 1799{ 1800 GLfloat dudx = dsdx * invQ * width; 1801 GLfloat dudy = dsdy * invQ * width; 1802 GLfloat dvdx = dtdx * invQ * height; 1803 GLfloat dvdy = dtdy * invQ * height; 1804 GLfloat r1 = dudx * dudx + dudy * dudy; 1805 GLfloat r2 = dvdx * dvdx + dvdy * dvdy; 1806 GLfloat rho2 = r1 + r2; /* used to be: rho2 = MAX2(r1,r2); */ 1807 /* return log base 2 of rho */ 1808 return log(rho2) * 1.442695 * 0.5; /* 1.442695 = 1/log(2) */ 1809} 1810 1811 1812/* 1813 * Render a smooth-shaded, textured, RGBA triangle. 1814 * Interpolate S,T,U with perspective correction and compute lambda for 1815 * each fragment. Lambda is used to determine whether to use the 1816 * minification or magnification filter. If minification and using 1817 * mipmaps, lambda is also used to select the texture level of detail. 1818 */ 1819static void lambda_textured_triangle1( GLcontext *ctx, 1820 const SWvertex *v0, 1821 const SWvertex *v1, 1822 const SWvertex *v2, 1823 GLfloat s[MAX_WIDTH], 1824 GLfloat t[MAX_WIDTH], 1825 GLfloat u[MAX_WIDTH] ) 1826{ 1827#define INTERP_Z 1 1828#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1829#define INTERP_RGB 1 1830#define INTERP_ALPHA 1 1831#define INTERP_TEX 1 1832 1833#define SETUP_CODE \ 1834 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \ 1835 const GLint baseLevel = obj->BaseLevel; \ 1836 const struct gl_texture_image *texImage = obj->Image[baseLevel]; \ 1837 const GLfloat twidth = (GLfloat) texImage->Width; \ 1838 const GLfloat theight = (GLfloat) texImage->Height; \ 1839 const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \ 1840 GLint r, g, b, a; \ 1841 if (flat_shade) { \ 1842 r = v0->color[0]; \ 1843 g = v0->color[1]; \ 1844 b = v0->color[2]; \ 1845 a = v0->color[3]; \ 1846 } 1847 1848#define INNER_LOOP( LEFT, RIGHT, Y ) \ 1849 { \ 1850 GLint i; \ 1851 const GLint n = RIGHT-LEFT; \ 1852 GLdepth zspan[MAX_WIDTH]; \ 1853 GLfixed fogspan[MAX_WIDTH]; \ 1854 GLchan rgba[MAX_WIDTH][4]; \ 1855 GLfloat lambda[MAX_WIDTH]; \ 1856 if (n>0) { \ 1857 if (flat_shade) { \ 1858 for (i=0;i<n;i++) { \ 1859 GLdouble invQ = 1.0 / vv; \ 1860 zspan[i] = FixedToDepth(ffz); \ 1861 fogspan[i] = fffog / 256; \ 1862 rgba[i][RCOMP] = r; \ 1863 rgba[i][GCOMP] = g; \ 1864 rgba[i][BCOMP] = b; \ 1865 rgba[i][ACOMP] = a; \ 1866 s[i] = ss*invQ; \ 1867 t[i] = tt*invQ; \ 1868 u[i] = uu*invQ; \ 1869 lambda[i] = compute_lambda( dsdx, dsdy, dtdx, dtdy, \ 1870 invQ, twidth, theight );\ 1871 ffz += fdzdx; \ 1872 fffog += fdfogdx; \ 1873 ss += dsdx; \ 1874 tt += dtdx; \ 1875 uu += dudx; \ 1876 vv += dvdx; \ 1877 } \ 1878 } \ 1879 else { \ 1880 for (i=0;i<n;i++) { \ 1881 GLdouble invQ = 1.0 / vv; \ 1882 zspan[i] = FixedToDepth(ffz); \ 1883 fogspan[i] = fffog / 256; \ 1884 rgba[i][RCOMP] = FixedToInt(ffr); \ 1885 rgba[i][GCOMP] = FixedToInt(ffg); \ 1886 rgba[i][BCOMP] = FixedToInt(ffb); \ 1887 rgba[i][ACOMP] = FixedToInt(ffa); \ 1888 s[i] = ss*invQ; \ 1889 t[i] = tt*invQ; \ 1890 u[i] = uu*invQ; \ 1891 lambda[i] = compute_lambda( dsdx, dsdy, dtdx, dtdy, \ 1892 invQ, twidth, theight );\ 1893 ffz += fdzdx; \ 1894 fffog += fdfogdx; \ 1895 ffr += fdrdx; \ 1896 ffg += fdgdx; \ 1897 ffb += fdbdx; \ 1898 ffa += fdadx; \ 1899 ss += dsdx; \ 1900 tt += dtdx; \ 1901 uu += dudx; \ 1902 vv += dvdx; \ 1903 } \ 1904 } \ 1905 gl_write_texture_span( ctx, n, LEFT, Y, zspan, fogspan, \ 1906 s, t, u, lambda, \ 1907 rgba, NULL, GL_POLYGON ); \ 1908 } \ 1909 } 1910 1911#include "s_tritemp.h" 1912} 1913 1914 1915/* 1916 * Render a smooth-shaded, textured, RGBA triangle with separate specular 1917 * interpolation. 1918 * Interpolate S,T,U with perspective correction and compute lambda for 1919 * each fragment. Lambda is used to determine whether to use the 1920 * minification or magnification filter. If minification and using 1921 * mipmaps, lambda is also used to select the texture level of detail. 1922 */ 1923static void lambda_textured_spec_triangle1( GLcontext *ctx, 1924 const SWvertex *v0, 1925 const SWvertex *v1, 1926 const SWvertex *v2, 1927 GLfloat s[MAX_WIDTH], 1928 GLfloat t[MAX_WIDTH], 1929 GLfloat u[MAX_WIDTH] ) 1930{ 1931#define INTERP_Z 1 1932#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1933#define INTERP_RGB 1 1934#define INTERP_SPEC 1 1935#define INTERP_ALPHA 1 1936#define INTERP_TEX 1 1937 1938#define SETUP_CODE \ 1939 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \ 1940 const GLint baseLevel = obj->BaseLevel; \ 1941 const struct gl_texture_image *texImage = obj->Image[baseLevel]; \ 1942 const GLfloat twidth = (GLfloat) texImage->Width; \ 1943 const GLfloat theight = (GLfloat) texImage->Height; \ 1944 const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \ 1945 GLint r, g, b, a, sr, sg, sb; \ 1946 if (flat_shade) { \ 1947 r = v0->color[0]; \ 1948 g = v0->color[1]; \ 1949 b = v0->color[2]; \ 1950 a = v0->color[3]; \ 1951 sr = v0->specular[0]; \ 1952 sg = v0->specular[1]; \ 1953 sb = v0->specular[2]; \ 1954 } 1955 1956#define INNER_LOOP( LEFT, RIGHT, Y ) \ 1957 { \ 1958 GLint i; \ 1959 const GLint n = RIGHT-LEFT; \ 1960 GLdepth zspan[MAX_WIDTH]; \ 1961 GLfixed fogspan[MAX_WIDTH]; \ 1962 GLchan spec[MAX_WIDTH][4]; \ 1963 GLchan rgba[MAX_WIDTH][4]; \ 1964 GLfloat lambda[MAX_WIDTH]; \ 1965 if (n>0) { \ 1966 if (flat_shade) { \ 1967 for (i=0;i<n;i++) { \ 1968 GLdouble invQ = 1.0 / vv; \ 1969 zspan[i] = FixedToDepth(ffz); \ 1970 fogspan[i] = fffog / 256; \ 1971 rgba[i][RCOMP] = r; \ 1972 rgba[i][GCOMP] = g; \ 1973 rgba[i][BCOMP] = b; \ 1974 rgba[i][ACOMP] = a; \ 1975 spec[i][RCOMP] = sr; \ 1976 spec[i][GCOMP] = sg; \ 1977 spec[i][BCOMP] = sb; \ 1978 s[i] = ss*invQ; \ 1979 t[i] = tt*invQ; \ 1980 u[i] = uu*invQ; \ 1981 lambda[i] = compute_lambda( dsdx, dsdy, dtdx, dtdy, \ 1982 invQ, twidth, theight );\ 1983 fffog += fdfogdx; \ 1984 ffz += fdzdx; \ 1985 ss += dsdx; \ 1986 tt += dtdx; \ 1987 uu += dudx; \ 1988 vv += dvdx; \ 1989 } \ 1990 } \ 1991 else { \ 1992 for (i=0;i<n;i++) { \ 1993 GLdouble invQ = 1.0 / vv; \ 1994 zspan[i] = FixedToDepth(ffz); \ 1995 fogspan[i] = fffog / 256; \ 1996 rgba[i][RCOMP] = FixedToInt(ffr); \ 1997 rgba[i][GCOMP] = FixedToInt(ffg); \ 1998 rgba[i][BCOMP] = FixedToInt(ffb); \ 1999 rgba[i][ACOMP] = FixedToInt(ffa); \ 2000 spec[i][RCOMP] = FixedToInt(ffsr); \ 2001 spec[i][GCOMP] = FixedToInt(ffsg); \ 2002 spec[i][BCOMP] = FixedToInt(ffsb); \ 2003 s[i] = ss*invQ; \ 2004 t[i] = tt*invQ; \ 2005 u[i] = uu*invQ; \ 2006 lambda[i] = compute_lambda( dsdx, dsdy, dtdx, dtdy, \ 2007 invQ, twidth, theight );\ 2008 fffog += fdfogdx; \ 2009 ffz += fdzdx; \ 2010 ffr += fdrdx; \ 2011 ffg += fdgdx; \ 2012 ffb += fdbdx; \ 2013 ffa += fdadx; \ 2014 ffsr += fdsrdx; \ 2015 ffsg += fdsgdx; \ 2016 ffsb += fdsbdx; \ 2017 ss += dsdx; \ 2018 tt += dtdx; \ 2019 uu += dudx; \ 2020 vv += dvdx; \ 2021 } \ 2022 } \ 2023 gl_write_texture_span( ctx, n, LEFT, Y, zspan, fogspan, \ 2024 s, t, u, lambda, \ 2025 rgba, (CONST GLchan (*)[4]) spec, \ 2026 GL_POLYGON ); \ 2027 } \ 2028 } 2029 2030#include "s_tritemp.h" 2031} 2032 2033 2034/* 2035 * This is the big one! 2036 * Interpolate Z, RGB, Alpha, and two sets of texture coordinates. 2037 * Yup, it's slow. 2038 */ 2039static void 2040lambda_multitextured_triangle1( GLcontext *ctx, 2041 const SWvertex *v0, 2042 const SWvertex *v1, 2043 const SWvertex *v2, 2044 GLfloat s[MAX_TEXTURE_UNITS][MAX_WIDTH], 2045 GLfloat t[MAX_TEXTURE_UNITS][MAX_WIDTH], 2046 GLfloat u[MAX_TEXTURE_UNITS][MAX_WIDTH]) 2047{ 2048#define INTERP_Z 1 2049#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 2050#define INTERP_RGB 1 2051#define INTERP_ALPHA 1 2052#define INTERP_MULTITEX 1 2053 2054#define SETUP_CODE \ 2055 GLchan rgba[MAX_WIDTH][4]; \ 2056 const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \ 2057 GLfloat twidth[MAX_TEXTURE_UNITS], theight[MAX_TEXTURE_UNITS]; \ 2058 GLint r, g, b, a; \ 2059 if (flat_shade) { \ 2060 r = v0->color[0]; \ 2061 g = v0->color[1]; \ 2062 b = v0->color[2]; \ 2063 a = v0->color[3]; \ 2064 } \ 2065 { \ 2066 GLuint unit; \ 2067 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { \ 2068 if (ctx->Texture.Unit[unit]._ReallyEnabled) { \ 2069 const struct gl_texture_object *obj = ctx->Texture.Unit[unit]._Current; \ 2070 const GLint baseLevel = obj->BaseLevel; \ 2071 const struct gl_texture_image *texImage = obj->Image[baseLevel]; \ 2072 twidth[unit] = (GLfloat) texImage->Width; \ 2073 theight[unit] = (GLfloat) texImage->Height; \ 2074 } \ 2075 } \ 2076 } 2077 2078 2079 2080#define INNER_LOOP( LEFT, RIGHT, Y ) \ 2081 { \ 2082 GLint i; \ 2083 const GLint n = RIGHT-LEFT; \ 2084 GLdepth zspan[MAX_WIDTH]; \ 2085 GLfixed fogspan[MAX_WIDTH]; \ 2086 GLfloat lambda[MAX_TEXTURE_UNITS][MAX_WIDTH]; \ 2087 if (n > 0) { \ 2088 if (flat_shade) { \ 2089 for (i=0;i<n;i++) { \ 2090 zspan[i] = FixedToDepth(ffz); \ 2091 fogspan[i] = fffog / 256; \ 2092 fffog += fdfogdx; \ 2093 ffz += fdzdx; \ 2094 rgba[i][RCOMP] = r; \ 2095 rgba[i][GCOMP] = g; \ 2096 rgba[i][BCOMP] = b; \ 2097 rgba[i][ACOMP] = a; \ 2098 { \ 2099 GLuint unit; \ 2100 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { \ 2101 if (ctx->Texture.Unit[unit]._ReallyEnabled) { \ 2102 GLdouble invQ = 1.0 / vv[unit]; \ 2103 s[unit][i] = ss[unit] * invQ; \ 2104 t[unit][i] = tt[unit] * invQ; \ 2105 u[unit][i] = uu[unit] * invQ; \ 2106 lambda[unit][i] = compute_lambda(dsdx[unit], dsdy[unit],\ 2107 dtdx[unit], dtdy[unit], invQ, \ 2108 twidth[unit], theight[unit] ); \ 2109 ss[unit] += dsdx[unit]; \ 2110 tt[unit] += dtdx[unit]; \ 2111 uu[unit] += dudx[unit]; \ 2112 vv[unit] += dvdx[unit]; \ 2113 } \ 2114 } \ 2115 } \ 2116 } \ 2117 } \ 2118 else { /* smooth shade */ \ 2119 for (i=0;i<n;i++) { \ 2120 zspan[i] = FixedToDepth(ffz); \ 2121 fogspan[i] = fffog / 256; \ 2122 ffz += fdzdx; \ 2123 fffog += fdfogdx; \ 2124 rgba[i][RCOMP] = FixedToInt(ffr); \ 2125 rgba[i][GCOMP] = FixedToInt(ffg); \ 2126 rgba[i][BCOMP] = FixedToInt(ffb); \ 2127 rgba[i][ACOMP] = FixedToInt(ffa); \ 2128 ffr += fdrdx; \ 2129 ffg += fdgdx; \ 2130 ffb += fdbdx; \ 2131 ffa += fdadx; \ 2132 { \ 2133 GLuint unit; \ 2134 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { \ 2135 if (ctx->Texture.Unit[unit]._ReallyEnabled) { \ 2136 GLdouble invQ = 1.0 / vv[unit]; \ 2137 s[unit][i] = ss[unit] * invQ; \ 2138 t[unit][i] = tt[unit] * invQ; \ 2139 u[unit][i] = uu[unit] * invQ; \ 2140 lambda[unit][i] = compute_lambda(dsdx[unit], dsdy[unit],\ 2141 dtdx[unit], dtdy[unit], invQ, \ 2142 twidth[unit], theight[unit] ); \ 2143 ss[unit] += dsdx[unit]; \ 2144 tt[unit] += dtdx[unit]; \ 2145 uu[unit] += dudx[unit]; \ 2146 vv[unit] += dvdx[unit]; \ 2147 } \ 2148 } \ 2149 } \ 2150 } \ 2151 } \ 2152 gl_write_multitexture_span( ctx, n, LEFT, Y, zspan, fogspan, \ 2153 (const GLfloat (*)[MAX_WIDTH]) s, \ 2154 (const GLfloat (*)[MAX_WIDTH]) t, \ 2155 (const GLfloat (*)[MAX_WIDTH]) u, \ 2156 (GLfloat (*)[MAX_WIDTH]) lambda, \ 2157 rgba, NULL, GL_POLYGON ); \ 2158 } \ 2159 } 2160#include "s_tritemp.h" 2161} 2162 2163 2164/* 2165 * These wrappers are needed to deal with the 32KB / stack frame limit 2166 * on Mac / PowerPC systems. 2167 */ 2168 2169static void general_textured_spec_triangle(GLcontext *ctx, 2170 const SWvertex *v0, 2171 const SWvertex *v1, 2172 const SWvertex *v2 ) 2173{ 2174 GLdepth zspan[MAX_WIDTH]; 2175 GLfixed fogspan[MAX_WIDTH]; 2176 GLchan rgba[MAX_WIDTH][4], spec[MAX_WIDTH][4]; 2177 general_textured_spec_triangle1(ctx,v0,v1,v2,zspan,fogspan,rgba,spec); 2178} 2179 2180static void lambda_textured_triangle( GLcontext *ctx, 2181 const SWvertex *v0, 2182 const SWvertex *v1, 2183 const SWvertex *v2 ) 2184{ 2185 GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH]; 2186 lambda_textured_triangle1(ctx,v0,v1,v2,s,t,u); 2187} 2188 2189static void lambda_textured_spec_triangle( GLcontext *ctx, 2190 const SWvertex *v0, 2191 const SWvertex *v1, 2192 const SWvertex *v2 ) 2193{ 2194 GLfloat s[MAX_WIDTH]; 2195 GLfloat t[MAX_WIDTH]; 2196 GLfloat u[MAX_WIDTH]; 2197 lambda_textured_spec_triangle1(ctx,v0,v1,v2,s,t,u); 2198} 2199 2200 2201static void lambda_multitextured_triangle( GLcontext *ctx, 2202 const SWvertex *v0, 2203 const SWvertex *v1, 2204 const SWvertex *v2 ) 2205{ 2206 2207 GLfloat s[MAX_TEXTURE_UNITS][MAX_WIDTH]; 2208 GLfloat t[MAX_TEXTURE_UNITS][MAX_WIDTH]; 2209 DEFMARRAY(GLfloat,u,MAX_TEXTURE_UNITS,MAX_WIDTH); 2210 CHECKARRAY(u,return); 2211 2212 lambda_multitextured_triangle1(ctx,v0,v1,v2,s,t,u); 2213 2214 UNDEFARRAY(u); 2215} 2216 2217 2218 2219static void occlusion_zless_triangle( GLcontext *ctx, 2220 const SWvertex *v0, 2221 const SWvertex *v1, 2222 const SWvertex *v2 ) 2223{ 2224 if (ctx->OcclusionResult) { 2225 return; 2226 } 2227 2228#define DO_OCCLUSION_TEST 2229#define INTERP_Z 1 2230#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 2231#define INNER_LOOP( LEFT, RIGHT, Y ) \ 2232 { \ 2233 GLint i; \ 2234 const GLint len = RIGHT-LEFT; \ 2235 for (i=0;i<len;i++) { \ 2236 GLdepth z = FixedToDepth(ffz); \ 2237 (void) fffog; \ 2238 if (z < zRow[i]) { \ 2239 ctx->OcclusionResult = GL_TRUE; \ 2240 return; \ 2241 } \ 2242 ffz += fdzdx; \ 2243 } \ 2244 } 2245#include "s_tritemp.h" 2246} 2247 2248 2249 2250 2251 2252#if 0 2253# define dputs(s) puts(s) 2254#else 2255# define dputs(s) 2256#endif 2257 2258 2259 2260/* 2261 * Determine which triangle rendering function to use given the current 2262 * rendering context. 2263 * 2264 * Please update the summary flag _SWRAST_NEW_TRIANGLE if you add or 2265 * remove tests to this code. 2266 */ 2267void 2268_swrast_choose_triangle( GLcontext *ctx ) 2269{ 2270 SWcontext *swrast = SWRAST_CONTEXT(ctx); 2271 const GLboolean rgbmode = ctx->Visual.RGBAflag; 2272 2273 if (ctx->RenderMode==GL_RENDER) { 2274 2275 if (ctx->Polygon.SmoothFlag) { 2276 _mesa_set_aa_triangle_function(ctx); 2277 ASSERT(swrast->Triangle); 2278 return; 2279 } 2280 2281 if (ctx->Depth.OcclusionTest && 2282 ctx->Depth.Test && 2283 ctx->Depth.Mask == GL_FALSE && 2284 ctx->Depth.Func == GL_LESS && 2285 !ctx->Stencil.Enabled) { 2286 if ((rgbmode && 2287 ctx->Color.ColorMask[0] == 0 && 2288 ctx->Color.ColorMask[1] == 0 && 2289 ctx->Color.ColorMask[2] == 0 && 2290 ctx->Color.ColorMask[3] == 0) 2291 || 2292 (!rgbmode && ctx->Color.IndexMask == 0)) { 2293 dputs("occlusion_test_triangle"); 2294 swrast->Triangle = occlusion_zless_triangle; 2295 return; 2296 } 2297 } 2298 2299 if (ctx->Texture._ReallyEnabled) { 2300 /* Ugh, we do a _lot_ of tests to pick the best textured tri func */ 2301 GLint format, filter; 2302 const struct gl_texture_object *current2Dtex = ctx->Texture.Unit[0].Current2D; 2303 const struct gl_texture_image *image; 2304 /* First see if we can used an optimized 2-D texture function */ 2305 if (ctx->Texture._ReallyEnabled==TEXTURE0_2D 2306 && current2Dtex->WrapS==GL_REPEAT 2307 && current2Dtex->WrapT==GL_REPEAT 2308 && ((image = current2Dtex->Image[current2Dtex->BaseLevel]) != 0) /* correct! */ 2309 && image->Border==0 2310 && ((format = image->Format)==GL_RGB || format==GL_RGBA) 2311 && (filter = current2Dtex->MinFilter)==current2Dtex->MagFilter 2312 && ctx->Light.Model.ColorControl==GL_SINGLE_COLOR 2313 && ctx->Texture.Unit[0].EnvMode!=GL_COMBINE_EXT) { 2314 2315 if (ctx->Hint.PerspectiveCorrection==GL_FASTEST) { 2316 2317 if (filter==GL_NEAREST 2318 && format==GL_RGB 2319 && (ctx->Texture.Unit[0].EnvMode==GL_REPLACE 2320 || ctx->Texture.Unit[0].EnvMode==GL_DECAL) 2321 && ((swrast->_RasterMask==DEPTH_BIT 2322 && ctx->Depth.Func==GL_LESS 2323 && ctx->Depth.Mask==GL_TRUE) 2324 || swrast->_RasterMask==0) 2325 && ctx->Polygon.StippleFlag==GL_FALSE) { 2326 2327 if (swrast->_RasterMask==DEPTH_BIT) { 2328 swrast->Triangle = simple_z_textured_triangle; 2329 dputs("simple_z_textured_triangle"); 2330 } 2331 else { 2332 swrast->Triangle = simple_textured_triangle; 2333 dputs("simple_textured_triangle"); 2334 } 2335 } 2336 else { 2337 if (ctx->Texture.Unit[0].EnvMode==GL_ADD) { 2338 swrast->Triangle = general_textured_triangle; 2339 dputs("general_textured_triangle"); 2340 } 2341 else { 2342 swrast->Triangle = affine_textured_triangle; 2343 dputs("affine_textured_triangle"); 2344 } 2345 } 2346 } 2347 else { 2348 if (filter==GL_NEAREST) { 2349 swrast->Triangle = near_persp_textured_triangle; 2350 dputs("near_persp_textured_triangle"); 2351 } 2352 else { 2353 swrast->Triangle = lin_persp_textured_triangle; 2354 dputs("lin_persp_textured_triangle"); 2355 } 2356 } 2357 } 2358 else { 2359 /* More complicated textures (mipmap, multi-tex, sep specular) */ 2360 GLboolean needLambda; 2361 /* if mag filter != min filter we need to compute lambda */ 2362 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; 2363 if (obj && obj->MinFilter != obj->MagFilter) 2364 needLambda = GL_TRUE; 2365 else 2366 needLambda = GL_FALSE; 2367 if (swrast->_MultiTextureEnabled) { 2368 swrast->Triangle = lambda_multitextured_triangle; 2369 dputs("lambda_multitextured_triangle"); 2370 } 2371 else if ((ctx->Light.Enabled && 2372 ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) 2373 || ctx->Fog.ColorSumEnabled) { 2374 /* separate specular color interpolation */ 2375 if (needLambda) { 2376 swrast->Triangle = lambda_textured_spec_triangle; 2377 dputs("lambda_textured_spec_triangle"); 2378 } 2379 else { 2380 swrast->Triangle = general_textured_spec_triangle; 2381 dputs("general_textured_spec_triangle"); 2382 } 2383 } 2384 else { 2385 if (needLambda) { 2386 swrast->Triangle = lambda_textured_triangle; 2387 dputs("lambda_textured_triangle"); 2388 } 2389 else { 2390 swrast->Triangle = general_textured_triangle; 2391 dputs("general_textured_triangle"); 2392 } 2393 } 2394 } 2395 } 2396 else { 2397 if (ctx->Light.ShadeModel==GL_SMOOTH) { 2398 /* smooth shaded, no texturing, stippled or some raster ops */ 2399 if (rgbmode) { 2400 dputs("smooth_rgba_triangle"); 2401 swrast->Triangle = smooth_rgba_triangle; 2402 } 2403 else { 2404 dputs("smooth_ci_triangle"); 2405 swrast->Triangle = smooth_ci_triangle; 2406 } 2407 } 2408 else { 2409 /* flat shaded, no texturing, stippled or some raster ops */ 2410 if (rgbmode) { 2411 dputs("flat_rgba_triangle"); 2412 swrast->Triangle = flat_rgba_triangle; 2413 } 2414 else { 2415 dputs("flat_ci_triangle"); 2416 swrast->Triangle = flat_ci_triangle; 2417 } 2418 } 2419 } 2420 } 2421 else if (ctx->RenderMode==GL_FEEDBACK) { 2422 swrast->Triangle = gl_feedback_triangle; 2423 } 2424 else { 2425 /* GL_SELECT mode */ 2426 swrast->Triangle = gl_select_triangle; 2427 } 2428} 2429