s_linetemp.h revision e307931314f1145305ac2946f13f5e2f020313ec
1/* $Id: s_linetemp.h,v 1.14 2002/11/09 21:26:41 brianp Exp $ */ 2 3/* 4 * Mesa 3-D graphics library 5 * Version: 5.0 6 * 7 * Copyright (C) 1999-2002 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 * Line Rasterizer Template 30 * 31 * This file is #include'd to generate custom line rasterizers. 32 * 33 * The following macros may be defined to indicate what auxillary information 34 * must be interplated along the line: 35 * INTERP_Z - if defined, interpolate Z values 36 * INTERP_FOG - if defined, interpolate FOG values 37 * INTERP_RGB - if defined, interpolate RGB values 38 * INTERP_SPEC - if defined, interpolate specular RGB values 39 * INTERP_ALPHA - if defined, interpolate Alpha values 40 * INTERP_INDEX - if defined, interpolate color index values 41 * INTERP_TEX - if defined, interpolate unit 0 texcoords 42 * INTERP_MULTITEX - if defined, interpolate multi-texcoords 43 * 44 * When one can directly address pixels in the color buffer the following 45 * macros can be defined and used to directly compute pixel addresses during 46 * rasterization (see pixelPtr): 47 * PIXEL_TYPE - the datatype of a pixel (GLubyte, GLushort, GLuint) 48 * BYTES_PER_ROW - number of bytes per row in the color buffer 49 * PIXEL_ADDRESS(X,Y) - returns the address of pixel at (X,Y) where 50 * Y==0 at bottom of screen and increases upward. 51 * 52 * Similarly, for direct depth buffer access, this type is used for depth 53 * buffer addressing: 54 * DEPTH_TYPE - either GLushort or GLuint 55 * 56 * Optionally, one may provide one-time setup code 57 * SETUP_CODE - code which is to be executed once per line 58 * 59 * To actually "plot" each pixel the PLOT macro must be defined... 60 * PLOT(X,Y) - code to plot a pixel. Example: 61 * if (Z < *zPtr) { 62 * *zPtr = Z; 63 * color = pack_rgb( FixedToInt(r0), FixedToInt(g0), 64 * FixedToInt(b0) ); 65 * put_pixel( X, Y, color ); 66 * } 67 * 68 * This code was designed for the origin to be in the lower-left corner. 69 * 70 */ 71 72 73/*void line( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 )*/ 74{ 75 GLint x0 = (GLint) vert0->win[0]; 76 GLint x1 = (GLint) vert1->win[0]; 77 GLint y0 = (GLint) vert0->win[1]; 78 GLint y1 = (GLint) vert1->win[1]; 79 GLint dx, dy; 80#ifdef INTERP_XY 81 GLint xstep, ystep; 82#endif 83#ifdef INTERP_Z 84 GLint z0, z1, dz; 85 const GLint depthBits = ctx->Visual.depthBits; 86 const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0; 87# define FixedToDepth(F) ((F) >> fixedToDepthShift) 88# ifdef DEPTH_TYPE 89 GLint zPtrXstep, zPtrYstep; 90 DEPTH_TYPE *zPtr; 91# endif 92#endif 93#ifdef INTERP_FOG 94 GLfloat fog0 = vert0->fog; 95 GLfloat dfog = vert1->fog - fog0; 96#endif 97#ifdef INTERP_RGB 98 GLfixed r0 = ChanToFixed(vert0->color[0]); 99 GLfixed dr = ChanToFixed(vert1->color[0]) - r0; 100 GLfixed g0 = ChanToFixed(vert0->color[1]); 101 GLfixed dg = ChanToFixed(vert1->color[1]) - g0; 102 GLfixed b0 = ChanToFixed(vert0->color[2]); 103 GLfixed db = ChanToFixed(vert1->color[2]) - b0; 104#endif 105#ifdef INTERP_SPEC 106 GLfixed sr0 = ChanToFixed(vert0->specular[0]); 107 GLfixed dsr = ChanToFixed(vert1->specular[0]) - sr0; 108 GLfixed sg0 = ChanToFixed(vert0->specular[1]); 109 GLfixed dsg = ChanToFixed(vert1->specular[1]) - sg0; 110 GLfixed sb0 = ChanToFixed(vert0->specular[2]); 111 GLfixed dsb = ChanToFixed(vert1->specular[2]) - sb0; 112#endif 113#ifdef INTERP_ALPHA 114 GLfixed a0 = ChanToFixed(vert0->color[3]); 115 GLfixed da = ChanToFixed(vert1->color[3]) - a0; 116#endif 117#ifdef INTERP_INDEX 118 GLint i0 = vert0->index << 8; 119 GLint di = (GLint) (vert1->index << 8) - i0; 120#endif 121#ifdef INTERP_TEX 122 const GLfloat invw0 = vert0->win[3]; 123 const GLfloat invw1 = vert1->win[3]; 124 GLfloat tex[4]; 125 GLfloat dtex[4]; 126 GLfloat fragTexcoord[4]; 127#endif 128#ifdef INTERP_MULTITEX 129 const GLfloat invw0 = vert0->win[3]; 130 const GLfloat invw1 = vert1->win[3]; 131 GLfloat tex[MAX_TEXTURE_UNITS][4]; 132 GLfloat dtex[MAX_TEXTURE_UNITS][4]; 133 GLfloat fragTexcoord[MAX_TEXTURE_UNITS][4]; 134#endif 135#ifdef PIXEL_ADDRESS 136 PIXEL_TYPE *pixelPtr; 137 GLint pixelXstep, pixelYstep; 138#endif 139#ifdef INTERP_TEX 140 { 141 tex[0] = invw0 * vert0->texcoord[0][0]; 142 dtex[0] = invw1 * vert1->texcoord[0][0] - tex[0]; 143 tex[1] = invw0 * vert0->texcoord[0][1]; 144 dtex[1] = invw1 * vert1->texcoord[0][1] - tex[1]; 145 tex[2] = invw0 * vert0->texcoord[0][2]; 146 dtex[2] = invw1 * vert1->texcoord[0][2] - tex[2]; 147 tex[3] = invw0 * vert0->texcoord[0][3]; 148 dtex[3] = invw1 * vert1->texcoord[0][3] - tex[3]; 149 } 150#endif 151#ifdef INTERP_MULTITEX 152 { 153 GLuint u; 154 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { 155 if (ctx->Texture.Unit[u]._ReallyEnabled) { 156 tex[u][0] = invw0 * vert0->texcoord[u][0]; 157 dtex[u][0] = invw1 * vert1->texcoord[u][0] - tex[u][0]; 158 tex[u][1] = invw0 * vert0->texcoord[u][1]; 159 dtex[u][1] = invw1 * vert1->texcoord[u][1] - tex[u][1]; 160 tex[u][2] = invw0 * vert0->texcoord[u][2]; 161 dtex[u][2] = invw1 * vert1->texcoord[u][2] - tex[u][2]; 162 tex[u][3] = invw0 * vert0->texcoord[u][3]; 163 dtex[u][3] = invw1 * vert1->texcoord[u][3] - tex[u][3]; 164 } 165 } 166 } 167#endif 168 169 /* Cull primitives with malformed coordinates. 170 */ 171 { 172 float tmp = vert0->win[0] + vert0->win[1] + vert1->win[0] + vert1->win[1]; 173 if (IS_INF_OR_NAN(tmp)) 174 return; 175 } 176 177 /* 178 printf("%s():\n", __FUNCTION__); 179 printf(" (%f, %f, %f) -> (%f, %f, %f)\n", 180 vert0->win[0], vert0->win[1], vert0->win[2], 181 vert1->win[0], vert1->win[1], vert1->win[2]); 182 printf(" (%d, %d, %d) -> (%d, %d, %d)\n", 183 vert0->color[0], vert0->color[1], vert0->color[2], 184 vert1->color[0], vert1->color[1], vert1->color[2]); 185 printf(" (%d, %d, %d) -> (%d, %d, %d)\n", 186 vert0->specular[0], vert0->specular[1], vert0->specular[2], 187 vert1->specular[0], vert1->specular[1], vert1->specular[2]); 188 */ 189 190/* 191 * Despite being clipped to the view volume, the line's window coordinates 192 * may just lie outside the window bounds. That is, if the legal window 193 * coordinates are [0,W-1][0,H-1], it's possible for x==W and/or y==H. 194 * This quick and dirty code nudges the endpoints inside the window if 195 * necessary. 196 */ 197#ifdef CLIP_HACK 198 { 199 GLint w = ctx->DrawBuffer->Width; 200 GLint h = ctx->DrawBuffer->Height; 201 if ((x0==w) | (x1==w)) { 202 if ((x0==w) & (x1==w)) 203 return; 204 x0 -= x0==w; 205 x1 -= x1==w; 206 } 207 if ((y0==h) | (y1==h)) { 208 if ((y0==h) & (y1==h)) 209 return; 210 y0 -= y0==h; 211 y1 -= y1==h; 212 } 213 } 214#endif 215 dx = x1 - x0; 216 dy = y1 - y0; 217 if (dx==0 && dy==0) { 218 return; 219 } 220 221 /* 222 * Setup 223 */ 224#ifdef SETUP_CODE 225 SETUP_CODE 226#endif 227 228#ifdef INTERP_Z 229# ifdef DEPTH_TYPE 230 zPtr = (DEPTH_TYPE *) _mesa_zbuffer_address(ctx, x0, y0); 231# endif 232 if (depthBits <= 16) { 233 z0 = FloatToFixed(vert0->win[2]) + FIXED_HALF; 234 z1 = FloatToFixed(vert1->win[2]) + FIXED_HALF; 235 } 236 else { 237 z0 = (int) vert0->win[2]; 238 z1 = (int) vert1->win[2]; 239 } 240#endif 241#ifdef PIXEL_ADDRESS 242 pixelPtr = (PIXEL_TYPE *) PIXEL_ADDRESS(x0,y0); 243#endif 244 245 if (dx<0) { 246 dx = -dx; /* make positive */ 247#ifdef INTERP_XY 248 xstep = -1; 249#endif 250#if defined(INTERP_Z) && defined(DEPTH_TYPE) 251 zPtrXstep = -((GLint)sizeof(DEPTH_TYPE)); 252#endif 253#ifdef PIXEL_ADDRESS 254 pixelXstep = -((GLint)sizeof(PIXEL_TYPE)); 255#endif 256 } 257 else { 258#ifdef INTERP_XY 259 xstep = 1; 260#endif 261#if defined(INTERP_Z) && defined(DEPTH_TYPE) 262 zPtrXstep = ((GLint)sizeof(DEPTH_TYPE)); 263#endif 264#ifdef PIXEL_ADDRESS 265 pixelXstep = ((GLint)sizeof(PIXEL_TYPE)); 266#endif 267 } 268 269 if (dy<0) { 270 dy = -dy; /* make positive */ 271#ifdef INTERP_XY 272 ystep = -1; 273#endif 274#if defined(INTERP_Z) && defined(DEPTH_TYPE) 275 zPtrYstep = -((GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE))); 276#endif 277#ifdef PIXEL_ADDRESS 278 pixelYstep = BYTES_PER_ROW; 279#endif 280 } 281 else { 282#ifdef INTERP_XY 283 ystep = 1; 284#endif 285#if defined(INTERP_Z) && defined(DEPTH_TYPE) 286 zPtrYstep = (GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE)); 287#endif 288#ifdef PIXEL_ADDRESS 289 pixelYstep = -(BYTES_PER_ROW); 290#endif 291 } 292 293 /* 294 * Draw 295 */ 296 297 if (dx>dy) { 298 /*** X-major line ***/ 299 GLint i; 300 GLint errorInc = dy+dy; 301 GLint error = errorInc-dx; 302 GLint errorDec = error-dx; 303#ifdef SET_XMAJOR 304 xMajor = GL_TRUE; 305#endif 306#ifdef INTERP_Z 307 dz = (z1-z0) / dx; 308#endif 309#ifdef INTERP_FOG 310 dfog /= dx; 311#endif 312#ifdef INTERP_RGB 313 dr /= dx; /* convert from whole line delta to per-pixel delta */ 314 dg /= dx; 315 db /= dx; 316#endif 317#ifdef INTERP_SPEC 318 dsr /= dx; /* convert from whole line delta to per-pixel delta */ 319 dsg /= dx; 320 dsb /= dx; 321#endif 322#ifdef INTERP_ALPHA 323 da /= dx; 324#endif 325#ifdef INTERP_INDEX 326 di /= dx; 327#endif 328#ifdef INTERP_TEX 329 { 330 const GLfloat invDx = 1.0F / (GLfloat) dx; 331 dtex[0] *= invDx; 332 dtex[1] *= invDx; 333 dtex[2] *= invDx; 334 dtex[3] *= invDx; 335 } 336#endif 337#ifdef INTERP_MULTITEX 338 { 339 const GLfloat invDx = 1.0F / (GLfloat) dx; 340 GLuint u; 341 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { 342 if (ctx->Texture.Unit[u]._ReallyEnabled) { 343 dtex[u][0] *= invDx; 344 dtex[u][1] *= invDx; 345 dtex[u][2] *= invDx; 346 dtex[u][3] *= invDx; 347 } 348 } 349 } 350#endif 351 352 for (i=0;i<dx;i++) { 353#ifdef INTERP_Z 354 GLdepth Z = FixedToDepth(z0); 355#endif 356#ifdef INTERP_INDEX 357 GLint I = i0 >> 8; 358#endif 359#ifdef INTERP_TEX 360 { 361 const GLfloat invQ = tex[3] ? (1.0F / tex[3]) : 1.0F; 362 fragTexcoord[0] = tex[0] * invQ; 363 fragTexcoord[1] = tex[1] * invQ; 364 fragTexcoord[2] = tex[2] * invQ; 365 fragTexcoord[3] = tex[3]; 366 } 367#endif 368#ifdef INTERP_MULTITEX 369 { 370 GLuint u; 371 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { 372 if (ctx->Texture.Unit[u]._ReallyEnabled) { 373 const GLfloat invQ = 1.0F / tex[u][3]; 374 fragTexcoord[u][0] = tex[u][0] * invQ; 375 fragTexcoord[u][1] = tex[u][1] * invQ; 376 fragTexcoord[u][2] = tex[u][2] * invQ; 377 fragTexcoord[u][3] = tex[u][3]; 378 } 379 } 380 } 381#endif 382 383 PLOT( x0, y0 ); 384 385#ifdef INTERP_XY 386 x0 += xstep; 387#endif 388#ifdef INTERP_Z 389# ifdef DEPTH_TYPE 390 zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep); 391# endif 392 z0 += dz; 393#endif 394#ifdef INTERP_FOG 395 fog0 += dfog; 396#endif 397#ifdef INTERP_RGB 398 r0 += dr; 399 g0 += dg; 400 b0 += db; 401#endif 402#ifdef INTERP_SPEC 403 sr0 += dsr; 404 sg0 += dsg; 405 sb0 += dsb; 406#endif 407#ifdef INTERP_ALPHA 408 a0 += da; 409#endif 410#ifdef INTERP_INDEX 411 i0 += di; 412#endif 413#ifdef INTERP_TEX 414 tex[0] += dtex[0]; 415 tex[1] += dtex[1]; 416 tex[2] += dtex[2]; 417 tex[3] += dtex[3]; 418#endif 419#ifdef INTERP_MULTITEX 420 { 421 GLuint u; 422 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { 423 if (ctx->Texture.Unit[u]._ReallyEnabled) { 424 tex[u][0] += dtex[u][0]; 425 tex[u][1] += dtex[u][1]; 426 tex[u][2] += dtex[u][2]; 427 tex[u][3] += dtex[u][3]; 428 } 429 } 430 } 431#endif 432 433#ifdef PIXEL_ADDRESS 434 pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep); 435#endif 436 if (error<0) { 437 error += errorInc; 438 } 439 else { 440 error += errorDec; 441#ifdef INTERP_XY 442 y0 += ystep; 443#endif 444#if defined(INTERP_Z) && defined(DEPTH_TYPE) 445 zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep); 446#endif 447#ifdef PIXEL_ADDRESS 448 pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep); 449#endif 450 } 451 } 452 } 453 else { 454 /*** Y-major line ***/ 455 GLint i; 456 GLint errorInc = dx+dx; 457 GLint error = errorInc-dy; 458 GLint errorDec = error-dy; 459#ifdef INTERP_Z 460 dz = (z1-z0) / dy; 461#endif 462#ifdef INTERP_FOG 463 dfog /= dy; 464#endif 465#ifdef INTERP_RGB 466 dr /= dy; /* convert from whole line delta to per-pixel delta */ 467 dg /= dy; 468 db /= dy; 469#endif 470#ifdef INTERP_SPEC 471 dsr /= dy; /* convert from whole line delta to per-pixel delta */ 472 dsg /= dy; 473 dsb /= dy; 474#endif 475#ifdef INTERP_ALPHA 476 da /= dy; 477#endif 478#ifdef INTERP_INDEX 479 di /= dy; 480#endif 481#ifdef INTERP_TEX 482 { 483 const GLfloat invDy = 1.0F / (GLfloat) dy; 484 dtex[0] *= invDy; 485 dtex[1] *= invDy; 486 dtex[2] *= invDy; 487 dtex[3] *= invDy; 488 } 489#endif 490#ifdef INTERP_MULTITEX 491 { 492 const GLfloat invDy = 1.0F / (GLfloat) dy; 493 GLuint u; 494 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { 495 if (ctx->Texture.Unit[u]._ReallyEnabled) { 496 dtex[u][0] *= invDy; 497 dtex[u][1] *= invDy; 498 dtex[u][2] *= invDy; 499 dtex[u][3] *= invDy; 500 } 501 } 502 } 503#endif 504 505 for (i=0;i<dy;i++) { 506#ifdef INTERP_Z 507 GLdepth Z = FixedToDepth(z0); 508#endif 509#ifdef INTERP_INDEX 510 GLint I = i0 >> 8; 511#endif 512#ifdef INTERP_TEX 513 { 514 const GLfloat invQ = tex[3] ? (1.0F / tex[3]) : 1.0F; 515 fragTexcoord[0] = tex[0] * invQ; 516 fragTexcoord[1] = tex[1] * invQ; 517 fragTexcoord[2] = tex[2] * invQ; 518 fragTexcoord[3] = tex[3]; 519 } 520#endif 521#ifdef INTERP_MULTITEX 522 { 523 GLuint u; 524 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { 525 if (ctx->Texture.Unit[u]._ReallyEnabled) { 526 const GLfloat invQ = 1.0F / tex[u][3]; 527 fragTexcoord[u][0] = tex[u][0] * invQ; 528 fragTexcoord[u][1] = tex[u][1] * invQ; 529 fragTexcoord[u][2] = tex[u][2] * invQ; 530 fragTexcoord[u][3] = tex[u][3]; 531 } 532 } 533 } 534#endif 535 536 PLOT( x0, y0 ); 537 538#ifdef INTERP_XY 539 y0 += ystep; 540#endif 541#ifdef INTERP_Z 542# ifdef DEPTH_TYPE 543 zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep); 544# endif 545 z0 += dz; 546#endif 547#ifdef INTERP_FOG 548 fog0 += dfog; 549#endif 550#ifdef INTERP_RGB 551 r0 += dr; 552 g0 += dg; 553 b0 += db; 554#endif 555#ifdef INTERP_SPEC 556 sr0 += dsr; 557 sg0 += dsg; 558 sb0 += dsb; 559#endif 560#ifdef INTERP_ALPHA 561 a0 += da; 562#endif 563#ifdef INTERP_INDEX 564 i0 += di; 565#endif 566#ifdef INTERP_TEX 567 tex[0] += dtex[0]; 568 tex[1] += dtex[1]; 569 tex[2] += dtex[2]; 570 tex[3] += dtex[3]; 571#endif 572#ifdef INTERP_MULTITEX 573 { 574 GLuint u; 575 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { 576 if (ctx->Texture.Unit[u]._ReallyEnabled) { 577 tex[u][0] += dtex[u][0]; 578 tex[u][1] += dtex[u][1]; 579 tex[u][2] += dtex[u][2]; 580 tex[u][3] += dtex[u][3]; 581 } 582 } 583 } 584#endif 585#ifdef PIXEL_ADDRESS 586 pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep); 587#endif 588 if (error<0) { 589 error += errorInc; 590 } 591 else { 592 error += errorDec; 593#ifdef INTERP_XY 594 x0 += xstep; 595#endif 596#if defined(INTERP_Z) && defined(DEPTH_TYPE) 597 zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep); 598#endif 599#ifdef PIXEL_ADDRESS 600 pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep); 601#endif 602 } 603 } 604 } 605 606} 607 608 609#undef INTERP_XY 610#undef INTERP_Z 611#undef INTERP_FOG 612#undef INTERP_RGB 613#undef INTERP_SPEC 614#undef INTERP_ALPHA 615#undef INTERP_TEX 616#undef INTERP_MULTITEX 617#undef INTERP_INDEX 618#undef PIXEL_ADDRESS 619#undef PIXEL_TYPE 620#undef DEPTH_TYPE 621#undef BYTES_PER_ROW 622#undef SETUP_CODE 623#undef PLOT 624#undef CLIP_HACK 625#undef FixedToDepth 626#undef SET_XMAJOR 627