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