s_triangle.c revision 71340e861edf35bfdeb536718cd230fc33c41ee2
1/* $Id: s_triangle.c,v 1.40 2001/11/19 01:18:28 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] = FixedToChan(span.red); \ 190 rgbaSpan[i][GCOMP] = FixedToChan(span.green); \ 191 rgbaSpan[i][BCOMP] = FixedToChan(span.blue); \ 192 rgbaSpan[i][ACOMP] = FixedToChan(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#if CHAN_TYPE != GL_FLOAT 333 334struct affine_info 335{ 336 GLenum filter; 337 GLenum format; 338 GLenum envmode; 339 GLint smask, tmask; 340 GLint twidth_log2; 341 const GLchan *texture; 342 GLchan er, eg, eb, ea; 343 GLint tbytesline, tsize; 344 GLint fixedToDepthShift; 345}; 346 347 348/* This function can handle GL_NEAREST or GL_LINEAR sampling of 2D RGB or RGBA 349 * textures with GL_REPLACE, GL_MODULATE, GL_BLEND, GL_DECAL or GL_ADD 350 * texture env modes. 351 */ 352static INLINE void 353affine_span(GLcontext *ctx, struct triangle_span *span, 354 struct affine_info *info) 355{ 356 GLchan sample[4]; /* the filtered texture sample */ 357 358 /* Instead of defining a function for each mode, a test is done 359 * between the outer and inner loops. This is to reduce code size 360 * and complexity. Observe that an optimizing compiler kills 361 * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST). 362 */ 363 364#define NEAREST_RGB \ 365 sample[RCOMP] = tex00[RCOMP]; \ 366 sample[GCOMP] = tex00[GCOMP]; \ 367 sample[BCOMP] = tex00[BCOMP]; \ 368 sample[ACOMP] = CHAN_MAX 369 370#define LINEAR_RGB \ 371 sample[RCOMP] = (ti * (si * tex00[0] + sf * tex01[0]) + \ 372 tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \ 373 sample[GCOMP] = (ti * (si * tex00[1] + sf * tex01[1]) + \ 374 tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \ 375 sample[BCOMP] = (ti * (si * tex00[2] + sf * tex01[2]) + \ 376 tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \ 377 sample[ACOMP] = CHAN_MAX 378 379#define NEAREST_RGBA COPY_CHAN4(sample, tex00) 380 381#define LINEAR_RGBA \ 382 sample[RCOMP] = (ti * (si * tex00[0] + sf * tex01[0]) + \ 383 tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT;\ 384 sample[GCOMP] = (ti * (si * tex00[1] + sf * tex01[1]) + \ 385 tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT;\ 386 sample[BCOMP] = (ti * (si * tex00[2] + sf * tex01[2]) + \ 387 tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT;\ 388 sample[ACOMP] = (ti * (si * tex00[3] + sf * tex01[3]) + \ 389 tf * (si * tex10[3] + sf * tex11[3])) >> 2 * FIXED_SHIFT 390 391#define MODULATE \ 392 dest[RCOMP] = span->red * (sample[RCOMP] + 1u) >> (FIXED_SHIFT + 8); \ 393 dest[GCOMP] = span->green * (sample[GCOMP] + 1u) >> (FIXED_SHIFT + 8); \ 394 dest[BCOMP] = span->blue * (sample[BCOMP] + 1u) >> (FIXED_SHIFT + 8); \ 395 dest[ACOMP] = span->alpha * (sample[ACOMP] + 1u) >> (FIXED_SHIFT + 8) 396 397#define DECAL \ 398 dest[RCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->red + \ 399 ((sample[ACOMP] + 1) * sample[RCOMP] << FIXED_SHIFT)) \ 400 >> (FIXED_SHIFT + 8); \ 401 dest[GCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->green + \ 402 ((sample[ACOMP] + 1) * sample[GCOMP] << FIXED_SHIFT)) \ 403 >> (FIXED_SHIFT + 8); \ 404 dest[BCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->blue + \ 405 ((sample[ACOMP] + 1) * sample[BCOMP] << FIXED_SHIFT)) \ 406 >> (FIXED_SHIFT + 8); \ 407 dest[ACOMP] = FixedToInt(span->alpha) 408 409#define BLEND \ 410 dest[RCOMP] = ((CHAN_MAX - sample[RCOMP]) * span->red \ 411 + (sample[RCOMP] + 1) * info->er) >> (FIXED_SHIFT + 8); \ 412 dest[GCOMP] = ((CHAN_MAX - sample[GCOMP]) * span->green \ 413 + (sample[GCOMP] + 1) * info->eg) >> (FIXED_SHIFT + 8); \ 414 dest[BCOMP] = ((CHAN_MAX - sample[BCOMP]) * span->blue \ 415 + (sample[BCOMP] + 1) * info->eb) >> (FIXED_SHIFT + 8); \ 416 dest[ACOMP] = span->alpha * (sample[ACOMP] + 1) >> (FIXED_SHIFT + 8) 417 418#define REPLACE COPY_CHAN4(dest, sample) 419 420#define ADD \ 421 { \ 422 GLint rSum = FixedToInt(span->red) + (GLint) sample[RCOMP]; \ 423 GLint gSum = FixedToInt(span->green) + (GLint) sample[GCOMP]; \ 424 GLint bSum = FixedToInt(span->blue) + (GLint) sample[BCOMP]; \ 425 dest[RCOMP] = MIN2(rSum, CHAN_MAX); \ 426 dest[GCOMP] = MIN2(gSum, CHAN_MAX); \ 427 dest[BCOMP] = MIN2(bSum, CHAN_MAX); \ 428 dest[ACOMP] = span->alpha * (sample[ACOMP] + 1) >> (FIXED_SHIFT + 8); \ 429 } 430 431/* shortcuts */ 432 433#define NEAREST_RGB_REPLACE NEAREST_RGB;REPLACE 434 435#define NEAREST_RGBA_REPLACE COPY_CHAN4(dest, tex00) 436 437#define SPAN_NEAREST(DO_TEX,COMP) \ 438 for (i = 0; i < span->count; i++) { \ 439 /* Isn't it necessary to use FixedFloor below?? */ \ 440 GLint s = FixedToInt(span->intTex[0]) & info->smask; \ 441 GLint t = FixedToInt(span->intTex[1]) & info->tmask; \ 442 GLint pos = (t << info->twidth_log2) + s; \ 443 const GLchan *tex00 = info->texture + COMP * pos; \ 444 zspan[i] = FixedToDepth(span->z); \ 445 fogspan[i] = span->fog; \ 446 DO_TEX; \ 447 span->fog += span->fogStep; \ 448 span->z += span->zStep; \ 449 span->red += span->redStep; \ 450 span->green += span->greenStep; \ 451 span->blue += span->blueStep; \ 452 span->alpha += span->alphaStep; \ 453 span->intTex[0] += span->intTexStep[0]; \ 454 span->intTex[1] += span->intTexStep[1]; \ 455 dest += 4; \ 456 } 457 458#define SPAN_LINEAR(DO_TEX,COMP) \ 459 for (i = 0; i < span->count; i++) { \ 460 /* Isn't it necessary to use FixedFloor below?? */ \ 461 GLint s = FixedToInt(span->intTex[0]) & info->smask; \ 462 GLint t = FixedToInt(span->intTex[1]) & info->tmask; \ 463 GLfixed sf = span->intTex[0] & FIXED_FRAC_MASK; \ 464 GLfixed tf = span->intTex[1] & FIXED_FRAC_MASK; \ 465 GLfixed si = FIXED_FRAC_MASK - sf; \ 466 GLfixed ti = FIXED_FRAC_MASK - tf; \ 467 GLint pos = (t << info->twidth_log2) + s; \ 468 const GLchan *tex00 = info->texture + COMP * pos; \ 469 const GLchan *tex10 = tex00 + info->tbytesline; \ 470 const GLchan *tex01 = tex00 + COMP; \ 471 const GLchan *tex11 = tex10 + COMP; \ 472 (void) ti; \ 473 (void) si; \ 474 if (t == info->tmask) { \ 475 tex10 -= info->tsize; \ 476 tex11 -= info->tsize; \ 477 } \ 478 if (s == info->smask) { \ 479 tex01 -= info->tbytesline; \ 480 tex11 -= info->tbytesline; \ 481 } \ 482 zspan[i] = FixedToDepth(span->z); \ 483 fogspan[i] = span->fog; \ 484 DO_TEX; \ 485 span->fog += span->fogStep; \ 486 span->z += span->zStep; \ 487 span->red += span->redStep; \ 488 span->green += span->greenStep; \ 489 span->blue += span->blueStep; \ 490 span->alpha += span->alphaStep; \ 491 span->intTex[0] += span->intTexStep[0]; \ 492 span->intTex[1] += span->intTexStep[1]; \ 493 dest += 4; \ 494 } 495 496#define FixedToDepth(F) ((F) >> fixedToDepthShift) 497 498 GLuint i; 499 GLdepth zspan[MAX_WIDTH]; 500 GLfloat fogspan[MAX_WIDTH]; 501 GLchan rgba[MAX_WIDTH][4]; 502 GLchan *dest = rgba[0]; 503 const GLint fixedToDepthShift = info->fixedToDepthShift; 504 505 span->intTex[0] -= FIXED_HALF; 506 span->intTex[1] -= FIXED_HALF; 507 switch (info->filter) { 508 case GL_NEAREST: 509 switch (info->format) { 510 case GL_RGB: 511 switch (info->envmode) { 512 case GL_MODULATE: 513 SPAN_NEAREST(NEAREST_RGB;MODULATE,3); 514 break; 515 case GL_DECAL: 516 case GL_REPLACE: 517 SPAN_NEAREST(NEAREST_RGB_REPLACE,3); 518 break; 519 case GL_BLEND: 520 SPAN_NEAREST(NEAREST_RGB;BLEND,3); 521 break; 522 case GL_ADD: 523 SPAN_NEAREST(NEAREST_RGB;ADD,3); 524 break; 525 default: 526 abort(); 527 } 528 break; 529 case GL_RGBA: 530 switch(info->envmode) { 531 case GL_MODULATE: 532 SPAN_NEAREST(NEAREST_RGBA;MODULATE,4); 533 break; 534 case GL_DECAL: 535 SPAN_NEAREST(NEAREST_RGBA;DECAL,4); 536 break; 537 case GL_BLEND: 538 SPAN_NEAREST(NEAREST_RGBA;BLEND,4); 539 break; 540 case GL_ADD: 541 SPAN_NEAREST(NEAREST_RGBA;ADD,4); 542 break; 543 case GL_REPLACE: 544 SPAN_NEAREST(NEAREST_RGBA_REPLACE,4); 545 break; 546 default: 547 abort(); 548 } 549 break; 550 } 551 break; 552 553 case GL_LINEAR: 554 span->intTex[0] -= FIXED_HALF; 555 span->intTex[1] -= FIXED_HALF; 556 switch (info->format) { 557 case GL_RGB: 558 switch (info->envmode) { 559 case GL_MODULATE: 560 SPAN_LINEAR(LINEAR_RGB;MODULATE,3); 561 break; 562 case GL_DECAL: 563 case GL_REPLACE: 564 SPAN_LINEAR(LINEAR_RGB;REPLACE,3); 565 break; 566 case GL_BLEND: 567 SPAN_LINEAR(LINEAR_RGB;BLEND,3); 568 break; 569 case GL_ADD: 570 SPAN_LINEAR(LINEAR_RGB;ADD,3); 571 break; 572 default: 573 abort(); 574 } 575 break; 576 case GL_RGBA: 577 switch (info->envmode) { 578 case GL_MODULATE: 579 SPAN_LINEAR(LINEAR_RGBA;MODULATE,4); 580 break; 581 case GL_DECAL: 582 SPAN_LINEAR(LINEAR_RGBA;DECAL,4); 583 break; 584 case GL_BLEND: 585 SPAN_LINEAR(LINEAR_RGBA;BLEND,4); 586 break; 587 case GL_ADD: 588 SPAN_LINEAR(LINEAR_RGBA;ADD,4); 589 break; 590 case GL_REPLACE: 591 SPAN_LINEAR(LINEAR_RGBA;REPLACE,4); 592 break; 593 default: 594 abort(); 595 } break; 596 } 597 break; 598 } 599 _mesa_write_rgba_span(ctx, span->count, span->x, span->y, 600 zspan, fogspan, rgba, NULL, GL_POLYGON); 601 602#undef SPAN_NEAREST 603#undef SPAN_LINEAR 604#undef FixedToDepth 605} 606 607 608 609/* 610 * Render an RGB/RGBA textured triangle without perspective correction. 611 */ 612static void affine_textured_triangle( GLcontext *ctx, 613 const SWvertex *v0, 614 const SWvertex *v1, 615 const SWvertex *v2 ) 616{ 617#define INTERP_Z 1 618#define INTERP_FOG 1 619#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 620#define INTERP_RGB 1 621#define INTERP_ALPHA 1 622#define INTERP_INT_TEX 1 623#define S_SCALE twidth 624#define T_SCALE theight 625 626#define SETUP_CODE \ 627 struct affine_info info; \ 628 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \ 629 struct gl_texture_object *obj = unit->Current2D; \ 630 GLint b = obj->BaseLevel; \ 631 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \ 632 GLfloat theight = (GLfloat) obj->Image[b]->Height; \ 633 info.fixedToDepthShift = ctx->Visual.depthBits <= 16 ? FIXED_SHIFT : 0;\ 634 info.texture = (const GLchan *) obj->Image[b]->Data; \ 635 info.twidth_log2 = obj->Image[b]->WidthLog2; \ 636 info.smask = obj->Image[b]->Width - 1; \ 637 info.tmask = obj->Image[b]->Height - 1; \ 638 info.format = obj->Image[b]->Format; \ 639 info.filter = obj->MinFilter; \ 640 info.envmode = unit->EnvMode; \ 641 \ 642 if (info.envmode == GL_BLEND) { \ 643 /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \ 644 info.er = FloatToFixed(unit->EnvColor[RCOMP]); \ 645 info.eg = FloatToFixed(unit->EnvColor[GCOMP]); \ 646 info.eb = FloatToFixed(unit->EnvColor[BCOMP]); \ 647 info.ea = FloatToFixed(unit->EnvColor[ACOMP]); \ 648 } \ 649 if (!info.texture) { \ 650 /* this shouldn't happen */ \ 651 return; \ 652 } \ 653 \ 654 switch (info.format) { \ 655 case GL_ALPHA: \ 656 case GL_LUMINANCE: \ 657 case GL_INTENSITY: \ 658 info.tbytesline = obj->Image[b]->Width; \ 659 break; \ 660 case GL_LUMINANCE_ALPHA: \ 661 info.tbytesline = obj->Image[b]->Width * 2; \ 662 break; \ 663 case GL_RGB: \ 664 info.tbytesline = obj->Image[b]->Width * 3; \ 665 break; \ 666 case GL_RGBA: \ 667 info.tbytesline = obj->Image[b]->Width * 4; \ 668 break; \ 669 default: \ 670 _mesa_problem(NULL, "Bad texture format in affine_texture_triangle");\ 671 return; \ 672 } \ 673 info.tsize = obj->Image[b]->Height * info.tbytesline; 674 675#define RENDER_SPAN( span ) affine_span(ctx, &span, &info); 676 677#include "s_tritemp.h" 678 679} 680 681 682 683struct persp_info 684{ 685 GLenum filter; 686 GLenum format; 687 GLenum envmode; 688 GLint smask, tmask; 689 GLint twidth_log2; 690 const GLchan *texture; 691 GLchan er, eg, eb, ea; /* texture env color */ 692 GLint tbytesline, tsize; 693 GLint fixedToDepthShift; 694}; 695 696 697static INLINE void 698fast_persp_span(GLcontext *ctx, struct triangle_span *span, 699 struct persp_info *info) 700{ 701 GLchan sample[4]; /* the filtered texture sample */ 702 703 /* Instead of defining a function for each mode, a test is done 704 * between the outer and inner loops. This is to reduce code size 705 * and complexity. Observe that an optimizing compiler kills 706 * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST). 707 */ 708#define SPAN_NEAREST(DO_TEX,COMP) \ 709 for (i = 0; i < span->count; i++) { \ 710 GLdouble invQ = tex_coord[2] ? \ 711 (1.0 / tex_coord[2]) : 1.0; \ 712 GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ); \ 713 GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ); \ 714 GLint s = IFLOOR(s_tmp) & info->smask; \ 715 GLint t = IFLOOR(t_tmp) & info->tmask; \ 716 GLint pos = (t << info->twidth_log2) + s; \ 717 const GLchan *tex00 = info->texture + COMP * pos; \ 718 zspan[i] = FixedToDepth(span->z); \ 719 fogspan[i] = span->fog; \ 720 DO_TEX; \ 721 span->fog += span->fogStep; \ 722 span->z += span->zStep; \ 723 span->red += span->redStep; \ 724 span->green += span->greenStep; \ 725 span->blue += span->blueStep; \ 726 span->alpha += span->alphaStep; \ 727 tex_coord[0] += tex_step[0]; \ 728 tex_coord[1] += tex_step[1]; \ 729 tex_coord[2] += tex_step[2]; \ 730 dest += 4; \ 731 } 732 733#define SPAN_LINEAR(DO_TEX,COMP) \ 734 for (i = 0; i < span->count; i++) { \ 735 GLdouble invQ = tex_coord[2] ? \ 736 (1.0 / tex_coord[2]) : 1.0; \ 737 GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ); \ 738 GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ); \ 739 GLfixed s_fix = FloatToFixed(s_tmp) - FIXED_HALF; \ 740 GLfixed t_fix = FloatToFixed(t_tmp) - FIXED_HALF; \ 741 GLint s = FixedToInt(FixedFloor(s_fix)) & info->smask; \ 742 GLint t = FixedToInt(FixedFloor(t_fix)) & info->tmask; \ 743 GLfixed sf = s_fix & FIXED_FRAC_MASK; \ 744 GLfixed tf = t_fix & FIXED_FRAC_MASK; \ 745 GLfixed si = FIXED_FRAC_MASK - sf; \ 746 GLfixed ti = FIXED_FRAC_MASK - tf; \ 747 GLint pos = (t << info->twidth_log2) + s; \ 748 const GLchan *tex00 = info->texture + COMP * pos; \ 749 const GLchan *tex10 = tex00 + info->tbytesline; \ 750 const GLchan *tex01 = tex00 + COMP; \ 751 const GLchan *tex11 = tex10 + COMP; \ 752 (void) ti; \ 753 (void) si; \ 754 if (t == info->tmask) { \ 755 tex10 -= info->tsize; \ 756 tex11 -= info->tsize; \ 757 } \ 758 if (s == info->smask) { \ 759 tex01 -= info->tbytesline; \ 760 tex11 -= info->tbytesline; \ 761 } \ 762 zspan[i] = FixedToDepth(span->z); \ 763 fogspan[i] = span->fog; \ 764 DO_TEX; \ 765 span->fog += span->fogStep; \ 766 span->z += span->zStep; \ 767 span->red += span->redStep; \ 768 span->green += span->greenStep; \ 769 span->blue += span->blueStep; \ 770 span->alpha += span->alphaStep; \ 771 tex_coord[0] += tex_step[0]; \ 772 tex_coord[1] += tex_step[1]; \ 773 tex_coord[2] += tex_step[2]; \ 774 dest += 4; \ 775 } 776 777#define FixedToDepth(F) ((F) >> fixedToDepthShift) 778 779 GLuint i; 780 GLdepth zspan[MAX_WIDTH]; 781 GLfloat tex_coord[3], tex_step[3]; 782 GLfloat fogspan[MAX_WIDTH]; 783 GLchan rgba[MAX_WIDTH][4]; 784 GLchan *dest = rgba[0]; 785 const GLint fixedToDepthShift = info->fixedToDepthShift; 786 787 tex_coord[0] = span->tex[0][0] * (info->smask + 1), 788 tex_step[0] = span->texStep[0][0] * (info->smask + 1); 789 tex_coord[1] = span->tex[0][1] * (info->tmask + 1), 790 tex_step[1] = span->texStep[0][1] * (info->tmask + 1); 791 /* span->tex[0][2] only if 3D-texturing, here only 2D */ 792 tex_coord[2] = span->tex[0][3], 793 tex_step[2] = span->texStep[0][3]; 794 795 switch (info->filter) { 796 case GL_NEAREST: 797 switch (info->format) { 798 case GL_RGB: 799 switch (info->envmode) { 800 case GL_MODULATE: 801 SPAN_NEAREST(NEAREST_RGB;MODULATE,3); 802 break; 803 case GL_DECAL: 804 case GL_REPLACE: 805 SPAN_NEAREST(NEAREST_RGB_REPLACE,3); 806 break; 807 case GL_BLEND: 808 SPAN_NEAREST(NEAREST_RGB;BLEND,3); 809 break; 810 case GL_ADD: 811 SPAN_NEAREST(NEAREST_RGB;ADD,3); 812 break; 813 default: 814 abort(); 815 } 816 break; 817 case GL_RGBA: 818 switch(info->envmode) { 819 case GL_MODULATE: 820 SPAN_NEAREST(NEAREST_RGBA;MODULATE,4); 821 break; 822 case GL_DECAL: 823 SPAN_NEAREST(NEAREST_RGBA;DECAL,4); 824 break; 825 case GL_BLEND: 826 SPAN_NEAREST(NEAREST_RGBA;BLEND,4); 827 break; 828 case GL_ADD: 829 SPAN_NEAREST(NEAREST_RGBA;ADD,4); 830 break; 831 case GL_REPLACE: 832 SPAN_NEAREST(NEAREST_RGBA_REPLACE,4); 833 break; 834 default: 835 abort(); 836 } 837 break; 838 } 839 break; 840 841 case GL_LINEAR: 842 switch (info->format) { 843 case GL_RGB: 844 switch (info->envmode) { 845 case GL_MODULATE: 846 SPAN_LINEAR(LINEAR_RGB;MODULATE,3); 847 break; 848 case GL_DECAL: 849 case GL_REPLACE: 850 SPAN_LINEAR(LINEAR_RGB;REPLACE,3); 851 break; 852 case GL_BLEND: 853 SPAN_LINEAR(LINEAR_RGB;BLEND,3); 854 break; 855 case GL_ADD: 856 SPAN_LINEAR(LINEAR_RGB;ADD,3); 857 break; 858 default: 859 abort(); 860 } 861 break; 862 case GL_RGBA: 863 switch (info->envmode) { 864 case GL_MODULATE: 865 SPAN_LINEAR(LINEAR_RGBA;MODULATE,4); 866 break; 867 case GL_DECAL: 868 SPAN_LINEAR(LINEAR_RGBA;DECAL,4); 869 break; 870 case GL_BLEND: 871 SPAN_LINEAR(LINEAR_RGBA;BLEND,4); 872 break; 873 case GL_ADD: 874 SPAN_LINEAR(LINEAR_RGBA;ADD,4); 875 break; 876 case GL_REPLACE: 877 SPAN_LINEAR(LINEAR_RGBA;REPLACE,4); 878 break; 879 default: 880 abort(); 881 } 882 break; 883 } 884 break; 885 } 886 /* This does not seem to be necessary, but I don't know !! */ 887 /* span->tex[0][0] = tex_coord[0] / (info->smask + 1), 888 span->tex[0][1] = tex_coord[1] / (info->tmask + 1),*/ 889 /* span->tex[0][2] only if 3D-texturing, here only 2D */ 890 /* span->tex[0][3] = tex_coord[2]; */ 891 892 _mesa_write_rgba_span(ctx, span->count, span->x, span->y, 893 zspan, fogspan, rgba, NULL, GL_POLYGON); 894 895 896#undef SPAN_NEAREST 897#undef SPAN_LINEAR 898#undef FixedToDepth 899} 900 901 902/* 903 * Render an perspective corrected RGB/RGBA textured triangle. 904 * The Q (aka V in Mesa) coordinate must be zero such that the divide 905 * by interpolated Q/W comes out right. 906 * 907 */ 908static void persp_textured_triangle( GLcontext *ctx, 909 const SWvertex *v0, 910 const SWvertex *v1, 911 const SWvertex *v2 ) 912{ 913#define INTERP_Z 1 914#define INTERP_FOG 1 915#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 916#define INTERP_RGB 1 917#define INTERP_ALPHA 1 918#define INTERP_TEX 1 919 920#define SETUP_CODE \ 921 struct persp_info info; \ 922 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \ 923 struct gl_texture_object *obj = unit->Current2D; \ 924 GLint b = obj->BaseLevel; \ 925 info.fixedToDepthShift = ctx->Visual.depthBits <= 16 ? FIXED_SHIFT : 0;\ 926 info.texture = (const GLchan *) obj->Image[b]->Data; \ 927 info.twidth_log2 = obj->Image[b]->WidthLog2; \ 928 info.smask = obj->Image[b]->Width - 1; \ 929 info.tmask = obj->Image[b]->Height - 1; \ 930 info.format = obj->Image[b]->Format; \ 931 info.filter = obj->MinFilter; \ 932 info.envmode = unit->EnvMode; \ 933 \ 934 if (info.envmode == GL_BLEND) { \ 935 /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \ 936 info.er = FloatToFixed(unit->EnvColor[RCOMP]); \ 937 info.eg = FloatToFixed(unit->EnvColor[GCOMP]); \ 938 info.eb = FloatToFixed(unit->EnvColor[BCOMP]); \ 939 info.ea = FloatToFixed(unit->EnvColor[ACOMP]); \ 940 } \ 941 if (!info.texture) { \ 942 /* this shouldn't happen */ \ 943 return; \ 944 } \ 945 \ 946 switch (info.format) { \ 947 case GL_ALPHA: \ 948 case GL_LUMINANCE: \ 949 case GL_INTENSITY: \ 950 info.tbytesline = obj->Image[b]->Width; \ 951 break; \ 952 case GL_LUMINANCE_ALPHA: \ 953 info.tbytesline = obj->Image[b]->Width * 2; \ 954 break; \ 955 case GL_RGB: \ 956 info.tbytesline = obj->Image[b]->Width * 3; \ 957 break; \ 958 case GL_RGBA: \ 959 info.tbytesline = obj->Image[b]->Width * 4; \ 960 break; \ 961 default: \ 962 _mesa_problem(NULL, "Bad texture format in persp_textured_triangle");\ 963 return; \ 964 } \ 965 info.tsize = obj->Image[b]->Height * info.tbytesline; 966 967#define RENDER_SPAN( span ) fast_persp_span(ctx, &span, &info); 968 969#include "s_tritemp.h" 970 971} 972 973 974#endif /* CHAN_BITS != GL_FLOAT */ 975 976 977 978 979/* 980 * Render a smooth-shaded, textured, RGBA triangle. 981 * Interpolate S,T,R with perspective correction, w/out mipmapping. 982 */ 983static void general_textured_triangle( GLcontext *ctx, 984 const SWvertex *v0, 985 const SWvertex *v1, 986 const SWvertex *v2 ) 987{ 988#define INTERP_Z 1 989#define INTERP_FOG 1 990#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 991#define INTERP_RGB 1 992#define INTERP_ALPHA 1 993#define INTERP_TEX 1 994 995#define SETUP_CODE \ 996 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \ 997 const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\ 998 DEFARRAY(GLfloat, sSpan, MAX_WIDTH); /* mac 32k limitation */ \ 999 DEFARRAY(GLfloat, tSpan, MAX_WIDTH); /* mac 32k limitation */ \ 1000 DEFARRAY(GLfloat, uSpan, MAX_WIDTH); /* mac 32k limitation */ \ 1001 CHECKARRAY(sSpan, return); /* mac 32k limitation */ \ 1002 CHECKARRAY(tSpan, return); /* mac 32k limitation */ \ 1003 CHECKARRAY(uSpan, return); /* mac 32k limitation */ \ 1004 span.texWidth[0] = (GLfloat) texImage->Width; \ 1005 span.texHeight[0] = (GLfloat) texImage->Height; \ 1006 (void) fixedToDepthShift; 1007 1008#define RENDER_SPAN( span ) \ 1009 GLdepth zSpan[MAX_WIDTH]; \ 1010 GLfloat fogSpan[MAX_WIDTH]; \ 1011 GLchan rgbaSpan[MAX_WIDTH][4]; \ 1012 GLuint i; \ 1013 /* NOTE: we could just call rasterize_span() here instead */ \ 1014 for (i = 0; i < span.count; i++) { \ 1015 GLdouble invQ = span.tex[0][3] ? (1.0 / span.tex[0][3]) : 1.0; \ 1016 zSpan[i] = FixedToDepth(span.z); \ 1017 span.z += span.zStep; \ 1018 fogSpan[i] = span.fog; \ 1019 span.fog += span.fogStep; \ 1020 rgbaSpan[i][RCOMP] = FixedToChan(span.red); \ 1021 rgbaSpan[i][GCOMP] = FixedToChan(span.green); \ 1022 rgbaSpan[i][BCOMP] = FixedToChan(span.blue); \ 1023 rgbaSpan[i][ACOMP] = FixedToChan(span.alpha); \ 1024 span.red += span.redStep; \ 1025 span.green += span.greenStep; \ 1026 span.blue += span.blueStep; \ 1027 span.alpha += span.alphaStep; \ 1028 sSpan[i] = (GLfloat) (span.tex[0][0] * invQ); \ 1029 tSpan[i] = (GLfloat) (span.tex[0][1] * invQ); \ 1030 uSpan[i] = (GLfloat) (span.tex[0][2] * invQ); \ 1031 span.tex[0][0] += span.texStep[0][0]; \ 1032 span.tex[0][1] += span.texStep[0][1]; \ 1033 span.tex[0][2] += span.texStep[0][2]; \ 1034 span.tex[0][3] += span.texStep[0][3]; \ 1035 } \ 1036 _mesa_write_texture_span(ctx, span.count, span.x, span.y, \ 1037 zSpan, fogSpan, sSpan, tSpan, uSpan, \ 1038 NULL, rgbaSpan, NULL, NULL, GL_POLYGON ); 1039 1040#define CLEANUP_CODE \ 1041 UNDEFARRAY(sSpan); /* mac 32k limitation */ \ 1042 UNDEFARRAY(tSpan); \ 1043 UNDEFARRAY(uSpan); 1044 1045#include "s_tritemp.h" 1046} 1047 1048 1049/* 1050 * Render a smooth-shaded, textured, RGBA triangle with separate specular 1051 * color interpolation. 1052 * Interpolate texcoords with perspective correction, w/out mipmapping. 1053 */ 1054static void general_textured_spec_triangle( GLcontext *ctx, 1055 const SWvertex *v0, 1056 const SWvertex *v1, 1057 const SWvertex *v2 ) 1058{ 1059#define INTERP_Z 1 1060#define INTERP_FOG 1 1061#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1062#define INTERP_RGB 1 1063#define INTERP_SPEC 1 1064#define INTERP_ALPHA 1 1065#define INTERP_TEX 1 1066 1067#define SETUP_CODE \ 1068 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \ 1069 const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\ 1070 span.texWidth[0] = (GLfloat) texImage->Width; \ 1071 span.texHeight[0] = (GLfloat) texImage->Height; \ 1072 (void) fixedToDepthShift; 1073 1074#define RENDER_SPAN( span ) _mesa_rasterize_span(ctx, &span); 1075 1076#include "s_tritemp.h" 1077} 1078 1079 1080/* 1081 * Render a smooth-shaded, textured, RGBA triangle. 1082 * Interpolate S,T,R with perspective correction and compute lambda for 1083 * each fragment. Lambda is used to determine whether to use the 1084 * minification or magnification filter. If minification and using 1085 * mipmaps, lambda is also used to select the texture level of detail. 1086 */ 1087static void lambda_textured_triangle( GLcontext *ctx, 1088 const SWvertex *v0, 1089 const SWvertex *v1, 1090 const SWvertex *v2 ) 1091{ 1092#define INTERP_Z 1 1093#define INTERP_FOG 1 1094#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1095#define INTERP_RGB 1 1096#define INTERP_ALPHA 1 1097#define INTERP_TEX 1 1098#define INTERP_LAMBDA 1 1099 1100#define SETUP_CODE \ 1101 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \ 1102 const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\ 1103 span.texWidth[0] = (GLfloat) texImage->Width; \ 1104 span.texHeight[0] = (GLfloat) texImage->Height; \ 1105 (void) fixedToDepthShift; 1106 1107#define RENDER_SPAN( span ) _mesa_rasterize_span(ctx, &span); 1108 1109#include "s_tritemp.h" 1110} 1111 1112 1113/* 1114 * Render a smooth-shaded, textured, RGBA triangle with separate specular 1115 * interpolation. 1116 * Interpolate S,T,R with perspective correction and compute lambda for 1117 * each fragment. Lambda is used to determine whether to use the 1118 * minification or magnification filter. If minification and using 1119 * mipmaps, lambda is also used to select the texture level of detail. 1120 */ 1121static void lambda_textured_spec_triangle( GLcontext *ctx, 1122 const SWvertex *v0, 1123 const SWvertex *v1, 1124 const SWvertex *v2 ) 1125{ 1126#define INTERP_Z 1 1127#define INTERP_FOG 1 1128#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1129#define INTERP_RGB 1 1130#define INTERP_SPEC 1 1131#define INTERP_ALPHA 1 1132#define INTERP_TEX 1 1133#define INTERP_LAMBDA 1 1134 1135#define SETUP_CODE \ 1136 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \ 1137 const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\ 1138 span.texWidth[0] = (GLfloat) texImage->Width; \ 1139 span.texHeight[0] = (GLfloat) texImage->Height; \ 1140 (void) fixedToDepthShift; 1141 1142#define RENDER_SPAN( span ) _mesa_rasterize_span(ctx, &span); 1143 1144#include "s_tritemp.h" 1145} 1146 1147 1148/* 1149 * This is the big one! 1150 * Interpolate Z, RGB, Alpha, specular, fog, and N sets of texture coordinates 1151 * with lambda (LOD). 1152 * Yup, it's slow. 1153 */ 1154static void 1155lambda_multitextured_triangle( GLcontext *ctx, 1156 const SWvertex *v0, 1157 const SWvertex *v1, 1158 const SWvertex *v2 ) 1159{ 1160 1161#define INTERP_Z 1 1162#define INTERP_FOG 1 1163#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1164#define INTERP_RGB 1 1165#define INTERP_ALPHA 1 1166#define INTERP_SPEC 1 1167#define INTERP_MULTITEX 1 1168#define INTERP_LAMBDA 1 1169 1170#define SETUP_CODE \ 1171 GLuint u; \ 1172 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { \ 1173 if (ctx->Texture.Unit[u]._ReallyEnabled) { \ 1174 const struct gl_texture_object *texObj; \ 1175 const struct gl_texture_image *texImage; \ 1176 texObj = ctx->Texture.Unit[u]._Current; \ 1177 texImage = texObj->Image[texObj->BaseLevel]; \ 1178 span.texWidth[u] = (GLfloat) texImage->Width; \ 1179 span.texHeight[u] = (GLfloat) texImage->Height; \ 1180 } \ 1181 } \ 1182 (void) fixedToDepthShift; 1183 1184#define RENDER_SPAN( span ) _mesa_rasterize_span(ctx, &span); 1185 1186#include "s_tritemp.h" 1187 1188} 1189 1190 1191static void occlusion_zless_triangle( GLcontext *ctx, 1192 const SWvertex *v0, 1193 const SWvertex *v1, 1194 const SWvertex *v2 ) 1195{ 1196 if (ctx->OcclusionResult) { 1197 return; 1198 } 1199 1200#define DO_OCCLUSION_TEST 1201#define INTERP_Z 1 1202#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1203 1204#define RENDER_SPAN( span ) \ 1205 GLuint i; \ 1206 for (i = 0; i < span.count; i++) { \ 1207 GLdepth z = FixedToDepth(span.z); \ 1208 if (z < zRow[i]) { \ 1209 ctx->OcclusionResult = GL_TRUE; \ 1210 return; \ 1211 } \ 1212 span.z += span.zStep; \ 1213 } 1214 1215#include "s_tritemp.h" 1216} 1217 1218static void nodraw_triangle( GLcontext *ctx, 1219 const SWvertex *v0, 1220 const SWvertex *v1, 1221 const SWvertex *v2 ) 1222{ 1223 (void) (ctx && v0 && v1 && v2); 1224} 1225 1226void _swrast_add_spec_terms_triangle( GLcontext *ctx, 1227 const SWvertex *v0, 1228 const SWvertex *v1, 1229 const SWvertex *v2 ) 1230{ 1231 SWvertex *ncv0 = (SWvertex *)v0; /* drop const qualifier */ 1232 SWvertex *ncv1 = (SWvertex *)v1; 1233 SWvertex *ncv2 = (SWvertex *)v2; 1234 GLchan c[3][4]; 1235 COPY_CHAN4( c[0], ncv0->color ); 1236 COPY_CHAN4( c[1], ncv1->color ); 1237 COPY_CHAN4( c[2], ncv2->color ); 1238 ACC_3V( ncv0->color, ncv0->specular ); 1239 ACC_3V( ncv1->color, ncv1->specular ); 1240 ACC_3V( ncv2->color, ncv2->specular ); 1241 SWRAST_CONTEXT(ctx)->SpecTriangle( ctx, ncv0, ncv1, ncv2 ); 1242 COPY_CHAN4( ncv0->color, c[0] ); 1243 COPY_CHAN4( ncv1->color, c[1] ); 1244 COPY_CHAN4( ncv2->color, c[2] ); 1245} 1246 1247 1248 1249#ifdef DEBUG 1250 1251/* record the current triangle function name */ 1252static const char *triFuncName = NULL; 1253 1254#define USE(triFunc) \ 1255do { \ 1256 triFuncName = #triFunc; \ 1257 /*printf("%s\n", triFuncName);*/ \ 1258 swrast->Triangle = triFunc; \ 1259} while (0) 1260 1261#else 1262 1263#define USE(triFunc) swrast->Triangle = triFunc; 1264 1265#endif 1266 1267 1268 1269 1270/* 1271 * Determine which triangle rendering function to use given the current 1272 * rendering context. 1273 * 1274 * Please update the summary flag _SWRAST_NEW_TRIANGLE if you add or 1275 * remove tests to this code. 1276 */ 1277void 1278_swrast_choose_triangle( GLcontext *ctx ) 1279{ 1280 SWcontext *swrast = SWRAST_CONTEXT(ctx); 1281 const GLboolean rgbmode = ctx->Visual.rgbMode; 1282 1283 if (ctx->Polygon.CullFlag && 1284 ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) { 1285 USE(nodraw_triangle); 1286 return; 1287 } 1288 1289 if (ctx->RenderMode==GL_RENDER) { 1290 1291 if (ctx->Polygon.SmoothFlag) { 1292 _mesa_set_aa_triangle_function(ctx); 1293 ASSERT(swrast->Triangle); 1294 return; 1295 } 1296 1297 if (ctx->Depth.OcclusionTest && 1298 ctx->Depth.Test && 1299 ctx->Depth.Mask == GL_FALSE && 1300 ctx->Depth.Func == GL_LESS && 1301 !ctx->Stencil.Enabled) { 1302 if ((rgbmode && 1303 ctx->Color.ColorMask[0] == 0 && 1304 ctx->Color.ColorMask[1] == 0 && 1305 ctx->Color.ColorMask[2] == 0 && 1306 ctx->Color.ColorMask[3] == 0) 1307 || 1308 (!rgbmode && ctx->Color.IndexMask == 0)) { 1309 USE(occlusion_zless_triangle); 1310 return; 1311 } 1312 } 1313 1314 if (ctx->Texture._ReallyEnabled) { 1315 /* Ugh, we do a _lot_ of tests to pick the best textured tri func */ 1316 const struct gl_texture_object *texObj2D; 1317 const struct gl_texture_image *texImg; 1318 GLenum minFilter, magFilter, envMode; 1319 GLint format; 1320 texObj2D = ctx->Texture.Unit[0].Current2D; 1321 texImg = texObj2D ? texObj2D->Image[texObj2D->BaseLevel] : NULL; 1322 format = texImg ? texImg->TexFormat->MesaFormat : -1; 1323 minFilter = texObj2D ? texObj2D->MinFilter : (GLenum) 0; 1324 magFilter = texObj2D ? texObj2D->MagFilter : (GLenum) 0; 1325 envMode = ctx->Texture.Unit[0].EnvMode; 1326 1327 /* First see if we can used an optimized 2-D texture function */ 1328 if (ctx->Texture._ReallyEnabled==TEXTURE0_2D 1329 && texObj2D->WrapS==GL_REPEAT 1330 && texObj2D->WrapT==GL_REPEAT 1331 && texImg->Border==0 1332 && (format == MESA_FORMAT_RGB || format == MESA_FORMAT_RGBA) 1333 && minFilter == magFilter 1334 && ctx->Light.Model.ColorControl == GL_SINGLE_COLOR 1335 && ctx->Texture.Unit[0].EnvMode != GL_COMBINE_EXT) { 1336 if (ctx->Hint.PerspectiveCorrection==GL_FASTEST) { 1337 if (minFilter == GL_NEAREST 1338 && format == MESA_FORMAT_RGB 1339 && (envMode == GL_REPLACE || envMode == GL_DECAL) 1340 && ((swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT) 1341 && ctx->Depth.Func == GL_LESS 1342 && ctx->Depth.Mask == GL_TRUE) 1343 || swrast->_RasterMask == TEXTURE_BIT) 1344 && ctx->Polygon.StippleFlag == GL_FALSE) { 1345 if (swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)) { 1346 USE(simple_z_textured_triangle); 1347 } 1348 else { 1349 USE(simple_textured_triangle); 1350 } 1351 } 1352 else { 1353#if CHAN_TYPE == GL_FLOAT 1354 USE(general_textured_triangle); 1355#else 1356 USE(affine_textured_triangle); 1357#endif 1358 } 1359 } 1360 else { 1361#if CHAN_TYPE == GL_FLOAT 1362 USE(general_textured_triangle); 1363#else 1364 USE(persp_textured_triangle); 1365#endif 1366 } 1367 } 1368 else { 1369 /* More complicated textures (mipmap, multi-tex, sep specular) */ 1370 GLboolean needLambda; 1371 /* if mag filter != min filter we need to compute lambda */ 1372 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; 1373 if (obj && obj->MinFilter != obj->MagFilter) 1374 needLambda = GL_TRUE; 1375 else 1376 needLambda = GL_FALSE; 1377 if (ctx->Texture._ReallyEnabled > TEXTURE0_ANY) { 1378 USE(lambda_multitextured_triangle); 1379 } 1380 else if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) { 1381 /* separate specular color interpolation */ 1382 if (needLambda) { 1383 USE(lambda_textured_spec_triangle); 1384 } 1385 else { 1386 USE(general_textured_spec_triangle); 1387 } 1388 } 1389 else { 1390 if (needLambda) { 1391 USE(lambda_textured_triangle); 1392 } 1393 else { 1394 USE(general_textured_triangle); 1395 } 1396 } 1397 } 1398 } 1399 else { 1400 ASSERT(!ctx->Texture._ReallyEnabled); 1401 if (ctx->Light.ShadeModel==GL_SMOOTH) { 1402 /* smooth shaded, no texturing, stippled or some raster ops */ 1403 if (rgbmode) { 1404 USE(smooth_rgba_triangle); 1405 } 1406 else { 1407 USE(smooth_ci_triangle); 1408 } 1409 } 1410 else { 1411 /* flat shaded, no texturing, stippled or some raster ops */ 1412 if (rgbmode) { 1413 USE(flat_rgba_triangle); 1414 } 1415 else { 1416 USE(flat_ci_triangle); 1417 } 1418 } 1419 } 1420 } 1421 else if (ctx->RenderMode==GL_FEEDBACK) { 1422 USE(_mesa_feedback_triangle); 1423 } 1424 else { 1425 /* GL_SELECT mode */ 1426 USE(_mesa_select_triangle); 1427 } 1428} 1429