s_lines.c revision 7117f1b4
1/* 2 * Mesa 3-D graphics library 3 * Version: 6.5.3 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 "glheader.h" 27#include "context.h" 28#include "colormac.h" 29#include "macros.h" 30#include "s_aaline.h" 31#include "s_context.h" 32#include "s_depth.h" 33#include "s_feedback.h" 34#include "s_lines.h" 35#include "s_span.h" 36 37 38/* 39 * Init the mask[] array to implement a line stipple. 40 */ 41static void 42compute_stipple_mask( GLcontext *ctx, GLuint len, GLubyte mask[] ) 43{ 44 SWcontext *swrast = SWRAST_CONTEXT(ctx); 45 GLuint i; 46 47 for (i = 0; i < len; i++) { 48 GLuint bit = (swrast->StippleCounter / ctx->Line.StippleFactor) & 0xf; 49 if ((1 << bit) & ctx->Line.StipplePattern) { 50 mask[i] = GL_TRUE; 51 } 52 else { 53 mask[i] = GL_FALSE; 54 } 55 swrast->StippleCounter++; 56 } 57} 58 59 60/* 61 * To draw a wide line we can simply redraw the span N times, side by side. 62 */ 63static void 64draw_wide_line( GLcontext *ctx, SWspan *span, GLboolean xMajor ) 65{ 66 GLint width, start; 67 68 ASSERT(span->end < MAX_WIDTH); 69 70 width = (GLint) CLAMP( ctx->Line._Width, MIN_LINE_WIDTH, MAX_LINE_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_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_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 general_ci_line 138#define INTERP_INDEX 139#define INTERP_Z 140#define INTERP_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 general_rgba_line 157#define INTERP_RGBA 158#define INTERP_Z 159#define INTERP_FOG 160#define RENDER_SPAN(span) \ 161 if (ctx->Line.StippleFlag) { \ 162 span.arrayMask |= SPAN_MASK; \ 163 compute_stipple_mask(ctx, span.end, span.array->mask); \ 164 } \ 165 if (ctx->Line._Width > 1.0) { \ 166 draw_wide_line(ctx, &span, (GLboolean)(dx > dy)); \ 167 } \ 168 else { \ 169 _swrast_write_rgba_span(ctx, &span); \ 170 } 171#include "s_linetemp.h" 172 173 174/* General-purpose textured line (any/all features). */ 175#define NAME textured_line 176#define INTERP_RGBA 177#define INTERP_SPEC 178#define INTERP_Z 179#define INTERP_FOG 180#define INTERP_ATTRIBS 181#define RENDER_SPAN(span) \ 182 if (ctx->Line.StippleFlag) { \ 183 span.arrayMask |= SPAN_MASK; \ 184 compute_stipple_mask(ctx, span.end, span.array->mask); \ 185 } \ 186 if (ctx->Line._Width > 1.0) { \ 187 draw_wide_line(ctx, &span, (GLboolean)(dx > dy)); \ 188 } \ 189 else { \ 190 _swrast_write_rgba_span(ctx, &span); \ 191 } 192#include "s_linetemp.h" 193 194 195 196void 197_swrast_add_spec_terms_line( GLcontext *ctx, 198 const SWvertex *v0, 199 const SWvertex *v1 ) 200{ 201 SWvertex *ncv0 = (SWvertex *)v0; 202 SWvertex *ncv1 = (SWvertex *)v1; 203 GLchan c[2][4]; 204 COPY_CHAN4( c[0], ncv0->color ); 205 COPY_CHAN4( c[1], ncv1->color ); 206 ACC_3V( ncv0->color, ncv0->specular ); 207 ACC_3V( ncv1->color, ncv1->specular ); 208 SWRAST_CONTEXT(ctx)->SpecLine( ctx, ncv0, ncv1 ); 209 COPY_CHAN4( ncv0->color, c[0] ); 210 COPY_CHAN4( ncv1->color, c[1] ); 211} 212 213 214#ifdef DEBUG 215extern void 216_mesa_print_line_function(GLcontext *ctx); /* silence compiler warning */ 217void 218_mesa_print_line_function(GLcontext *ctx) 219{ 220 SWcontext *swrast = SWRAST_CONTEXT(ctx); 221 222 _mesa_printf("Line Func == "); 223 if (swrast->Line == simple_ci_line) 224 _mesa_printf("simple_ci_line\n"); 225 else if (swrast->Line == simple_rgba_line) 226 _mesa_printf("simple_rgba_line\n"); 227 else if (swrast->Line == general_ci_line) 228 _mesa_printf("general_ci_line\n"); 229 else if (swrast->Line == general_rgba_line) 230 _mesa_printf("general_rgba_line\n"); 231 else if (swrast->Line == textured_line) 232 _mesa_printf("textured_line\n"); 233 else 234 _mesa_printf("Driver func %p\n", (void *(*)()) swrast->Line); 235} 236#endif 237 238 239 240#ifdef DEBUG 241 242/* record the current line function name */ 243static const char *lineFuncName = NULL; 244 245#define USE(lineFunc) \ 246do { \ 247 lineFuncName = #lineFunc; \ 248 /*_mesa_printf("%s\n", lineFuncName);*/ \ 249 swrast->Line = lineFunc; \ 250} while (0) 251 252#else 253 254#define USE(lineFunc) swrast->Line = lineFunc 255 256#endif 257 258 259 260/* 261 * Determine which line drawing function to use given the current 262 * rendering context. 263 * 264 * Please update the summary flag _SWRAST_NEW_LINE if you add or remove 265 * tests to this code. 266 */ 267void 268_swrast_choose_line( GLcontext *ctx ) 269{ 270 SWcontext *swrast = SWRAST_CONTEXT(ctx); 271 const GLboolean rgbmode = ctx->Visual.rgbMode; 272 273 if (ctx->RenderMode == GL_RENDER) { 274 if (ctx->Line.SmoothFlag) { 275 /* antialiased lines */ 276 _swrast_choose_aa_line_function(ctx); 277 ASSERT(swrast->Line); 278 } 279 else if (ctx->Texture._EnabledCoordUnits 280 || ctx->FragmentProgram._Current) { 281 /* textured lines */ 282 USE(textured_line); 283 } 284 else if (ctx->Depth.Test || swrast->_FogEnabled || ctx->Line._Width != 1.0 285 || ctx->Line.StippleFlag) { 286 /* no texture, but Z, fog, width>1, stipple, etc. */ 287 if (rgbmode) 288 USE(general_rgba_line); 289 else 290 USE(general_ci_line); 291 } 292 else { 293 /* simplest lines */ 294 if (rgbmode) 295 USE(simple_rgba_line); 296 else 297 USE(simple_ci_line); 298 } 299 } 300 else if (ctx->RenderMode == GL_FEEDBACK) { 301 USE(_swrast_feedback_line); 302 } 303 else { 304 ASSERT(ctx->RenderMode == GL_SELECT); 305 USE(_swrast_select_line); 306 } 307 308 /*_mesa_print_line_function(ctx);*/ 309} 310