Home | History | Annotate | Download | only in swrast
      1 /*
      2  * Mesa 3-D graphics library
      3  * Version:  7.1
      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 #include "main/glheader.h"
     27 #include "main/context.h"
     28 #include "main/colormac.h"
     29 #include "main/macros.h"
     30 #include "s_aaline.h"
     31 #include "s_context.h"
     32 #include "s_feedback.h"
     33 #include "s_lines.h"
     34 #include "s_span.h"
     35 
     36 
     37 /*
     38  * Init the mask[] array to implement a line stipple.
     39  */
     40 static void
     41 compute_stipple_mask( struct gl_context *ctx, GLuint len, GLubyte mask[] )
     42 {
     43    SWcontext *swrast = SWRAST_CONTEXT(ctx);
     44    GLuint i;
     45 
     46    for (i = 0; i < len; i++) {
     47       GLuint bit = (swrast->StippleCounter / ctx->Line.StippleFactor) & 0xf;
     48       if ((1 << bit) & ctx->Line.StipplePattern) {
     49          mask[i] = GL_TRUE;
     50       }
     51       else {
     52          mask[i] = GL_FALSE;
     53       }
     54       swrast->StippleCounter++;
     55    }
     56 }
     57 
     58 
     59 /*
     60  * To draw a wide line we can simply redraw the span N times, side by side.
     61  */
     62 static void
     63 draw_wide_line( struct gl_context *ctx, SWspan *span, GLboolean xMajor )
     64 {
     65    const GLint width = (GLint) CLAMP(ctx->Line.Width,
     66                                      ctx->Const.MinLineWidth,
     67                                      ctx->Const.MaxLineWidth);
     68    GLint start;
     69 
     70    ASSERT(span->end < SWRAST_MAX_WIDTH);
     71 
     72    if (width & 1)
     73       start = width / 2;
     74    else
     75       start = width / 2 - 1;
     76 
     77    if (xMajor) {
     78       GLint *y = span->array->y;
     79       GLuint i;
     80       GLint w;
     81       for (w = 0; w < width; w++) {
     82          if (w == 0) {
     83             for (i = 0; i < span->end; i++)
     84                y[i] -= start;
     85          }
     86          else {
     87             for (i = 0; i < span->end; i++)
     88                y[i]++;
     89          }
     90 	 _swrast_write_rgba_span(ctx, span);
     91       }
     92    }
     93    else {
     94       GLint *x = span->array->x;
     95       GLuint i;
     96       GLint w;
     97       for (w = 0; w < width; w++) {
     98          if (w == 0) {
     99             for (i = 0; i < span->end; i++)
    100                x[i] -= start;
    101          }
    102          else {
    103             for (i = 0; i < span->end; i++)
    104                x[i]++;
    105          }
    106 	 _swrast_write_rgba_span(ctx, span);
    107       }
    108    }
    109 }
    110 
    111 
    112 
    113 /**********************************************************************/
    114 /*****                    Rasterization                           *****/
    115 /**********************************************************************/
    116 
    117 /* Simple RGBA index line (no stipple, width=1, no Z, no fog, no tex)*/
    118 #define NAME simple_no_z_rgba_line
    119 #define INTERP_RGBA
    120 #define RENDER_SPAN(span) _swrast_write_rgba_span(ctx, &span);
    121 #include "s_linetemp.h"
    122 
    123 
    124 /* Z, fog, wide, stipple RGBA line */
    125 #define NAME rgba_line
    126 #define INTERP_RGBA
    127 #define INTERP_Z
    128 #define RENDER_SPAN(span)					\
    129    if (ctx->Line.StippleFlag) {					\
    130       span.arrayMask |= SPAN_MASK;				\
    131       compute_stipple_mask(ctx, span.end, span.array->mask);	\
    132    }								\
    133    if (ctx->Line.Width > 1.0) {					\
    134       draw_wide_line(ctx, &span, (GLboolean)(dx > dy));		\
    135    }								\
    136    else {							\
    137       _swrast_write_rgba_span(ctx, &span);			\
    138    }
    139 #include "s_linetemp.h"
    140 
    141 
    142 /* General-purpose line (any/all features). */
    143 #define NAME general_line
    144 #define INTERP_RGBA
    145 #define INTERP_Z
    146 #define INTERP_ATTRIBS
    147 #define RENDER_SPAN(span)					\
    148    if (ctx->Line.StippleFlag) {					\
    149       span.arrayMask |= SPAN_MASK;				\
    150       compute_stipple_mask(ctx, span.end, span.array->mask);	\
    151    }								\
    152    if (ctx->Line.Width > 1.0) {					\
    153       draw_wide_line(ctx, &span, (GLboolean)(dx > dy));		\
    154    }								\
    155    else {							\
    156       _swrast_write_rgba_span(ctx, &span);			\
    157    }
    158 #include "s_linetemp.h"
    159 
    160 
    161 
    162 void
    163 _swrast_add_spec_terms_line(struct gl_context *ctx,
    164                             const SWvertex *v0, const SWvertex *v1)
    165 {
    166    SWvertex *ncv0 = (SWvertex *)v0;
    167    SWvertex *ncv1 = (SWvertex *)v1;
    168    GLfloat rSum, gSum, bSum;
    169    GLchan cSave[2][4];
    170 
    171    /* save original colors */
    172    COPY_CHAN4(cSave[0], ncv0->color);
    173    COPY_CHAN4(cSave[1], ncv1->color);
    174    /* sum v0 */
    175    rSum = CHAN_TO_FLOAT(ncv0->color[0]) + ncv0->attrib[FRAG_ATTRIB_COL1][0];
    176    gSum = CHAN_TO_FLOAT(ncv0->color[1]) + ncv0->attrib[FRAG_ATTRIB_COL1][1];
    177    bSum = CHAN_TO_FLOAT(ncv0->color[2]) + ncv0->attrib[FRAG_ATTRIB_COL1][2];
    178    UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[0], rSum);
    179    UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[1], gSum);
    180    UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[2], bSum);
    181    /* sum v1 */
    182    rSum = CHAN_TO_FLOAT(ncv1->color[0]) + ncv1->attrib[FRAG_ATTRIB_COL1][0];
    183    gSum = CHAN_TO_FLOAT(ncv1->color[1]) + ncv1->attrib[FRAG_ATTRIB_COL1][1];
    184    bSum = CHAN_TO_FLOAT(ncv1->color[2]) + ncv1->attrib[FRAG_ATTRIB_COL1][2];
    185    UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[0], rSum);
    186    UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[1], gSum);
    187    UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[2], bSum);
    188    /* draw */
    189    SWRAST_CONTEXT(ctx)->SpecLine( ctx, ncv0, ncv1 );
    190    /* restore original colors */
    191    COPY_CHAN4(ncv0->color, cSave[0]);
    192    COPY_CHAN4(ncv1->color, cSave[1]);
    193 }
    194 
    195 
    196 
    197 #ifdef DEBUG
    198 
    199 /* record the current line function name */
    200 static const char *lineFuncName = NULL;
    201 
    202 #define USE(lineFunc)                   \
    203 do {                                    \
    204     lineFuncName = #lineFunc;           \
    205     /*printf("%s\n", lineFuncName);*/   \
    206     swrast->Line = lineFunc;            \
    207 } while (0)
    208 
    209 #else
    210 
    211 #define USE(lineFunc)  swrast->Line = lineFunc
    212 
    213 #endif
    214 
    215 
    216 
    217 /**
    218  * Determine which line drawing function to use given the current
    219  * rendering context.
    220  *
    221  * Please update the summary flag _SWRAST_NEW_LINE if you add or remove
    222  * tests to this code.
    223  */
    224 void
    225 _swrast_choose_line( struct gl_context *ctx )
    226 {
    227    SWcontext *swrast = SWRAST_CONTEXT(ctx);
    228    GLboolean specular = (ctx->Fog.ColorSumEnabled ||
    229                          (ctx->Light.Enabled &&
    230                           ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR));
    231 
    232    if (ctx->RenderMode == GL_RENDER) {
    233       if (ctx->Line.SmoothFlag) {
    234          /* antialiased lines */
    235          _swrast_choose_aa_line_function(ctx);
    236          ASSERT(swrast->Line);
    237       }
    238       else if (ctx->Texture._EnabledCoordUnits
    239                || _swrast_use_fragment_program(ctx)
    240                || swrast->_FogEnabled
    241                || specular) {
    242          USE(general_line);
    243       }
    244       else if (ctx->Depth.Test
    245                || ctx->Line.Width != 1.0
    246                || ctx->Line.StippleFlag) {
    247          /* no texture, but Z, fog, width>1, stipple, etc. */
    248 #if CHAN_BITS == 32
    249          USE(general_line);
    250 #else
    251          USE(rgba_line);
    252 #endif
    253       }
    254       else {
    255          ASSERT(!ctx->Depth.Test);
    256          ASSERT(ctx->Line.Width == 1.0);
    257          /* simple lines */
    258          USE(simple_no_z_rgba_line);
    259       }
    260    }
    261    else if (ctx->RenderMode == GL_FEEDBACK) {
    262       USE(_swrast_feedback_line);
    263    }
    264    else {
    265       ASSERT(ctx->RenderMode == GL_SELECT);
    266       USE(_swrast_select_line);
    267    }
    268 }
    269