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