Home | History | Annotate | Download | only in swrast
      1 /*
      2  * Mesa 3-D graphics library
      3  *
      4  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included
     14  * in all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     22  * OTHER DEALINGS IN THE SOFTWARE.
     23  */
     24 
     25 
     26 #include "main/glheader.h"
     27 #include "main/context.h"
     28 #include "main/macros.h"
     29 #include "s_aaline.h"
     30 #include "s_context.h"
     31 #include "s_feedback.h"
     32 #include "s_lines.h"
     33 #include "s_span.h"
     34 
     35 
     36 /*
     37  * Init the mask[] array to implement a line stipple.
     38  */
     39 static void
     40 compute_stipple_mask( struct gl_context *ctx, GLuint len, GLubyte mask[] )
     41 {
     42    SWcontext *swrast = SWRAST_CONTEXT(ctx);
     43    GLuint i;
     44 
     45    for (i = 0; i < len; i++) {
     46       GLuint bit = (swrast->StippleCounter / ctx->Line.StippleFactor) & 0xf;
     47       if ((1 << bit) & ctx->Line.StipplePattern) {
     48          mask[i] = GL_TRUE;
     49       }
     50       else {
     51          mask[i] = GL_FALSE;
     52       }
     53       swrast->StippleCounter++;
     54    }
     55 }
     56 
     57 
     58 /*
     59  * To draw a wide line we can simply redraw the span N times, side by side.
     60  */
     61 static void
     62 draw_wide_line( struct gl_context *ctx, SWspan *span, GLboolean xMajor )
     63 {
     64    const GLint width = (GLint) CLAMP(ctx->Line.Width,
     65                                      ctx->Const.MinLineWidth,
     66                                      ctx->Const.MaxLineWidth);
     67    GLint start;
     68 
     69    assert(span->end < SWRAST_MAX_WIDTH);
     70 
     71    if (width & 1)
     72       start = width / 2;
     73    else
     74       start = width / 2 - 1;
     75 
     76    if (xMajor) {
     77       GLint *y = span->array->y;
     78       GLuint i;
     79       GLint w;
     80       for (w = 0; w < width; w++) {
     81          if (w == 0) {
     82             for (i = 0; i < span->end; i++)
     83                y[i] -= start;
     84          }
     85          else {
     86             for (i = 0; i < span->end; i++)
     87                y[i]++;
     88          }
     89 	 _swrast_write_rgba_span(ctx, span);
     90       }
     91    }
     92    else {
     93       GLint *x = span->array->x;
     94       GLuint i;
     95       GLint w;
     96       for (w = 0; w < width; w++) {
     97          if (w == 0) {
     98             for (i = 0; i < span->end; i++)
     99                x[i] -= start;
    100          }
    101          else {
    102             for (i = 0; i < span->end; i++)
    103                x[i]++;
    104          }
    105 	 _swrast_write_rgba_span(ctx, span);
    106       }
    107    }
    108 }
    109 
    110 
    111 
    112 /**********************************************************************/
    113 /*****                    Rasterization                           *****/
    114 /**********************************************************************/
    115 
    116 /* Simple RGBA index line (no stipple, width=1, no Z, no fog, no tex)*/
    117 #define NAME simple_no_z_rgba_line
    118 #define INTERP_RGBA
    119 #define RENDER_SPAN(span) _swrast_write_rgba_span(ctx, &span);
    120 #include "s_linetemp.h"
    121 
    122 
    123 /* Z, fog, wide, stipple RGBA line */
    124 #define NAME rgba_line
    125 #define INTERP_RGBA
    126 #define INTERP_Z
    127 #define RENDER_SPAN(span)					\
    128    if (ctx->Line.StippleFlag) {					\
    129       span.arrayMask |= SPAN_MASK;				\
    130       compute_stipple_mask(ctx, span.end, span.array->mask);	\
    131    }								\
    132    if (ctx->Line.Width > 1.0) {					\
    133       draw_wide_line(ctx, &span, (GLboolean)(dx > dy));		\
    134    }								\
    135    else {							\
    136       _swrast_write_rgba_span(ctx, &span);			\
    137    }
    138 #include "s_linetemp.h"
    139 
    140 
    141 /* General-purpose line (any/all features). */
    142 #define NAME general_line
    143 #define INTERP_RGBA
    144 #define INTERP_Z
    145 #define INTERP_ATTRIBS
    146 #define RENDER_SPAN(span)					\
    147    if (ctx->Line.StippleFlag) {					\
    148       span.arrayMask |= SPAN_MASK;				\
    149       compute_stipple_mask(ctx, span.end, span.array->mask);	\
    150    }								\
    151    if (ctx->Line.Width > 1.0) {					\
    152       draw_wide_line(ctx, &span, (GLboolean)(dx > dy));		\
    153    }								\
    154    else {							\
    155       _swrast_write_rgba_span(ctx, &span);			\
    156    }
    157 #include "s_linetemp.h"
    158 
    159 
    160 
    161 void
    162 _swrast_add_spec_terms_line(struct gl_context *ctx,
    163                             const SWvertex *v0, const SWvertex *v1)
    164 {
    165    SWvertex *ncv0 = (SWvertex *)v0;
    166    SWvertex *ncv1 = (SWvertex *)v1;
    167    GLfloat rSum, gSum, bSum;
    168    GLchan cSave[2][4];
    169 
    170    /* save original colors */
    171    COPY_CHAN4(cSave[0], ncv0->color);
    172    COPY_CHAN4(cSave[1], ncv1->color);
    173    /* sum v0 */
    174    rSum = CHAN_TO_FLOAT(ncv0->color[0]) + ncv0->attrib[VARYING_SLOT_COL1][0];
    175    gSum = CHAN_TO_FLOAT(ncv0->color[1]) + ncv0->attrib[VARYING_SLOT_COL1][1];
    176    bSum = CHAN_TO_FLOAT(ncv0->color[2]) + ncv0->attrib[VARYING_SLOT_COL1][2];
    177    UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[0], rSum);
    178    UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[1], gSum);
    179    UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[2], bSum);
    180    /* sum v1 */
    181    rSum = CHAN_TO_FLOAT(ncv1->color[0]) + ncv1->attrib[VARYING_SLOT_COL1][0];
    182    gSum = CHAN_TO_FLOAT(ncv1->color[1]) + ncv1->attrib[VARYING_SLOT_COL1][1];
    183    bSum = CHAN_TO_FLOAT(ncv1->color[2]) + ncv1->attrib[VARYING_SLOT_COL1][2];
    184    UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[0], rSum);
    185    UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[1], gSum);
    186    UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[2], bSum);
    187    /* draw */
    188    SWRAST_CONTEXT(ctx)->SpecLine( ctx, ncv0, ncv1 );
    189    /* restore original colors */
    190    COPY_CHAN4(ncv0->color, cSave[0]);
    191    COPY_CHAN4(ncv1->color, cSave[1]);
    192 }
    193 
    194 
    195 
    196 #ifdef DEBUG
    197 
    198 /* record the current line function name */
    199 static const char *lineFuncName = NULL;
    200 
    201 #define USE(lineFunc)                   \
    202 do {                                    \
    203     lineFuncName = #lineFunc;           \
    204     /*printf("%s\n", lineFuncName);*/   \
    205     swrast->Line = lineFunc;            \
    206 } while (0)
    207 
    208 #else
    209 
    210 #define USE(lineFunc)  swrast->Line = lineFunc
    211 
    212 #endif
    213 
    214 
    215 
    216 /**
    217  * Determine which line drawing function to use given the current
    218  * rendering context.
    219  *
    220  * Please update the summary flag _SWRAST_NEW_LINE if you add or remove
    221  * tests to this code.
    222  */
    223 void
    224 _swrast_choose_line( struct gl_context *ctx )
    225 {
    226    SWcontext *swrast = SWRAST_CONTEXT(ctx);
    227    GLboolean specular = (ctx->Fog.ColorSumEnabled ||
    228                          (ctx->Light.Enabled &&
    229                           ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR));
    230 
    231    if (ctx->RenderMode == GL_RENDER) {
    232       if (ctx->Line.SmoothFlag) {
    233          /* antialiased lines */
    234          _swrast_choose_aa_line_function(ctx);
    235          assert(swrast->Line);
    236       }
    237       else if (ctx->Texture._EnabledCoordUnits
    238                || _swrast_use_fragment_program(ctx)
    239                || swrast->_FogEnabled
    240                || specular) {
    241          USE(general_line);
    242       }
    243       else if (ctx->Depth.Test
    244                || ctx->Line.Width != 1.0F
    245                || ctx->Line.StippleFlag) {
    246          /* no texture, but Z, fog, width>1, stipple, etc. */
    247 #if CHAN_BITS == 32
    248          USE(general_line);
    249 #else
    250          USE(rgba_line);
    251 #endif
    252       }
    253       else {
    254          assert(!ctx->Depth.Test);
    255          assert(ctx->Line.Width == 1.0F);
    256          /* simple lines */
    257          USE(simple_no_z_rgba_line);
    258       }
    259    }
    260    else if (ctx->RenderMode == GL_FEEDBACK) {
    261       USE(_swrast_feedback_line);
    262    }
    263    else {
    264       assert(ctx->RenderMode == GL_SELECT);
    265       USE(_swrast_select_line);
    266    }
    267 }
    268