1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the "Software"), 8848b8605Smrg * to deal in the Software without restriction, including without limitation 9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 11848b8605Smrg * Software is furnished to do so, subject to the following conditions: 12848b8605Smrg * 13848b8605Smrg * The above copyright notice and this permission notice shall be included 14848b8605Smrg * in all copies or substantial portions of the Software. 15848b8605Smrg * 16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 23848b8605Smrg */ 24848b8605Smrg 25848b8605Smrg 26848b8605Smrg/* 27848b8605Smrg * Line Rasterizer Template 28848b8605Smrg * 29848b8605Smrg * This file is #include'd to generate custom line rasterizers. 30848b8605Smrg * 31848b8605Smrg * The following macros may be defined to indicate what auxillary information 32848b8605Smrg * must be interplated along the line: 33848b8605Smrg * INTERP_Z - if defined, interpolate Z values 34848b8605Smrg * INTERP_ATTRIBS - if defined, interpolate attribs (texcoords, varying, etc) 35848b8605Smrg * 36848b8605Smrg * When one can directly address pixels in the color buffer the following 37848b8605Smrg * macros can be defined and used to directly compute pixel addresses during 38848b8605Smrg * rasterization (see pixelPtr): 39848b8605Smrg * PIXEL_TYPE - the datatype of a pixel (GLubyte, GLushort, GLuint) 40848b8605Smrg * BYTES_PER_ROW - number of bytes per row in the color buffer 41848b8605Smrg * PIXEL_ADDRESS(X,Y) - returns the address of pixel at (X,Y) where 42848b8605Smrg * Y==0 at bottom of screen and increases upward. 43848b8605Smrg * 44848b8605Smrg * Similarly, for direct depth buffer access, this type is used for depth 45848b8605Smrg * buffer addressing: 46848b8605Smrg * DEPTH_TYPE - either GLushort or GLuint 47848b8605Smrg * 48848b8605Smrg * Optionally, one may provide one-time setup code 49848b8605Smrg * SETUP_CODE - code which is to be executed once per line 50848b8605Smrg * 51848b8605Smrg * To actually "plot" each pixel the PLOT macro must be defined... 52848b8605Smrg * PLOT(X,Y) - code to plot a pixel. Example: 53848b8605Smrg * if (Z < *zPtr) { 54848b8605Smrg * *zPtr = Z; 55848b8605Smrg * color = pack_rgb( FixedToInt(r0), FixedToInt(g0), 56848b8605Smrg * FixedToInt(b0) ); 57848b8605Smrg * put_pixel( X, Y, color ); 58848b8605Smrg * } 59848b8605Smrg * 60848b8605Smrg * This code was designed for the origin to be in the lower-left corner. 61848b8605Smrg * 62848b8605Smrg */ 63848b8605Smrg 64848b8605Smrg 65848b8605Smrgstatic void 66848b8605SmrgNAME( struct gl_context *ctx, const SWvertex *vert0, const SWvertex *vert1 ) 67848b8605Smrg{ 68848b8605Smrg const SWcontext *swrast = SWRAST_CONTEXT(ctx); 69848b8605Smrg SWspan span; 70848b8605Smrg GLuint interpFlags = 0; 71848b8605Smrg GLint x0 = (GLint) vert0->attrib[VARYING_SLOT_POS][0]; 72848b8605Smrg GLint x1 = (GLint) vert1->attrib[VARYING_SLOT_POS][0]; 73848b8605Smrg GLint y0 = (GLint) vert0->attrib[VARYING_SLOT_POS][1]; 74848b8605Smrg GLint y1 = (GLint) vert1->attrib[VARYING_SLOT_POS][1]; 75848b8605Smrg GLint dx, dy; 76848b8605Smrg GLint numPixels; 77848b8605Smrg GLint xstep, ystep; 78848b8605Smrg#if defined(DEPTH_TYPE) 79848b8605Smrg const GLint depthBits = ctx->DrawBuffer->Visual.depthBits; 80848b8605Smrg const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0; 81848b8605Smrg struct gl_renderbuffer *zrb = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; 82848b8605Smrg#define FixedToDepth(F) ((F) >> fixedToDepthShift) 83848b8605Smrg GLint zPtrXstep, zPtrYstep; 84848b8605Smrg DEPTH_TYPE *zPtr; 85848b8605Smrg#elif defined(INTERP_Z) 86848b8605Smrg const GLint depthBits = ctx->DrawBuffer->Visual.depthBits; 87848b8605Smrg#endif 88848b8605Smrg#ifdef PIXEL_ADDRESS 89848b8605Smrg PIXEL_TYPE *pixelPtr; 90848b8605Smrg GLint pixelXstep, pixelYstep; 91848b8605Smrg#endif 92848b8605Smrg 93848b8605Smrg#ifdef SETUP_CODE 94848b8605Smrg SETUP_CODE 95848b8605Smrg#endif 96848b8605Smrg 97848b8605Smrg (void) swrast; 98848b8605Smrg 99848b8605Smrg /* Cull primitives with malformed coordinates. 100848b8605Smrg */ 101848b8605Smrg { 102848b8605Smrg GLfloat tmp = vert0->attrib[VARYING_SLOT_POS][0] + vert0->attrib[VARYING_SLOT_POS][1] 103848b8605Smrg + vert1->attrib[VARYING_SLOT_POS][0] + vert1->attrib[VARYING_SLOT_POS][1]; 104848b8605Smrg if (IS_INF_OR_NAN(tmp)) 105848b8605Smrg return; 106848b8605Smrg } 107848b8605Smrg 108848b8605Smrg /* 109b8e80941Smrg printf("%s():\n", __func__); 110848b8605Smrg printf(" (%f, %f, %f) -> (%f, %f, %f)\n", 111848b8605Smrg vert0->attrib[VARYING_SLOT_POS][0], 112848b8605Smrg vert0->attrib[VARYING_SLOT_POS][1], 113848b8605Smrg vert0->attrib[VARYING_SLOT_POS][2], 114848b8605Smrg vert1->attrib[VARYING_SLOT_POS][0], 115848b8605Smrg vert1->attrib[VARYING_SLOT_POS][1], 116848b8605Smrg vert1->attrib[VARYING_SLOT_POS][2]); 117848b8605Smrg printf(" (%d, %d, %d) -> (%d, %d, %d)\n", 118848b8605Smrg vert0->color[0], vert0->color[1], vert0->color[2], 119848b8605Smrg vert1->color[0], vert1->color[1], vert1->color[2]); 120848b8605Smrg printf(" (%d, %d, %d) -> (%d, %d, %d)\n", 121848b8605Smrg vert0->specular[0], vert0->specular[1], vert0->specular[2], 122848b8605Smrg vert1->specular[0], vert1->specular[1], vert1->specular[2]); 123848b8605Smrg */ 124848b8605Smrg 125848b8605Smrg/* 126848b8605Smrg * Despite being clipped to the view volume, the line's window coordinates 127848b8605Smrg * may just lie outside the window bounds. That is, if the legal window 128848b8605Smrg * coordinates are [0,W-1][0,H-1], it's possible for x==W and/or y==H. 129848b8605Smrg * This quick and dirty code nudges the endpoints inside the window if 130848b8605Smrg * necessary. 131848b8605Smrg */ 132848b8605Smrg#ifdef CLIP_HACK 133848b8605Smrg { 134848b8605Smrg GLint w = ctx->DrawBuffer->Width; 135848b8605Smrg GLint h = ctx->DrawBuffer->Height; 136848b8605Smrg if ((x0==w) | (x1==w)) { 137848b8605Smrg if ((x0==w) & (x1==w)) 138848b8605Smrg return; 139848b8605Smrg x0 -= x0==w; 140848b8605Smrg x1 -= x1==w; 141848b8605Smrg } 142848b8605Smrg if ((y0==h) | (y1==h)) { 143848b8605Smrg if ((y0==h) & (y1==h)) 144848b8605Smrg return; 145848b8605Smrg y0 -= y0==h; 146848b8605Smrg y1 -= y1==h; 147848b8605Smrg } 148848b8605Smrg } 149848b8605Smrg#endif 150848b8605Smrg 151848b8605Smrg dx = x1 - x0; 152848b8605Smrg dy = y1 - y0; 153848b8605Smrg if (dx == 0 && dy == 0) 154848b8605Smrg return; 155848b8605Smrg 156848b8605Smrg /* 157b8e80941Smrg printf("%s %d,%d %g %g %g %g %g %g %g %g\n", __func__, dx, dy, 158848b8605Smrg vert0->attrib[VARYING_SLOT_COL1][0], 159848b8605Smrg vert0->attrib[VARYING_SLOT_COL1][1], 160848b8605Smrg vert0->attrib[VARYING_SLOT_COL1][2], 161848b8605Smrg vert0->attrib[VARYING_SLOT_COL1][3], 162848b8605Smrg vert1->attrib[VARYING_SLOT_COL1][0], 163848b8605Smrg vert1->attrib[VARYING_SLOT_COL1][1], 164848b8605Smrg vert1->attrib[VARYING_SLOT_COL1][2], 165848b8605Smrg vert1->attrib[VARYING_SLOT_COL1][3]); 166848b8605Smrg */ 167848b8605Smrg 168848b8605Smrg#ifdef DEPTH_TYPE 169848b8605Smrg zPtr = (DEPTH_TYPE *) _swrast_pixel_address(zrb, x0, y0); 170848b8605Smrg#endif 171848b8605Smrg#ifdef PIXEL_ADDRESS 172848b8605Smrg pixelPtr = (PIXEL_TYPE *) PIXEL_ADDRESS(x0,y0); 173848b8605Smrg#endif 174848b8605Smrg 175848b8605Smrg if (dx<0) { 176848b8605Smrg dx = -dx; /* make positive */ 177848b8605Smrg xstep = -1; 178848b8605Smrg#ifdef DEPTH_TYPE 179848b8605Smrg zPtrXstep = -((GLint)sizeof(DEPTH_TYPE)); 180848b8605Smrg#endif 181848b8605Smrg#ifdef PIXEL_ADDRESS 182848b8605Smrg pixelXstep = -((GLint)sizeof(PIXEL_TYPE)); 183848b8605Smrg#endif 184848b8605Smrg } 185848b8605Smrg else { 186848b8605Smrg xstep = 1; 187848b8605Smrg#ifdef DEPTH_TYPE 188848b8605Smrg zPtrXstep = ((GLint)sizeof(DEPTH_TYPE)); 189848b8605Smrg#endif 190848b8605Smrg#ifdef PIXEL_ADDRESS 191848b8605Smrg pixelXstep = ((GLint)sizeof(PIXEL_TYPE)); 192848b8605Smrg#endif 193848b8605Smrg } 194848b8605Smrg 195848b8605Smrg if (dy<0) { 196848b8605Smrg dy = -dy; /* make positive */ 197848b8605Smrg ystep = -1; 198848b8605Smrg#ifdef DEPTH_TYPE 199848b8605Smrg zPtrYstep = -((GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE))); 200848b8605Smrg#endif 201848b8605Smrg#ifdef PIXEL_ADDRESS 202848b8605Smrg pixelYstep = BYTES_PER_ROW; 203848b8605Smrg#endif 204848b8605Smrg } 205848b8605Smrg else { 206848b8605Smrg ystep = 1; 207848b8605Smrg#ifdef DEPTH_TYPE 208848b8605Smrg zPtrYstep = (GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE)); 209848b8605Smrg#endif 210848b8605Smrg#ifdef PIXEL_ADDRESS 211848b8605Smrg pixelYstep = -(BYTES_PER_ROW); 212848b8605Smrg#endif 213848b8605Smrg } 214848b8605Smrg 215b8e80941Smrg assert(dx >= 0); 216b8e80941Smrg assert(dy >= 0); 217848b8605Smrg 218848b8605Smrg numPixels = MAX2(dx, dy); 219848b8605Smrg 220848b8605Smrg /* 221848b8605Smrg * Span setup: compute start and step values for all interpolated values. 222848b8605Smrg */ 223848b8605Smrg interpFlags |= SPAN_RGBA; 224848b8605Smrg if (ctx->Light.ShadeModel == GL_SMOOTH) { 225848b8605Smrg span.red = ChanToFixed(vert0->color[0]); 226848b8605Smrg span.green = ChanToFixed(vert0->color[1]); 227848b8605Smrg span.blue = ChanToFixed(vert0->color[2]); 228848b8605Smrg span.alpha = ChanToFixed(vert0->color[3]); 229848b8605Smrg span.redStep = (ChanToFixed(vert1->color[0]) - span.red ) / numPixels; 230848b8605Smrg span.greenStep = (ChanToFixed(vert1->color[1]) - span.green) / numPixels; 231848b8605Smrg span.blueStep = (ChanToFixed(vert1->color[2]) - span.blue ) / numPixels; 232848b8605Smrg span.alphaStep = (ChanToFixed(vert1->color[3]) - span.alpha) / numPixels; 233848b8605Smrg } 234848b8605Smrg else { 235848b8605Smrg span.red = ChanToFixed(vert1->color[0]); 236848b8605Smrg span.green = ChanToFixed(vert1->color[1]); 237848b8605Smrg span.blue = ChanToFixed(vert1->color[2]); 238848b8605Smrg span.alpha = ChanToFixed(vert1->color[3]); 239848b8605Smrg span.redStep = 0; 240848b8605Smrg span.greenStep = 0; 241848b8605Smrg span.blueStep = 0; 242848b8605Smrg span.alphaStep = 0; 243848b8605Smrg } 244848b8605Smrg#if defined(INTERP_Z) || defined(DEPTH_TYPE) 245848b8605Smrg interpFlags |= SPAN_Z; 246848b8605Smrg { 247848b8605Smrg if (depthBits <= 16) { 248848b8605Smrg span.z = FloatToFixed(vert0->attrib[VARYING_SLOT_POS][2]) + FIXED_HALF; 249848b8605Smrg span.zStep = FloatToFixed( vert1->attrib[VARYING_SLOT_POS][2] 250848b8605Smrg - vert0->attrib[VARYING_SLOT_POS][2]) / numPixels; 251848b8605Smrg } 252848b8605Smrg else { 253848b8605Smrg /* don't use fixed point */ 254848b8605Smrg span.z = (GLuint) vert0->attrib[VARYING_SLOT_POS][2]; 255848b8605Smrg span.zStep = (GLint) (( vert1->attrib[VARYING_SLOT_POS][2] 256848b8605Smrg - vert0->attrib[VARYING_SLOT_POS][2]) / numPixels); 257848b8605Smrg } 258848b8605Smrg } 259848b8605Smrg#endif 260848b8605Smrg#if defined(INTERP_ATTRIBS) 261848b8605Smrg { 262848b8605Smrg const GLfloat invLen = 1.0F / numPixels; 263848b8605Smrg const GLfloat invw0 = vert0->attrib[VARYING_SLOT_POS][3]; 264848b8605Smrg const GLfloat invw1 = vert1->attrib[VARYING_SLOT_POS][3]; 265848b8605Smrg 266848b8605Smrg span.attrStart[VARYING_SLOT_POS][3] = invw0; 267848b8605Smrg span.attrStepX[VARYING_SLOT_POS][3] = (invw1 - invw0) * invLen; 268848b8605Smrg span.attrStepY[VARYING_SLOT_POS][3] = 0.0; 269848b8605Smrg 270848b8605Smrg ATTRIB_LOOP_BEGIN 271848b8605Smrg if (swrast->_InterpMode[attr] == GL_FLAT) { 272848b8605Smrg COPY_4V(span.attrStart[attr], vert1->attrib[attr]); 273848b8605Smrg ASSIGN_4V(span.attrStepX[attr], 0.0, 0.0, 0.0, 0.0); 274848b8605Smrg } 275848b8605Smrg else { 276848b8605Smrg GLuint c; 277848b8605Smrg for (c = 0; c < 4; c++) { 278848b8605Smrg float da; 279848b8605Smrg span.attrStart[attr][c] = invw0 * vert0->attrib[attr][c]; 280848b8605Smrg da = (invw1 * vert1->attrib[attr][c]) - span.attrStart[attr][c]; 281848b8605Smrg span.attrStepX[attr][c] = da * invLen; 282848b8605Smrg } 283848b8605Smrg } 284848b8605Smrg ASSIGN_4V(span.attrStepY[attr], 0.0, 0.0, 0.0, 0.0); 285848b8605Smrg ATTRIB_LOOP_END 286848b8605Smrg } 287848b8605Smrg#endif 288848b8605Smrg 289848b8605Smrg INIT_SPAN(span, GL_LINE); 290848b8605Smrg span.end = numPixels; 291848b8605Smrg span.interpMask = interpFlags; 292848b8605Smrg span.arrayMask = SPAN_XY; 293848b8605Smrg 294848b8605Smrg span.facing = swrast->PointLineFacing; 295848b8605Smrg 296848b8605Smrg 297848b8605Smrg /* 298848b8605Smrg * Draw 299848b8605Smrg */ 300848b8605Smrg 301848b8605Smrg if (dx > dy) { 302848b8605Smrg /*** X-major line ***/ 303848b8605Smrg GLint i; 304848b8605Smrg GLint errorInc = dy+dy; 305848b8605Smrg GLint error = errorInc-dx; 306848b8605Smrg GLint errorDec = error-dx; 307848b8605Smrg 308848b8605Smrg for (i = 0; i < dx; i++) { 309848b8605Smrg#ifdef DEPTH_TYPE 310848b8605Smrg GLuint Z = FixedToDepth(span.z); 311848b8605Smrg#endif 312848b8605Smrg#ifdef PLOT 313848b8605Smrg PLOT( x0, y0 ); 314848b8605Smrg#else 315848b8605Smrg span.array->x[i] = x0; 316848b8605Smrg span.array->y[i] = y0; 317848b8605Smrg#endif 318848b8605Smrg x0 += xstep; 319848b8605Smrg#ifdef DEPTH_TYPE 320848b8605Smrg zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep); 321848b8605Smrg span.z += span.zStep; 322848b8605Smrg#endif 323848b8605Smrg#ifdef PIXEL_ADDRESS 324848b8605Smrg pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep); 325848b8605Smrg#endif 326848b8605Smrg if (error < 0) { 327848b8605Smrg error += errorInc; 328848b8605Smrg } 329848b8605Smrg else { 330848b8605Smrg error += errorDec; 331848b8605Smrg y0 += ystep; 332848b8605Smrg#ifdef DEPTH_TYPE 333848b8605Smrg zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep); 334848b8605Smrg#endif 335848b8605Smrg#ifdef PIXEL_ADDRESS 336848b8605Smrg pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep); 337848b8605Smrg#endif 338848b8605Smrg } 339848b8605Smrg } 340848b8605Smrg } 341848b8605Smrg else { 342848b8605Smrg /*** Y-major line ***/ 343848b8605Smrg GLint i; 344848b8605Smrg GLint errorInc = dx+dx; 345848b8605Smrg GLint error = errorInc-dy; 346848b8605Smrg GLint errorDec = error-dy; 347848b8605Smrg 348848b8605Smrg for (i=0;i<dy;i++) { 349848b8605Smrg#ifdef DEPTH_TYPE 350848b8605Smrg GLuint Z = FixedToDepth(span.z); 351848b8605Smrg#endif 352848b8605Smrg#ifdef PLOT 353848b8605Smrg PLOT( x0, y0 ); 354848b8605Smrg#else 355848b8605Smrg span.array->x[i] = x0; 356848b8605Smrg span.array->y[i] = y0; 357848b8605Smrg#endif 358848b8605Smrg y0 += ystep; 359848b8605Smrg#ifdef DEPTH_TYPE 360848b8605Smrg zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep); 361848b8605Smrg span.z += span.zStep; 362848b8605Smrg#endif 363848b8605Smrg#ifdef PIXEL_ADDRESS 364848b8605Smrg pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep); 365848b8605Smrg#endif 366848b8605Smrg if (error<0) { 367848b8605Smrg error += errorInc; 368848b8605Smrg } 369848b8605Smrg else { 370848b8605Smrg error += errorDec; 371848b8605Smrg x0 += xstep; 372848b8605Smrg#ifdef DEPTH_TYPE 373848b8605Smrg zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep); 374848b8605Smrg#endif 375848b8605Smrg#ifdef PIXEL_ADDRESS 376848b8605Smrg pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep); 377848b8605Smrg#endif 378848b8605Smrg } 379848b8605Smrg } 380848b8605Smrg } 381848b8605Smrg 382848b8605Smrg#ifdef RENDER_SPAN 383848b8605Smrg RENDER_SPAN( span ); 384848b8605Smrg#endif 385848b8605Smrg 386848b8605Smrg (void)span; 387848b8605Smrg 388848b8605Smrg} 389848b8605Smrg 390848b8605Smrg 391848b8605Smrg#undef NAME 392848b8605Smrg#undef INTERP_Z 393848b8605Smrg#undef INTERP_ATTRIBS 394848b8605Smrg#undef PIXEL_ADDRESS 395848b8605Smrg#undef PIXEL_TYPE 396848b8605Smrg#undef DEPTH_TYPE 397848b8605Smrg#undef BYTES_PER_ROW 398848b8605Smrg#undef SETUP_CODE 399848b8605Smrg#undef PLOT 400848b8605Smrg#undef CLIP_HACK 401848b8605Smrg#undef FixedToDepth 402848b8605Smrg#undef RENDER_SPAN 403