s_triangle.c revision 9bf68ad963ba92b5d1e725f965979042495a5313
1/* $Id: s_triangle.c,v 1.26 2001/05/14 16:23:04 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, 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, 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, \ 158 zSpan, fogSpan, v2->color, 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, 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 = 0xff 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 = 0xff 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] = ((0xff - ta) * span->red \ 397 + ((ta + 1) * tr << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \ 398 dest[GCOMP] = ((0xff - ta) * span->green \ 399 + ((ta + 1) * tg << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \ 400 dest[BCOMP] = ((0xff - 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] = ((0xff - tr) * span->red \ 406 + (tr + 1) * info->er) >> (FIXED_SHIFT + 8); \ 407 dest[GCOMP] = ((0xff - tg) * span->green \ 408 + (tg + 1) * info->eg) >> (FIXED_SHIFT + 8); \ 409 dest[BCOMP] = ((0xff - 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 SPAN1(DO_TEX,COMP) \ 435 for (i = 0; i < span->count; i++) { \ 436 GLint s = FixedToInt(span->intTex[0]) & info->smask; \ 437 GLint t = FixedToInt(span->intTex[1]) & info->tmask; \ 438 GLint pos = (t << info->twidth_log2) + s; \ 439 const GLchan *tex00 = info->texture + COMP * pos; \ 440 zspan[i] = FixedToDepth(span->z); \ 441 fogspan[i] = span->fog; \ 442 DO_TEX; \ 443 span->fog += span->fogStep; \ 444 span->z += span->zStep; \ 445 span->red += span->redStep; \ 446 span->green += span->greenStep; \ 447 span->blue += span->blueStep; \ 448 span->alpha += span->alphaStep; \ 449 span->intTex[0] += span->intTexStep[0]; \ 450 span->intTex[1] += span->intTexStep[1]; \ 451 dest += 4; \ 452 } 453 454#define SPAN2(DO_TEX,COMP) \ 455 for (i = 0; i < span->count; i++) { \ 456 GLint s = FixedToInt(span->intTex[0]) & info->smask; \ 457 GLint t = FixedToInt(span->intTex[1]) & info->tmask; \ 458 GLint sf = span->intTex[0] & FIXED_FRAC_MASK; \ 459 GLint tf = span->intTex[1] & FIXED_FRAC_MASK; \ 460 GLint si = FIXED_FRAC_MASK - sf; \ 461 GLint ti = FIXED_FRAC_MASK - tf; \ 462 GLint pos = (t << info->twidth_log2) + s; \ 463 const GLchan *tex00 = info->texture + COMP * pos; \ 464 const GLchan *tex10 = tex00 + info->tbytesline; \ 465 const GLchan *tex01 = tex00 + COMP; \ 466 const GLchan *tex11 = tex10 + COMP; \ 467 (void) ti; \ 468 (void) si; \ 469 if (t == info->tmask) { \ 470 tex10 -= info->tsize; \ 471 tex11 -= info->tsize; \ 472 } \ 473 if (s == info->smask) { \ 474 tex01 -= info->tbytesline; \ 475 tex11 -= info->tbytesline; \ 476 } \ 477 zspan[i] = FixedToDepth(span->z); \ 478 fogspan[i] = span->fog; \ 479 DO_TEX; \ 480 span->fog += span->fogStep; \ 481 span->z += span->zStep; \ 482 span->red += span->redStep; \ 483 span->green += span->greenStep; \ 484 span->blue += span->blueStep; \ 485 span->alpha += span->alphaStep; \ 486 span->intTex[0] += span->intTexStep[0]; \ 487 span->intTex[1] += span->intTexStep[1]; \ 488 dest += 4; \ 489 } 490 491#define FixedToDepth(F) ((F) >> fixedToDepthShift) 492 493 GLuint i; 494 GLdepth zspan[MAX_WIDTH]; 495 GLfloat fogspan[MAX_WIDTH]; 496 GLchan rgba[MAX_WIDTH][4]; 497 GLchan *dest = rgba[0]; 498 const GLint fixedToDepthShift = info->fixedToDepthShift; 499 500 span->intTex[0] -= FIXED_HALF; 501 span->intTex[1] -= FIXED_HALF; 502 switch (info->filter) { 503 case GL_NEAREST: 504 switch (info->format) { 505 case GL_RGB: 506 switch (info->envmode) { 507 case GL_MODULATE: 508 SPAN1(NEAREST_RGB;MODULATE,3); 509 break; 510 case GL_DECAL: 511 case GL_REPLACE: 512 SPAN1(NEAREST_RGB_REPLACE,3); 513 break; 514 case GL_BLEND: 515 SPAN1(NEAREST_RGB;BLEND,3); 516 break; 517 case GL_ADD: 518 SPAN1(NEAREST_RGB;ADD,3); 519 break; 520 default: 521 abort(); 522 } 523 break; 524 case GL_RGBA: 525 switch(info->envmode) { 526 case GL_MODULATE: 527 SPAN1(NEAREST_RGBA;MODULATE,4); 528 break; 529 case GL_DECAL: 530 SPAN1(NEAREST_RGBA;DECAL,4); 531 break; 532 case GL_BLEND: 533 SPAN1(NEAREST_RGBA;BLEND,4); 534 break; 535 case GL_ADD: 536 SPAN1(NEAREST_RGBA;ADD,4); 537 break; 538 case GL_REPLACE: 539 SPAN1(NEAREST_RGBA_REPLACE,4); 540 break; 541 default: 542 abort(); 543 } 544 break; 545 } 546 break; 547 548 case GL_LINEAR: 549 span->intTex[0] -= FIXED_HALF; 550 span->intTex[1] -= FIXED_HALF; 551 switch (info->format) { 552 case GL_RGB: 553 switch (info->envmode) { 554 case GL_MODULATE: 555 SPAN2(LINEAR_RGB;MODULATE,3); 556 break; 557 case GL_DECAL: 558 case GL_REPLACE: 559 SPAN2(LINEAR_RGB;REPLACE,3); 560 break; 561 case GL_BLEND: 562 SPAN2(LINEAR_RGB;BLEND,3); 563 break; 564 case GL_ADD: 565 SPAN2(LINEAR_RGB;ADD,3); 566 break; 567 default: 568 abort(); 569 } 570 break; 571 case GL_RGBA: 572 switch (info->envmode) { 573 case GL_MODULATE: 574 SPAN2(LINEAR_RGBA;MODULATE,4); 575 break; 576 case GL_DECAL: 577 SPAN2(LINEAR_RGBA;DECAL,4); 578 break; 579 case GL_BLEND: 580 SPAN2(LINEAR_RGBA;BLEND,4); 581 break; 582 case GL_ADD: 583 SPAN2(LINEAR_RGBA;ADD,4); 584 break; 585 case GL_REPLACE: 586 SPAN2(LINEAR_RGBA;REPLACE,4); 587 break; 588 default: 589 abort(); 590 } break; 591 } 592 break; 593 } 594 _mesa_write_rgba_span(ctx, span->count, span->x, span->y, 595 zspan, fogspan, rgba, GL_POLYGON); 596 597#undef SPAN1 598#undef SPAN2 599#undef FixedToDepth 600} 601 602 603 604/* 605 * Render an RGB/RGBA textured triangle without perspective correction. 606 */ 607static void affine_textured_triangle( GLcontext *ctx, 608 const SWvertex *v0, 609 const SWvertex *v1, 610 const SWvertex *v2 ) 611{ 612#define INTERP_Z 1 613#define INTERP_FOG 1 614#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 615#define INTERP_RGB 1 616#define INTERP_ALPHA 1 617#define INTERP_INT_TEX 1 618#define S_SCALE twidth 619#define T_SCALE theight 620 621#define SETUP_CODE 622 struct affine_info info; 623 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \ 624 struct gl_texture_object *obj = unit->Current2D; \ 625 GLint b = obj->BaseLevel; \ 626 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ 627 GLfloat theight = (GLfloat) obj->Image[b]->Height; \ 628 info.fixedToDepthShift = ctx->Visual.depthBits <= 16 ? FIXED_SHIFT : 0;\ 629 info.texture = (const GLchan *) obj->Image[b]->Data; \ 630 info.twidth_log2 = obj->Image[b]->WidthLog2; \ 631 info.smask = obj->Image[b]->Width - 1; \ 632 info.tmask = obj->Image[b]->Height - 1; \ 633 info.format = obj->Image[b]->Format; \ 634 info.filter = obj->MinFilter; \ 635 info.envmode = unit->EnvMode; \ 636 \ 637 if (info.envmode == GL_BLEND) { \ 638 /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \ 639 info.er = FloatToFixed(unit->EnvColor[RCOMP]); \ 640 info.eg = FloatToFixed(unit->EnvColor[GCOMP]); \ 641 info.eb = FloatToFixed(unit->EnvColor[BCOMP]); \ 642 info.ea = FloatToFixed(unit->EnvColor[ACOMP]); \ 643 } \ 644 if (!info.texture) { \ 645 /* this shouldn't happen */ \ 646 return; \ 647 } \ 648 \ 649 switch (info.format) { \ 650 case GL_ALPHA: \ 651 case GL_LUMINANCE: \ 652 case GL_INTENSITY: \ 653 info.tbytesline = obj->Image[b]->Width; \ 654 break; \ 655 case GL_LUMINANCE_ALPHA: \ 656 info.tbytesline = obj->Image[b]->Width * 2; \ 657 break; \ 658 case GL_RGB: \ 659 info.tbytesline = obj->Image[b]->Width * 3; \ 660 break; \ 661 case GL_RGBA: \ 662 info.tbytesline = obj->Image[b]->Width * 4; \ 663 break; \ 664 default: \ 665 _mesa_problem(NULL, "Bad texture format in affine_texture_triangle");\ 666 return; \ 667 } \ 668 info.tsize = obj->Image[b]->Height * info.tbytesline; 669 670#define RENDER_SPAN( span ) \ 671 affine_span(ctx, &span, &info); 672 673#include "s_tritemp.h" 674 675} 676 677 678#if 0 /* XXX disabled because of texcoord interpolation errors */ 679/* 680 * Render an perspective corrected RGB/RGBA textured triangle. 681 * The Q (aka V in Mesa) coordinate must be zero such that the divide 682 * by interpolated Q/W comes out right. 683 * 684 * This function only renders textured triangles that use GL_NEAREST. 685 * Perspective correction works right. 686 * 687 * This function written by Klaus Niederkrueger <klaus@math.leidenuniv.nl> 688 * Send all questions and bug reports to him. 689 */ 690static void near_persp_textured_triangle(GLcontext *ctx, 691 const SWvertex *v0, 692 const SWvertex *v1, 693 const SWvertex *v2 ) 694{ 695/* The BIAS value is used to shift negative values into positive values. 696 * Without this, negative texture values don't GL_REPEAT correctly at just 697 * below zero, because (int)-0.5 = 0 = (int)0.5. We're not going to worry 698 * about texture coords less than -BIAS. This could be fixed by using 699 * FLOORF etc. instead, but this is slower... 700 */ 701#define BIAS 4096.0F 702 703#define INTERP_Z 1 704#define INTERP_FOG 1 705#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 706#define INTERP_RGB 1 707#define INTERP_ALPHA 1 708#define INTERP_TEX 1 709 710#define SETUP_CODE \ 711 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \ 712 struct gl_texture_object *obj = unit->Current2D; \ 713 const GLint b = obj->BaseLevel; \ 714 const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ 715 const GLfloat theight = (GLfloat) obj->Image[b]->Height; \ 716 const GLint twidth_log2 = obj->Image[b]->WidthLog2; \ 717 const GLchan *texture = (const GLchan *) obj->Image[b]->Data; \ 718 const GLint smask = (obj->Image[b]->Width - 1); \ 719 const GLint tmask = (obj->Image[b]->Height - 1); \ 720 const GLint format = obj->Image[b]->Format; \ 721 const GLint envmode = unit->EnvMode; \ 722 GLfloat sscale, tscale; \ 723 GLfixed er, eg, eb, ea; \ 724 GLint tr, tg, tb, ta; \ 725 if (!texture) { \ 726 /* this shouldn't happen */ \ 727 return; \ 728 } \ 729 if (envmode == GL_BLEND || envmode == GL_ADD) { \ 730 er = FloatToFixed(unit->EnvColor[RCOMP]); \ 731 eg = FloatToFixed(unit->EnvColor[GCOMP]); \ 732 eb = FloatToFixed(unit->EnvColor[BCOMP]); \ 733 ea = FloatToFixed(unit->EnvColor[ACOMP]); \ 734 } \ 735 sscale = twidth; \ 736 tscale = theight; \ 737 738 739#define OLD_SPAN(DO_TEX,COMP) \ 740 for (i=0;i<n;i++) { \ 741 GLfloat invQ = 1.0f / vv; \ 742 GLint s = (int)(SS * invQ + BIAS) & smask; \ 743 GLint t = (int)(TT * invQ + BIAS) & tmask; \ 744 GLint pos = COMP * ((t << twidth_log2) + s); \ 745 const GLchan *tex00 = texture + pos; \ 746 zspan[i] = FixedToDepth(span.z); \ 747 fogspan[i] = span.fog; \ 748 DO_TEX; \ 749 span.fog += span.fogStep; \ 750 span.z += span.zStep; \ 751 span.red += span.redStep; \ 752 span.green += span.greenStep; \ 753 span.blue += span.blueStep; \ 754 span.alpha += span.alphaStep; \ 755 SS += dSdx; \ 756 TT += dTdx; \ 757 vv += dvdx; \ 758 dest += 4; \ 759 } 760 761#define X_Y_TEX_COORD(X, Y) ((((int)(X) & tmask) << twidth_log2) + ((int)(Y) & smask)) 762#define Y_X_TEX_COORD(X, Y) ((((int)(Y) & tmask) << twidth_log2) + ((int)(X) & smask)) 763 764#define SPAN1(DO_TEX, COMP, TEX_COORD) { \ 765 GLfloat x_max = CEILF(x_tex); \ 766 GLfloat y_max = y_tex + (x_max - x_tex) * dy_dx; \ 767 GLint j, x_m = (int)x_max; \ 768 GLint pos; \ 769 if ((int)y_max != (int)y_tex) { \ 770 GLfloat x_mid = x_tex + (CEILF(y_tex)-y_tex) * dx_dy; \ 771 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \ 772 pos = COMP * TEX_COORD(x_tex, y_tex); \ 773 DRAW_LINE (DO_TEX); \ 774 y_tex = y_max; \ 775 } \ 776 nominator += vv * x_max; \ 777 denominator -= dvdx * x_max; \ 778 j = nominator / denominator; \ 779 pos = COMP * TEX_COORD(x_tex, y_tex); \ 780 DRAW_LINE (DO_TEX); \ 781 while (i<n) { \ 782 y_tex = y_max; \ 783 y_max += dy_dx; \ 784 if ((int)y_max != (int)y_tex) { \ 785 GLfloat x_mid = (CEILF(y_tex)-y_tex) * dx_dy; \ 786 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \ 787 pos = COMP * TEX_COORD(x_m, y_tex); \ 788 DRAW_LINE (DO_TEX); \ 789 y_tex = y_max; \ 790 } \ 791 nominator += vv; \ 792 denominator -= dvdx; \ 793 j = nominator/denominator; \ 794 pos = COMP * TEX_COORD(x_m, y_tex); \ 795 DRAW_LINE (DO_TEX); \ 796 x_m ++; \ 797 } \ 798} 799 800#define SPAN2(DO_TEX, COMP, TEX_COORD) { \ 801 GLfloat x_max = CEILF (x_tex); \ 802 GLfloat y_max = y_tex + (x_max - x_tex) * dy_dx; \ 803 GLint j, x_m = (int) x_max; \ 804 GLint pos; \ 805 if ((int)y_max != (int)y_tex) { \ 806 GLfloat x_mid = x_tex + (FLOORF(y_tex)-y_tex) * dx_dy; \ 807 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \ 808 pos = COMP * TEX_COORD(x_tex, y_tex); \ 809 DRAW_LINE (DO_TEX); \ 810 y_tex = y_max; \ 811 } \ 812 nominator += vv * x_max; \ 813 denominator -= dvdx * x_max; \ 814 j = nominator / denominator; \ 815 pos = COMP * TEX_COORD(x_tex, y_tex); \ 816 DRAW_LINE (DO_TEX); \ 817 while (i<n) { \ 818 y_tex = y_max; \ 819 y_max += dy_dx; \ 820 if ((int)y_max != (int)y_tex) { \ 821 GLfloat x_mid = (FLOORF(y_tex)-y_tex) * dx_dy; \ 822 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid);\ 823 pos = COMP * TEX_COORD(x_m, y_tex); \ 824 DRAW_LINE (DO_TEX); \ 825 y_tex = y_max; \ 826 } \ 827 nominator += vv; \ 828 denominator -= dvdx; \ 829 j = nominator/denominator; \ 830 pos = COMP * TEX_COORD(x_m, y_tex); \ 831 DRAW_LINE (DO_TEX); \ 832 x_m ++; \ 833 } \ 834} 835 836#define SPAN3(DO_TEX, COMP, TEX_COORD) { \ 837 GLfloat x_min = FLOORF (x_tex); \ 838 GLfloat y_min = y_tex + (x_min - x_tex) * dy_dx; \ 839 GLint j, x_m = (int)x_min; \ 840 GLint pos; \ 841 if ((int)y_min != (int)y_tex) { \ 842 GLfloat x_mid = x_tex + (CEILF(y_tex)-y_tex) * dx_dy; \ 843 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \ 844 pos = COMP * TEX_COORD(x_m, y_tex); \ 845 DRAW_LINE (DO_TEX); \ 846 y_tex = y_min; \ 847 } \ 848 nominator += vv*x_min; \ 849 denominator -= dvdx*x_min; \ 850 j = nominator / denominator; \ 851 pos = COMP * TEX_COORD(x_m, y_tex); \ 852 DRAW_LINE (DO_TEX); \ 853 while (i<n) { \ 854 x_m --; \ 855 y_tex = y_min; \ 856 y_min -= dy_dx; \ 857 if ((int)y_min != (int)y_tex) { \ 858 GLfloat x_mid = (CEILF(y_tex)-y_tex) * dx_dy; \ 859 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \ 860 pos = COMP * TEX_COORD(x_m, y_tex); \ 861 DRAW_LINE (DO_TEX); \ 862 y_tex = y_min; \ 863 } \ 864 nominator -= vv; \ 865 denominator += dvdx; \ 866 j = nominator/denominator; \ 867 pos = COMP * TEX_COORD(x_m, y_tex); \ 868 DRAW_LINE (DO_TEX); \ 869 } \ 870} 871 872#define SPAN4(DO_TEX, COMP, TEX_COORD) \ 873{ \ 874 GLfloat x_min = FLOORF(x_tex); \ 875 GLint x_m = (int)x_min; \ 876 GLfloat y_min = y_tex + (x_min - x_tex) * dy_dx; \ 877 GLint j; \ 878 GLint pos; \ 879 if ((int)y_min != (int)y_tex) { \ 880 GLfloat x_mid = x_tex + (FLOORF(y_tex)-y_tex) * dx_dy; \ 881 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \ 882 pos = COMP * TEX_COORD(x_m, y_tex); \ 883 DRAW_LINE (DO_TEX); \ 884 y_tex = y_min; \ 885 } \ 886 nominator += vv * x_min; \ 887 denominator -= dvdx * x_min; \ 888 j = nominator / denominator; \ 889 pos = COMP * TEX_COORD(x_m, y_tex); \ 890 DRAW_LINE (DO_TEX); \ 891 while (i<n) { \ 892 x_m --; \ 893 y_tex = y_min; \ 894 y_min -= dy_dx; \ 895 if ((int)y_min != (int)y_tex) { \ 896 GLfloat x_mid = (FLOORF(y_tex)-y_tex) * dx_dy; \ 897 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \ 898 pos = COMP * TEX_COORD(x_m, (y_tex)); \ 899 DRAW_LINE (DO_TEX); \ 900 y_tex = y_min; \ 901 } \ 902 nominator -= vv; \ 903 denominator += dvdx; \ 904 j = nominator/denominator; \ 905 pos = COMP * TEX_COORD(x_m, y_tex); \ 906 DRAW_LINE (DO_TEX); \ 907 } \ 908} 909 910#define DRAW_LINE(DO_TEX) \ 911 { \ 912 GLchan *tex00 = texture + pos; \ 913 if (j>n || j<-100000) \ 914 j = n; \ 915 while (i<j) { \ 916 zspan[i] = FixedToDepth(span.z); \ 917 fogspan[i] = span.fog; \ 918 DO_TEX; \ 919 span.fog += span.fogStep; \ 920 span.z += span.zStep; \ 921 span.red += span.redStep; \ 922 span.green += span.greenStep; \ 923 span.blue += span.blueStep; \ 924 span.alpha += span.alphaStep; \ 925 dest += 4; \ 926 i++; \ 927 } \ 928 } 929 930#define INNER_LOOP( LEFT, RIGHT, Y ) \ 931 { \ 932 GLint i = 0; \ 933 const GLint n = RIGHT-LEFT; \ 934 GLdepth zspan[MAX_WIDTH]; \ 935 GLfloat fogspan[MAX_WIDTH]; \ 936 GLchan rgba[MAX_WIDTH][4]; \ 937 (void)uu; /* please GCC */ \ 938 if (n > 0) { \ 939 GLchan *dest = rgba[0]; \ 940 GLfloat SS = ss * sscale; \ 941 GLfloat TT = tt * tscale; \ 942 GLfloat dSdx = dsdx * sscale; \ 943 GLfloat dTdx = dtdx * tscale; \ 944 GLfloat x_tex; \ 945 GLfloat y_tex; \ 946 GLfloat dx_tex; \ 947 GLfloat dy_tex; \ 948 if (n<5) /* When line very short, setup-time > speed-gain. */ \ 949 goto old_span; /* So: take old method */ \ 950 x_tex = SS / vv, \ 951 y_tex = TT / vv; \ 952 dx_tex = (SS + n * dSdx) / (vv + n * dvdx) - x_tex, \ 953 dy_tex = (TT + n * dTdx) / (vv + n * dvdx) - y_tex; \ 954 /* Choose between walking over texture or over pixelline: */ \ 955 /* If there are few texels, walk over texture otherwise */ \ 956 /* walk over pixelarray. The quotient on the right side */ \ 957 /* should give the timeratio needed to draw one texel in */ \ 958 /* comparison to one pixel. Depends on CPU. */ \ 959 if (dx_tex*dx_tex + dy_tex*dy_tex < (n*n)/16) { \ 960 x_tex += BIAS; \ 961 y_tex += BIAS; \ 962 if (dx_tex*dx_tex > dy_tex*dy_tex) { \ 963 /* if (FABSF(dx_tex) > FABSF(dy_tex)) */ \ 964 GLfloat nominator = - SS - vv * BIAS; \ 965 GLfloat denominator = dvdx * BIAS + dSdx; \ 966 GLfloat dy_dx; \ 967 GLfloat dx_dy; \ 968 if (dy_tex != 0.0f) { \ 969 dy_dx = dy_tex / dx_tex; \ 970 dx_dy = 1.0f/dy_dx; \ 971 } \ 972 else \ 973 dy_dx = 0.0f; \ 974 if (dx_tex > 0.0f) { \ 975 if (dy_tex > 0.0f) { \ 976 switch (format) { \ 977 case GL_RGB: \ 978 switch (envmode) { \ 979 case GL_MODULATE: \ 980 SPAN1(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\ 981 break; \ 982 case GL_DECAL: \ 983 case GL_REPLACE: \ 984 SPAN1(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \ 985 break; \ 986 case GL_BLEND: \ 987 SPAN1(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \ 988 break; \ 989 case GL_ADD: \ 990 SPAN1(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \ 991 break; \ 992 default: /* unexpected env mode */ \ 993 abort(); \ 994 } \ 995 break; \ 996 case GL_RGBA: \ 997 switch(envmode) { \ 998 case GL_MODULATE: \ 999 SPAN1(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\ 1000 break; \ 1001 case GL_DECAL: \ 1002 SPAN1(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \ 1003 break; \ 1004 case GL_BLEND: \ 1005 SPAN1(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \ 1006 break; \ 1007 case GL_ADD: \ 1008 SPAN1(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \ 1009 break; \ 1010 case GL_REPLACE: \ 1011 SPAN1(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\ 1012 break; \ 1013 default: /* unexpected env mode */ \ 1014 abort(); \ 1015 } \ 1016 break; \ 1017 } \ 1018 } \ 1019 else { /* dy_tex <= 0.0f */ \ 1020 switch (format) { \ 1021 case GL_RGB: \ 1022 switch (envmode) { \ 1023 case GL_MODULATE: \ 1024 SPAN2(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\ 1025 break; \ 1026 case GL_DECAL: \ 1027 case GL_REPLACE: \ 1028 SPAN2(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \ 1029 break; \ 1030 case GL_BLEND: \ 1031 SPAN2(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \ 1032 break; \ 1033 case GL_ADD: \ 1034 SPAN2(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \ 1035 break; \ 1036 default: /* unexpected env mode */ \ 1037 abort(); \ 1038 } \ 1039 break; \ 1040 case GL_RGBA: \ 1041 switch(envmode) { \ 1042 case GL_MODULATE: \ 1043 SPAN2(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\ 1044 break; \ 1045 case GL_DECAL: \ 1046 SPAN2(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \ 1047 break; \ 1048 case GL_BLEND: \ 1049 SPAN2(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \ 1050 break; \ 1051 case GL_ADD: \ 1052 SPAN2(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \ 1053 break; \ 1054 case GL_REPLACE: \ 1055 SPAN2(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\ 1056 break; \ 1057 default: /* unexpected env mode */ \ 1058 abort(); \ 1059 } \ 1060 break; \ 1061 } \ 1062 } \ 1063 } \ 1064 else { /* dx_tex < 0.0f */ \ 1065 if (dy_tex > 0.0f) { \ 1066 switch (format) { \ 1067 case GL_RGB: \ 1068 switch (envmode) { \ 1069 case GL_MODULATE: \ 1070 SPAN3(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\ 1071 break; \ 1072 case GL_DECAL: \ 1073 case GL_REPLACE: \ 1074 SPAN3(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \ 1075 break; \ 1076 case GL_BLEND: \ 1077 SPAN3(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \ 1078 break; \ 1079 case GL_ADD: \ 1080 SPAN3(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \ 1081 break; \ 1082 default: /* unexpected env mode */ \ 1083 abort(); \ 1084 } \ 1085 break; \ 1086 case GL_RGBA: \ 1087 switch(envmode) { \ 1088 case GL_MODULATE: \ 1089 SPAN3(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\ 1090 break; \ 1091 case GL_DECAL: \ 1092 SPAN3(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \ 1093 break; \ 1094 case GL_BLEND: \ 1095 SPAN3(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \ 1096 break; \ 1097 case GL_ADD: \ 1098 SPAN3(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \ 1099 break; \ 1100 case GL_REPLACE: \ 1101 SPAN3(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\ 1102 break; \ 1103 default: /* unexpected env mode */ \ 1104 abort(); \ 1105 } \ 1106 break; \ 1107 } \ 1108 } \ 1109 else { /* dy_tex <= 0.0f */ \ 1110 switch (format) { \ 1111 case GL_RGB: \ 1112 switch (envmode) { \ 1113 case GL_MODULATE: \ 1114 SPAN4(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\ 1115 break; \ 1116 case GL_DECAL: \ 1117 case GL_REPLACE: \ 1118 SPAN4(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \ 1119 break; \ 1120 case GL_BLEND: \ 1121 SPAN4(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \ 1122 break; \ 1123 case GL_ADD: \ 1124 SPAN4(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \ 1125 break; \ 1126 default: \ 1127 abort(); \ 1128 } \ 1129 break; \ 1130 case GL_RGBA: \ 1131 switch(envmode) { \ 1132 case GL_MODULATE: \ 1133 SPAN4(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\ 1134 break; \ 1135 case GL_DECAL: \ 1136 SPAN4(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \ 1137 break; \ 1138 case GL_BLEND: \ 1139 SPAN4(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \ 1140 break; \ 1141 case GL_ADD: \ 1142 SPAN4(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \ 1143 break; \ 1144 case GL_REPLACE: \ 1145 SPAN4(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\ 1146 break; \ 1147 default: /* unexpected env mode */ \ 1148 abort(); \ 1149 } \ 1150 break; \ 1151 } \ 1152 } \ 1153 } \ 1154 } \ 1155 else { /* FABSF(dx_tex) > FABSF(dy_tex) */ \ 1156 GLfloat swap; \ 1157 GLfloat dy_dx; \ 1158 GLfloat dx_dy; \ 1159 GLfloat nominator, denominator; \ 1160 if (dx_tex == 0.0f /* && dy_tex == 0.0f*/) \ 1161 goto old_span; /* case so special, that use old */ \ 1162 /* swap some x-values and y-values */ \ 1163 SS = TT; \ 1164 dSdx = dTdx; \ 1165 swap = x_tex, x_tex = y_tex, y_tex = swap; \ 1166 swap = dx_tex, dx_tex = dy_tex, dy_tex = swap; \ 1167 nominator = - SS - vv * BIAS; \ 1168 denominator = dvdx * BIAS + dSdx; \ 1169 if (dy_tex != 0.0f) { \ 1170 dy_dx = dy_tex / dx_tex; \ 1171 dx_dy = 1.0f/dy_dx; \ 1172 } \ 1173 else \ 1174 dy_dx = 0.0f; \ 1175 if (dx_tex > 0.0f) { \ 1176 if (dy_tex > 0.0f) { \ 1177 switch (format) { \ 1178 case GL_RGB: \ 1179 switch (envmode) { \ 1180 case GL_MODULATE: \ 1181 SPAN1(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\ 1182 break; \ 1183 case GL_DECAL: \ 1184 case GL_REPLACE: \ 1185 SPAN1(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \ 1186 break; \ 1187 case GL_BLEND: \ 1188 SPAN1(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \ 1189 break; \ 1190 case GL_ADD: \ 1191 SPAN1(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \ 1192 break; \ 1193 default: /* unexpected env mode */ \ 1194 abort(); \ 1195 } \ 1196 break; \ 1197 case GL_RGBA: \ 1198 switch(envmode) { \ 1199 case GL_MODULATE: \ 1200 SPAN1(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\ 1201 break; \ 1202 case GL_DECAL: \ 1203 SPAN1(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \ 1204 break; \ 1205 case GL_BLEND: \ 1206 SPAN1(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \ 1207 break; \ 1208 case GL_ADD: \ 1209 SPAN1(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \ 1210 break; \ 1211 case GL_REPLACE: \ 1212 SPAN1(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\ 1213 break; \ 1214 default: \ 1215 abort(); \ 1216 } \ 1217 break; \ 1218 } \ 1219 } \ 1220 else { /* dy_tex <= 0.0f */ \ 1221 switch (format) { \ 1222 case GL_RGB: \ 1223 switch (envmode) { \ 1224 case GL_MODULATE: \ 1225 SPAN2(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\ 1226 break; \ 1227 case GL_DECAL: \ 1228 case GL_REPLACE: \ 1229 SPAN2(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \ 1230 break; \ 1231 case GL_BLEND: \ 1232 SPAN2(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \ 1233 break; \ 1234 case GL_ADD: \ 1235 SPAN2(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \ 1236 break; \ 1237 default: \ 1238 abort(); \ 1239 } \ 1240 break; \ 1241 case GL_RGBA: \ 1242 switch(envmode) { \ 1243 case GL_MODULATE: \ 1244 SPAN2(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\ 1245 break; \ 1246 case GL_DECAL: \ 1247 SPAN2(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \ 1248 break; \ 1249 case GL_BLEND: \ 1250 SPAN2(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \ 1251 break; \ 1252 case GL_ADD: \ 1253 SPAN2(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \ 1254 break; \ 1255 case GL_REPLACE: \ 1256 SPAN2(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\ 1257 break; \ 1258 default: \ 1259 abort(); \ 1260 } \ 1261 break; \ 1262 } \ 1263 } \ 1264 } \ 1265 else { /* dx_tex < 0.0f */ \ 1266 if (dy_tex > 0.0f) { \ 1267 switch (format) { \ 1268 case GL_RGB: \ 1269 switch (envmode) { \ 1270 case GL_MODULATE: \ 1271 SPAN3(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\ 1272 break; \ 1273 case GL_DECAL: \ 1274 case GL_REPLACE: \ 1275 SPAN3(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \ 1276 break; \ 1277 case GL_BLEND: \ 1278 SPAN3(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \ 1279 break; \ 1280 case GL_ADD: \ 1281 SPAN3(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \ 1282 break; \ 1283 default: \ 1284 abort(); \ 1285 } \ 1286 break; \ 1287 case GL_RGBA: \ 1288 switch(envmode) { \ 1289 case GL_MODULATE: \ 1290 SPAN3(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\ 1291 break; \ 1292 case GL_DECAL: \ 1293 SPAN3(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \ 1294 break; \ 1295 case GL_BLEND: \ 1296 SPAN3(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \ 1297 break; \ 1298 case GL_ADD: \ 1299 SPAN3(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \ 1300 break; \ 1301 case GL_REPLACE: \ 1302 SPAN3(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\ 1303 break; \ 1304 default: \ 1305 abort(); \ 1306 } \ 1307 break; \ 1308 } \ 1309 } \ 1310 else { /* dy_tex <= 0.0f */ \ 1311 switch (format) { \ 1312 case GL_RGB: \ 1313 switch (envmode) { \ 1314 case GL_MODULATE: \ 1315 SPAN4(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\ 1316 break; \ 1317 case GL_DECAL: \ 1318 case GL_REPLACE: \ 1319 SPAN4(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \ 1320 break; \ 1321 case GL_BLEND: \ 1322 SPAN4(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \ 1323 break; \ 1324 case GL_ADD: \ 1325 SPAN4(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \ 1326 break; \ 1327 default: \ 1328 abort(); \ 1329 } \ 1330 break; \ 1331 case GL_RGBA: \ 1332 switch(envmode) { \ 1333 case GL_MODULATE: \ 1334 SPAN4(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\ 1335 break; \ 1336 case GL_DECAL: \ 1337 SPAN4(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \ 1338 break; \ 1339 case GL_BLEND: \ 1340 SPAN4(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \ 1341 break; \ 1342 case GL_ADD: \ 1343 SPAN4(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \ 1344 break; \ 1345 case GL_REPLACE: \ 1346 SPAN4(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\ 1347 break; \ 1348 default: \ 1349 abort(); \ 1350 } \ 1351 break; \ 1352 } \ 1353 } \ 1354 } \ 1355 } \ 1356 } \ 1357 else { \ 1358 old_span: \ 1359 switch (format) { \ 1360 case GL_RGB: \ 1361 switch (envmode) { \ 1362 case GL_MODULATE: \ 1363 OLD_SPAN(NEAREST_RGB;MODULATE,3); \ 1364 break; \ 1365 case GL_DECAL: \ 1366 case GL_REPLACE: \ 1367 OLD_SPAN(NEAREST_RGB_REPLACE,3); \ 1368 break; \ 1369 case GL_BLEND: \ 1370 OLD_SPAN(NEAREST_RGB;BLEND,3); \ 1371 break; \ 1372 case GL_ADD: \ 1373 OLD_SPAN(NEAREST_RGB;ADD,3); \ 1374 break; \ 1375 default: \ 1376 abort(); \ 1377 } \ 1378 break; \ 1379 case GL_RGBA: \ 1380 switch(envmode) { \ 1381 case GL_MODULATE: \ 1382 OLD_SPAN(NEAREST_RGBA;MODULATE,4); \ 1383 break; \ 1384 case GL_DECAL: \ 1385 OLD_SPAN(NEAREST_RGBA;DECAL,4); \ 1386 break; \ 1387 case GL_BLEND: \ 1388 OLD_SPAN(NEAREST_RGBA;BLEND,4); \ 1389 break; \ 1390 case GL_ADD: \ 1391 OLD_SPAN(NEAREST_RGBA;ADD,4); \ 1392 break; \ 1393 case GL_REPLACE: \ 1394 OLD_SPAN(NEAREST_RGBA_REPLACE,4); \ 1395 break; \ 1396 default: \ 1397 abort(); \ 1398 } \ 1399 break; \ 1400 } \ 1401 } \ 1402 _mesa_write_rgba_span( ctx, n, LEFT, Y, zspan, \ 1403 fogspan, rgba, GL_POLYGON); \ 1404 span.red = span.green = span.blue = span.alpha = 0; \ 1405 } \ 1406 } \ 1407 1408#include "s_tritemp.h" 1409#undef OLD_SPAN 1410#undef SPAN1 1411#undef SPAN2 1412#undef SPAN3 1413#undef SPAN4 1414#undef X_Y_TEX_COORD 1415#undef Y_X_TEX_COORD 1416#undef DRAW_LINE 1417#undef BIAS 1418} 1419#endif 1420 1421 1422#if 0 /* XXX disabled because of texcoord interpolation errors */ 1423/* 1424 * Render an perspective corrected RGB/RGBA textured triangle. 1425 * The Q (aka V in Mesa) coordinate must be zero such that the divide 1426 * by interpolated Q/W comes out right. 1427 * 1428 * This function written by Klaus Niederkrueger <klaus@math.leidenuniv.nl> 1429 * Send all questions and bug reports to him. 1430 */ 1431static void lin_persp_textured_triangle( GLcontext *ctx, 1432 const SWvertex *v0, 1433 const SWvertex *v1, 1434 const SWvertex *v2 ) 1435{ 1436#define INTERP_Z 1 1437#define INTERP_FOG 1 1438#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1439#define INTERP_RGB 1 1440#define INTERP_ALPHA 1 1441#define INTERP_TEX 1 1442 1443#define SETUP_CODE \ 1444 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \ 1445 struct gl_texture_object *obj = unit->Current2D; \ 1446 const GLint b = obj->BaseLevel; \ 1447 const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ 1448 const GLfloat theight = (GLfloat) obj->Image[b]->Height; \ 1449 const GLint twidth_log2 = obj->Image[b]->WidthLog2; \ 1450 GLchan *texture = obj->Image[b]->Data; \ 1451 const GLint smask = (obj->Image[b]->Width - 1); \ 1452 const GLint tmask = (obj->Image[b]->Height - 1); \ 1453 const GLint format = obj->Image[b]->Format; \ 1454 const GLint envmode = unit->EnvMode; \ 1455 GLfloat sscale, tscale; \ 1456 GLint comp, tbytesline, tsize; \ 1457 GLfixed er, eg, eb, ea; \ 1458 GLint tr, tg, tb, ta; \ 1459 if (!texture) { \ 1460 return; \ 1461 } \ 1462 if (envmode == GL_BLEND || envmode == GL_ADD) { \ 1463 er = FloatToFixed(unit->EnvColor[RCOMP]); \ 1464 eg = FloatToFixed(unit->EnvColor[GCOMP]); \ 1465 eb = FloatToFixed(unit->EnvColor[BCOMP]); \ 1466 ea = FloatToFixed(unit->EnvColor[ACOMP]); \ 1467 } \ 1468 switch (format) { \ 1469 case GL_ALPHA: \ 1470 case GL_LUMINANCE: \ 1471 case GL_INTENSITY: \ 1472 comp = 1; \ 1473 break; \ 1474 case GL_LUMINANCE_ALPHA: \ 1475 comp = 2; \ 1476 break; \ 1477 case GL_RGB: \ 1478 comp = 3; \ 1479 break; \ 1480 case GL_RGBA: \ 1481 comp = 4; \ 1482 break; \ 1483 default: \ 1484 _mesa_problem(NULL, "Bad texture format in lin_persp_texture_triangle"); \ 1485 return; \ 1486 } \ 1487 sscale = FIXED_SCALE * twidth; \ 1488 tscale = FIXED_SCALE * theight; \ 1489 tbytesline = obj->Image[b]->Width * comp; \ 1490 tsize = theight * tbytesline; 1491 1492 1493#define SPAN(DO_TEX,COMP) \ 1494 for (i=0;i<n;i++) { \ 1495 GLfloat invQ = 1.0f / vv; \ 1496 GLfixed span.intTex[0] = (int)(SS * invQ); \ 1497 GLfixed span.intTex[1] = (int)(TT * invQ); \ 1498 GLint s = FixedToInt(span.intTex[0]) & smask; \ 1499 GLint t = FixedToInt(span.intTex[1]) & tmask; \ 1500 GLint sf = span.intTex[0] & FIXED_FRAC_MASK; \ 1501 GLint tf = span.intTex[1] & FIXED_FRAC_MASK; \ 1502 GLint si = FIXED_FRAC_MASK - sf; \ 1503 GLint ti = FIXED_FRAC_MASK - tf; \ 1504 GLint pos = COMP * ((t << twidth_log2) + s); \ 1505 GLchan *tex00 = texture + pos; \ 1506 GLchan *tex10 = tex00 + tbytesline; \ 1507 GLchan *tex01 = tex00 + COMP; \ 1508 GLchan *tex11 = tex10 + COMP; \ 1509 if (t == tmask) { \ 1510 tex10 -= tsize; \ 1511 tex11 -= tsize; \ 1512 } \ 1513 if (s == smask) { \ 1514 tex01 -= tbytesline; \ 1515 tex11 -= tbytesline; \ 1516 } \ 1517 zspan[i] = FixedToDepth(span.z); \ 1518 fogspan[i] = span.fog; \ 1519 DO_TEX; \ 1520 span.fog += span.fogStep; \ 1521 span.z += span.zStep; \ 1522 span.red += span.redStep; \ 1523 span.green += span.greenStep; \ 1524 span.blue += span.blueStep; \ 1525 span.alpha += span.alphaStep; \ 1526 SS += dSdx; \ 1527 TT += dTdx; \ 1528 vv += dvdx; \ 1529 dest += 4; \ 1530 } 1531 1532#define INNER_LOOP( LEFT, RIGHT, Y ) \ 1533 { \ 1534 GLint i; \ 1535 const GLint n = RIGHT-LEFT; \ 1536 GLdepth zspan[MAX_WIDTH]; \ 1537 GLfloat fogspan[MAX_WIDTH]; \ 1538 GLchan rgba[MAX_WIDTH][4]; \ 1539 (void) uu; /* please GCC */ \ 1540 if (n > 0) { \ 1541 GLfloat SS = ss * sscale; \ 1542 GLfloat TT = tt * tscale; \ 1543 GLfloat dSdx = dsdx * sscale; \ 1544 GLfloat dTdx = dtdx * tscale; \ 1545 GLchan *dest = rgba[0]; \ 1546 SS -= 0.5f * FIXED_SCALE * vv; \ 1547 TT -= 0.5f * FIXED_SCALE * vv; \ 1548 switch (format) { \ 1549 case GL_RGB: \ 1550 switch (envmode) { \ 1551 case GL_MODULATE: \ 1552 SPAN(LINEAR_RGB;MODULATE,3); \ 1553 break; \ 1554 case GL_DECAL: \ 1555 case GL_REPLACE: \ 1556 SPAN(LINEAR_RGB;REPLACE,3); \ 1557 break; \ 1558 case GL_BLEND: \ 1559 SPAN(LINEAR_RGB;BLEND,3); \ 1560 break; \ 1561 case GL_ADD: \ 1562 SPAN(LINEAR_RGB;ADD,3); \ 1563 break; \ 1564 default: \ 1565 abort(); \ 1566 } \ 1567 break; \ 1568 case GL_RGBA: \ 1569 switch (envmode) { \ 1570 case GL_MODULATE: \ 1571 SPAN(LINEAR_RGBA;MODULATE,4); \ 1572 break; \ 1573 case GL_DECAL: \ 1574 SPAN(LINEAR_RGBA;DECAL,4); \ 1575 break; \ 1576 case GL_BLEND: \ 1577 SPAN(LINEAR_RGBA;BLEND,4); \ 1578 break; \ 1579 case GL_REPLACE: \ 1580 SPAN(LINEAR_RGBA;REPLACE,4); \ 1581 break; \ 1582 case GL_ADD: \ 1583 SPAN(LINEAR_RGBA;ADD,4); \ 1584 break; \ 1585 default: /* unexpected env mode */ \ 1586 abort(); \ 1587 } \ 1588 } \ 1589 _mesa_write_rgba_span( ctx, n, LEFT, Y, zspan, \ 1590 fogspan, \ 1591 rgba, GL_POLYGON ); \ 1592 } \ 1593 } 1594 1595#include "s_tritemp.h" 1596#undef SPAN 1597} 1598#endif 1599 1600 1601/* 1602 * Generate arrays of fragment colors, z, fog, texcoords, etc from a 1603 * triangle span object. Then call the span/fragment processsing 1604 * functions in s_span.[ch]. 1605 */ 1606static void 1607rasterize_span(GLcontext *ctx, const struct triangle_span *span) 1608{ 1609 GLchan rgba[MAX_WIDTH][4]; 1610 GLchan spec[MAX_WIDTH][4]; 1611 GLuint index[MAX_WIDTH]; 1612 GLuint z[MAX_WIDTH]; 1613 GLfloat fog[MAX_WIDTH]; 1614 GLfloat sTex[MAX_WIDTH], tTex[MAX_WIDTH], rTex[MAX_WIDTH]; 1615 GLfloat lambda[MAX_WIDTH]; 1616 GLfloat msTex[MAX_TEXTURE_UNITS][MAX_WIDTH]; 1617 GLfloat mtTex[MAX_TEXTURE_UNITS][MAX_WIDTH]; 1618 GLfloat mrTex[MAX_TEXTURE_UNITS][MAX_WIDTH]; 1619 GLfloat mLambda[MAX_TEXTURE_UNITS][MAX_WIDTH]; 1620 1621 if (span->activeMask & SPAN_RGBA) { 1622 GLfixed r = span->red; 1623 GLfixed g = span->green; 1624 GLfixed b = span->blue; 1625 GLfixed a = span->alpha; 1626 GLuint i; 1627 for (i = 0; i < span->count; i++) { 1628 rgba[i][RCOMP] = FixedToInt(r); 1629 rgba[i][GCOMP] = FixedToInt(g); 1630 rgba[i][BCOMP] = FixedToInt(b); 1631 rgba[i][ACOMP] = FixedToInt(a); 1632 r += span->redStep; 1633 g += span->greenStep; 1634 b += span->blueStep; 1635 a += span->alphaStep; 1636 } 1637 } 1638 if (span->activeMask & SPAN_SPEC) { 1639 GLfixed r = span->specRed; 1640 GLfixed g = span->specGreen; 1641 GLfixed b = span->specBlue; 1642 GLuint i; 1643 for (i = 0; i < span->count; i++) { 1644 spec[i][RCOMP] = FixedToInt(r); 1645 spec[i][GCOMP] = FixedToInt(g); 1646 spec[i][BCOMP] = FixedToInt(b); 1647 r += span->specRedStep; 1648 g += span->specGreenStep; 1649 b += span->specBlueStep; 1650 } 1651 } 1652 if (span->activeMask & SPAN_INDEX) { 1653 GLuint i; 1654 GLfixed ind = span->index; 1655 for (i = 0; i < span->count; i++) { 1656 index[i] = FixedToInt(ind); 1657 ind += span->indexStep; 1658 } 1659 } 1660 if (span->activeMask & SPAN_Z) { 1661 if (ctx->Visual.depthBits <= 16) { 1662 GLuint i; 1663 GLfixed zval = span->z; 1664 for (i = 0; i < span->count; i++) { 1665 z[i] = FixedToInt(zval); 1666 zval += span->zStep; 1667 } 1668 } 1669 else { 1670 /* Deep Z buffer, no fixed->int shift */ 1671 GLuint i; 1672 GLfixed zval = span->z; 1673 for (i = 0; i < span->count; i++) { 1674 z[i] = zval; 1675 zval += span->zStep; 1676 } 1677 } 1678 } 1679 if (span->activeMask & SPAN_FOG) { 1680 GLuint i; 1681 GLfloat f = span->fog; 1682 for (i = 0; i < span->count; i++) { 1683 fog[i] = f; 1684 f += span->fogStep; 1685 } 1686 } 1687 if (span->activeMask & SPAN_TEXTURE) { 1688 if (ctx->Texture._ReallyEnabled & ~TEXTURE0_ANY) { 1689 /* multitexture */ 1690 if (span->activeMask & SPAN_LAMBDA) { 1691 /* with lambda */ 1692 GLuint u; 1693 for (u = 0; u < MAX_TEXTURE_UNITS; u++) { 1694 if (ctx->Texture.Unit[u]._ReallyEnabled) { 1695 GLfloat s = span->tex[u][0]; 1696 GLfloat t = span->tex[u][1]; 1697 GLfloat r = span->tex[u][2]; 1698 GLfloat q = span->tex[u][3]; 1699 GLuint i; 1700 for (i = 0; i < span->count; i++) { 1701 const GLfloat invQ = (q == 0.0F) ? 1.0 : (1.0F / q); 1702 msTex[u][i] = s * invQ; 1703 mtTex[u][i] = t * invQ; 1704 mrTex[u][i] = r * invQ; 1705 mLambda[u][i] = log(span->rho[u] * invQ * invQ) * 1.442695F * 0.5F; 1706 s += span->texStep[u][0]; 1707 t += span->texStep[u][1]; 1708 r += span->texStep[u][2]; 1709 q += span->texStep[u][3]; 1710 } 1711 } 1712 } 1713 } 1714 else { 1715 /* without lambda */ 1716 GLuint u; 1717 for (u = 0; u < MAX_TEXTURE_UNITS; u++) { 1718 if (ctx->Texture.Unit[u]._ReallyEnabled) { 1719 GLfloat s = span->tex[u][0]; 1720 GLfloat t = span->tex[u][1]; 1721 GLfloat r = span->tex[u][2]; 1722 GLfloat q = span->tex[u][3]; 1723 GLuint i; 1724 for (i = 0; i < span->count; i++) { 1725 const GLfloat invQ = (q == 0.0F) ? 1.0 : (1.0F / q); 1726 msTex[u][i] = s * invQ; 1727 mtTex[u][i] = t * invQ; 1728 mrTex[u][i] = r * invQ; 1729 s += span->texStep[u][0]; 1730 t += span->texStep[u][1]; 1731 r += span->texStep[u][2]; 1732 q += span->texStep[u][3]; 1733 } 1734 } 1735 } 1736 } 1737 } 1738 else { 1739 /* just texture unit 0 */ 1740 if (span->activeMask & SPAN_LAMBDA) { 1741 /* with lambda */ 1742 GLfloat s = span->tex[0][0]; 1743 GLfloat t = span->tex[0][1]; 1744 GLfloat r = span->tex[0][2]; 1745 GLfloat q = span->tex[0][3]; 1746 GLuint i; 1747 for (i = 0; i < span->count; i++) { 1748 const GLfloat invQ = (q == 0.0F) ? 1.0 : (1.0F / q); 1749 sTex[i] = s * invQ; 1750 tTex[i] = t * invQ; 1751 rTex[i] = r * invQ; 1752 lambda[i] = log(span->rho[0] * invQ * invQ) * 1.442695F * 0.5F; 1753 s += span->texStep[0][0]; 1754 t += span->texStep[0][1]; 1755 r += span->texStep[0][2]; 1756 q += span->texStep[0][3]; 1757 } 1758 } 1759 else { 1760 /* without lambda */ 1761 GLfloat s = span->tex[0][0]; 1762 GLfloat t = span->tex[0][1]; 1763 GLfloat r = span->tex[0][2]; 1764 GLfloat q = span->tex[0][3]; 1765 GLuint i; 1766 for (i = 0; i < span->count; i++) { 1767 const GLfloat invQ = (q == 0.0F) ? 1.0 : (1.0F / q); 1768 sTex[i] = s * invQ; 1769 tTex[i] = t * invQ; 1770 rTex[i] = r * invQ; 1771 s += span->texStep[0][0]; 1772 t += span->texStep[0][1]; 1773 r += span->texStep[0][2]; 1774 q += span->texStep[0][3]; 1775 } 1776 } 1777 } 1778 } 1779 /* XXX keep this? */ 1780 if (span->activeMask & SPAN_INT_TEXTURE) { 1781 GLint intTexcoord[MAX_WIDTH][2]; 1782 GLfixed s = span->intTex[0]; 1783 GLfixed t = span->intTex[1]; 1784 GLuint i; 1785 for (i = 0; i < span->count; i++) { 1786 intTexcoord[i][0] = FixedToInt(s); 1787 intTexcoord[i][1] = FixedToInt(t); 1788 s += span->intTexStep[0]; 1789 t += span->intTexStep[1]; 1790 } 1791 } 1792 1793 /* examine activeMask and call a s_span.c function */ 1794 if (span->activeMask & SPAN_TEXTURE) { 1795 const GLfloat *fogPtr; 1796 if (span->activeMask & SPAN_FOG) 1797 fogPtr = fog; 1798 else 1799 fogPtr = NULL; 1800 1801 if (ctx->Texture._ReallyEnabled & ~TEXTURE0_ANY) { 1802 if (span->activeMask & SPAN_SPEC) { 1803 _mesa_write_multitexture_span(ctx, span->count, span->x, span->y, 1804 z, fogPtr, 1805 (const GLfloat (*)[MAX_WIDTH]) msTex, 1806 (const GLfloat (*)[MAX_WIDTH]) mtTex, 1807 (const GLfloat (*)[MAX_WIDTH]) mrTex, 1808 (GLfloat (*)[MAX_WIDTH]) mLambda, 1809 rgba, (CONST GLchan (*)[4]) spec, 1810 GL_POLYGON ); 1811 } 1812 else { 1813 _mesa_write_multitexture_span(ctx, span->count, span->x, span->y, 1814 z, fogPtr, 1815 (const GLfloat (*)[MAX_WIDTH]) msTex, 1816 (const GLfloat (*)[MAX_WIDTH]) mtTex, 1817 (const GLfloat (*)[MAX_WIDTH]) mrTex, 1818 (GLfloat (*)[MAX_WIDTH]) mLambda, 1819 rgba, NULL, GL_POLYGON); 1820 } 1821 } 1822 else { 1823 /* single texture */ 1824 if (span->activeMask & SPAN_SPEC) { 1825 _mesa_write_texture_span(ctx, span->count, span->x, span->y, 1826 z, fogPtr, sTex, tTex, rTex, lambda, 1827 rgba, (CONST GLchan (*)[4]) spec, 1828 GL_POLYGON); 1829 } 1830 else { 1831 _mesa_write_texture_span(ctx, span->count, span->x, span->y, 1832 z, fogPtr, sTex, tTex, rTex, lambda, 1833 rgba, NULL, GL_POLYGON); 1834 } 1835 } 1836 } 1837 else { 1838 _mesa_problem(ctx, "rasterize_span() should only be used for texturing"); 1839 } 1840} 1841 1842 1843 1844 1845/* 1846 * Render a smooth-shaded, textured, RGBA triangle. 1847 * Interpolate S,T,R with perspective correction, w/out mipmapping. 1848 */ 1849static void general_textured_triangle( GLcontext *ctx, 1850 const SWvertex *v0, 1851 const SWvertex *v1, 1852 const SWvertex *v2 ) 1853{ 1854#define INTERP_Z 1 1855#define INTERP_FOG 1 1856#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1857#define INTERP_RGB 1 1858#define INTERP_ALPHA 1 1859#define INTERP_TEX 1 1860 1861#define SETUP_CODE \ 1862 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \ 1863 const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\ 1864 const GLboolean flatShade = (ctx->Light.ShadeModel==GL_FLAT); \ 1865 GLfixed rFlat, gFlat, bFlat, aFlat; \ 1866 if (flatShade) { \ 1867 rFlat = IntToFixed(v2->color[RCOMP]); \ 1868 gFlat = IntToFixed(v2->color[GCOMP]); \ 1869 bFlat = IntToFixed(v2->color[BCOMP]); \ 1870 aFlat = IntToFixed(v2->color[ACOMP]); \ 1871 } \ 1872 span.texWidth[0] = (GLfloat) texImage->Width; \ 1873 span.texHeight[0] = (GLfloat) texImage->Height; \ 1874 (void) fixedToDepthShift; 1875 1876#define RENDER_SPAN( span ) \ 1877 GLdepth zSpan[MAX_WIDTH]; \ 1878 GLfloat fogSpan[MAX_WIDTH]; \ 1879 GLchan rgbaSpan[MAX_WIDTH][4]; \ 1880 GLfloat sSpan[MAX_WIDTH], tSpan[MAX_WIDTH], uSpan[MAX_WIDTH]; \ 1881 GLuint i; \ 1882 if (flatShade) { \ 1883 span.red = rFlat; span.redStep = 0; \ 1884 span.green = gFlat; span.greenStep = 0; \ 1885 span.blue = bFlat; span.blueStep = 0; \ 1886 span.alpha = aFlat; span.alphaStep = 0; \ 1887 } \ 1888 /* NOTE: we could just call rasterize_span() here instead */ \ 1889 for (i = 0; i < span.count; i++) { \ 1890 GLdouble invQ = span.tex[0][3] ? (1.0 / span.tex[0][3]) : 1.0; \ 1891 zSpan[i] = FixedToDepth(span.z); \ 1892 span.z += span.zStep; \ 1893 fogSpan[i] = span.fog; \ 1894 span.fog += span.fogStep; \ 1895 rgbaSpan[i][RCOMP] = FixedToInt(span.red); \ 1896 rgbaSpan[i][GCOMP] = FixedToInt(span.green); \ 1897 rgbaSpan[i][BCOMP] = FixedToInt(span.blue); \ 1898 rgbaSpan[i][ACOMP] = FixedToInt(span.alpha); \ 1899 span.red += span.redStep; \ 1900 span.green += span.greenStep; \ 1901 span.blue += span.blueStep; \ 1902 span.alpha += span.alphaStep; \ 1903 sSpan[i] = span.tex[0][0] * invQ; \ 1904 tSpan[i] = span.tex[0][1] * invQ; \ 1905 uSpan[i] = span.tex[0][2] * invQ; \ 1906 span.tex[0][0] += span.texStep[0][0]; \ 1907 span.tex[0][1] += span.texStep[0][1]; \ 1908 span.tex[0][2] += span.texStep[0][2]; \ 1909 span.tex[0][3] += span.texStep[0][3]; \ 1910 } \ 1911 _mesa_write_texture_span(ctx, span.count, span.x, span.y, \ 1912 zSpan, fogSpan, sSpan, tSpan, uSpan, \ 1913 NULL, rgbaSpan, NULL, GL_POLYGON ); 1914 1915#include "s_tritemp.h" 1916} 1917 1918 1919/* 1920 * Render a smooth-shaded, textured, RGBA triangle with separate specular 1921 * color interpolation. 1922 * Interpolate texcoords with perspective correction, w/out mipmapping. 1923 */ 1924static void general_textured_spec_triangle( GLcontext *ctx, 1925 const SWvertex *v0, 1926 const SWvertex *v1, 1927 const SWvertex *v2 ) 1928{ 1929#define INTERP_Z 1 1930#define INTERP_FOG 1 1931#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1932#define INTERP_RGB 1 1933#define INTERP_SPEC 1 1934#define INTERP_ALPHA 1 1935#define INTERP_TEX 1 1936 1937#define SETUP_CODE \ 1938 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \ 1939 const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\ 1940 const GLboolean flatShade = (ctx->Light.ShadeModel == GL_FLAT); \ 1941 GLfixed rFlat, gFlat, bFlat, aFlat; \ 1942 GLfixed srFlat, sgFlat, sbFlat; \ 1943 if (flatShade) { \ 1944 rFlat = IntToFixed(v2->color[RCOMP]); \ 1945 gFlat = IntToFixed(v2->color[GCOMP]); \ 1946 bFlat = IntToFixed(v2->color[BCOMP]); \ 1947 aFlat = IntToFixed(v2->color[ACOMP]); \ 1948 srFlat = IntToFixed(v2->specular[RCOMP]); \ 1949 sgFlat = IntToFixed(v2->specular[GCOMP]); \ 1950 sbFlat = IntToFixed(v2->specular[BCOMP]); \ 1951 } \ 1952 span.texWidth[0] = (GLfloat) texImage->Width; \ 1953 span.texHeight[0] = (GLfloat) texImage->Height; \ 1954 (void) fixedToDepthShift; 1955 1956#define RENDER_SPAN( span ) \ 1957 if (flatShade) { \ 1958 span.red = rFlat; span.redStep = 0; \ 1959 span.green = gFlat; span.greenStep = 0; \ 1960 span.blue = bFlat; span.blueStep = 0; \ 1961 span.alpha = aFlat; span.alphaStep = 0; \ 1962 span.specRed = srFlat; span.specRedStep = 0; \ 1963 span.specGreen = sgFlat; span.specGreenStep = 0; \ 1964 span.specBlue = sbFlat; span.specBlueStep = 0; \ 1965 } \ 1966 rasterize_span(ctx, &span); 1967 1968#include "s_tritemp.h" 1969} 1970 1971 1972/* 1973 * Render a smooth-shaded, textured, RGBA triangle. 1974 * Interpolate S,T,R with perspective correction and compute lambda for 1975 * each fragment. Lambda is used to determine whether to use the 1976 * minification or magnification filter. If minification and using 1977 * mipmaps, lambda is also used to select the texture level of detail. 1978 */ 1979static void lambda_textured_triangle( GLcontext *ctx, 1980 const SWvertex *v0, 1981 const SWvertex *v1, 1982 const SWvertex *v2 ) 1983{ 1984#define INTERP_Z 1 1985#define INTERP_FOG 1 1986#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1987#define INTERP_RGB 1 1988#define INTERP_ALPHA 1 1989#define INTERP_TEX 1 1990#define INTERP_LAMBDA 1 1991 1992#define SETUP_CODE \ 1993 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \ 1994 const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\ 1995 const GLboolean flatShade = (ctx->Light.ShadeModel==GL_FLAT); \ 1996 GLfixed rFlat, gFlat, bFlat, aFlat; \ 1997 GLfixed srFlat, sgFlat, sbFlat; \ 1998 if (flatShade) { \ 1999 rFlat = IntToFixed(v2->color[RCOMP]); \ 2000 gFlat = IntToFixed(v2->color[GCOMP]); \ 2001 bFlat = IntToFixed(v2->color[BCOMP]); \ 2002 aFlat = IntToFixed(v2->color[ACOMP]); \ 2003 srFlat = IntToFixed(v2->specular[RCOMP]); \ 2004 sgFlat = IntToFixed(v2->specular[GCOMP]); \ 2005 sbFlat = IntToFixed(v2->specular[BCOMP]); \ 2006 } \ 2007 span.texWidth[0] = (GLfloat) texImage->Width; \ 2008 span.texHeight[0] = (GLfloat) texImage->Height; \ 2009 (void) fixedToDepthShift; 2010 2011#define RENDER_SPAN( span ) \ 2012 if (flatShade) { \ 2013 span.red = rFlat; span.redStep = 0; \ 2014 span.green = gFlat; span.greenStep = 0; \ 2015 span.blue = bFlat; span.blueStep = 0; \ 2016 span.alpha = aFlat; span.alphaStep = 0; \ 2017 span.specRed = srFlat; span.specRedStep = 0; \ 2018 span.specGreen = sgFlat; span.specGreenStep = 0; \ 2019 span.specBlue = sbFlat; span.specBlueStep = 0; \ 2020 } \ 2021 rasterize_span(ctx, &span); 2022 2023#include "s_tritemp.h" 2024} 2025 2026 2027/* 2028 * Render a smooth-shaded, textured, RGBA triangle with separate specular 2029 * interpolation. 2030 * Interpolate S,T,R with perspective correction and compute lambda for 2031 * each fragment. Lambda is used to determine whether to use the 2032 * minification or magnification filter. If minification and using 2033 * mipmaps, lambda is also used to select the texture level of detail. 2034 */ 2035static void lambda_textured_spec_triangle( GLcontext *ctx, 2036 const SWvertex *v0, 2037 const SWvertex *v1, 2038 const SWvertex *v2 ) 2039{ 2040#define INTERP_Z 1 2041#define INTERP_FOG 1 2042#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 2043#define INTERP_RGB 1 2044#define INTERP_SPEC 1 2045#define INTERP_ALPHA 1 2046#define INTERP_TEX 1 2047#define INTERP_LAMBDA 1 2048 2049#define SETUP_CODE \ 2050 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \ 2051 const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\ 2052 const GLboolean flatShade = (ctx->Light.ShadeModel == GL_FLAT); \ 2053 GLfixed rFlat, gFlat, bFlat, aFlat; \ 2054 GLfixed srFlat, sgFlat, sbFlat; \ 2055 if (flatShade) { \ 2056 rFlat = IntToFixed(v2->color[RCOMP]); \ 2057 gFlat = IntToFixed(v2->color[GCOMP]); \ 2058 bFlat = IntToFixed(v2->color[BCOMP]); \ 2059 aFlat = IntToFixed(v2->color[ACOMP]); \ 2060 srFlat = IntToFixed(v2->specular[RCOMP]); \ 2061 sgFlat = IntToFixed(v2->specular[GCOMP]); \ 2062 sbFlat = IntToFixed(v2->specular[BCOMP]); \ 2063 } \ 2064 span.texWidth[0] = (GLfloat) texImage->Width; \ 2065 span.texHeight[0] = (GLfloat) texImage->Height; \ 2066 (void) fixedToDepthShift; 2067 2068#define RENDER_SPAN( span ) \ 2069 if (flatShade) { \ 2070 span.red = rFlat; span.redStep = 0; \ 2071 span.green = gFlat; span.greenStep = 0; \ 2072 span.blue = bFlat; span.blueStep = 0; \ 2073 span.alpha = aFlat; span.alphaStep = 0; \ 2074 span.specRed = srFlat; span.specRedStep = 0; \ 2075 span.specGreen = sgFlat; span.specGreenStep = 0; \ 2076 span.specBlue = sbFlat; span.specBlueStep = 0; \ 2077 } \ 2078 rasterize_span(ctx, &span); 2079 2080#include "s_tritemp.h" 2081} 2082 2083 2084/* 2085 * This is the big one! 2086 * Interpolate Z, RGB, Alpha, specular, fog, and N sets of texture coordinates 2087 * with lambda (LOD). 2088 * Yup, it's slow. 2089 */ 2090static void 2091lambda_multitextured_triangle( GLcontext *ctx, 2092 const SWvertex *v0, 2093 const SWvertex *v1, 2094 const SWvertex *v2 ) 2095{ 2096 2097#define INTERP_Z 1 2098#define INTERP_FOG 1 2099#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 2100#define INTERP_RGB 1 2101#define INTERP_ALPHA 1 2102#define INTERP_SPEC 1 2103#define INTERP_MULTITEX 1 2104#define INTERP_LAMBDA 1 2105 2106#define SETUP_CODE \ 2107 const GLboolean flatShade = (ctx->Light.ShadeModel == GL_FLAT); \ 2108 GLfixed rFlat, gFlat, bFlat, aFlat; \ 2109 GLfixed srFlat, sgFlat, sbFlat; \ 2110 GLuint u; \ 2111 if (flatShade) { \ 2112 rFlat = IntToFixed(v2->color[RCOMP]); \ 2113 gFlat = IntToFixed(v2->color[GCOMP]); \ 2114 bFlat = IntToFixed(v2->color[BCOMP]); \ 2115 aFlat = IntToFixed(v2->color[ACOMP]); \ 2116 srFlat = IntToFixed(v2->specular[RCOMP]); \ 2117 sgFlat = IntToFixed(v2->specular[GCOMP]); \ 2118 sbFlat = IntToFixed(v2->specular[BCOMP]); \ 2119 } \ 2120 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { \ 2121 if (ctx->Texture.Unit[u]._ReallyEnabled) { \ 2122 const struct gl_texture_object *texObj; \ 2123 const struct gl_texture_image *texImage; \ 2124 texObj = ctx->Texture.Unit[u]._Current; \ 2125 texImage = texObj->Image[texObj->BaseLevel]; \ 2126 span.texWidth[u] = (GLfloat) texImage->Width; \ 2127 span.texHeight[u] = (GLfloat) texImage->Height; \ 2128 } \ 2129 } \ 2130 (void) fixedToDepthShift; 2131 2132#define RENDER_SPAN( span ) \ 2133 if (flatShade) { \ 2134 span.red = rFlat; span.redStep = 0; \ 2135 span.green = gFlat; span.greenStep = 0; \ 2136 span.blue = bFlat; span.blueStep = 0; \ 2137 span.alpha = aFlat; span.alphaStep = 0; \ 2138 span.specRed = srFlat; span.specRedStep = 0; \ 2139 span.specGreen = sgFlat; span.specGreenStep = 0; \ 2140 span.specBlue = sbFlat; span.specBlueStep = 0; \ 2141 } \ 2142 rasterize_span(ctx, &span); 2143 2144#include "s_tritemp.h" 2145 2146} 2147 2148 2149static void occlusion_zless_triangle( GLcontext *ctx, 2150 const SWvertex *v0, 2151 const SWvertex *v1, 2152 const SWvertex *v2 ) 2153{ 2154 if (ctx->OcclusionResult) { 2155 return; 2156 } 2157 2158#define DO_OCCLUSION_TEST 2159#define INTERP_Z 1 2160#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 2161 2162#define RENDER_SPAN( span ) \ 2163 GLuint i; \ 2164 for (i = 0; i < span.count; i++) { \ 2165 GLdepth z = FixedToDepth(span.z); \ 2166 if (z < zRow[i]) { \ 2167 ctx->OcclusionResult = GL_TRUE; \ 2168 return; \ 2169 } \ 2170 span.z += span.zStep; \ 2171 } 2172 2173#include "s_tritemp.h" 2174} 2175 2176static void nodraw_triangle( GLcontext *ctx, 2177 const SWvertex *v0, 2178 const SWvertex *v1, 2179 const SWvertex *v2 ) 2180{ 2181 (void) (ctx && v0 && v1 && v2); 2182} 2183 2184void _swrast_add_spec_terms_triangle( GLcontext *ctx, 2185 const SWvertex *v0, 2186 const SWvertex *v1, 2187 const SWvertex *v2 ) 2188{ 2189 SWvertex *ncv0 = (SWvertex *)v0; /* drop const qualifier */ 2190 SWvertex *ncv1 = (SWvertex *)v1; 2191 SWvertex *ncv2 = (SWvertex *)v2; 2192 GLchan c[3][4]; 2193 COPY_CHAN4( c[0], ncv0->color ); 2194 COPY_CHAN4( c[1], ncv1->color ); 2195 COPY_CHAN4( c[2], ncv2->color ); 2196 ACC_3V( ncv0->color, ncv0->specular ); 2197 ACC_3V( ncv1->color, ncv1->specular ); 2198 ACC_3V( ncv2->color, ncv2->specular ); 2199 SWRAST_CONTEXT(ctx)->SpecTriangle( ctx, ncv0, ncv1, ncv2 ); 2200 COPY_CHAN4( ncv0->color, c[0] ); 2201 COPY_CHAN4( ncv1->color, c[1] ); 2202 COPY_CHAN4( ncv2->color, c[2] ); 2203} 2204 2205 2206 2207#ifdef DEBUG 2208 2209/* record the current triangle function name */ 2210static const char *triFuncName = NULL; 2211 2212#define USE(triFunc) \ 2213do { \ 2214 triFuncName = #triFunc; \ 2215 /*printf("%s\n", triFuncName);*/ \ 2216 swrast->Triangle = triFunc; \ 2217} while (0) 2218 2219#else 2220 2221#define USE(triFunc) swrast->Triangle = triFunc; 2222 2223#endif 2224 2225 2226 2227 2228/* 2229 * Determine which triangle rendering function to use given the current 2230 * rendering context. 2231 * 2232 * Please update the summary flag _SWRAST_NEW_TRIANGLE if you add or 2233 * remove tests to this code. 2234 */ 2235void 2236_swrast_choose_triangle( GLcontext *ctx ) 2237{ 2238 SWcontext *swrast = SWRAST_CONTEXT(ctx); 2239 const GLboolean rgbmode = ctx->Visual.rgbMode; 2240 2241 if (ctx->Polygon.CullFlag && 2242 ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) { 2243 USE(nodraw_triangle); 2244 return; 2245 } 2246 2247 if (ctx->RenderMode==GL_RENDER) { 2248 2249 if (ctx->Polygon.SmoothFlag) { 2250 _mesa_set_aa_triangle_function(ctx); 2251 ASSERT(swrast->Triangle); 2252 return; 2253 } 2254 2255 if (ctx->Depth.OcclusionTest && 2256 ctx->Depth.Test && 2257 ctx->Depth.Mask == GL_FALSE && 2258 ctx->Depth.Func == GL_LESS && 2259 !ctx->Stencil.Enabled) { 2260 if ((rgbmode && 2261 ctx->Color.ColorMask[0] == 0 && 2262 ctx->Color.ColorMask[1] == 0 && 2263 ctx->Color.ColorMask[2] == 0 && 2264 ctx->Color.ColorMask[3] == 0) 2265 || 2266 (!rgbmode && ctx->Color.IndexMask == 0)) { 2267 USE(occlusion_zless_triangle); 2268 return; 2269 } 2270 } 2271 2272 if (ctx->Texture._ReallyEnabled) { 2273 /* Ugh, we do a _lot_ of tests to pick the best textured tri func */ 2274 const struct gl_texture_object *texObj2D; 2275 const struct gl_texture_image *texImg; 2276 GLenum minFilter, magFilter, envMode; 2277 GLint format; 2278 texObj2D = ctx->Texture.Unit[0].Current2D; 2279 texImg = texObj2D ? texObj2D->Image[texObj2D->BaseLevel] : NULL; 2280 format = texImg ? texImg->TexFormat->MesaFormat : -1; 2281 minFilter = texObj2D ? texObj2D->MinFilter : (GLenum) 0; 2282 magFilter = texObj2D ? texObj2D->MagFilter : (GLenum) 0; 2283 envMode = ctx->Texture.Unit[0].EnvMode; 2284 2285 /* First see if we can used an optimized 2-D texture function */ 2286 if (ctx->Texture._ReallyEnabled==TEXTURE0_2D 2287 && texObj2D->WrapS==GL_REPEAT 2288 && texObj2D->WrapT==GL_REPEAT 2289 && texImg->Border==0 2290 && (format == MESA_FORMAT_RGB || format == MESA_FORMAT_RGBA) 2291 && minFilter == magFilter 2292 && ctx->Light.Model.ColorControl == GL_SINGLE_COLOR 2293 && ctx->Texture.Unit[0].EnvMode != GL_COMBINE_EXT) { 2294 if (ctx->Hint.PerspectiveCorrection==GL_FASTEST) { 2295 if (minFilter == GL_NEAREST 2296 && format == MESA_FORMAT_RGB 2297 && (envMode == GL_REPLACE || envMode == GL_DECAL) 2298 && ((swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT) 2299 && ctx->Depth.Func == GL_LESS 2300 && ctx->Depth.Mask == GL_TRUE) 2301 || swrast->_RasterMask == TEXTURE_BIT) 2302 && ctx->Polygon.StippleFlag == GL_FALSE) { 2303 if (swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)) { 2304 USE(simple_z_textured_triangle); 2305 } 2306 else { 2307 USE(simple_textured_triangle); 2308 } 2309 } 2310 else { 2311 if (ctx->Texture.Unit[0].EnvMode==GL_ADD) { 2312 USE(general_textured_triangle); 2313 } 2314 else { 2315 USE(affine_textured_triangle); 2316 } 2317 } 2318 } 2319 else { 2320#if 00 /* XXX these function have problems with texture coord interpolation */ 2321 if (filter==GL_NEAREST) { 2322 USE(near_persp_textured_triangle); 2323 } 2324 else { 2325 USE(lin_persp_textured_triangle); 2326 } 2327#endif 2328 USE(general_textured_triangle); 2329 } 2330 } 2331 else { 2332 /* More complicated textures (mipmap, multi-tex, sep specular) */ 2333 GLboolean needLambda; 2334 /* if mag filter != min filter we need to compute lambda */ 2335 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; 2336 if (obj && obj->MinFilter != obj->MagFilter) 2337 needLambda = GL_TRUE; 2338 else 2339 needLambda = GL_FALSE; 2340 if (swrast->_MultiTextureEnabled) { 2341 USE(lambda_multitextured_triangle); 2342 } 2343 else if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) { 2344 /* separate specular color interpolation */ 2345 if (needLambda) { 2346 USE(lambda_textured_spec_triangle); 2347 } 2348 else { 2349 USE(general_textured_spec_triangle); 2350 } 2351 } 2352 else { 2353 if (needLambda) { 2354 USE(lambda_textured_triangle); 2355 } 2356 else { 2357 USE(general_textured_triangle); 2358 } 2359 } 2360 } 2361 } 2362 else { 2363 ASSERT(!ctx->Texture._ReallyEnabled); 2364 if (ctx->Light.ShadeModel==GL_SMOOTH) { 2365 /* smooth shaded, no texturing, stippled or some raster ops */ 2366 if (rgbmode) { 2367 USE(smooth_rgba_triangle); 2368 } 2369 else { 2370 USE(smooth_ci_triangle); 2371 } 2372 } 2373 else { 2374 /* flat shaded, no texturing, stippled or some raster ops */ 2375 if (rgbmode) { 2376 USE(flat_rgba_triangle); 2377 } 2378 else { 2379 USE(flat_ci_triangle); 2380 } 2381 } 2382 } 2383 } 2384 else if (ctx->RenderMode==GL_FEEDBACK) { 2385 USE(_mesa_feedback_triangle); 2386 } 2387 else { 2388 /* GL_SELECT mode */ 2389 USE(_mesa_select_triangle); 2390 } 2391} 2392