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