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