Home | History | Annotate | Download | only in swrast
      1 /*
      2  * Mesa 3-D graphics library
      3  * Version:  7.0
      4  *
      5  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the "Software"),
      9  * to deal in the Software without restriction, including without limitation
     10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     11  * and/or sell copies of the Software, and to permit persons to whom the
     12  * Software is furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included
     15  * in all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     21  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     23  */
     24 
     25 
     26 /*
     27  * Line Rasterizer Template
     28  *
     29  * This file is #include'd to generate custom line rasterizers.
     30  *
     31  * The following macros may be defined to indicate what auxillary information
     32  * must be interplated along the line:
     33  *    INTERP_Z        - if defined, interpolate Z values
     34  *    INTERP_ATTRIBS  - if defined, interpolate attribs (texcoords, varying, etc)
     35  *
     36  * When one can directly address pixels in the color buffer the following
     37  * macros can be defined and used to directly compute pixel addresses during
     38  * rasterization (see pixelPtr):
     39  *    PIXEL_TYPE          - the datatype of a pixel (GLubyte, GLushort, GLuint)
     40  *    BYTES_PER_ROW       - number of bytes per row in the color buffer
     41  *    PIXEL_ADDRESS(X,Y)  - returns the address of pixel at (X,Y) where
     42  *                          Y==0 at bottom of screen and increases upward.
     43  *
     44  * Similarly, for direct depth buffer access, this type is used for depth
     45  * buffer addressing:
     46  *    DEPTH_TYPE          - either GLushort or GLuint
     47  *
     48  * Optionally, one may provide one-time setup code
     49  *    SETUP_CODE    - code which is to be executed once per line
     50  *
     51  * To actually "plot" each pixel the PLOT macro must be defined...
     52  *    PLOT(X,Y) - code to plot a pixel.  Example:
     53  *                if (Z < *zPtr) {
     54  *                   *zPtr = Z;
     55  *                   color = pack_rgb( FixedToInt(r0), FixedToInt(g0),
     56  *                                     FixedToInt(b0) );
     57  *                   put_pixel( X, Y, color );
     58  *                }
     59  *
     60  * This code was designed for the origin to be in the lower-left corner.
     61  *
     62  */
     63 
     64 
     65 static void
     66 NAME( struct gl_context *ctx, const SWvertex *vert0, const SWvertex *vert1 )
     67 {
     68    const SWcontext *swrast = SWRAST_CONTEXT(ctx);
     69    SWspan span;
     70    GLuint interpFlags = 0;
     71    GLint x0 = (GLint) vert0->attrib[FRAG_ATTRIB_WPOS][0];
     72    GLint x1 = (GLint) vert1->attrib[FRAG_ATTRIB_WPOS][0];
     73    GLint y0 = (GLint) vert0->attrib[FRAG_ATTRIB_WPOS][1];
     74    GLint y1 = (GLint) vert1->attrib[FRAG_ATTRIB_WPOS][1];
     75    GLint dx, dy;
     76    GLint numPixels;
     77    GLint xstep, ystep;
     78 #if defined(DEPTH_TYPE)
     79    const GLint depthBits = ctx->DrawBuffer->Visual.depthBits;
     80    const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0;
     81    struct gl_renderbuffer *zrb = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
     82 #define FixedToDepth(F)  ((F) >> fixedToDepthShift)
     83    GLint zPtrXstep, zPtrYstep;
     84    DEPTH_TYPE *zPtr;
     85 #elif defined(INTERP_Z)
     86    const GLint depthBits = ctx->DrawBuffer->Visual.depthBits;
     87 #endif
     88 #ifdef PIXEL_ADDRESS
     89    PIXEL_TYPE *pixelPtr;
     90    GLint pixelXstep, pixelYstep;
     91 #endif
     92 
     93 #ifdef SETUP_CODE
     94    SETUP_CODE
     95 #endif
     96 
     97    (void) swrast;
     98 
     99    /* Cull primitives with malformed coordinates.
    100     */
    101    {
    102       GLfloat tmp = vert0->attrib[FRAG_ATTRIB_WPOS][0] + vert0->attrib[FRAG_ATTRIB_WPOS][1]
    103                   + vert1->attrib[FRAG_ATTRIB_WPOS][0] + vert1->attrib[FRAG_ATTRIB_WPOS][1];
    104       if (IS_INF_OR_NAN(tmp))
    105 	 return;
    106    }
    107 
    108    /*
    109    printf("%s():\n", __FUNCTION__);
    110    printf(" (%f, %f, %f) -> (%f, %f, %f)\n",
    111           vert0->attrib[FRAG_ATTRIB_WPOS][0],
    112           vert0->attrib[FRAG_ATTRIB_WPOS][1],
    113           vert0->attrib[FRAG_ATTRIB_WPOS][2],
    114           vert1->attrib[FRAG_ATTRIB_WPOS][0],
    115           vert1->attrib[FRAG_ATTRIB_WPOS][1],
    116           vert1->attrib[FRAG_ATTRIB_WPOS][2]);
    117    printf(" (%d, %d, %d) -> (%d, %d, %d)\n",
    118           vert0->color[0], vert0->color[1], vert0->color[2],
    119           vert1->color[0], vert1->color[1], vert1->color[2]);
    120    printf(" (%d, %d, %d) -> (%d, %d, %d)\n",
    121           vert0->specular[0], vert0->specular[1], vert0->specular[2],
    122           vert1->specular[0], vert1->specular[1], vert1->specular[2]);
    123    */
    124 
    125 /*
    126  * Despite being clipped to the view volume, the line's window coordinates
    127  * may just lie outside the window bounds.  That is, if the legal window
    128  * coordinates are [0,W-1][0,H-1], it's possible for x==W and/or y==H.
    129  * This quick and dirty code nudges the endpoints inside the window if
    130  * necessary.
    131  */
    132 #ifdef CLIP_HACK
    133    {
    134       GLint w = ctx->DrawBuffer->Width;
    135       GLint h = ctx->DrawBuffer->Height;
    136       if ((x0==w) | (x1==w)) {
    137          if ((x0==w) & (x1==w))
    138            return;
    139          x0 -= x0==w;
    140          x1 -= x1==w;
    141       }
    142       if ((y0==h) | (y1==h)) {
    143          if ((y0==h) & (y1==h))
    144            return;
    145          y0 -= y0==h;
    146          y1 -= y1==h;
    147       }
    148    }
    149 #endif
    150 
    151    dx = x1 - x0;
    152    dy = y1 - y0;
    153    if (dx == 0 && dy == 0)
    154       return;
    155 
    156    /*
    157    printf("%s %d,%d  %g %g %g %g  %g %g %g %g\n", __FUNCTION__, dx, dy,
    158           vert0->attrib[FRAG_ATTRIB_COL1][0],
    159           vert0->attrib[FRAG_ATTRIB_COL1][1],
    160           vert0->attrib[FRAG_ATTRIB_COL1][2],
    161           vert0->attrib[FRAG_ATTRIB_COL1][3],
    162           vert1->attrib[FRAG_ATTRIB_COL1][0],
    163           vert1->attrib[FRAG_ATTRIB_COL1][1],
    164           vert1->attrib[FRAG_ATTRIB_COL1][2],
    165           vert1->attrib[FRAG_ATTRIB_COL1][3]);
    166    */
    167 
    168 #ifdef DEPTH_TYPE
    169    zPtr = (DEPTH_TYPE *) _swrast_pixel_address(zrb, x0, y0);
    170 #endif
    171 #ifdef PIXEL_ADDRESS
    172    pixelPtr = (PIXEL_TYPE *) PIXEL_ADDRESS(x0,y0);
    173 #endif
    174 
    175    if (dx<0) {
    176       dx = -dx;   /* make positive */
    177       xstep = -1;
    178 #ifdef DEPTH_TYPE
    179       zPtrXstep = -((GLint)sizeof(DEPTH_TYPE));
    180 #endif
    181 #ifdef PIXEL_ADDRESS
    182       pixelXstep = -((GLint)sizeof(PIXEL_TYPE));
    183 #endif
    184    }
    185    else {
    186       xstep = 1;
    187 #ifdef DEPTH_TYPE
    188       zPtrXstep = ((GLint)sizeof(DEPTH_TYPE));
    189 #endif
    190 #ifdef PIXEL_ADDRESS
    191       pixelXstep = ((GLint)sizeof(PIXEL_TYPE));
    192 #endif
    193    }
    194 
    195    if (dy<0) {
    196       dy = -dy;   /* make positive */
    197       ystep = -1;
    198 #ifdef DEPTH_TYPE
    199       zPtrYstep = -((GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE)));
    200 #endif
    201 #ifdef PIXEL_ADDRESS
    202       pixelYstep = BYTES_PER_ROW;
    203 #endif
    204    }
    205    else {
    206       ystep = 1;
    207 #ifdef DEPTH_TYPE
    208       zPtrYstep = (GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE));
    209 #endif
    210 #ifdef PIXEL_ADDRESS
    211       pixelYstep = -(BYTES_PER_ROW);
    212 #endif
    213    }
    214 
    215    ASSERT(dx >= 0);
    216    ASSERT(dy >= 0);
    217 
    218    numPixels = MAX2(dx, dy);
    219 
    220    /*
    221     * Span setup: compute start and step values for all interpolated values.
    222     */
    223    interpFlags |= SPAN_RGBA;
    224    if (ctx->Light.ShadeModel == GL_SMOOTH) {
    225       span.red   = ChanToFixed(vert0->color[0]);
    226       span.green = ChanToFixed(vert0->color[1]);
    227       span.blue  = ChanToFixed(vert0->color[2]);
    228       span.alpha = ChanToFixed(vert0->color[3]);
    229       span.redStep   = (ChanToFixed(vert1->color[0]) - span.red  ) / numPixels;
    230       span.greenStep = (ChanToFixed(vert1->color[1]) - span.green) / numPixels;
    231       span.blueStep  = (ChanToFixed(vert1->color[2]) - span.blue ) / numPixels;
    232       span.alphaStep = (ChanToFixed(vert1->color[3]) - span.alpha) / numPixels;
    233    }
    234    else {
    235       span.red   = ChanToFixed(vert1->color[0]);
    236       span.green = ChanToFixed(vert1->color[1]);
    237       span.blue  = ChanToFixed(vert1->color[2]);
    238       span.alpha = ChanToFixed(vert1->color[3]);
    239       span.redStep   = 0;
    240       span.greenStep = 0;
    241       span.blueStep  = 0;
    242       span.alphaStep = 0;
    243    }
    244 #if defined(INTERP_Z) || defined(DEPTH_TYPE)
    245    interpFlags |= SPAN_Z;
    246    {
    247       if (depthBits <= 16) {
    248          span.z = FloatToFixed(vert0->attrib[FRAG_ATTRIB_WPOS][2]) + FIXED_HALF;
    249          span.zStep = FloatToFixed(  vert1->attrib[FRAG_ATTRIB_WPOS][2]
    250                                    - vert0->attrib[FRAG_ATTRIB_WPOS][2]) / numPixels;
    251       }
    252       else {
    253          /* don't use fixed point */
    254          span.z = (GLuint) vert0->attrib[FRAG_ATTRIB_WPOS][2];
    255          span.zStep = (GLint) ((  vert1->attrib[FRAG_ATTRIB_WPOS][2]
    256                                 - vert0->attrib[FRAG_ATTRIB_WPOS][2]) / numPixels);
    257       }
    258    }
    259 #endif
    260 #if defined(INTERP_ATTRIBS)
    261    {
    262       const GLfloat invLen = 1.0F / numPixels;
    263       const GLfloat invw0 = vert0->attrib[FRAG_ATTRIB_WPOS][3];
    264       const GLfloat invw1 = vert1->attrib[FRAG_ATTRIB_WPOS][3];
    265 
    266       span.attrStart[FRAG_ATTRIB_WPOS][3] = invw0;
    267       span.attrStepX[FRAG_ATTRIB_WPOS][3] = (invw1 - invw0) * invLen;
    268       span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0;
    269 
    270       ATTRIB_LOOP_BEGIN
    271          if (swrast->_InterpMode[attr] == GL_FLAT) {
    272             COPY_4V(span.attrStart[attr], vert1->attrib[attr]);
    273             ASSIGN_4V(span.attrStepX[attr], 0.0, 0.0, 0.0, 0.0);
    274          }
    275          else {
    276             GLuint c;
    277             for (c = 0; c < 4; c++) {
    278                float da;
    279                span.attrStart[attr][c] = invw0 * vert0->attrib[attr][c];
    280                da = (invw1 * vert1->attrib[attr][c]) - span.attrStart[attr][c];
    281                span.attrStepX[attr][c] = da * invLen;
    282             }
    283          }
    284          ASSIGN_4V(span.attrStepY[attr], 0.0, 0.0, 0.0, 0.0);
    285       ATTRIB_LOOP_END
    286    }
    287 #endif
    288 
    289    INIT_SPAN(span, GL_LINE);
    290    span.end = numPixels;
    291    span.interpMask = interpFlags;
    292    span.arrayMask = SPAN_XY;
    293 
    294    span.facing = swrast->PointLineFacing;
    295 
    296 
    297    /*
    298     * Draw
    299     */
    300 
    301    if (dx > dy) {
    302       /*** X-major line ***/
    303       GLint i;
    304       GLint errorInc = dy+dy;
    305       GLint error = errorInc-dx;
    306       GLint errorDec = error-dx;
    307 
    308       for (i = 0; i < dx; i++) {
    309 #ifdef DEPTH_TYPE
    310          GLuint Z = FixedToDepth(span.z);
    311 #endif
    312 #ifdef PLOT
    313          PLOT( x0, y0 );
    314 #else
    315          span.array->x[i] = x0;
    316          span.array->y[i] = y0;
    317 #endif
    318          x0 += xstep;
    319 #ifdef DEPTH_TYPE
    320          zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep);
    321          span.z += span.zStep;
    322 #endif
    323 #ifdef PIXEL_ADDRESS
    324          pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep);
    325 #endif
    326          if (error < 0) {
    327             error += errorInc;
    328          }
    329          else {
    330             error += errorDec;
    331             y0 += ystep;
    332 #ifdef DEPTH_TYPE
    333             zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep);
    334 #endif
    335 #ifdef PIXEL_ADDRESS
    336             pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep);
    337 #endif
    338          }
    339       }
    340    }
    341    else {
    342       /*** Y-major line ***/
    343       GLint i;
    344       GLint errorInc = dx+dx;
    345       GLint error = errorInc-dy;
    346       GLint errorDec = error-dy;
    347 
    348       for (i=0;i<dy;i++) {
    349 #ifdef DEPTH_TYPE
    350          GLuint Z = FixedToDepth(span.z);
    351 #endif
    352 #ifdef PLOT
    353          PLOT( x0, y0 );
    354 #else
    355          span.array->x[i] = x0;
    356          span.array->y[i] = y0;
    357 #endif
    358          y0 += ystep;
    359 #ifdef DEPTH_TYPE
    360          zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep);
    361          span.z += span.zStep;
    362 #endif
    363 #ifdef PIXEL_ADDRESS
    364          pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep);
    365 #endif
    366          if (error<0) {
    367             error += errorInc;
    368          }
    369          else {
    370             error += errorDec;
    371             x0 += xstep;
    372 #ifdef DEPTH_TYPE
    373             zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep);
    374 #endif
    375 #ifdef PIXEL_ADDRESS
    376             pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep);
    377 #endif
    378          }
    379       }
    380    }
    381 
    382 #ifdef RENDER_SPAN
    383    RENDER_SPAN( span );
    384 #endif
    385 
    386    (void)span;
    387 
    388 }
    389 
    390 
    391 #undef NAME
    392 #undef INTERP_Z
    393 #undef INTERP_ATTRIBS
    394 #undef PIXEL_ADDRESS
    395 #undef PIXEL_TYPE
    396 #undef DEPTH_TYPE
    397 #undef BYTES_PER_ROW
    398 #undef SETUP_CODE
    399 #undef PLOT
    400 #undef CLIP_HACK
    401 #undef FixedToDepth
    402 #undef RENDER_SPAN
    403