s_triangle.c revision 571c8ecc8f9442fb8bbaa1f29b1d0d4f8e5b3cad
1/* $Id: s_triangle.c,v 1.31 2001/07/09 16:16:20 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#include "s_trispan.h" 51 52 53 54GLboolean _mesa_cull_triangle( GLcontext *ctx, 55 const SWvertex *v0, 56 const SWvertex *v1, 57 const SWvertex *v2 ) 58{ 59 GLfloat ex = v1->win[0] - v0->win[0]; 60 GLfloat ey = v1->win[1] - v0->win[1]; 61 GLfloat fx = v2->win[0] - v0->win[0]; 62 GLfloat fy = v2->win[1] - v0->win[1]; 63 GLfloat c = ex*fy-ey*fx; 64 65 if (c * SWRAST_CONTEXT(ctx)->_backface_sign > 0) 66 return 0; 67 68 return 1; 69} 70 71 72 73/* 74 * Render a flat-shaded color index triangle. 75 */ 76static void flat_ci_triangle( GLcontext *ctx, 77 const SWvertex *v0, 78 const SWvertex *v1, 79 const SWvertex *v2 ) 80{ 81#define INTERP_Z 1 82#define INTERP_FOG 1 83 84#define RENDER_SPAN( span ) \ 85 GLdepth zSpan[MAX_WIDTH]; \ 86 GLfloat fogSpan[MAX_WIDTH]; \ 87 GLuint i; \ 88 for (i = 0; i < span.count; i++) { \ 89 zSpan[i] = FixedToDepth(span.z); \ 90 span.z += span.zStep; \ 91 fogSpan[i] = span.fog; \ 92 span.fog += span.fogStep; \ 93 } \ 94 _mesa_write_monoindex_span(ctx, span.count, span.x, span.y, \ 95 zSpan, fogSpan, v0->index, NULL, GL_POLYGON ); 96 97#include "s_tritemp.h" 98} 99 100 101 102/* 103 * Render a smooth-shaded color index triangle. 104 */ 105static void smooth_ci_triangle( GLcontext *ctx, 106 const SWvertex *v0, 107 const SWvertex *v1, 108 const SWvertex *v2 ) 109{ 110#define INTERP_Z 1 111#define INTERP_FOG 1 112#define INTERP_INDEX 1 113 114#define RENDER_SPAN( span ) \ 115 GLdepth zSpan[MAX_WIDTH]; \ 116 GLfloat fogSpan[MAX_WIDTH]; \ 117 GLuint indexSpan[MAX_WIDTH]; \ 118 GLuint i; \ 119 for (i = 0; i < span.count; i++) { \ 120 zSpan[i] = FixedToDepth(span.z); \ 121 span.z += span.zStep; \ 122 indexSpan[i] = FixedToInt(span.index); \ 123 span.index += span.indexStep; \ 124 fogSpan[i] = span.fog; \ 125 span.fog += span.fogStep; \ 126 } \ 127 _mesa_write_index_span(ctx, span.count, span.x, span.y, \ 128 zSpan, fogSpan, indexSpan, NULL, GL_POLYGON); 129 130#include "s_tritemp.h" 131} 132 133 134 135/* 136 * Render a flat-shaded RGBA triangle. 137 */ 138static void flat_rgba_triangle( GLcontext *ctx, 139 const SWvertex *v0, 140 const SWvertex *v1, 141 const SWvertex *v2 ) 142{ 143#define INTERP_Z 1 144#define INTERP_FOG 1 145#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 146 147#define RENDER_SPAN( span ) \ 148 GLdepth zSpan[MAX_WIDTH]; \ 149 GLfloat fogSpan[MAX_WIDTH]; \ 150 GLuint i; \ 151 for (i = 0; i < span.count; i++) { \ 152 zSpan[i] = FixedToDepth(span.z); \ 153 span.z += span.zStep; \ 154 fogSpan[i] = span.fog; \ 155 span.fog += span.fogStep; \ 156 } \ 157 _mesa_write_monocolor_span(ctx, span.count, span.x, span.y, zSpan, \ 158 fogSpan, v2->color, NULL, GL_POLYGON ); 159 160#include "s_tritemp.h" 161 162 ASSERT(!ctx->Texture._ReallyEnabled); /* texturing must be off */ 163 ASSERT(ctx->Light.ShadeModel==GL_FLAT); 164} 165 166 167 168/* 169 * Render a smooth-shaded RGBA triangle. 170 */ 171static void smooth_rgba_triangle( GLcontext *ctx, 172 const SWvertex *v0, 173 const SWvertex *v1, 174 const SWvertex *v2 ) 175{ 176 177#define INTERP_Z 1 178#define INTERP_FOG 1 179#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 180#define INTERP_RGB 1 181#define INTERP_ALPHA 1 182 183#define RENDER_SPAN( span ) \ 184 GLdepth zSpan[MAX_WIDTH]; \ 185 GLchan rgbaSpan[MAX_WIDTH][4]; \ 186 GLfloat fogSpan[MAX_WIDTH]; \ 187 GLuint i; \ 188 for (i = 0; i < span.count; i++) { \ 189 rgbaSpan[i][RCOMP] = FixedToInt(span.red); \ 190 rgbaSpan[i][GCOMP] = FixedToInt(span.green); \ 191 rgbaSpan[i][BCOMP] = FixedToInt(span.blue); \ 192 rgbaSpan[i][ACOMP] = FixedToInt(span.alpha); \ 193 span.red += span.redStep; \ 194 span.green += span.greenStep; \ 195 span.blue += span.blueStep; \ 196 span.alpha += span.alphaStep; \ 197 zSpan[i] = FixedToDepth(span.z); \ 198 span.z += span.zStep; \ 199 fogSpan[i] = span.fog; \ 200 span.fog += span.fogStep; \ 201 } \ 202 _mesa_write_rgba_span(ctx, span.count, span.x, span.y, \ 203 (CONST GLdepth *) zSpan, \ 204 fogSpan, rgbaSpan, NULL, GL_POLYGON); 205 206#include "s_tritemp.h" 207 208 ASSERT(!ctx->Texture._ReallyEnabled); /* texturing must be off */ 209 ASSERT(ctx->Light.ShadeModel==GL_SMOOTH); 210} 211 212 213/* 214 * Render an RGB, GL_DECAL, textured triangle. 215 * Interpolate S,T only w/out mipmapping or perspective correction. 216 * 217 * No fog. 218 */ 219static void simple_textured_triangle( GLcontext *ctx, 220 const SWvertex *v0, 221 const SWvertex *v1, 222 const SWvertex *v2 ) 223{ 224#define INTERP_INT_TEX 1 225#define S_SCALE twidth 226#define T_SCALE theight 227 228#define SETUP_CODE \ 229 SWcontext *swrast = SWRAST_CONTEXT(ctx); \ 230 struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \ 231 GLint b = obj->BaseLevel; \ 232 const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ 233 const GLfloat theight = (GLfloat) obj->Image[b]->Height; \ 234 const GLint twidth_log2 = obj->Image[b]->WidthLog2; \ 235 const GLchan *texture = (const GLchan *) obj->Image[b]->Data; \ 236 const GLint smask = obj->Image[b]->Width - 1; \ 237 const GLint tmask = obj->Image[b]->Height - 1; \ 238 if (!texture) { \ 239 /* this shouldn't happen */ \ 240 return; \ 241 } 242 243#define RENDER_SPAN( span ) \ 244 GLchan rgbSpan[MAX_WIDTH][3]; \ 245 GLuint i; \ 246 span.intTex[0] -= FIXED_HALF; /* off-by-one error? */ \ 247 span.intTex[1] -= FIXED_HALF; \ 248 for (i = 0; i < span.count; i++) { \ 249 GLint s = FixedToInt(span.intTex[0]) & smask; \ 250 GLint t = FixedToInt(span.intTex[1]) & tmask; \ 251 GLint pos = (t << twidth_log2) + s; \ 252 pos = pos + pos + pos; /* multiply by 3 */ \ 253 rgbSpan[i][RCOMP] = texture[pos]; \ 254 rgbSpan[i][GCOMP] = texture[pos+1]; \ 255 rgbSpan[i][BCOMP] = texture[pos+2]; \ 256 span.intTex[0] += span.intTexStep[0]; \ 257 span.intTex[1] += span.intTexStep[1]; \ 258 } \ 259 (*swrast->Driver.WriteRGBSpan)(ctx, span.count, span.x, span.y, \ 260 (CONST GLchan (*)[3]) rgbSpan, NULL ); 261 262#include "s_tritemp.h" 263} 264 265 266/* 267 * Render an RGB, GL_DECAL, textured triangle. 268 * Interpolate S,T, GL_LESS depth test, w/out mipmapping or 269 * perspective correction. 270 * 271 * No fog. 272 */ 273static void simple_z_textured_triangle( GLcontext *ctx, 274 const SWvertex *v0, 275 const SWvertex *v1, 276 const SWvertex *v2 ) 277{ 278#define INTERP_Z 1 279#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 280#define INTERP_INT_TEX 1 281#define S_SCALE twidth 282#define T_SCALE theight 283 284#define SETUP_CODE \ 285 SWcontext *swrast = SWRAST_CONTEXT(ctx); \ 286 struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \ 287 GLint b = obj->BaseLevel; \ 288 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ 289 GLfloat theight = (GLfloat) obj->Image[b]->Height; \ 290 GLint twidth_log2 = obj->Image[b]->WidthLog2; \ 291 const GLchan *texture = (const GLchan *) obj->Image[b]->Data; \ 292 GLint smask = obj->Image[b]->Width - 1; \ 293 GLint tmask = obj->Image[b]->Height - 1; \ 294 if (!texture) { \ 295 /* this shouldn't happen */ \ 296 return; \ 297 } 298 299#define RENDER_SPAN( span ) \ 300 GLchan rgbSpan[MAX_WIDTH][3]; \ 301 GLubyte mask[MAX_WIDTH]; \ 302 GLuint i; \ 303 span.intTex[0] -= FIXED_HALF; /* off-by-one error? */ \ 304 span.intTex[1] -= FIXED_HALF; \ 305 for (i = 0; i < span.count; i++) { \ 306 const GLdepth z = FixedToDepth(span.z); \ 307 if (z < zRow[i]) { \ 308 GLint s = FixedToInt(span.intTex[0]) & smask; \ 309 GLint t = FixedToInt(span.intTex[1]) & tmask; \ 310 GLint pos = (t << twidth_log2) + s; \ 311 pos = pos + pos + pos; /* multiply by 3 */ \ 312 rgbSpan[i][RCOMP] = texture[pos]; \ 313 rgbSpan[i][GCOMP] = texture[pos+1]; \ 314 rgbSpan[i][BCOMP] = texture[pos+2]; \ 315 zRow[i] = z; \ 316 mask[i] = 1; \ 317 } \ 318 else { \ 319 mask[i] = 0; \ 320 } \ 321 span.intTex[0] += span.intTexStep[0]; \ 322 span.intTex[1] += span.intTexStep[1]; \ 323 span.z += span.zStep; \ 324 } \ 325 (*swrast->Driver.WriteRGBSpan)(ctx, span.count, span.x, span.y, \ 326 (CONST GLchan (*)[3]) rgbSpan, mask ); 327 328#include "s_tritemp.h" 329} 330 331 332 333struct affine_info 334{ 335 GLenum filter; 336 GLenum format; 337 GLenum envmode; 338 GLint smask, tmask; 339 GLint twidth_log2; 340 const GLchan *texture; 341 GLchan er, eg, eb, ea; 342 GLint tbytesline, tsize; 343 GLint fixedToDepthShift; 344}; 345 346static void 347affine_span(GLcontext *ctx, struct triangle_span *span, 348 struct affine_info *info) 349{ 350 GLint tr, tg, tb, ta; 351 352 /* Instead of defining a function for each mode, a test is done 353 * between the outer and inner loops. This is to reduce code size 354 * and complexity. Observe that an optimizing compiler kills 355 * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST). 356 */ 357 358#define NEAREST_RGB \ 359 tr = tex00[RCOMP]; \ 360 tg = tex00[GCOMP]; \ 361 tb = tex00[BCOMP]; \ 362 ta = CHAN_MAX 363 364#define LINEAR_RGB \ 365 tr = (ti * (si * tex00[0] + sf * tex01[0]) + \ 366 tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \ 367 tg = (ti * (si * tex00[1] + sf * tex01[1]) + \ 368 tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \ 369 tb = (ti * (si * tex00[2] + sf * tex01[2]) + \ 370 tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \ 371 ta = CHAN_MAX 372 373#define NEAREST_RGBA \ 374 tr = tex00[RCOMP]; \ 375 tg = tex00[GCOMP]; \ 376 tb = tex00[BCOMP]; \ 377 ta = tex00[ACOMP] 378 379#define LINEAR_RGBA \ 380 tr = (ti * (si * tex00[0] + sf * tex01[0]) + \ 381 tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \ 382 tg = (ti * (si * tex00[1] + sf * tex01[1]) + \ 383 tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \ 384 tb = (ti * (si * tex00[2] + sf * tex01[2]) + \ 385 tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \ 386 ta = (ti * (si * tex00[3] + sf * tex01[3]) + \ 387 tf * (si * tex10[3] + sf * tex11[3])) >> 2 * FIXED_SHIFT 388 389#define MODULATE \ 390 dest[RCOMP] = span->red * (tr + 1) >> (FIXED_SHIFT + 8); \ 391 dest[GCOMP] = span->green * (tg + 1) >> (FIXED_SHIFT + 8); \ 392 dest[BCOMP] = span->blue * (tb + 1) >> (FIXED_SHIFT + 8); \ 393 dest[ACOMP] = span->alpha * (ta + 1) >> (FIXED_SHIFT + 8) 394 395#define DECAL \ 396 dest[RCOMP] = ((CHAN_MAX - ta) * span->red \ 397 + ((ta + 1) * tr << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \ 398 dest[GCOMP] = ((CHAN_MAX - ta) * span->green \ 399 + ((ta + 1) * tg << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \ 400 dest[BCOMP] = ((CHAN_MAX - ta) * span->blue \ 401 + ((ta + 1) * tb << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \ 402 dest[ACOMP] = FixedToInt(span->alpha) 403 404#define BLEND \ 405 dest[RCOMP] = ((CHAN_MAX - tr) * span->red \ 406 + (tr + 1) * info->er) >> (FIXED_SHIFT + 8); \ 407 dest[GCOMP] = ((CHAN_MAX - tg) * span->green \ 408 + (tg + 1) * info->eg) >> (FIXED_SHIFT + 8); \ 409 dest[BCOMP] = ((CHAN_MAX - tb) * span->blue \ 410 + (tb + 1) * info->eb) >> (FIXED_SHIFT + 8); \ 411 dest[ACOMP] = span->alpha * (ta + 1) >> (FIXED_SHIFT + 8) 412 413#define REPLACE \ 414 dest[RCOMP] = tr; \ 415 dest[GCOMP] = tg; \ 416 dest[BCOMP] = tb; \ 417 dest[ACOMP] = ta 418 419#define ADD \ 420 dest[RCOMP] = ((span->red << 8) \ 421 + (tr + 1) * info->er) >> (FIXED_SHIFT + 8); \ 422 dest[GCOMP] = ((span->green << 8) \ 423 + (tg + 1) * info->eg) >> (FIXED_SHIFT + 8); \ 424 dest[BCOMP] = ((span->blue << 8) \ 425 + (tb + 1) * info->eb) >> (FIXED_SHIFT + 8); \ 426 dest[ACOMP] = span->alpha * (ta + 1) >> (FIXED_SHIFT + 8) 427 428/* shortcuts */ 429 430#define NEAREST_RGB_REPLACE NEAREST_RGB;REPLACE 431 432#define NEAREST_RGBA_REPLACE *(GLint *)dest = *(GLint *)tex00 433 434#define SPAN_NEAREST(DO_TEX,COMP) \ 435 for (i = 0; i < span->count; i++) { \ 436 /* Isn't it necessary to use FixedFloor below?? */ \ 437 GLint s = FixedToInt(span->intTex[0]) & info->smask; \ 438 GLint t = FixedToInt(span->intTex[1]) & info->tmask; \ 439 GLint pos = (t << info->twidth_log2) + s; \ 440 const GLchan *tex00 = info->texture + COMP * pos; \ 441 zspan[i] = FixedToDepth(span->z); \ 442 fogspan[i] = span->fog; \ 443 DO_TEX; \ 444 span->fog += span->fogStep; \ 445 span->z += span->zStep; \ 446 span->red += span->redStep; \ 447 span->green += span->greenStep; \ 448 span->blue += span->blueStep; \ 449 span->alpha += span->alphaStep; \ 450 span->intTex[0] += span->intTexStep[0]; \ 451 span->intTex[1] += span->intTexStep[1]; \ 452 dest += 4; \ 453 } 454 455#define SPAN_LINEAR(DO_TEX,COMP) \ 456 for (i = 0; i < span->count; i++) { \ 457 /* Isn't it necessary to use FixedFloor below?? */ \ 458 GLint s = FixedToInt(span->intTex[0]) & info->smask; \ 459 GLint t = FixedToInt(span->intTex[1]) & info->tmask; \ 460 GLfixed sf = span->intTex[0] & FIXED_FRAC_MASK; \ 461 GLfixed tf = span->intTex[1] & FIXED_FRAC_MASK; \ 462 GLfixed si = FIXED_FRAC_MASK - sf; \ 463 GLfixed ti = FIXED_FRAC_MASK - tf; \ 464 GLint pos = (t << info->twidth_log2) + s; \ 465 const GLchan *tex00 = info->texture + COMP * pos; \ 466 const GLchan *tex10 = tex00 + info->tbytesline; \ 467 const GLchan *tex01 = tex00 + COMP; \ 468 const GLchan *tex11 = tex10 + COMP; \ 469 (void) ti; \ 470 (void) si; \ 471 if (t == info->tmask) { \ 472 tex10 -= info->tsize; \ 473 tex11 -= info->tsize; \ 474 } \ 475 if (s == info->smask) { \ 476 tex01 -= info->tbytesline; \ 477 tex11 -= info->tbytesline; \ 478 } \ 479 zspan[i] = FixedToDepth(span->z); \ 480 fogspan[i] = span->fog; \ 481 DO_TEX; \ 482 span->fog += span->fogStep; \ 483 span->z += span->zStep; \ 484 span->red += span->redStep; \ 485 span->green += span->greenStep; \ 486 span->blue += span->blueStep; \ 487 span->alpha += span->alphaStep; \ 488 span->intTex[0] += span->intTexStep[0]; \ 489 span->intTex[1] += span->intTexStep[1]; \ 490 dest += 4; \ 491 } 492 493#define FixedToDepth(F) ((F) >> fixedToDepthShift) 494 495 GLuint i; 496 GLdepth zspan[MAX_WIDTH]; 497 GLfloat fogspan[MAX_WIDTH]; 498 GLchan rgba[MAX_WIDTH][4]; 499 GLchan *dest = rgba[0]; 500 const GLint fixedToDepthShift = info->fixedToDepthShift; 501 502 span->intTex[0] -= FIXED_HALF; 503 span->intTex[1] -= FIXED_HALF; 504 switch (info->filter) { 505 case GL_NEAREST: 506 switch (info->format) { 507 case GL_RGB: 508 switch (info->envmode) { 509 case GL_MODULATE: 510 SPAN_NEAREST(NEAREST_RGB;MODULATE,3); 511 break; 512 case GL_DECAL: 513 case GL_REPLACE: 514 SPAN_NEAREST(NEAREST_RGB_REPLACE,3); 515 break; 516 case GL_BLEND: 517 SPAN_NEAREST(NEAREST_RGB;BLEND,3); 518 break; 519 case GL_ADD: 520 SPAN_NEAREST(NEAREST_RGB;ADD,3); 521 break; 522 default: 523 abort(); 524 } 525 break; 526 case GL_RGBA: 527 switch(info->envmode) { 528 case GL_MODULATE: 529 SPAN_NEAREST(NEAREST_RGBA;MODULATE,4); 530 break; 531 case GL_DECAL: 532 SPAN_NEAREST(NEAREST_RGBA;DECAL,4); 533 break; 534 case GL_BLEND: 535 SPAN_NEAREST(NEAREST_RGBA;BLEND,4); 536 break; 537 case GL_ADD: 538 SPAN_NEAREST(NEAREST_RGBA;ADD,4); 539 break; 540 case GL_REPLACE: 541 SPAN_NEAREST(NEAREST_RGBA_REPLACE,4); 542 break; 543 default: 544 abort(); 545 } 546 break; 547 } 548 break; 549 550 case GL_LINEAR: 551 span->intTex[0] -= FIXED_HALF; 552 span->intTex[1] -= FIXED_HALF; 553 switch (info->format) { 554 case GL_RGB: 555 switch (info->envmode) { 556 case GL_MODULATE: 557 SPAN_LINEAR(LINEAR_RGB;MODULATE,3); 558 break; 559 case GL_DECAL: 560 case GL_REPLACE: 561 SPAN_LINEAR(LINEAR_RGB;REPLACE,3); 562 break; 563 case GL_BLEND: 564 SPAN_LINEAR(LINEAR_RGB;BLEND,3); 565 break; 566 case GL_ADD: 567 SPAN_LINEAR(LINEAR_RGB;ADD,3); 568 break; 569 default: 570 abort(); 571 } 572 break; 573 case GL_RGBA: 574 switch (info->envmode) { 575 case GL_MODULATE: 576 SPAN_LINEAR(LINEAR_RGBA;MODULATE,4); 577 break; 578 case GL_DECAL: 579 SPAN_LINEAR(LINEAR_RGBA;DECAL,4); 580 break; 581 case GL_BLEND: 582 SPAN_LINEAR(LINEAR_RGBA;BLEND,4); 583 break; 584 case GL_ADD: 585 SPAN_LINEAR(LINEAR_RGBA;ADD,4); 586 break; 587 case GL_REPLACE: 588 SPAN_LINEAR(LINEAR_RGBA;REPLACE,4); 589 break; 590 default: 591 abort(); 592 } break; 593 } 594 break; 595 } 596 _mesa_write_rgba_span(ctx, span->count, span->x, span->y, 597 zspan, fogspan, rgba, NULL, GL_POLYGON); 598 599#undef SPAN_NEAREST 600#undef SPAN_LINEAR 601#undef FixedToDepth 602} 603 604 605 606/* 607 * Render an RGB/RGBA textured triangle without perspective correction. 608 */ 609static void affine_textured_triangle( GLcontext *ctx, 610 const SWvertex *v0, 611 const SWvertex *v1, 612 const SWvertex *v2 ) 613{ 614#define INTERP_Z 1 615#define INTERP_FOG 1 616#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 617#define INTERP_RGB 1 618#define INTERP_ALPHA 1 619#define INTERP_INT_TEX 1 620#define S_SCALE twidth 621#define T_SCALE theight 622 623#define SETUP_CODE \ 624 struct affine_info info; \ 625 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \ 626 struct gl_texture_object *obj = unit->Current2D; \ 627 GLint b = obj->BaseLevel; \ 628 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ 629 GLfloat theight = (GLfloat) obj->Image[b]->Height; \ 630 info.fixedToDepthShift = ctx->Visual.depthBits <= 16 ? FIXED_SHIFT : 0;\ 631 info.texture = (const GLchan *) obj->Image[b]->Data; \ 632 info.twidth_log2 = obj->Image[b]->WidthLog2; \ 633 info.smask = obj->Image[b]->Width - 1; \ 634 info.tmask = obj->Image[b]->Height - 1; \ 635 info.format = obj->Image[b]->Format; \ 636 info.filter = obj->MinFilter; \ 637 info.envmode = unit->EnvMode; \ 638 \ 639 if (info.envmode == GL_BLEND) { \ 640 /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \ 641 info.er = FloatToFixed(unit->EnvColor[RCOMP]); \ 642 info.eg = FloatToFixed(unit->EnvColor[GCOMP]); \ 643 info.eb = FloatToFixed(unit->EnvColor[BCOMP]); \ 644 info.ea = FloatToFixed(unit->EnvColor[ACOMP]); \ 645 } \ 646 if (!info.texture) { \ 647 /* this shouldn't happen */ \ 648 return; \ 649 } \ 650 \ 651 switch (info.format) { \ 652 case GL_ALPHA: \ 653 case GL_LUMINANCE: \ 654 case GL_INTENSITY: \ 655 info.tbytesline = obj->Image[b]->Width; \ 656 break; \ 657 case GL_LUMINANCE_ALPHA: \ 658 info.tbytesline = obj->Image[b]->Width * 2; \ 659 break; \ 660 case GL_RGB: \ 661 info.tbytesline = obj->Image[b]->Width * 3; \ 662 break; \ 663 case GL_RGBA: \ 664 info.tbytesline = obj->Image[b]->Width * 4; \ 665 break; \ 666 default: \ 667 _mesa_problem(NULL, "Bad texture format in affine_texture_triangle");\ 668 return; \ 669 } \ 670 info.tsize = obj->Image[b]->Height * info.tbytesline; 671 672#define RENDER_SPAN( span ) \ 673 affine_span(ctx, &span, &info); 674 675#include "s_tritemp.h" 676 677} 678 679 680struct persp_info 681{ 682 GLenum filter; 683 GLenum format; 684 GLenum envmode; 685 GLint smask, tmask; 686 GLint twidth_log2; 687 const GLchan *texture; 688 GLchan er, eg, eb, ea; 689 GLint tbytesline, tsize; 690 GLint fixedToDepthShift; 691}; 692 693static void 694fast_persp_span(GLcontext *ctx, struct triangle_span *span, 695 struct persp_info *info) 696{ 697 GLint tr, tg, tb, ta; 698 699 /* Instead of defining a function for each mode, a test is done 700 * between the outer and inner loops. This is to reduce code size 701 * and complexity. Observe that an optimizing compiler kills 702 * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST). 703 */ 704 705#define SPAN_NEAREST(DO_TEX,COMP) \ 706 for (i = 0; i < span->count; i++) { \ 707 GLdouble invQ = tex_coord[2] ? \ 708 (1.0 / tex_coord[2]) : 1.0; \ 709 GLfloat s_tmp = tex_coord[0] * invQ; \ 710 GLfloat t_tmp = tex_coord[1] * invQ; \ 711 GLint s = IFLOOR(s_tmp) & info->smask; \ 712 GLint t = IFLOOR(t_tmp) & info->tmask; \ 713 GLint pos = (t << info->twidth_log2) + s; \ 714 const GLchan *tex00 = info->texture + COMP * pos; \ 715 zspan[i] = FixedToDepth(span->z); \ 716 fogspan[i] = span->fog; \ 717 DO_TEX; \ 718 span->fog += span->fogStep; \ 719 span->z += span->zStep; \ 720 span->red += span->redStep; \ 721 span->green += span->greenStep; \ 722 span->blue += span->blueStep; \ 723 span->alpha += span->alphaStep; \ 724 tex_coord[0] += tex_step[0]; \ 725 tex_coord[1] += tex_step[1]; \ 726 tex_coord[2] += tex_step[2]; \ 727 dest += 4; \ 728 } 729 730#define SPAN_LINEAR(DO_TEX,COMP) \ 731 for (i = 0; i < span->count; i++) { \ 732 GLdouble invQ = tex_coord[2] ? \ 733 (1.0 / tex_coord[2]) : 1.0; \ 734 GLfloat s_tmp = tex_coord[0] * invQ - 0.5F; \ 735 GLfloat t_tmp = tex_coord[1] * invQ - 0.5F; \ 736 GLfixed s_fix = FloatToFixed(s_tmp); \ 737 GLfixed t_fix = FloatToFixed(t_tmp); \ 738 GLint s = FixedToInt(FixedFloor(s_fix)) & info->smask; \ 739 GLint t = FixedToInt(FixedFloor(t_fix)) & info->tmask; \ 740 GLfixed sf = s_fix & FIXED_FRAC_MASK; \ 741 GLfixed tf = t_fix & FIXED_FRAC_MASK; \ 742 GLfixed si = FIXED_FRAC_MASK - sf; \ 743 GLfixed ti = FIXED_FRAC_MASK - tf; \ 744 GLint pos = (t << info->twidth_log2) + s; \ 745 const GLchan *tex00 = info->texture + COMP * pos; \ 746 const GLchan *tex10 = tex00 + info->tbytesline; \ 747 const GLchan *tex01 = tex00 + COMP; \ 748 const GLchan *tex11 = tex10 + COMP; \ 749 (void) ti; \ 750 (void) si; \ 751 if (t == info->tmask) { \ 752 tex10 -= info->tsize; \ 753 tex11 -= info->tsize; \ 754 } \ 755 if (s == info->smask) { \ 756 tex01 -= info->tbytesline; \ 757 tex11 -= info->tbytesline; \ 758 } \ 759 zspan[i] = FixedToDepth(span->z); \ 760 fogspan[i] = span->fog; \ 761 DO_TEX; \ 762 span->fog += span->fogStep; \ 763 span->z += span->zStep; \ 764 span->red += span->redStep; \ 765 span->green += span->greenStep; \ 766 span->blue += span->blueStep; \ 767 span->alpha += span->alphaStep; \ 768 tex_coord[0] += tex_step[0]; \ 769 tex_coord[1] += tex_step[1]; \ 770 tex_coord[2] += tex_step[2]; \ 771 dest += 4; \ 772 } 773 774#define FixedToDepth(F) ((F) >> fixedToDepthShift) 775 776 GLuint i; 777 GLdepth zspan[MAX_WIDTH]; 778 GLfloat tex_coord[3], tex_step[3]; 779 GLfloat fogspan[MAX_WIDTH]; 780 GLchan rgba[MAX_WIDTH][4]; 781 GLchan *dest = rgba[0]; 782 const GLint fixedToDepthShift = info->fixedToDepthShift; 783 784 tex_coord[0] = span->tex[0][0] * (info->smask + 1), 785 tex_step[0] = span->texStep[0][0] * (info->smask + 1); 786 tex_coord[1] = span->tex[0][1] * (info->tmask + 1), 787 tex_step[1] = span->texStep[0][1] * (info->tmask + 1); 788 /* span->tex[0][2] only if 3D-texturing, here only 2D */ 789 tex_coord[2] = span->tex[0][3], 790 tex_step[2] = span->texStep[0][3]; 791 792 switch (info->filter) { 793 case GL_NEAREST: 794 switch (info->format) { 795 case GL_RGB: 796 switch (info->envmode) { 797 case GL_MODULATE: 798 SPAN_NEAREST(NEAREST_RGB;MODULATE,3); 799 break; 800 case GL_DECAL: 801 case GL_REPLACE: 802 SPAN_NEAREST(NEAREST_RGB_REPLACE,3); 803 break; 804 case GL_BLEND: 805 SPAN_NEAREST(NEAREST_RGB;BLEND,3); 806 break; 807 case GL_ADD: 808 SPAN_NEAREST(NEAREST_RGB;ADD,3); 809 break; 810 default: 811 abort(); 812 } 813 break; 814 case GL_RGBA: 815 switch(info->envmode) { 816 case GL_MODULATE: 817 SPAN_NEAREST(NEAREST_RGBA;MODULATE,4); 818 break; 819 case GL_DECAL: 820 SPAN_NEAREST(NEAREST_RGBA;DECAL,4); 821 break; 822 case GL_BLEND: 823 SPAN_NEAREST(NEAREST_RGBA;BLEND,4); 824 break; 825 case GL_ADD: 826 SPAN_NEAREST(NEAREST_RGBA;ADD,4); 827 break; 828 case GL_REPLACE: 829 SPAN_NEAREST(NEAREST_RGBA_REPLACE,4); 830 break; 831 default: 832 abort(); 833 } 834 break; 835 } 836 break; 837 838 case GL_LINEAR: 839 switch (info->format) { 840 case GL_RGB: 841 switch (info->envmode) { 842 case GL_MODULATE: 843 SPAN_LINEAR(LINEAR_RGB;MODULATE,3); 844 break; 845 case GL_DECAL: 846 case GL_REPLACE: 847 SPAN_LINEAR(LINEAR_RGB;REPLACE,3); 848 break; 849 case GL_BLEND: 850 SPAN_LINEAR(LINEAR_RGB;BLEND,3); 851 break; 852 case GL_ADD: 853 SPAN_LINEAR(LINEAR_RGB;ADD,3); 854 break; 855 default: 856 abort(); 857 } 858 break; 859 case GL_RGBA: 860 switch (info->envmode) { 861 case GL_MODULATE: 862 SPAN_LINEAR(LINEAR_RGBA;MODULATE,4); 863 break; 864 case GL_DECAL: 865 SPAN_LINEAR(LINEAR_RGBA;DECAL,4); 866 break; 867 case GL_BLEND: 868 SPAN_LINEAR(LINEAR_RGBA;BLEND,4); 869 break; 870 case GL_ADD: 871 SPAN_LINEAR(LINEAR_RGBA;ADD,4); 872 break; 873 case GL_REPLACE: 874 SPAN_LINEAR(LINEAR_RGBA;REPLACE,4); 875 break; 876 default: 877 abort(); 878 } 879 break; 880 } 881 break; 882 } 883 /* This does not seem to be necessary, but I don't know !! */ 884 /* span->tex[0][0] = tex_coord[0] / (info->smask + 1), 885 span->tex[0][1] = tex_coord[1] / (info->tmask + 1),*/ 886 /* span->tex[0][2] only if 3D-texturing, here only 2D */ 887 /* span->tex[0][3] = tex_coord[2]; */ 888 889 _mesa_write_rgba_span(ctx, span->count, span->x, span->y, 890 zspan, fogspan, rgba, NULL, GL_POLYGON); 891 892 893#undef SPAN_NEAREST 894#undef SPAN_LINEAR 895#undef FixedToDepth 896} 897 898 899/* 900 * Render an perspective corrected RGB/RGBA textured triangle. 901 * The Q (aka V in Mesa) coordinate must be zero such that the divide 902 * by interpolated Q/W comes out right. 903 * 904 */ 905static void persp_textured_triangle( GLcontext *ctx, 906 const SWvertex *v0, 907 const SWvertex *v1, 908 const SWvertex *v2 ) 909{ 910#define INTERP_Z 1 911#define INTERP_FOG 1 912#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 913#define INTERP_RGB 1 914#define INTERP_ALPHA 1 915#define INTERP_TEX 1 916 917#define SETUP_CODE \ 918 struct persp_info info; \ 919 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \ 920 struct gl_texture_object *obj = unit->Current2D; \ 921 GLint b = obj->BaseLevel; \ 922 info.fixedToDepthShift = ctx->Visual.depthBits <= 16 ? FIXED_SHIFT : 0;\ 923 info.texture = (const GLchan *) obj->Image[b]->Data; \ 924 info.twidth_log2 = obj->Image[b]->WidthLog2; \ 925 info.smask = obj->Image[b]->Width - 1; \ 926 info.tmask = obj->Image[b]->Height - 1; \ 927 info.format = obj->Image[b]->Format; \ 928 info.filter = obj->MinFilter; \ 929 info.envmode = unit->EnvMode; \ 930 \ 931 if (info.envmode == GL_BLEND) { \ 932 /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \ 933 info.er = FloatToFixed(unit->EnvColor[RCOMP]); \ 934 info.eg = FloatToFixed(unit->EnvColor[GCOMP]); \ 935 info.eb = FloatToFixed(unit->EnvColor[BCOMP]); \ 936 info.ea = FloatToFixed(unit->EnvColor[ACOMP]); \ 937 } \ 938 if (!info.texture) { \ 939 /* this shouldn't happen */ \ 940 return; \ 941 } \ 942 \ 943 switch (info.format) { \ 944 case GL_ALPHA: \ 945 case GL_LUMINANCE: \ 946 case GL_INTENSITY: \ 947 info.tbytesline = obj->Image[b]->Width; \ 948 break; \ 949 case GL_LUMINANCE_ALPHA: \ 950 info.tbytesline = obj->Image[b]->Width * 2; \ 951 break; \ 952 case GL_RGB: \ 953 info.tbytesline = obj->Image[b]->Width * 3; \ 954 break; \ 955 case GL_RGBA: \ 956 info.tbytesline = obj->Image[b]->Width * 4; \ 957 break; \ 958 default: \ 959 _mesa_problem(NULL, "Bad texture format in affine_texture_triangle");\ 960 return; \ 961 } \ 962 info.tsize = obj->Image[b]->Height * info.tbytesline; 963 964#define RENDER_SPAN( span ) \ 965 fast_persp_span(ctx, &span, &info); 966 967#include "s_tritemp.h" 968 969} 970 971/* 972 * Generate arrays of fragment colors, z, fog, texcoords, etc from a 973 * triangle span object. Then call the span/fragment processsing 974 * functions in s_span.[ch]. 975 */ 976static void 977rasterize_span(GLcontext *ctx, const struct triangle_span *span) 978{ 979 DEFMARRAY(GLchan, rgba, MAX_WIDTH, 4); 980 DEFMARRAY(GLchan, spec, MAX_WIDTH, 4); 981 DEFARRAY(GLuint, index, MAX_WIDTH); 982 DEFARRAY(GLuint, z, MAX_WIDTH); 983 DEFARRAY(GLfloat, fog, MAX_WIDTH); 984 DEFARRAY(GLfloat, sTex, MAX_WIDTH); 985 DEFARRAY(GLfloat, tTex, MAX_WIDTH); 986 DEFARRAY(GLfloat, rTex, MAX_WIDTH); 987 DEFARRAY(GLfloat, lambda, MAX_WIDTH); 988 DEFMARRAY(GLfloat, msTex, MAX_TEXTURE_UNITS, MAX_WIDTH); 989 DEFMARRAY(GLfloat, mtTex, MAX_TEXTURE_UNITS, MAX_WIDTH); 990 DEFMARRAY(GLfloat, mrTex, MAX_TEXTURE_UNITS, MAX_WIDTH); 991 DEFMARRAY(GLfloat, mLambda, MAX_TEXTURE_UNITS, MAX_WIDTH); 992 993 CHECKARRAY(rgba, return); 994 CHECKARRAY(spec, return); 995 CHECKARRAY(index, return); 996 CHECKARRAY(z, return); 997 CHECKARRAY(fog, return); 998 CHECKARRAY(sTex, return); 999 CHECKARRAY(tTex, return); 1000 CHECKARRAY(rTex, return); 1001 CHECKARRAY(lambda, return); 1002 CHECKARRAY(msTex, return); 1003 CHECKARRAY(mtTex, return); 1004 CHECKARRAY(mrTex, return); 1005 CHECKARRAY(mLambda, return); 1006 1007 if (span->activeMask & SPAN_RGBA) { 1008 GLfixed r = span->red; 1009 GLfixed g = span->green; 1010 GLfixed b = span->blue; 1011 GLfixed a = span->alpha; 1012 GLuint i; 1013 for (i = 0; i < span->count; i++) { 1014 rgba[i][RCOMP] = FixedToInt(r); 1015 rgba[i][GCOMP] = FixedToInt(g); 1016 rgba[i][BCOMP] = FixedToInt(b); 1017 rgba[i][ACOMP] = FixedToInt(a); 1018 r += span->redStep; 1019 g += span->greenStep; 1020 b += span->blueStep; 1021 a += span->alphaStep; 1022 } 1023 } 1024 if (span->activeMask & SPAN_SPEC) { 1025 GLfixed r = span->specRed; 1026 GLfixed g = span->specGreen; 1027 GLfixed b = span->specBlue; 1028 GLuint i; 1029 for (i = 0; i < span->count; i++) { 1030 spec[i][RCOMP] = FixedToInt(r); 1031 spec[i][GCOMP] = FixedToInt(g); 1032 spec[i][BCOMP] = FixedToInt(b); 1033 r += span->specRedStep; 1034 g += span->specGreenStep; 1035 b += span->specBlueStep; 1036 } 1037 } 1038 if (span->activeMask & SPAN_INDEX) { 1039 GLuint i; 1040 GLfixed ind = span->index; 1041 for (i = 0; i < span->count; i++) { 1042 index[i] = FixedToInt(ind); 1043 ind += span->indexStep; 1044 } 1045 } 1046 if (span->activeMask & SPAN_Z) { 1047 if (ctx->Visual.depthBits <= 16) { 1048 GLuint i; 1049 GLfixed zval = span->z; 1050 for (i = 0; i < span->count; i++) { 1051 z[i] = FixedToInt(zval); 1052 zval += span->zStep; 1053 } 1054 } 1055 else { 1056 /* Deep Z buffer, no fixed->int shift */ 1057 GLuint i; 1058 GLfixed zval = span->z; 1059 for (i = 0; i < span->count; i++) { 1060 z[i] = zval; 1061 zval += span->zStep; 1062 } 1063 } 1064 } 1065 if (span->activeMask & SPAN_FOG) { 1066 GLuint i; 1067 GLfloat f = span->fog; 1068 for (i = 0; i < span->count; i++) { 1069 fog[i] = f; 1070 f += span->fogStep; 1071 } 1072 } 1073 if (span->activeMask & SPAN_TEXTURE) { 1074 if (ctx->Texture._ReallyEnabled & ~TEXTURE0_ANY) { 1075 /* multitexture */ 1076 if (span->activeMask & SPAN_LAMBDA) { 1077 /* with lambda */ 1078 GLuint u; 1079 for (u = 0; u < MAX_TEXTURE_UNITS; u++) { 1080 if (ctx->Texture.Unit[u]._ReallyEnabled) { 1081 GLfloat s = span->tex[u][0]; 1082 GLfloat t = span->tex[u][1]; 1083 GLfloat r = span->tex[u][2]; 1084 GLfloat q = span->tex[u][3]; 1085 GLuint i; 1086 for (i = 0; i < span->count; i++) { 1087 const GLfloat invQ = (q == 0.0F) ? 1.0 : (1.0F / q); 1088 msTex[u][i] = s * invQ; 1089 mtTex[u][i] = t * invQ; 1090 mrTex[u][i] = r * invQ; 1091 mLambda[u][i] = log(span->rho[u] * invQ * invQ) * 1.442695F * 0.5F; 1092 s += span->texStep[u][0]; 1093 t += span->texStep[u][1]; 1094 r += span->texStep[u][2]; 1095 q += span->texStep[u][3]; 1096 } 1097 } 1098 } 1099 } 1100 else { 1101 /* without lambda */ 1102 GLuint u; 1103 for (u = 0; u < MAX_TEXTURE_UNITS; u++) { 1104 if (ctx->Texture.Unit[u]._ReallyEnabled) { 1105 GLfloat s = span->tex[u][0]; 1106 GLfloat t = span->tex[u][1]; 1107 GLfloat r = span->tex[u][2]; 1108 GLfloat q = span->tex[u][3]; 1109 GLuint i; 1110 for (i = 0; i < span->count; i++) { 1111 const GLfloat invQ = (q == 0.0F) ? 1.0 : (1.0F / q); 1112 msTex[u][i] = s * invQ; 1113 mtTex[u][i] = t * invQ; 1114 mrTex[u][i] = r * invQ; 1115 s += span->texStep[u][0]; 1116 t += span->texStep[u][1]; 1117 r += span->texStep[u][2]; 1118 q += span->texStep[u][3]; 1119 } 1120 } 1121 } 1122 } 1123 } 1124 else { 1125 /* just texture unit 0 */ 1126 if (span->activeMask & SPAN_LAMBDA) { 1127 /* with lambda */ 1128 GLfloat s = span->tex[0][0]; 1129 GLfloat t = span->tex[0][1]; 1130 GLfloat r = span->tex[0][2]; 1131 GLfloat q = span->tex[0][3]; 1132 GLuint i; 1133 for (i = 0; i < span->count; i++) { 1134 const GLfloat invQ = (q == 0.0F) ? 1.0 : (1.0F / q); 1135 sTex[i] = s * invQ; 1136 tTex[i] = t * invQ; 1137 rTex[i] = r * invQ; 1138 lambda[i] = log(span->rho[0] * invQ * invQ) * 1.442695F * 0.5F; 1139 s += span->texStep[0][0]; 1140 t += span->texStep[0][1]; 1141 r += span->texStep[0][2]; 1142 q += span->texStep[0][3]; 1143 } 1144 } 1145 else { 1146 /* without lambda */ 1147 GLfloat s = span->tex[0][0]; 1148 GLfloat t = span->tex[0][1]; 1149 GLfloat r = span->tex[0][2]; 1150 GLfloat q = span->tex[0][3]; 1151 GLuint i; 1152 for (i = 0; i < span->count; i++) { 1153 const GLfloat invQ = (q == 0.0F) ? 1.0 : (1.0F / q); 1154 sTex[i] = s * invQ; 1155 tTex[i] = t * invQ; 1156 rTex[i] = r * invQ; 1157 s += span->texStep[0][0]; 1158 t += span->texStep[0][1]; 1159 r += span->texStep[0][2]; 1160 q += span->texStep[0][3]; 1161 } 1162 } 1163 } 1164 } 1165 /* XXX keep this? */ 1166 if (span->activeMask & SPAN_INT_TEXTURE) { 1167 GLint intTexcoord[MAX_WIDTH][2]; 1168 GLfixed s = span->intTex[0]; 1169 GLfixed t = span->intTex[1]; 1170 GLuint i; 1171 for (i = 0; i < span->count; i++) { 1172 intTexcoord[i][0] = FixedToInt(s); 1173 intTexcoord[i][1] = FixedToInt(t); 1174 s += span->intTexStep[0]; 1175 t += span->intTexStep[1]; 1176 } 1177 } 1178 1179 /* examine activeMask and call a s_span.c function */ 1180 if (span->activeMask & SPAN_TEXTURE) { 1181 const GLfloat *fogPtr; 1182 if (span->activeMask & SPAN_FOG) 1183 fogPtr = fog; 1184 else 1185 fogPtr = NULL; 1186 1187 if (ctx->Texture._ReallyEnabled & ~TEXTURE0_ANY) { 1188 if (span->activeMask & SPAN_SPEC) { 1189 _mesa_write_multitexture_span(ctx, span->count, span->x, span->y, 1190 z, fogPtr, 1191 (const GLfloat (*)[MAX_WIDTH]) msTex, 1192 (const GLfloat (*)[MAX_WIDTH]) mtTex, 1193 (const GLfloat (*)[MAX_WIDTH]) mrTex, 1194 (GLfloat (*)[MAX_WIDTH]) mLambda, 1195 rgba, (CONST GLchan (*)[4]) spec, 1196 NULL, GL_POLYGON ); 1197 } 1198 else { 1199 _mesa_write_multitexture_span(ctx, span->count, span->x, span->y, 1200 z, fogPtr, 1201 (const GLfloat (*)[MAX_WIDTH]) msTex, 1202 (const GLfloat (*)[MAX_WIDTH]) mtTex, 1203 (const GLfloat (*)[MAX_WIDTH]) mrTex, 1204 (GLfloat (*)[MAX_WIDTH]) mLambda, 1205 rgba, NULL, NULL, GL_POLYGON); 1206 } 1207 } 1208 else { 1209 /* single texture */ 1210 if (span->activeMask & SPAN_SPEC) { 1211 _mesa_write_texture_span(ctx, span->count, span->x, span->y, 1212 z, fogPtr, sTex, tTex, rTex, lambda, 1213 rgba, (CONST GLchan (*)[4]) spec, 1214 NULL, GL_POLYGON); 1215 } 1216 else { 1217 _mesa_write_texture_span(ctx, span->count, span->x, span->y, 1218 z, fogPtr, sTex, tTex, rTex, lambda, 1219 rgba, NULL, NULL, GL_POLYGON); 1220 } 1221 } 1222 } 1223 else { 1224 _mesa_problem(ctx, "rasterize_span() should only be used for texturing"); 1225 } 1226 1227 UNDEFARRAY(rgba); 1228 UNDEFARRAY(spec); 1229 UNDEFARRAY(index); 1230 UNDEFARRAY(z); 1231 UNDEFARRAY(fog); 1232 UNDEFARRAY(sTex); 1233 UNDEFARRAY(tTex); 1234 UNDEFARRAY(rTex); 1235 UNDEFARRAY(lambda); 1236 UNDEFARRAY(msTex); 1237 UNDEFARRAY(mtTex); 1238 UNDEFARRAY(mrTex); 1239 UNDEFARRAY(mLambda); 1240} 1241 1242 1243 1244 1245/* 1246 * Render a smooth-shaded, textured, RGBA triangle. 1247 * Interpolate S,T,R with perspective correction, w/out mipmapping. 1248 */ 1249static void general_textured_triangle( GLcontext *ctx, 1250 const SWvertex *v0, 1251 const SWvertex *v1, 1252 const SWvertex *v2 ) 1253{ 1254#define INTERP_Z 1 1255#define INTERP_FOG 1 1256#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1257#define INTERP_RGB 1 1258#define INTERP_ALPHA 1 1259#define INTERP_TEX 1 1260 1261#define SETUP_CODE \ 1262 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \ 1263 const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\ 1264 const GLboolean flatShade = (ctx->Light.ShadeModel==GL_FLAT); \ 1265 GLfixed rFlat, gFlat, bFlat, aFlat; \ 1266 DEFARRAY(GLfloat, sSpan, MAX_WIDTH); /* mac 32k limitation */ \ 1267 DEFARRAY(GLfloat, tSpan, MAX_WIDTH); /* mac 32k limitation */ \ 1268 DEFARRAY(GLfloat, uSpan, MAX_WIDTH); /* mac 32k limitation */ \ 1269 CHECKARRAY(sSpan, return); /* mac 32k limitation */ \ 1270 CHECKARRAY(tSpan, return); /* mac 32k limitation */ \ 1271 CHECKARRAY(uSpan, return); /* mac 32k limitation */ \ 1272 if (flatShade) { \ 1273 rFlat = IntToFixed(v2->color[RCOMP]); \ 1274 gFlat = IntToFixed(v2->color[GCOMP]); \ 1275 bFlat = IntToFixed(v2->color[BCOMP]); \ 1276 aFlat = IntToFixed(v2->color[ACOMP]); \ 1277 } \ 1278 span.texWidth[0] = (GLfloat) texImage->Width; \ 1279 span.texHeight[0] = (GLfloat) texImage->Height; \ 1280 (void) fixedToDepthShift; 1281 1282#define RENDER_SPAN( span ) \ 1283 GLdepth zSpan[MAX_WIDTH]; \ 1284 GLfloat fogSpan[MAX_WIDTH]; \ 1285 GLchan rgbaSpan[MAX_WIDTH][4]; \ 1286 GLuint i; \ 1287 if (flatShade) { \ 1288 span.red = rFlat; span.redStep = 0; \ 1289 span.green = gFlat; span.greenStep = 0; \ 1290 span.blue = bFlat; span.blueStep = 0; \ 1291 span.alpha = aFlat; span.alphaStep = 0; \ 1292 } \ 1293 /* NOTE: we could just call rasterize_span() here instead */ \ 1294 for (i = 0; i < span.count; i++) { \ 1295 GLdouble invQ = span.tex[0][3] ? (1.0 / span.tex[0][3]) : 1.0; \ 1296 zSpan[i] = FixedToDepth(span.z); \ 1297 span.z += span.zStep; \ 1298 fogSpan[i] = span.fog; \ 1299 span.fog += span.fogStep; \ 1300 rgbaSpan[i][RCOMP] = FixedToInt(span.red); \ 1301 rgbaSpan[i][GCOMP] = FixedToInt(span.green); \ 1302 rgbaSpan[i][BCOMP] = FixedToInt(span.blue); \ 1303 rgbaSpan[i][ACOMP] = FixedToInt(span.alpha); \ 1304 span.red += span.redStep; \ 1305 span.green += span.greenStep; \ 1306 span.blue += span.blueStep; \ 1307 span.alpha += span.alphaStep; \ 1308 sSpan[i] = span.tex[0][0] * invQ; \ 1309 tSpan[i] = span.tex[0][1] * invQ; \ 1310 uSpan[i] = span.tex[0][2] * invQ; \ 1311 span.tex[0][0] += span.texStep[0][0]; \ 1312 span.tex[0][1] += span.texStep[0][1]; \ 1313 span.tex[0][2] += span.texStep[0][2]; \ 1314 span.tex[0][3] += span.texStep[0][3]; \ 1315 } \ 1316 _mesa_write_texture_span(ctx, span.count, span.x, span.y, \ 1317 zSpan, fogSpan, sSpan, tSpan, uSpan, \ 1318 NULL, rgbaSpan, NULL, NULL, GL_POLYGON ); 1319 1320#define CLEANUP_CODE \ 1321 UNDEFARRAY(sSpan); /* mac 32k limitation */ \ 1322 UNDEFARRAY(tSpan); \ 1323 UNDEFARRAY(uSpan); 1324 1325#include "s_tritemp.h" 1326} 1327 1328 1329/* 1330 * Render a smooth-shaded, textured, RGBA triangle with separate specular 1331 * color interpolation. 1332 * Interpolate texcoords with perspective correction, w/out mipmapping. 1333 */ 1334static void general_textured_spec_triangle( GLcontext *ctx, 1335 const SWvertex *v0, 1336 const SWvertex *v1, 1337 const SWvertex *v2 ) 1338{ 1339#define INTERP_Z 1 1340#define INTERP_FOG 1 1341#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1342#define INTERP_RGB 1 1343#define INTERP_SPEC 1 1344#define INTERP_ALPHA 1 1345#define INTERP_TEX 1 1346 1347#define SETUP_CODE \ 1348 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \ 1349 const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\ 1350 const GLboolean flatShade = (ctx->Light.ShadeModel == GL_FLAT); \ 1351 GLfixed rFlat, gFlat, bFlat, aFlat; \ 1352 GLfixed srFlat, sgFlat, sbFlat; \ 1353 if (flatShade) { \ 1354 rFlat = IntToFixed(v2->color[RCOMP]); \ 1355 gFlat = IntToFixed(v2->color[GCOMP]); \ 1356 bFlat = IntToFixed(v2->color[BCOMP]); \ 1357 aFlat = IntToFixed(v2->color[ACOMP]); \ 1358 srFlat = IntToFixed(v2->specular[RCOMP]); \ 1359 sgFlat = IntToFixed(v2->specular[GCOMP]); \ 1360 sbFlat = IntToFixed(v2->specular[BCOMP]); \ 1361 } \ 1362 span.texWidth[0] = (GLfloat) texImage->Width; \ 1363 span.texHeight[0] = (GLfloat) texImage->Height; \ 1364 (void) fixedToDepthShift; 1365 1366#define RENDER_SPAN( span ) \ 1367 if (flatShade) { \ 1368 span.red = rFlat; span.redStep = 0; \ 1369 span.green = gFlat; span.greenStep = 0; \ 1370 span.blue = bFlat; span.blueStep = 0; \ 1371 span.alpha = aFlat; span.alphaStep = 0; \ 1372 span.specRed = srFlat; span.specRedStep = 0; \ 1373 span.specGreen = sgFlat; span.specGreenStep = 0; \ 1374 span.specBlue = sbFlat; span.specBlueStep = 0; \ 1375 } \ 1376 rasterize_span(ctx, &span); 1377 1378#include "s_tritemp.h" 1379} 1380 1381 1382/* 1383 * Render a smooth-shaded, textured, RGBA triangle. 1384 * Interpolate S,T,R with perspective correction and compute lambda for 1385 * each fragment. Lambda is used to determine whether to use the 1386 * minification or magnification filter. If minification and using 1387 * mipmaps, lambda is also used to select the texture level of detail. 1388 */ 1389static void lambda_textured_triangle( GLcontext *ctx, 1390 const SWvertex *v0, 1391 const SWvertex *v1, 1392 const SWvertex *v2 ) 1393{ 1394#define INTERP_Z 1 1395#define INTERP_FOG 1 1396#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1397#define INTERP_RGB 1 1398#define INTERP_ALPHA 1 1399#define INTERP_TEX 1 1400#define INTERP_LAMBDA 1 1401 1402#define SETUP_CODE \ 1403 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \ 1404 const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\ 1405 const GLboolean flatShade = (ctx->Light.ShadeModel==GL_FLAT); \ 1406 GLfixed rFlat, gFlat, bFlat, aFlat; \ 1407 GLfixed srFlat, sgFlat, sbFlat; \ 1408 if (flatShade) { \ 1409 rFlat = IntToFixed(v2->color[RCOMP]); \ 1410 gFlat = IntToFixed(v2->color[GCOMP]); \ 1411 bFlat = IntToFixed(v2->color[BCOMP]); \ 1412 aFlat = IntToFixed(v2->color[ACOMP]); \ 1413 srFlat = IntToFixed(v2->specular[RCOMP]); \ 1414 sgFlat = IntToFixed(v2->specular[GCOMP]); \ 1415 sbFlat = IntToFixed(v2->specular[BCOMP]); \ 1416 } \ 1417 span.texWidth[0] = (GLfloat) texImage->Width; \ 1418 span.texHeight[0] = (GLfloat) texImage->Height; \ 1419 (void) fixedToDepthShift; 1420 1421#define RENDER_SPAN( span ) \ 1422 if (flatShade) { \ 1423 span.red = rFlat; span.redStep = 0; \ 1424 span.green = gFlat; span.greenStep = 0; \ 1425 span.blue = bFlat; span.blueStep = 0; \ 1426 span.alpha = aFlat; span.alphaStep = 0; \ 1427 span.specRed = srFlat; span.specRedStep = 0; \ 1428 span.specGreen = sgFlat; span.specGreenStep = 0; \ 1429 span.specBlue = sbFlat; span.specBlueStep = 0; \ 1430 } \ 1431 rasterize_span(ctx, &span); 1432 1433#include "s_tritemp.h" 1434} 1435 1436 1437/* 1438 * Render a smooth-shaded, textured, RGBA triangle with separate specular 1439 * interpolation. 1440 * Interpolate S,T,R with perspective correction and compute lambda for 1441 * each fragment. Lambda is used to determine whether to use the 1442 * minification or magnification filter. If minification and using 1443 * mipmaps, lambda is also used to select the texture level of detail. 1444 */ 1445static void lambda_textured_spec_triangle( GLcontext *ctx, 1446 const SWvertex *v0, 1447 const SWvertex *v1, 1448 const SWvertex *v2 ) 1449{ 1450#define INTERP_Z 1 1451#define INTERP_FOG 1 1452#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1453#define INTERP_RGB 1 1454#define INTERP_SPEC 1 1455#define INTERP_ALPHA 1 1456#define INTERP_TEX 1 1457#define INTERP_LAMBDA 1 1458 1459#define SETUP_CODE \ 1460 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \ 1461 const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\ 1462 const GLboolean flatShade = (ctx->Light.ShadeModel == GL_FLAT); \ 1463 GLfixed rFlat, gFlat, bFlat, aFlat; \ 1464 GLfixed srFlat, sgFlat, sbFlat; \ 1465 if (flatShade) { \ 1466 rFlat = IntToFixed(v2->color[RCOMP]); \ 1467 gFlat = IntToFixed(v2->color[GCOMP]); \ 1468 bFlat = IntToFixed(v2->color[BCOMP]); \ 1469 aFlat = IntToFixed(v2->color[ACOMP]); \ 1470 srFlat = IntToFixed(v2->specular[RCOMP]); \ 1471 sgFlat = IntToFixed(v2->specular[GCOMP]); \ 1472 sbFlat = IntToFixed(v2->specular[BCOMP]); \ 1473 } \ 1474 span.texWidth[0] = (GLfloat) texImage->Width; \ 1475 span.texHeight[0] = (GLfloat) texImage->Height; \ 1476 (void) fixedToDepthShift; 1477 1478#define RENDER_SPAN( span ) \ 1479 if (flatShade) { \ 1480 span.red = rFlat; span.redStep = 0; \ 1481 span.green = gFlat; span.greenStep = 0; \ 1482 span.blue = bFlat; span.blueStep = 0; \ 1483 span.alpha = aFlat; span.alphaStep = 0; \ 1484 span.specRed = srFlat; span.specRedStep = 0; \ 1485 span.specGreen = sgFlat; span.specGreenStep = 0; \ 1486 span.specBlue = sbFlat; span.specBlueStep = 0; \ 1487 } \ 1488 rasterize_span(ctx, &span); 1489 1490#include "s_tritemp.h" 1491} 1492 1493 1494/* 1495 * This is the big one! 1496 * Interpolate Z, RGB, Alpha, specular, fog, and N sets of texture coordinates 1497 * with lambda (LOD). 1498 * Yup, it's slow. 1499 */ 1500static void 1501lambda_multitextured_triangle( GLcontext *ctx, 1502 const SWvertex *v0, 1503 const SWvertex *v1, 1504 const SWvertex *v2 ) 1505{ 1506 1507#define INTERP_Z 1 1508#define INTERP_FOG 1 1509#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1510#define INTERP_RGB 1 1511#define INTERP_ALPHA 1 1512#define INTERP_SPEC 1 1513#define INTERP_MULTITEX 1 1514#define INTERP_LAMBDA 1 1515 1516#define SETUP_CODE \ 1517 const GLboolean flatShade = (ctx->Light.ShadeModel == GL_FLAT); \ 1518 GLfixed rFlat, gFlat, bFlat, aFlat; \ 1519 GLfixed srFlat, sgFlat, sbFlat; \ 1520 GLuint u; \ 1521 if (flatShade) { \ 1522 rFlat = IntToFixed(v2->color[RCOMP]); \ 1523 gFlat = IntToFixed(v2->color[GCOMP]); \ 1524 bFlat = IntToFixed(v2->color[BCOMP]); \ 1525 aFlat = IntToFixed(v2->color[ACOMP]); \ 1526 srFlat = IntToFixed(v2->specular[RCOMP]); \ 1527 sgFlat = IntToFixed(v2->specular[GCOMP]); \ 1528 sbFlat = IntToFixed(v2->specular[BCOMP]); \ 1529 } \ 1530 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { \ 1531 if (ctx->Texture.Unit[u]._ReallyEnabled) { \ 1532 const struct gl_texture_object *texObj; \ 1533 const struct gl_texture_image *texImage; \ 1534 texObj = ctx->Texture.Unit[u]._Current; \ 1535 texImage = texObj->Image[texObj->BaseLevel]; \ 1536 span.texWidth[u] = (GLfloat) texImage->Width; \ 1537 span.texHeight[u] = (GLfloat) texImage->Height; \ 1538 } \ 1539 } \ 1540 (void) fixedToDepthShift; 1541 1542#define RENDER_SPAN( span ) \ 1543 if (flatShade) { \ 1544 span.red = rFlat; span.redStep = 0; \ 1545 span.green = gFlat; span.greenStep = 0; \ 1546 span.blue = bFlat; span.blueStep = 0; \ 1547 span.alpha = aFlat; span.alphaStep = 0; \ 1548 span.specRed = srFlat; span.specRedStep = 0; \ 1549 span.specGreen = sgFlat; span.specGreenStep = 0; \ 1550 span.specBlue = sbFlat; span.specBlueStep = 0; \ 1551 } \ 1552 rasterize_span(ctx, &span); 1553 1554#include "s_tritemp.h" 1555 1556} 1557 1558 1559static void occlusion_zless_triangle( GLcontext *ctx, 1560 const SWvertex *v0, 1561 const SWvertex *v1, 1562 const SWvertex *v2 ) 1563{ 1564 if (ctx->OcclusionResult) { 1565 return; 1566 } 1567 1568#define DO_OCCLUSION_TEST 1569#define INTERP_Z 1 1570#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1571 1572#define RENDER_SPAN( span ) \ 1573 GLuint i; \ 1574 for (i = 0; i < span.count; i++) { \ 1575 GLdepth z = FixedToDepth(span.z); \ 1576 if (z < zRow[i]) { \ 1577 ctx->OcclusionResult = GL_TRUE; \ 1578 return; \ 1579 } \ 1580 span.z += span.zStep; \ 1581 } 1582 1583#include "s_tritemp.h" 1584} 1585 1586static void nodraw_triangle( GLcontext *ctx, 1587 const SWvertex *v0, 1588 const SWvertex *v1, 1589 const SWvertex *v2 ) 1590{ 1591 (void) (ctx && v0 && v1 && v2); 1592} 1593 1594void _swrast_add_spec_terms_triangle( GLcontext *ctx, 1595 const SWvertex *v0, 1596 const SWvertex *v1, 1597 const SWvertex *v2 ) 1598{ 1599 SWvertex *ncv0 = (SWvertex *)v0; /* drop const qualifier */ 1600 SWvertex *ncv1 = (SWvertex *)v1; 1601 SWvertex *ncv2 = (SWvertex *)v2; 1602 GLchan c[3][4]; 1603 COPY_CHAN4( c[0], ncv0->color ); 1604 COPY_CHAN4( c[1], ncv1->color ); 1605 COPY_CHAN4( c[2], ncv2->color ); 1606 ACC_3V( ncv0->color, ncv0->specular ); 1607 ACC_3V( ncv1->color, ncv1->specular ); 1608 ACC_3V( ncv2->color, ncv2->specular ); 1609 SWRAST_CONTEXT(ctx)->SpecTriangle( ctx, ncv0, ncv1, ncv2 ); 1610 COPY_CHAN4( ncv0->color, c[0] ); 1611 COPY_CHAN4( ncv1->color, c[1] ); 1612 COPY_CHAN4( ncv2->color, c[2] ); 1613} 1614 1615 1616 1617#ifdef DEBUG 1618 1619/* record the current triangle function name */ 1620static const char *triFuncName = NULL; 1621 1622#define USE(triFunc) \ 1623do { \ 1624 triFuncName = #triFunc; \ 1625 /*printf("%s\n", triFuncName);*/ \ 1626 swrast->Triangle = triFunc; \ 1627} while (0) 1628 1629#else 1630 1631#define USE(triFunc) swrast->Triangle = triFunc; 1632 1633#endif 1634 1635 1636 1637 1638/* 1639 * Determine which triangle rendering function to use given the current 1640 * rendering context. 1641 * 1642 * Please update the summary flag _SWRAST_NEW_TRIANGLE if you add or 1643 * remove tests to this code. 1644 */ 1645void 1646_swrast_choose_triangle( GLcontext *ctx ) 1647{ 1648 SWcontext *swrast = SWRAST_CONTEXT(ctx); 1649 const GLboolean rgbmode = ctx->Visual.rgbMode; 1650 1651 if (ctx->Polygon.CullFlag && 1652 ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) { 1653 USE(nodraw_triangle); 1654 return; 1655 } 1656 1657 if (ctx->RenderMode==GL_RENDER) { 1658 1659 if (ctx->Polygon.SmoothFlag) { 1660 _mesa_set_aa_triangle_function(ctx); 1661 ASSERT(swrast->Triangle); 1662 return; 1663 } 1664 1665 if (ctx->Depth.OcclusionTest && 1666 ctx->Depth.Test && 1667 ctx->Depth.Mask == GL_FALSE && 1668 ctx->Depth.Func == GL_LESS && 1669 !ctx->Stencil.Enabled) { 1670 if ((rgbmode && 1671 ctx->Color.ColorMask[0] == 0 && 1672 ctx->Color.ColorMask[1] == 0 && 1673 ctx->Color.ColorMask[2] == 0 && 1674 ctx->Color.ColorMask[3] == 0) 1675 || 1676 (!rgbmode && ctx->Color.IndexMask == 0)) { 1677 USE(occlusion_zless_triangle); 1678 return; 1679 } 1680 } 1681 1682 if (ctx->Texture._ReallyEnabled) { 1683 /* Ugh, we do a _lot_ of tests to pick the best textured tri func */ 1684 const struct gl_texture_object *texObj2D; 1685 const struct gl_texture_image *texImg; 1686 GLenum minFilter, magFilter, envMode; 1687 GLint format; 1688 texObj2D = ctx->Texture.Unit[0].Current2D; 1689 texImg = texObj2D ? texObj2D->Image[texObj2D->BaseLevel] : NULL; 1690 format = texImg ? texImg->TexFormat->MesaFormat : -1; 1691 minFilter = texObj2D ? texObj2D->MinFilter : (GLenum) 0; 1692 magFilter = texObj2D ? texObj2D->MagFilter : (GLenum) 0; 1693 envMode = ctx->Texture.Unit[0].EnvMode; 1694 1695 /* First see if we can used an optimized 2-D texture function */ 1696 if (ctx->Texture._ReallyEnabled==TEXTURE0_2D 1697 && texObj2D->WrapS==GL_REPEAT 1698 && texObj2D->WrapT==GL_REPEAT 1699 && texImg->Border==0 1700 && (format == MESA_FORMAT_RGB || format == MESA_FORMAT_RGBA) 1701 && minFilter == magFilter 1702 && ctx->Light.Model.ColorControl == GL_SINGLE_COLOR 1703 && ctx->Texture.Unit[0].EnvMode != GL_COMBINE_EXT) { 1704 if (ctx->Hint.PerspectiveCorrection==GL_FASTEST) { 1705 if (minFilter == GL_NEAREST 1706 && format == MESA_FORMAT_RGB 1707 && (envMode == GL_REPLACE || envMode == GL_DECAL) 1708 && ((swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT) 1709 && ctx->Depth.Func == GL_LESS 1710 && ctx->Depth.Mask == GL_TRUE) 1711 || swrast->_RasterMask == TEXTURE_BIT) 1712 && ctx->Polygon.StippleFlag == GL_FALSE) { 1713 if (swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)) { 1714 USE(simple_z_textured_triangle); 1715 } 1716 else { 1717 USE(simple_textured_triangle); 1718 } 1719 } 1720 else { 1721 /* GL_MODULATE seems also not to work !! */ 1722 if (ctx->Texture.Unit[0].EnvMode==GL_ADD) { 1723 USE(general_textured_triangle); 1724 } 1725 else { 1726 USE(affine_textured_triangle); 1727 } 1728 } 1729 } 1730 else { 1731 /* GL_MODULATE seems also not to work !! */ 1732 if (ctx->Texture.Unit[0].EnvMode==GL_ADD) { 1733 USE(general_textured_triangle); 1734 } 1735 else { 1736 USE(persp_textured_triangle); 1737 } 1738 } 1739 } 1740 else { 1741 /* More complicated textures (mipmap, multi-tex, sep specular) */ 1742 GLboolean needLambda; 1743 /* if mag filter != min filter we need to compute lambda */ 1744 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; 1745 if (obj && obj->MinFilter != obj->MagFilter) 1746 needLambda = GL_TRUE; 1747 else 1748 needLambda = GL_FALSE; 1749 if (ctx->Texture._ReallyEnabled > TEXTURE0_ANY) { 1750 USE(lambda_multitextured_triangle); 1751 } 1752 else if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) { 1753 /* separate specular color interpolation */ 1754 if (needLambda) { 1755 USE(lambda_textured_spec_triangle); 1756 } 1757 else { 1758 USE(general_textured_spec_triangle); 1759 } 1760 } 1761 else { 1762 if (needLambda) { 1763 USE(lambda_textured_triangle); 1764 } 1765 else { 1766 USE(general_textured_triangle); 1767 } 1768 } 1769 } 1770 } 1771 else { 1772 ASSERT(!ctx->Texture._ReallyEnabled); 1773 if (ctx->Light.ShadeModel==GL_SMOOTH) { 1774 /* smooth shaded, no texturing, stippled or some raster ops */ 1775 if (rgbmode) { 1776 USE(smooth_rgba_triangle); 1777 } 1778 else { 1779 USE(smooth_ci_triangle); 1780 } 1781 } 1782 else { 1783 /* flat shaded, no texturing, stippled or some raster ops */ 1784 if (rgbmode) { 1785 USE(flat_rgba_triangle); 1786 } 1787 else { 1788 USE(flat_ci_triangle); 1789 } 1790 } 1791 } 1792 } 1793 else if (ctx->RenderMode==GL_FEEDBACK) { 1794 USE(_mesa_feedback_triangle); 1795 } 1796 else { 1797 /* GL_SELECT mode */ 1798 USE(_mesa_select_triangle); 1799 } 1800} 1801