s_triangle.c revision 2a182a98973edc9ecf2936b1288485bb2b3fa722
1/* $Id: s_triangle.c,v 1.49 2002/01/27 18:32:03 brianp Exp $ */ 2 3/* 4 * Mesa 3-D graphics library 5 * Version: 4.1 6 * 7 * Copyright (C) 1999-2002 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 51 52 53GLboolean _mesa_cull_triangle( GLcontext *ctx, 54 const SWvertex *v0, 55 const SWvertex *v1, 56 const SWvertex *v2 ) 57{ 58 GLfloat ex = v1->win[0] - v0->win[0]; 59 GLfloat ey = v1->win[1] - v0->win[1]; 60 GLfloat fx = v2->win[0] - v0->win[0]; 61 GLfloat fy = v2->win[1] - v0->win[1]; 62 GLfloat c = ex*fy-ey*fx; 63 64 if (c * SWRAST_CONTEXT(ctx)->_backface_sign > 0) 65 return 0; 66 67 return 1; 68} 69 70 71 72/* 73 * Render a flat-shaded color index triangle. 74 */ 75static void flat_ci_triangle( GLcontext *ctx, 76 const SWvertex *v0, 77 const SWvertex *v1, 78 const SWvertex *v2 ) 79{ 80#define INTERP_Z 1 81#define INTERP_FOG 1 82 83#define SETUP_CODE \ 84 span.interpMask |= SPAN_INDEX; \ 85 span.index = IntToFixed(v2->index); \ 86 span.indexStep = 0; 87 88#define RENDER_SPAN( span ) \ 89 _mesa_write_index_span(ctx, &span, GL_POLYGON ); 90 91#include "s_tritemp.h" 92} 93 94 95 96/* 97 * Render a smooth-shaded color index triangle. 98 */ 99static void smooth_ci_triangle( GLcontext *ctx, 100 const SWvertex *v0, 101 const SWvertex *v1, 102 const SWvertex *v2 ) 103{ 104#define INTERP_Z 1 105#define INTERP_FOG 1 106#define INTERP_INDEX 1 107 108#define RENDER_SPAN( span ) \ 109 GLuint i; \ 110 SW_SPAN_SET_FLAG(span.filledColor); \ 111 for (i = 0; i < span.end; i++) { \ 112 span.color.index[i] = FixedToInt(span.index); \ 113 span.index += span.indexStep; \ 114 } \ 115 _mesa_write_index_span(ctx, &span, GL_POLYGON); 116 117#include "s_tritemp.h" 118} 119 120 121 122/* 123 * Render a flat-shaded RGBA triangle. 124 */ 125static void flat_rgba_triangle( GLcontext *ctx, 126 const SWvertex *v0, 127 const SWvertex *v1, 128 const SWvertex *v2 ) 129{ 130#define INTERP_Z 1 131#define INTERP_FOG 1 132#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 133 134#define RENDER_SPAN( span ) \ 135 _mesa_write_monocolor_span(ctx, &span, v2->color, GL_POLYGON ); 136 137#include "s_tritemp.h" 138 139 ASSERT(!ctx->Texture._ReallyEnabled); /* texturing must be off */ 140 ASSERT(ctx->Light.ShadeModel==GL_FLAT); 141} 142 143 144 145/* 146 * Render a smooth-shaded RGBA triangle. 147 */ 148static void smooth_rgba_triangle( GLcontext *ctx, 149 const SWvertex *v0, 150 const SWvertex *v1, 151 const SWvertex *v2 ) 152{ 153 154#define INTERP_Z 1 155#define INTERP_FOG 1 156#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 157#define INTERP_RGB 1 158#define INTERP_ALPHA 1 159 160#define RENDER_SPAN( span ) \ 161 GLuint i; \ 162 SW_SPAN_SET_FLAG(span.filledColor); \ 163 SW_SPAN_SET_FLAG(span.filledAlpha); \ 164 ASSERT(span.interpMask & SPAN_RGBA); \ 165 span.arrayMask |= SPAN_RGBA; \ 166 for (i = 0; i < span.end; i++) { \ 167 span.color.rgba[i][RCOMP] = FixedToChan(span.red); \ 168 span.color.rgba[i][GCOMP] = FixedToChan(span.green); \ 169 span.color.rgba[i][BCOMP] = FixedToChan(span.blue); \ 170 span.color.rgba[i][ACOMP] = FixedToChan(span.alpha); \ 171 span.red += span.redStep; \ 172 span.green += span.greenStep; \ 173 span.blue += span.blueStep; \ 174 span.alpha += span.alphaStep; \ 175 } \ 176 _mesa_write_rgba_span(ctx, &span, GL_POLYGON); 177 178#include "s_tritemp.h" 179 180 ASSERT(!ctx->Texture._ReallyEnabled); /* texturing must be off */ 181 ASSERT(ctx->Light.ShadeModel==GL_SMOOTH); 182} 183 184 185/* 186 * Render an RGB, GL_DECAL, textured triangle. 187 * Interpolate S,T only w/out mipmapping or perspective correction. 188 * 189 * No fog. 190 */ 191static void simple_textured_triangle( GLcontext *ctx, 192 const SWvertex *v0, 193 const SWvertex *v1, 194 const SWvertex *v2 ) 195{ 196#define INTERP_INT_TEX 1 197#define S_SCALE twidth 198#define T_SCALE theight 199 200#define SETUP_CODE \ 201 SWcontext *swrast = SWRAST_CONTEXT(ctx); \ 202 struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \ 203 const GLint b = obj->BaseLevel; \ 204 const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ 205 const GLfloat theight = (GLfloat) obj->Image[b]->Height; \ 206 const GLint twidth_log2 = obj->Image[b]->WidthLog2; \ 207 const GLchan *texture = (const GLchan *) obj->Image[b]->Data; \ 208 const GLint smask = obj->Image[b]->Width - 1; \ 209 const GLint tmask = obj->Image[b]->Height - 1; \ 210 if (!texture) { \ 211 /* this shouldn't happen */ \ 212 return; \ 213 } 214 215#define RENDER_SPAN( span ) \ 216 GLuint i; \ 217 SW_SPAN_SET_FLAG(span.filledColor); \ 218 span.intTex[0] -= FIXED_HALF; /* off-by-one error? */ \ 219 span.intTex[1] -= FIXED_HALF; \ 220 for (i = 0; i < span.end; i++) { \ 221 GLint s = FixedToInt(span.intTex[0]) & smask; \ 222 GLint t = FixedToInt(span.intTex[1]) & tmask; \ 223 GLint pos = (t << twidth_log2) + s; \ 224 pos = pos + pos + pos; /* multiply by 3 */ \ 225 span.color.rgb[i][RCOMP] = texture[pos]; \ 226 span.color.rgb[i][GCOMP] = texture[pos+1]; \ 227 span.color.rgb[i][BCOMP] = texture[pos+2]; \ 228 span.intTex[0] += span.intTexStep[0]; \ 229 span.intTex[1] += span.intTexStep[1]; \ 230 } \ 231 (*swrast->Driver.WriteRGBSpan)(ctx, span.end, span.x, span.y, \ 232 (CONST GLchan (*)[3]) span.color.rgb, \ 233 NULL ); 234 235#include "s_tritemp.h" 236} 237 238 239/* 240 * Render an RGB, GL_DECAL, textured triangle. 241 * Interpolate S,T, GL_LESS depth test, w/out mipmapping or 242 * perspective correction. 243 * 244 * No fog. 245 */ 246static void simple_z_textured_triangle( GLcontext *ctx, 247 const SWvertex *v0, 248 const SWvertex *v1, 249 const SWvertex *v2 ) 250{ 251#define INTERP_Z 1 252#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 253#define INTERP_INT_TEX 1 254#define S_SCALE twidth 255#define T_SCALE theight 256 257#define SETUP_CODE \ 258 SWcontext *swrast = SWRAST_CONTEXT(ctx); \ 259 struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \ 260 const GLint b = obj->BaseLevel; \ 261 const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ 262 const GLfloat theight = (GLfloat) obj->Image[b]->Height; \ 263 const GLint twidth_log2 = obj->Image[b]->WidthLog2; \ 264 const GLchan *texture = (const GLchan *) obj->Image[b]->Data; \ 265 const GLint smask = obj->Image[b]->Width - 1; \ 266 const GLint tmask = obj->Image[b]->Height - 1; \ 267 if (!texture) { \ 268 /* this shouldn't happen */ \ 269 return; \ 270 } 271 272#define RENDER_SPAN( span ) \ 273 GLuint i; \ 274 span.intTex[0] -= FIXED_HALF; /* off-by-one error? */ \ 275 span.intTex[1] -= FIXED_HALF; \ 276 SW_SPAN_SET_FLAG(span.filledColor); \ 277 SW_SPAN_SET_FLAG(span.filledDepth); \ 278 for (i = 0; i < span.end; i++) { \ 279 const GLdepth z = FixedToDepth(span.z); \ 280 if (z < zRow[i]) { \ 281 GLint s = FixedToInt(span.intTex[0]) & smask; \ 282 GLint t = FixedToInt(span.intTex[1]) & tmask; \ 283 GLint pos = (t << twidth_log2) + s; \ 284 pos = pos + pos + pos; /* multiply by 3 */ \ 285 span.color.rgb[i][RCOMP] = texture[pos]; \ 286 span.color.rgb[i][GCOMP] = texture[pos+1]; \ 287 span.color.rgb[i][BCOMP] = texture[pos+2]; \ 288 zRow[i] = z; \ 289 span.mask[i] = 1; \ 290 } \ 291 else { \ 292 span.mask[i] = 0; \ 293 } \ 294 span.intTex[0] += span.intTexStep[0]; \ 295 span.intTex[1] += span.intTexStep[1]; \ 296 span.z += span.zStep; \ 297 } \ 298 (*swrast->Driver.WriteRGBSpan)(ctx, span.end, span.x, span.y, \ 299 (CONST GLchan (*)[3]) span.color.rgb, \ 300 span.mask ); 301 302#include "s_tritemp.h" 303} 304 305 306#if CHAN_TYPE != GL_FLOAT 307 308struct affine_info 309{ 310 GLenum filter; 311 GLenum format; 312 GLenum envmode; 313 GLint smask, tmask; 314 GLint twidth_log2; 315 const GLchan *texture; 316 GLfixed er, eg, eb, ea; 317 GLint tbytesline, tsize; 318}; 319 320 321/* This function can handle GL_NEAREST or GL_LINEAR sampling of 2D RGB or RGBA 322 * textures with GL_REPLACE, GL_MODULATE, GL_BLEND, GL_DECAL or GL_ADD 323 * texture env modes. 324 */ 325static INLINE void 326affine_span(GLcontext *ctx, struct sw_span *span, 327 struct affine_info *info) 328{ 329 GLchan sample[4]; /* the filtered texture sample */ 330 331 /* Instead of defining a function for each mode, a test is done 332 * between the outer and inner loops. This is to reduce code size 333 * and complexity. Observe that an optimizing compiler kills 334 * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST). 335 */ 336 337#define NEAREST_RGB \ 338 sample[RCOMP] = tex00[RCOMP]; \ 339 sample[GCOMP] = tex00[GCOMP]; \ 340 sample[BCOMP] = tex00[BCOMP]; \ 341 sample[ACOMP] = CHAN_MAX 342 343#define LINEAR_RGB \ 344 sample[RCOMP] = (ti * (si * tex00[0] + sf * tex01[0]) + \ 345 tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \ 346 sample[GCOMP] = (ti * (si * tex00[1] + sf * tex01[1]) + \ 347 tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \ 348 sample[BCOMP] = (ti * (si * tex00[2] + sf * tex01[2]) + \ 349 tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \ 350 sample[ACOMP] = CHAN_MAX 351 352#define NEAREST_RGBA COPY_CHAN4(sample, tex00) 353 354#define LINEAR_RGBA \ 355 sample[RCOMP] = (ti * (si * tex00[0] + sf * tex01[0]) + \ 356 tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT;\ 357 sample[GCOMP] = (ti * (si * tex00[1] + sf * tex01[1]) + \ 358 tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT;\ 359 sample[BCOMP] = (ti * (si * tex00[2] + sf * tex01[2]) + \ 360 tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT;\ 361 sample[ACOMP] = (ti * (si * tex00[3] + sf * tex01[3]) + \ 362 tf * (si * tex10[3] + sf * tex11[3])) >> 2 * FIXED_SHIFT 363 364#define MODULATE \ 365 dest[RCOMP] = span->red * (sample[RCOMP] + 1u) >> (FIXED_SHIFT + 8); \ 366 dest[GCOMP] = span->green * (sample[GCOMP] + 1u) >> (FIXED_SHIFT + 8); \ 367 dest[BCOMP] = span->blue * (sample[BCOMP] + 1u) >> (FIXED_SHIFT + 8); \ 368 dest[ACOMP] = span->alpha * (sample[ACOMP] + 1u) >> (FIXED_SHIFT + 8) 369 370#define DECAL \ 371 dest[RCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->red + \ 372 ((sample[ACOMP] + 1) * sample[RCOMP] << FIXED_SHIFT)) \ 373 >> (FIXED_SHIFT + 8); \ 374 dest[GCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->green + \ 375 ((sample[ACOMP] + 1) * sample[GCOMP] << FIXED_SHIFT)) \ 376 >> (FIXED_SHIFT + 8); \ 377 dest[BCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->blue + \ 378 ((sample[ACOMP] + 1) * sample[BCOMP] << FIXED_SHIFT)) \ 379 >> (FIXED_SHIFT + 8); \ 380 dest[ACOMP] = FixedToInt(span->alpha) 381 382#define BLEND \ 383 dest[RCOMP] = ((CHAN_MAX - sample[RCOMP]) * span->red \ 384 + (sample[RCOMP] + 1) * info->er) >> (FIXED_SHIFT + 8); \ 385 dest[GCOMP] = ((CHAN_MAX - sample[GCOMP]) * span->green \ 386 + (sample[GCOMP] + 1) * info->eg) >> (FIXED_SHIFT + 8); \ 387 dest[BCOMP] = ((CHAN_MAX - sample[BCOMP]) * span->blue \ 388 + (sample[BCOMP] + 1) * info->eb) >> (FIXED_SHIFT + 8); \ 389 dest[ACOMP] = span->alpha * (sample[ACOMP] + 1) >> (FIXED_SHIFT + 8) 390 391#define REPLACE COPY_CHAN4(dest, sample) 392 393#define ADD \ 394 { \ 395 GLint rSum = FixedToInt(span->red) + (GLint) sample[RCOMP]; \ 396 GLint gSum = FixedToInt(span->green) + (GLint) sample[GCOMP]; \ 397 GLint bSum = FixedToInt(span->blue) + (GLint) sample[BCOMP]; \ 398 dest[RCOMP] = MIN2(rSum, CHAN_MAX); \ 399 dest[GCOMP] = MIN2(gSum, CHAN_MAX); \ 400 dest[BCOMP] = MIN2(bSum, CHAN_MAX); \ 401 dest[ACOMP] = span->alpha * (sample[ACOMP] + 1) >> (FIXED_SHIFT + 8); \ 402 } 403 404/* shortcuts */ 405 406#define NEAREST_RGB_REPLACE \ 407 NEAREST_RGB; \ 408 dest[0] = sample[0]; \ 409 dest[1] = sample[1]; \ 410 dest[2] = sample[2]; \ 411 dest[3] = FixedToInt(span->alpha); 412 413#define NEAREST_RGBA_REPLACE COPY_CHAN4(dest, tex00) 414 415#define SPAN_NEAREST(DO_TEX,COMP) \ 416 for (i = 0; i < span->end; i++) { \ 417 /* Isn't it necessary to use FixedFloor below?? */ \ 418 GLint s = FixedToInt(span->intTex[0]) & info->smask; \ 419 GLint t = FixedToInt(span->intTex[1]) & info->tmask; \ 420 GLint pos = (t << info->twidth_log2) + s; \ 421 const GLchan *tex00 = info->texture + COMP * pos; \ 422 DO_TEX; \ 423 span->red += span->redStep; \ 424 span->green += span->greenStep; \ 425 span->blue += span->blueStep; \ 426 span->alpha += span->alphaStep; \ 427 span->intTex[0] += span->intTexStep[0]; \ 428 span->intTex[1] += span->intTexStep[1]; \ 429 dest += 4; \ 430 } 431 432#define SPAN_LINEAR(DO_TEX,COMP) \ 433 for (i = 0; i < span->end; i++) { \ 434 /* Isn't it necessary to use FixedFloor below?? */ \ 435 GLint s = FixedToInt(span->intTex[0]) & info->smask; \ 436 GLint t = FixedToInt(span->intTex[1]) & info->tmask; \ 437 GLfixed sf = span->intTex[0] & FIXED_FRAC_MASK; \ 438 GLfixed tf = span->intTex[1] & FIXED_FRAC_MASK; \ 439 GLfixed si = FIXED_FRAC_MASK - sf; \ 440 GLfixed ti = FIXED_FRAC_MASK - tf; \ 441 GLint pos = (t << info->twidth_log2) + s; \ 442 const GLchan *tex00 = info->texture + COMP * pos; \ 443 const GLchan *tex10 = tex00 + info->tbytesline; \ 444 const GLchan *tex01 = tex00 + COMP; \ 445 const GLchan *tex11 = tex10 + COMP; \ 446 (void) ti; \ 447 (void) si; \ 448 if (t == info->tmask) { \ 449 tex10 -= info->tsize; \ 450 tex11 -= info->tsize; \ 451 } \ 452 if (s == info->smask) { \ 453 tex01 -= info->tbytesline; \ 454 tex11 -= info->tbytesline; \ 455 } \ 456 DO_TEX; \ 457 span->red += span->redStep; \ 458 span->green += span->greenStep; \ 459 span->blue += span->blueStep; \ 460 span->alpha += span->alphaStep; \ 461 span->intTex[0] += span->intTexStep[0]; \ 462 span->intTex[1] += span->intTexStep[1]; \ 463 dest += 4; \ 464 } 465 466 467 GLuint i; 468 GLchan *dest = span->color.rgba[0]; 469 470 SW_SPAN_SET_FLAG(span->filledColor); 471 SW_SPAN_SET_FLAG(span->filledAlpha); 472 473 span->intTex[0] -= FIXED_HALF; 474 span->intTex[1] -= FIXED_HALF; 475 switch (info->filter) { 476 case GL_NEAREST: 477 switch (info->format) { 478 case GL_RGB: 479 switch (info->envmode) { 480 case GL_MODULATE: 481 SPAN_NEAREST(NEAREST_RGB;MODULATE,3); 482 break; 483 case GL_DECAL: 484 case GL_REPLACE: 485 SPAN_NEAREST(NEAREST_RGB_REPLACE,3); 486 break; 487 case GL_BLEND: 488 SPAN_NEAREST(NEAREST_RGB;BLEND,3); 489 break; 490 case GL_ADD: 491 SPAN_NEAREST(NEAREST_RGB;ADD,3); 492 break; 493 default: 494 abort(); 495 } 496 break; 497 case GL_RGBA: 498 switch(info->envmode) { 499 case GL_MODULATE: 500 SPAN_NEAREST(NEAREST_RGBA;MODULATE,4); 501 break; 502 case GL_DECAL: 503 SPAN_NEAREST(NEAREST_RGBA;DECAL,4); 504 break; 505 case GL_BLEND: 506 SPAN_NEAREST(NEAREST_RGBA;BLEND,4); 507 break; 508 case GL_ADD: 509 SPAN_NEAREST(NEAREST_RGBA;ADD,4); 510 break; 511 case GL_REPLACE: 512 SPAN_NEAREST(NEAREST_RGBA_REPLACE,4); 513 break; 514 default: 515 abort(); 516 } 517 break; 518 } 519 break; 520 521 case GL_LINEAR: 522 span->intTex[0] -= FIXED_HALF; 523 span->intTex[1] -= FIXED_HALF; 524 switch (info->format) { 525 case GL_RGB: 526 switch (info->envmode) { 527 case GL_MODULATE: 528 SPAN_LINEAR(LINEAR_RGB;MODULATE,3); 529 break; 530 case GL_DECAL: 531 case GL_REPLACE: 532 SPAN_LINEAR(LINEAR_RGB;REPLACE,3); 533 break; 534 case GL_BLEND: 535 SPAN_LINEAR(LINEAR_RGB;BLEND,3); 536 break; 537 case GL_ADD: 538 SPAN_LINEAR(LINEAR_RGB;ADD,3); 539 break; 540 default: 541 abort(); 542 } 543 break; 544 case GL_RGBA: 545 switch (info->envmode) { 546 case GL_MODULATE: 547 SPAN_LINEAR(LINEAR_RGBA;MODULATE,4); 548 break; 549 case GL_DECAL: 550 SPAN_LINEAR(LINEAR_RGBA;DECAL,4); 551 break; 552 case GL_BLEND: 553 SPAN_LINEAR(LINEAR_RGBA;BLEND,4); 554 break; 555 case GL_ADD: 556 SPAN_LINEAR(LINEAR_RGBA;ADD,4); 557 break; 558 case GL_REPLACE: 559 SPAN_LINEAR(LINEAR_RGBA;REPLACE,4); 560 break; 561 default: 562 abort(); 563 } break; 564 } 565 break; 566 } 567 ASSERT(span->interpMask & SPAN_RGBA); 568 ASSERT(span->arrayMask & SPAN_RGBA); 569 _mesa_write_rgba_span(ctx, span, GL_POLYGON); 570 571#undef SPAN_NEAREST 572#undef SPAN_LINEAR 573} 574 575 576 577/* 578 * Render an RGB/RGBA textured triangle without perspective correction. 579 */ 580static void affine_textured_triangle( GLcontext *ctx, 581 const SWvertex *v0, 582 const SWvertex *v1, 583 const SWvertex *v2 ) 584{ 585#define INTERP_Z 1 586#define INTERP_FOG 1 587#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 588#define INTERP_RGB 1 589#define INTERP_ALPHA 1 590#define INTERP_INT_TEX 1 591#define S_SCALE twidth 592#define T_SCALE theight 593 594#define SETUP_CODE \ 595 struct affine_info info; \ 596 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \ 597 struct gl_texture_object *obj = unit->Current2D; \ 598 const GLint b = obj->BaseLevel; \ 599 const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ 600 const GLfloat theight = (GLfloat) obj->Image[b]->Height; \ 601 info.texture = (const GLchan *) obj->Image[b]->Data; \ 602 info.twidth_log2 = obj->Image[b]->WidthLog2; \ 603 info.smask = obj->Image[b]->Width - 1; \ 604 info.tmask = obj->Image[b]->Height - 1; \ 605 info.format = obj->Image[b]->Format; \ 606 info.filter = obj->MinFilter; \ 607 info.envmode = unit->EnvMode; \ 608 span.arrayMask |= SPAN_RGBA; \ 609 \ 610 if (info.envmode == GL_BLEND) { \ 611 /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \ 612 info.er = FloatToFixed(unit->EnvColor[RCOMP] * CHAN_MAXF); \ 613 info.eg = FloatToFixed(unit->EnvColor[GCOMP] * CHAN_MAXF); \ 614 info.eb = FloatToFixed(unit->EnvColor[BCOMP] * CHAN_MAXF); \ 615 info.ea = FloatToFixed(unit->EnvColor[ACOMP] * CHAN_MAXF); \ 616 } \ 617 if (!info.texture) { \ 618 /* this shouldn't happen */ \ 619 return; \ 620 } \ 621 \ 622 switch (info.format) { \ 623 case GL_ALPHA: \ 624 case GL_LUMINANCE: \ 625 case GL_INTENSITY: \ 626 info.tbytesline = obj->Image[b]->Width; \ 627 break; \ 628 case GL_LUMINANCE_ALPHA: \ 629 info.tbytesline = obj->Image[b]->Width * 2; \ 630 break; \ 631 case GL_RGB: \ 632 info.tbytesline = obj->Image[b]->Width * 3; \ 633 break; \ 634 case GL_RGBA: \ 635 info.tbytesline = obj->Image[b]->Width * 4; \ 636 break; \ 637 default: \ 638 _mesa_problem(NULL, "Bad texture format in affine_texture_triangle");\ 639 return; \ 640 } \ 641 info.tsize = obj->Image[b]->Height * info.tbytesline; 642 643#define RENDER_SPAN( span ) affine_span(ctx, &span, &info); 644 645#include "s_tritemp.h" 646 647} 648 649 650 651struct persp_info 652{ 653 GLenum filter; 654 GLenum format; 655 GLenum envmode; 656 GLint smask, tmask; 657 GLint twidth_log2; 658 const GLchan *texture; 659 GLfixed er, eg, eb, ea; /* texture env color */ 660 GLint tbytesline, tsize; 661}; 662 663 664static INLINE void 665fast_persp_span(GLcontext *ctx, struct sw_span *span, 666 struct persp_info *info) 667{ 668 GLchan sample[4]; /* the filtered texture sample */ 669 670 /* Instead of defining a function for each mode, a test is done 671 * between the outer and inner loops. This is to reduce code size 672 * and complexity. Observe that an optimizing compiler kills 673 * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST). 674 */ 675#define SPAN_NEAREST(DO_TEX,COMP) \ 676 for (i = 0; i < span->end; i++) { \ 677 GLdouble invQ = tex_coord[2] ? \ 678 (1.0 / tex_coord[2]) : 1.0; \ 679 GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ); \ 680 GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ); \ 681 GLint s = IFLOOR(s_tmp) & info->smask; \ 682 GLint t = IFLOOR(t_tmp) & info->tmask; \ 683 GLint pos = (t << info->twidth_log2) + s; \ 684 const GLchan *tex00 = info->texture + COMP * pos; \ 685 DO_TEX; \ 686 span->red += span->redStep; \ 687 span->green += span->greenStep; \ 688 span->blue += span->blueStep; \ 689 span->alpha += span->alphaStep; \ 690 tex_coord[0] += tex_step[0]; \ 691 tex_coord[1] += tex_step[1]; \ 692 tex_coord[2] += tex_step[2]; \ 693 dest += 4; \ 694 } 695 696#define SPAN_LINEAR(DO_TEX,COMP) \ 697 for (i = 0; i < span->end; i++) { \ 698 GLdouble invQ = tex_coord[2] ? \ 699 (1.0 / tex_coord[2]) : 1.0; \ 700 GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ); \ 701 GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ); \ 702 GLfixed s_fix = FloatToFixed(s_tmp) - FIXED_HALF; \ 703 GLfixed t_fix = FloatToFixed(t_tmp) - FIXED_HALF; \ 704 GLint s = FixedToInt(FixedFloor(s_fix)) & info->smask; \ 705 GLint t = FixedToInt(FixedFloor(t_fix)) & info->tmask; \ 706 GLfixed sf = s_fix & FIXED_FRAC_MASK; \ 707 GLfixed tf = t_fix & FIXED_FRAC_MASK; \ 708 GLfixed si = FIXED_FRAC_MASK - sf; \ 709 GLfixed ti = FIXED_FRAC_MASK - tf; \ 710 GLint pos = (t << info->twidth_log2) + s; \ 711 const GLchan *tex00 = info->texture + COMP * pos; \ 712 const GLchan *tex10 = tex00 + info->tbytesline; \ 713 const GLchan *tex01 = tex00 + COMP; \ 714 const GLchan *tex11 = tex10 + COMP; \ 715 (void) ti; \ 716 (void) si; \ 717 if (t == info->tmask) { \ 718 tex10 -= info->tsize; \ 719 tex11 -= info->tsize; \ 720 } \ 721 if (s == info->smask) { \ 722 tex01 -= info->tbytesline; \ 723 tex11 -= info->tbytesline; \ 724 } \ 725 DO_TEX; \ 726 span->red += span->redStep; \ 727 span->green += span->greenStep; \ 728 span->blue += span->blueStep; \ 729 span->alpha += span->alphaStep; \ 730 tex_coord[0] += tex_step[0]; \ 731 tex_coord[1] += tex_step[1]; \ 732 tex_coord[2] += tex_step[2]; \ 733 dest += 4; \ 734 } 735 736 GLuint i; 737 GLfloat tex_coord[3], tex_step[3]; 738 GLchan *dest = span->color.rgba[0]; 739 740 SW_SPAN_SET_FLAG(span->filledColor); 741 SW_SPAN_SET_FLAG(span->filledAlpha); 742 743 tex_coord[0] = span->tex[0][0] * (info->smask + 1), 744 tex_step[0] = span->texStep[0][0] * (info->smask + 1); 745 tex_coord[1] = span->tex[0][1] * (info->tmask + 1), 746 tex_step[1] = span->texStep[0][1] * (info->tmask + 1); 747 /* span->tex[0][2] only if 3D-texturing, here only 2D */ 748 tex_coord[2] = span->tex[0][3], 749 tex_step[2] = span->texStep[0][3]; 750 751 switch (info->filter) { 752 case GL_NEAREST: 753 switch (info->format) { 754 case GL_RGB: 755 switch (info->envmode) { 756 case GL_MODULATE: 757 SPAN_NEAREST(NEAREST_RGB;MODULATE,3); 758 break; 759 case GL_DECAL: 760 case GL_REPLACE: 761 SPAN_NEAREST(NEAREST_RGB_REPLACE,3); 762 break; 763 case GL_BLEND: 764 SPAN_NEAREST(NEAREST_RGB;BLEND,3); 765 break; 766 case GL_ADD: 767 SPAN_NEAREST(NEAREST_RGB;ADD,3); 768 break; 769 default: 770 abort(); 771 } 772 break; 773 case GL_RGBA: 774 switch(info->envmode) { 775 case GL_MODULATE: 776 SPAN_NEAREST(NEAREST_RGBA;MODULATE,4); 777 break; 778 case GL_DECAL: 779 SPAN_NEAREST(NEAREST_RGBA;DECAL,4); 780 break; 781 case GL_BLEND: 782 SPAN_NEAREST(NEAREST_RGBA;BLEND,4); 783 break; 784 case GL_ADD: 785 SPAN_NEAREST(NEAREST_RGBA;ADD,4); 786 break; 787 case GL_REPLACE: 788 SPAN_NEAREST(NEAREST_RGBA_REPLACE,4); 789 break; 790 default: 791 abort(); 792 } 793 break; 794 } 795 break; 796 797 case GL_LINEAR: 798 switch (info->format) { 799 case GL_RGB: 800 switch (info->envmode) { 801 case GL_MODULATE: 802 SPAN_LINEAR(LINEAR_RGB;MODULATE,3); 803 break; 804 case GL_DECAL: 805 case GL_REPLACE: 806 SPAN_LINEAR(LINEAR_RGB;REPLACE,3); 807 break; 808 case GL_BLEND: 809 SPAN_LINEAR(LINEAR_RGB;BLEND,3); 810 break; 811 case GL_ADD: 812 SPAN_LINEAR(LINEAR_RGB;ADD,3); 813 break; 814 default: 815 abort(); 816 } 817 break; 818 case GL_RGBA: 819 switch (info->envmode) { 820 case GL_MODULATE: 821 SPAN_LINEAR(LINEAR_RGBA;MODULATE,4); 822 break; 823 case GL_DECAL: 824 SPAN_LINEAR(LINEAR_RGBA;DECAL,4); 825 break; 826 case GL_BLEND: 827 SPAN_LINEAR(LINEAR_RGBA;BLEND,4); 828 break; 829 case GL_ADD: 830 SPAN_LINEAR(LINEAR_RGBA;ADD,4); 831 break; 832 case GL_REPLACE: 833 SPAN_LINEAR(LINEAR_RGBA;REPLACE,4); 834 break; 835 default: 836 abort(); 837 } 838 break; 839 } 840 break; 841 } 842 843 ASSERT(span->interpMask & SPAN_RGBA); 844 ASSERT(span->arrayMask & SPAN_RGBA); 845 _mesa_write_rgba_span(ctx, span, GL_POLYGON); 846 847 848#undef SPAN_NEAREST 849#undef SPAN_LINEAR 850} 851 852 853/* 854 * Render an perspective corrected RGB/RGBA textured triangle. 855 * The Q (aka V in Mesa) coordinate must be zero such that the divide 856 * by interpolated Q/W comes out right. 857 * 858 */ 859static void persp_textured_triangle( GLcontext *ctx, 860 const SWvertex *v0, 861 const SWvertex *v1, 862 const SWvertex *v2 ) 863{ 864#define INTERP_Z 1 865#define INTERP_FOG 1 866#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 867#define INTERP_RGB 1 868#define INTERP_ALPHA 1 869#define INTERP_TEX 1 870 871#define SETUP_CODE \ 872 struct persp_info info; \ 873 const struct gl_texture_unit *unit = ctx->Texture.Unit+0; \ 874 const struct gl_texture_object *obj = unit->Current2D; \ 875 const GLint b = obj->BaseLevel; \ 876 info.texture = (const GLchan *) obj->Image[b]->Data; \ 877 info.twidth_log2 = obj->Image[b]->WidthLog2; \ 878 info.smask = obj->Image[b]->Width - 1; \ 879 info.tmask = obj->Image[b]->Height - 1; \ 880 info.format = obj->Image[b]->Format; \ 881 info.filter = obj->MinFilter; \ 882 info.envmode = unit->EnvMode; \ 883 span.arrayMask |= SPAN_RGBA; \ 884 \ 885 if (info.envmode == GL_BLEND) { \ 886 /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \ 887 info.er = FloatToFixed(unit->EnvColor[RCOMP] * CHAN_MAXF); \ 888 info.eg = FloatToFixed(unit->EnvColor[GCOMP] * CHAN_MAXF); \ 889 info.eb = FloatToFixed(unit->EnvColor[BCOMP] * CHAN_MAXF); \ 890 info.ea = FloatToFixed(unit->EnvColor[ACOMP] * CHAN_MAXF); \ 891 } \ 892 if (!info.texture) { \ 893 /* this shouldn't happen */ \ 894 return; \ 895 } \ 896 \ 897 switch (info.format) { \ 898 case GL_ALPHA: \ 899 case GL_LUMINANCE: \ 900 case GL_INTENSITY: \ 901 info.tbytesline = obj->Image[b]->Width; \ 902 break; \ 903 case GL_LUMINANCE_ALPHA: \ 904 info.tbytesline = obj->Image[b]->Width * 2; \ 905 break; \ 906 case GL_RGB: \ 907 info.tbytesline = obj->Image[b]->Width * 3; \ 908 break; \ 909 case GL_RGBA: \ 910 info.tbytesline = obj->Image[b]->Width * 4; \ 911 break; \ 912 default: \ 913 _mesa_problem(NULL, "Bad texture format in persp_textured_triangle");\ 914 return; \ 915 } \ 916 info.tsize = obj->Image[b]->Height * info.tbytesline; 917 918#define RENDER_SPAN( span ) fast_persp_span(ctx, &span, &info); 919 920#include "s_tritemp.h" 921 922} 923 924 925#endif /* CHAN_BITS != GL_FLOAT */ 926 927 928 929 930/* 931 * Render a smooth-shaded, textured, RGBA triangle. 932 * Interpolate S,T,R with perspective correction, w/out mipmapping. 933 */ 934static void general_textured_triangle( GLcontext *ctx, 935 const SWvertex *v0, 936 const SWvertex *v1, 937 const SWvertex *v2 ) 938{ 939#define INTERP_Z 1 940#define INTERP_FOG 1 941#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 942#define INTERP_RGB 1 943#define INTERP_ALPHA 1 944#define INTERP_TEX 1 945 946#define SETUP_CODE \ 947 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \ 948 const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\ 949 span.texWidth[0] = (GLfloat) texImage->Width; \ 950 span.texHeight[0] = (GLfloat) texImage->Height; \ 951 (void) fixedToDepthShift; 952 953#define RENDER_SPAN( span ) \ 954 GLuint i; \ 955 SW_SPAN_SET_FLAG(span.filledColor); \ 956 SW_SPAN_SET_FLAG(span.filledAlpha); \ 957 SW_SPAN_SET_FLAG(span.filledTex[0]); \ 958 SW_SPAN_SET_FLAG(span.filledDepth); \ 959 /* NOTE: we could just call rasterize_span() here instead */ \ 960 for (i = 0; i < span.end; i++) { \ 961 GLdouble invQ = span.tex[0][3] ? (1.0 / span.tex[0][3]) : 1.0; \ 962 span.zArray[i] = FixedToDepth(span.z); \ 963 span.z += span.zStep; \ 964 span.color.rgba[i][RCOMP] = FixedToChan(span.red); \ 965 span.color.rgba[i][GCOMP] = FixedToChan(span.green); \ 966 span.color.rgba[i][BCOMP] = FixedToChan(span.blue); \ 967 span.color.rgba[i][ACOMP] = FixedToChan(span.alpha); \ 968 span.red += span.redStep; \ 969 span.green += span.greenStep; \ 970 span.blue += span.blueStep; \ 971 span.alpha += span.alphaStep; \ 972 span.texcoords[0][i][0] = (GLfloat) (span.tex[0][0] * invQ); \ 973 span.texcoords[0][i][1] = (GLfloat) (span.tex[0][1] * invQ); \ 974 span.texcoords[0][i][2] = (GLfloat) (span.tex[0][2] * invQ); \ 975 span.tex[0][0] += span.texStep[0][0]; \ 976 span.tex[0][1] += span.texStep[0][1]; \ 977 span.tex[0][2] += span.texStep[0][2]; \ 978 span.tex[0][3] += span.texStep[0][3]; \ 979 } \ 980 _mesa_write_texture_span( ctx, &span, GL_POLYGON ); 981 982#include "s_tritemp.h" 983} 984 985 986/* 987 * Render a smooth-shaded, textured, RGBA triangle with separate specular 988 * color interpolation. 989 * Interpolate texcoords with perspective correction, w/out mipmapping. 990 */ 991static void general_textured_spec_triangle( GLcontext *ctx, 992 const SWvertex *v0, 993 const SWvertex *v1, 994 const SWvertex *v2 ) 995{ 996#define INTERP_Z 1 997#define INTERP_FOG 1 998#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 999#define INTERP_RGB 1 1000#define INTERP_SPEC 1 1001#define INTERP_ALPHA 1 1002#define INTERP_TEX 1 1003 1004#define SETUP_CODE \ 1005 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \ 1006 const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\ 1007 span.texWidth[0] = (GLfloat) texImage->Width; \ 1008 span.texHeight[0] = (GLfloat) texImage->Height; \ 1009 (void) fixedToDepthShift; 1010 1011#define RENDER_SPAN( span ) _mesa_rasterize_span(ctx, &span); 1012 1013#include "s_tritemp.h" 1014} 1015 1016 1017/* 1018 * Render a smooth-shaded, textured, RGBA triangle. 1019 * Interpolate S,T,R with perspective correction and compute lambda for 1020 * each fragment. Lambda is used to determine whether to use the 1021 * minification or magnification filter. If minification and using 1022 * mipmaps, lambda is also used to select the texture level of detail. 1023 */ 1024static void lambda_textured_triangle( GLcontext *ctx, 1025 const SWvertex *v0, 1026 const SWvertex *v1, 1027 const SWvertex *v2 ) 1028{ 1029#define INTERP_Z 1 1030#define INTERP_FOG 1 1031#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1032#define INTERP_RGB 1 1033#define INTERP_ALPHA 1 1034#define INTERP_TEX 1 1035#define INTERP_LAMBDA 1 1036 1037#define SETUP_CODE \ 1038 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \ 1039 const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\ 1040 span.texWidth[0] = (GLfloat) texImage->Width; \ 1041 span.texHeight[0] = (GLfloat) texImage->Height; \ 1042 (void) fixedToDepthShift; 1043 1044#define RENDER_SPAN( span ) _mesa_rasterize_span(ctx, &span); 1045 1046#include "s_tritemp.h" 1047} 1048 1049 1050/* 1051 * Render a smooth-shaded, textured, RGBA triangle with separate specular 1052 * interpolation. 1053 * Interpolate S,T,R with perspective correction and compute lambda for 1054 * each fragment. Lambda is used to determine whether to use the 1055 * minification or magnification filter. If minification and using 1056 * mipmaps, lambda is also used to select the texture level of detail. 1057 */ 1058static void lambda_textured_spec_triangle( GLcontext *ctx, 1059 const SWvertex *v0, 1060 const SWvertex *v1, 1061 const SWvertex *v2 ) 1062{ 1063#define INTERP_Z 1 1064#define INTERP_FOG 1 1065#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1066#define INTERP_RGB 1 1067#define INTERP_SPEC 1 1068#define INTERP_ALPHA 1 1069#define INTERP_TEX 1 1070#define INTERP_LAMBDA 1 1071 1072#define SETUP_CODE \ 1073 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \ 1074 const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\ 1075 span.texWidth[0] = (GLfloat) texImage->Width; \ 1076 span.texHeight[0] = (GLfloat) texImage->Height; \ 1077 (void) fixedToDepthShift; 1078 1079#define RENDER_SPAN( span ) _mesa_rasterize_span(ctx, &span); 1080 1081#include "s_tritemp.h" 1082} 1083 1084 1085/* 1086 * This is the big one! 1087 * Interpolate Z, RGB, Alpha, specular, fog, and N sets of texture coordinates 1088 * with lambda (LOD). 1089 * Yup, it's slow. 1090 */ 1091static void 1092lambda_multitextured_triangle( GLcontext *ctx, 1093 const SWvertex *v0, 1094 const SWvertex *v1, 1095 const SWvertex *v2 ) 1096{ 1097 1098#define INTERP_Z 1 1099#define INTERP_FOG 1 1100#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1101#define INTERP_RGB 1 1102#define INTERP_ALPHA 1 1103#define INTERP_SPEC 1 1104#define INTERP_MULTITEX 1 1105#define INTERP_LAMBDA 1 1106 1107#define SETUP_CODE \ 1108 GLuint u; \ 1109 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { \ 1110 if (ctx->Texture.Unit[u]._ReallyEnabled) { \ 1111 const struct gl_texture_object *texObj; \ 1112 const struct gl_texture_image *texImage; \ 1113 texObj = ctx->Texture.Unit[u]._Current; \ 1114 texImage = texObj->Image[texObj->BaseLevel]; \ 1115 span.texWidth[u] = (GLfloat) texImage->Width; \ 1116 span.texHeight[u] = (GLfloat) texImage->Height; \ 1117 } \ 1118 } \ 1119 (void) fixedToDepthShift; 1120 1121#define RENDER_SPAN( span ) _mesa_rasterize_span(ctx, &span); 1122 1123#include "s_tritemp.h" 1124 1125} 1126 1127 1128static void occlusion_zless_triangle( GLcontext *ctx, 1129 const SWvertex *v0, 1130 const SWvertex *v1, 1131 const SWvertex *v2 ) 1132{ 1133 if (ctx->OcclusionResult) { 1134 return; 1135 } 1136 1137#define DO_OCCLUSION_TEST 1138#define INTERP_Z 1 1139#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1140 1141#define RENDER_SPAN( span ) \ 1142 GLuint i; \ 1143 for (i = 0; i < span.end; i++) { \ 1144 GLdepth z = FixedToDepth(span.z); \ 1145 if (z < zRow[i]) { \ 1146 ctx->OcclusionResult = GL_TRUE; \ 1147 return; \ 1148 } \ 1149 span.z += span.zStep; \ 1150 } 1151 1152#include "s_tritemp.h" 1153} 1154 1155static void nodraw_triangle( GLcontext *ctx, 1156 const SWvertex *v0, 1157 const SWvertex *v1, 1158 const SWvertex *v2 ) 1159{ 1160 (void) (ctx && v0 && v1 && v2); 1161} 1162 1163 1164/* 1165 * This is used when separate specular color is enabled, but not 1166 * texturing. We add the specular color to the primary color, 1167 * draw the triangle, then restore the original primary color. 1168 * Inefficient, but seldom needed. 1169 */ 1170void _swrast_add_spec_terms_triangle( GLcontext *ctx, 1171 const SWvertex *v0, 1172 const SWvertex *v1, 1173 const SWvertex *v2 ) 1174{ 1175 SWvertex *ncv0 = (SWvertex *)v0; /* drop const qualifier */ 1176 SWvertex *ncv1 = (SWvertex *)v1; 1177 SWvertex *ncv2 = (SWvertex *)v2; 1178#if CHAN_TYPE == GL_FLOAT 1179 GLfloat rSum, gSum, bSum; 1180#else 1181 GLint rSum, gSum, bSum; 1182#endif 1183 GLchan c[3][4]; 1184 /* save original colors */ 1185 COPY_CHAN4( c[0], ncv0->color ); 1186 COPY_CHAN4( c[1], ncv1->color ); 1187 COPY_CHAN4( c[2], ncv2->color ); 1188 /* sum v0 */ 1189 rSum = ncv0->color[0] + ncv0->specular[0]; 1190 gSum = ncv0->color[1] + ncv0->specular[1]; 1191 bSum = ncv0->color[2] + ncv0->specular[2]; 1192 ncv0->color[0] = MIN2(rSum, CHAN_MAX); 1193 ncv0->color[1] = MIN2(gSum, CHAN_MAX); 1194 ncv0->color[2] = MIN2(bSum, CHAN_MAX); 1195 /* sum v1 */ 1196 rSum = ncv1->color[0] + ncv1->specular[0]; 1197 gSum = ncv1->color[1] + ncv1->specular[1]; 1198 bSum = ncv1->color[2] + ncv1->specular[2]; 1199 ncv1->color[0] = MIN2(rSum, CHAN_MAX); 1200 ncv1->color[1] = MIN2(gSum, CHAN_MAX); 1201 ncv1->color[2] = MIN2(bSum, CHAN_MAX); 1202 /* sum v2 */ 1203 rSum = ncv2->color[0] + ncv2->specular[0]; 1204 gSum = ncv2->color[1] + ncv2->specular[1]; 1205 bSum = ncv2->color[2] + ncv2->specular[2]; 1206 ncv2->color[0] = MIN2(rSum, CHAN_MAX); 1207 ncv2->color[1] = MIN2(gSum, CHAN_MAX); 1208 ncv2->color[2] = MIN2(bSum, CHAN_MAX); 1209 /* draw */ 1210 SWRAST_CONTEXT(ctx)->SpecTriangle( ctx, ncv0, ncv1, ncv2 ); 1211 /* restore original colors */ 1212 COPY_CHAN4( ncv0->color, c[0] ); 1213 COPY_CHAN4( ncv1->color, c[1] ); 1214 COPY_CHAN4( ncv2->color, c[2] ); 1215} 1216 1217 1218 1219#ifdef DEBUG 1220 1221/* record the current triangle function name */ 1222const char *_mesa_triFuncName = NULL; 1223 1224#define USE(triFunc) \ 1225do { \ 1226 _mesa_triFuncName = #triFunc; \ 1227 /*printf("%s\n", _mesa_triFuncName);*/ \ 1228 swrast->Triangle = triFunc; \ 1229} while (0) 1230 1231#else 1232 1233#define USE(triFunc) swrast->Triangle = triFunc; 1234 1235#endif 1236 1237 1238 1239 1240/* 1241 * Determine which triangle rendering function to use given the current 1242 * rendering context. 1243 * 1244 * Please update the summary flag _SWRAST_NEW_TRIANGLE if you add or 1245 * remove tests to this code. 1246 */ 1247void 1248_swrast_choose_triangle( GLcontext *ctx ) 1249{ 1250 SWcontext *swrast = SWRAST_CONTEXT(ctx); 1251 const GLboolean rgbmode = ctx->Visual.rgbMode; 1252 1253 if (ctx->Polygon.CullFlag && 1254 ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) { 1255 USE(nodraw_triangle); 1256 return; 1257 } 1258 1259 if (ctx->RenderMode==GL_RENDER) { 1260 1261 if (ctx->Polygon.SmoothFlag) { 1262 _mesa_set_aa_triangle_function(ctx); 1263 ASSERT(swrast->Triangle); 1264 return; 1265 } 1266 1267 if (ctx->Depth.OcclusionTest && 1268 ctx->Depth.Test && 1269 ctx->Depth.Mask == GL_FALSE && 1270 ctx->Depth.Func == GL_LESS && 1271 !ctx->Stencil.Enabled) { 1272 if ((rgbmode && 1273 ctx->Color.ColorMask[0] == 0 && 1274 ctx->Color.ColorMask[1] == 0 && 1275 ctx->Color.ColorMask[2] == 0 && 1276 ctx->Color.ColorMask[3] == 0) 1277 || 1278 (!rgbmode && ctx->Color.IndexMask == 0)) { 1279 USE(occlusion_zless_triangle); 1280 return; 1281 } 1282 } 1283 1284 if (ctx->Texture._ReallyEnabled) { 1285 /* Ugh, we do a _lot_ of tests to pick the best textured tri func */ 1286 const struct gl_texture_object *texObj2D; 1287 const struct gl_texture_image *texImg; 1288 GLenum minFilter, magFilter, envMode; 1289 GLint format; 1290 texObj2D = ctx->Texture.Unit[0].Current2D; 1291 texImg = texObj2D ? texObj2D->Image[texObj2D->BaseLevel] : NULL; 1292 format = texImg ? texImg->TexFormat->MesaFormat : -1; 1293 minFilter = texObj2D ? texObj2D->MinFilter : (GLenum) 0; 1294 magFilter = texObj2D ? texObj2D->MagFilter : (GLenum) 0; 1295 envMode = ctx->Texture.Unit[0].EnvMode; 1296 1297 /* First see if we can used an optimized 2-D texture function */ 1298 if (ctx->Texture._ReallyEnabled==TEXTURE0_2D 1299 && texObj2D->WrapS==GL_REPEAT 1300 && texObj2D->WrapT==GL_REPEAT 1301 && texImg->Border==0 1302 && (format == MESA_FORMAT_RGB || format == MESA_FORMAT_RGBA) 1303 && minFilter == magFilter 1304 && ctx->Light.Model.ColorControl == GL_SINGLE_COLOR 1305 && ctx->Texture.Unit[0].EnvMode != GL_COMBINE_EXT) { 1306 if (ctx->Hint.PerspectiveCorrection==GL_FASTEST) { 1307 if (minFilter == GL_NEAREST 1308 && format == MESA_FORMAT_RGB 1309 && (envMode == GL_REPLACE || envMode == GL_DECAL) 1310 && ((swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT) 1311 && ctx->Depth.Func == GL_LESS 1312 && ctx->Depth.Mask == GL_TRUE) 1313 || swrast->_RasterMask == TEXTURE_BIT) 1314 && ctx->Polygon.StippleFlag == GL_FALSE) { 1315 if (swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)) { 1316 USE(simple_z_textured_triangle); 1317 } 1318 else { 1319 USE(simple_textured_triangle); 1320 } 1321 } 1322 else { 1323#if CHAN_TYPE == GL_FLOAT 1324 USE(general_textured_triangle); 1325#else 1326 USE(affine_textured_triangle); 1327#endif 1328 } 1329 } 1330 else { 1331#if CHAN_TYPE == GL_FLOAT 1332 USE(general_textured_triangle); 1333#else 1334 USE(persp_textured_triangle); 1335#endif 1336 } 1337 } 1338 else { 1339 /* More complicated textures (mipmap, multi-tex, sep specular) */ 1340 GLboolean needLambda; 1341 /* if mag filter != min filter we need to compute lambda */ 1342 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; 1343 if (obj && obj->MinFilter != obj->MagFilter) 1344 needLambda = GL_TRUE; 1345 else 1346 needLambda = GL_FALSE; 1347 if (ctx->Texture._ReallyEnabled > TEXTURE0_ANY) { 1348 USE(lambda_multitextured_triangle); 1349 } 1350 else if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) { 1351 /* separate specular color interpolation */ 1352 if (needLambda) { 1353 USE(lambda_textured_spec_triangle); 1354 } 1355 else { 1356 USE(general_textured_spec_triangle); 1357 } 1358 } 1359 else { 1360 if (needLambda) { 1361 USE(lambda_textured_triangle); 1362 } 1363 else { 1364 USE(general_textured_triangle); 1365 } 1366 } 1367 } 1368 } 1369 else { 1370 ASSERT(!ctx->Texture._ReallyEnabled); 1371 if (ctx->Light.ShadeModel==GL_SMOOTH) { 1372 /* smooth shaded, no texturing, stippled or some raster ops */ 1373 if (rgbmode) { 1374 USE(smooth_rgba_triangle); 1375 } 1376 else { 1377 USE(smooth_ci_triangle); 1378 } 1379 } 1380 else { 1381 /* flat shaded, no texturing, stippled or some raster ops */ 1382 if (rgbmode) { 1383 USE(flat_rgba_triangle); 1384 } 1385 else { 1386 USE(flat_ci_triangle); 1387 } 1388 } 1389 } 1390 } 1391 else if (ctx->RenderMode==GL_FEEDBACK) { 1392 USE(_mesa_feedback_triangle); 1393 } 1394 else { 1395 /* GL_SELECT mode */ 1396 USE(_mesa_select_triangle); 1397 } 1398} 1399