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