s_lines.c revision 4a49301e
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 */ 40static void 41compute_stipple_mask( GLcontext *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 */ 62static void 63draw_wide_line( GLcontext *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 < 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 if (ctx->Visual.rgbMode) 91 _swrast_write_rgba_span(ctx, span); 92 else 93 _swrast_write_index_span(ctx, span); 94 } 95 } 96 else { 97 GLint *x = span->array->x; 98 GLuint i; 99 GLint w; 100 for (w = 0; w < width; w++) { 101 if (w == 0) { 102 for (i = 0; i < span->end; i++) 103 x[i] -= start; 104 } 105 else { 106 for (i = 0; i < span->end; i++) 107 x[i]++; 108 } 109 if (ctx->Visual.rgbMode) 110 _swrast_write_rgba_span(ctx, span); 111 else 112 _swrast_write_index_span(ctx, span); 113 } 114 } 115} 116 117 118 119/**********************************************************************/ 120/***** Rasterization *****/ 121/**********************************************************************/ 122 123/* Simple color index line (no stipple, width=1, no Z, no fog, no tex)*/ 124#define NAME simple_no_z_ci_line 125#define INTERP_INDEX 126#define RENDER_SPAN(span) _swrast_write_index_span(ctx, &span) 127#include "s_linetemp.h" 128 129/* Simple RGBA index line (no stipple, width=1, no Z, no fog, no tex)*/ 130#define NAME simple_no_z_rgba_line 131#define INTERP_RGBA 132#define RENDER_SPAN(span) _swrast_write_rgba_span(ctx, &span); 133#include "s_linetemp.h" 134 135 136/* Z, fog, wide, stipple color index line */ 137#define NAME ci_line 138#define INTERP_INDEX 139#define INTERP_Z 140#define INTERP_ATTRIBS /* for fog */ 141#define RENDER_SPAN(span) \ 142 if (ctx->Line.StippleFlag) { \ 143 span.arrayMask |= SPAN_MASK; \ 144 compute_stipple_mask(ctx, span.end, span.array->mask); \ 145 } \ 146 if (ctx->Line.Width > 1.0) { \ 147 draw_wide_line(ctx, &span, (GLboolean)(dx > dy)); \ 148 } \ 149 else { \ 150 _swrast_write_index_span(ctx, &span); \ 151 } 152#include "s_linetemp.h" 153 154 155/* Z, fog, wide, stipple RGBA line */ 156#define NAME rgba_line 157#define INTERP_RGBA 158#define INTERP_Z 159#define RENDER_SPAN(span) \ 160 if (ctx->Line.StippleFlag) { \ 161 span.arrayMask |= SPAN_MASK; \ 162 compute_stipple_mask(ctx, span.end, span.array->mask); \ 163 } \ 164 if (ctx->Line.Width > 1.0) { \ 165 draw_wide_line(ctx, &span, (GLboolean)(dx > dy)); \ 166 } \ 167 else { \ 168 _swrast_write_rgba_span(ctx, &span); \ 169 } 170#include "s_linetemp.h" 171 172 173/* General-purpose line (any/all features). */ 174#define NAME general_line 175#define INTERP_RGBA 176#define INTERP_Z 177#define INTERP_ATTRIBS 178#define RENDER_SPAN(span) \ 179 if (ctx->Line.StippleFlag) { \ 180 span.arrayMask |= SPAN_MASK; \ 181 compute_stipple_mask(ctx, span.end, span.array->mask); \ 182 } \ 183 if (ctx->Line.Width > 1.0) { \ 184 draw_wide_line(ctx, &span, (GLboolean)(dx > dy)); \ 185 } \ 186 else { \ 187 _swrast_write_rgba_span(ctx, &span); \ 188 } 189#include "s_linetemp.h" 190 191 192 193void 194_swrast_add_spec_terms_line(GLcontext *ctx, 195 const SWvertex *v0, const SWvertex *v1) 196{ 197 SWvertex *ncv0 = (SWvertex *)v0; 198 SWvertex *ncv1 = (SWvertex *)v1; 199 GLfloat rSum, gSum, bSum; 200 GLchan cSave[2][4]; 201 202 /* save original colors */ 203 COPY_CHAN4(cSave[0], ncv0->color); 204 COPY_CHAN4(cSave[1], ncv1->color); 205 /* sum v0 */ 206 rSum = CHAN_TO_FLOAT(ncv0->color[0]) + ncv0->attrib[FRAG_ATTRIB_COL1][0]; 207 gSum = CHAN_TO_FLOAT(ncv0->color[1]) + ncv0->attrib[FRAG_ATTRIB_COL1][1]; 208 bSum = CHAN_TO_FLOAT(ncv0->color[2]) + ncv0->attrib[FRAG_ATTRIB_COL1][2]; 209 UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[0], rSum); 210 UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[1], gSum); 211 UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[2], bSum); 212 /* sum v1 */ 213 rSum = CHAN_TO_FLOAT(ncv1->color[0]) + ncv1->attrib[FRAG_ATTRIB_COL1][0]; 214 gSum = CHAN_TO_FLOAT(ncv1->color[1]) + ncv1->attrib[FRAG_ATTRIB_COL1][1]; 215 bSum = CHAN_TO_FLOAT(ncv1->color[2]) + ncv1->attrib[FRAG_ATTRIB_COL1][2]; 216 UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[0], rSum); 217 UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[1], gSum); 218 UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[2], bSum); 219 /* draw */ 220 SWRAST_CONTEXT(ctx)->SpecLine( ctx, ncv0, ncv1 ); 221 /* restore original colors */ 222 COPY_CHAN4( ncv0->attrib[FRAG_ATTRIB_COL0], cSave[0] ); 223 COPY_CHAN4( ncv1->attrib[FRAG_ATTRIB_COL0], cSave[1] ); 224} 225 226 227 228#ifdef DEBUG 229 230/* record the current line function name */ 231static const char *lineFuncName = NULL; 232 233#define USE(lineFunc) \ 234do { \ 235 lineFuncName = #lineFunc; \ 236 /*_mesa_printf("%s\n", lineFuncName);*/ \ 237 swrast->Line = lineFunc; \ 238} while (0) 239 240#else 241 242#define USE(lineFunc) swrast->Line = lineFunc 243 244#endif 245 246 247 248/** 249 * Determine which line drawing function to use given the current 250 * rendering context. 251 * 252 * Please update the summary flag _SWRAST_NEW_LINE if you add or remove 253 * tests to this code. 254 */ 255void 256_swrast_choose_line( GLcontext *ctx ) 257{ 258 SWcontext *swrast = SWRAST_CONTEXT(ctx); 259 const GLboolean rgbmode = ctx->Visual.rgbMode; 260 GLboolean specular = (ctx->Fog.ColorSumEnabled || 261 (ctx->Light.Enabled && 262 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)); 263 264 if (ctx->RenderMode == GL_RENDER) { 265 if (ctx->Line.SmoothFlag) { 266 /* antialiased lines */ 267 _swrast_choose_aa_line_function(ctx); 268 ASSERT(swrast->Line); 269 } 270 else if (ctx->Texture._EnabledCoordUnits 271 || ctx->FragmentProgram._Current 272 || swrast->_FogEnabled 273 || specular) { 274 USE(general_line); 275 } 276 else if (ctx->Depth.Test 277 || ctx->Line.Width != 1.0 278 || ctx->Line.StippleFlag) { 279 /* no texture, but Z, fog, width>1, stipple, etc. */ 280 if (rgbmode) 281#if CHAN_BITS == 32 282 USE(general_line); 283#else 284 USE(rgba_line); 285#endif 286 else 287 USE(ci_line); 288 } 289 else { 290 ASSERT(!ctx->Depth.Test); 291 ASSERT(ctx->Line.Width == 1.0); 292 /* simple lines */ 293 if (rgbmode) 294 USE(simple_no_z_rgba_line); 295 else 296 USE(simple_no_z_ci_line); 297 } 298 } 299 else if (ctx->RenderMode == GL_FEEDBACK) { 300 USE(_swrast_feedback_line); 301 } 302 else { 303 ASSERT(ctx->RenderMode == GL_SELECT); 304 USE(_swrast_select_line); 305 } 306} 307