s_lines.c revision 45bc887da226403f2c41077e40ca38b6f60f1359
1/* $Id: s_lines.c,v 1.36 2003/03/25 02:23:46 brianp Exp $ */ 2 3/* 4 * Mesa 3-D graphics library 5 * Version: 5.1 6 * 7 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a 10 * copy of this software and associated documentation files (the "Software"), 11 * to deal in the Software without restriction, including without limitation 12 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 * and/or sell copies of the Software, and to permit persons to whom the 14 * Software is furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included 17 * in all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 */ 26 27 28#include "glheader.h" 29#include "colormac.h" 30#include "macros.h" 31#include "s_aaline.h" 32#include "s_context.h" 33#include "s_depth.h" 34#include "s_feedback.h" 35#include "s_lines.h" 36#include "s_span.h" 37 38 39/* 40 * Init the mask[] array to implement a line stipple. 41 */ 42static void 43compute_stipple_mask( GLcontext *ctx, GLuint len, GLubyte mask[] ) 44{ 45 SWcontext *swrast = SWRAST_CONTEXT(ctx); 46 GLuint i; 47 48 for (i = 0; i < len; i++) { 49 GLuint bit = (swrast->StippleCounter / ctx->Line.StippleFactor) & 0xf; 50 if ((1 << bit) & ctx->Line.StipplePattern) { 51 mask[i] = GL_TRUE; 52 } 53 else { 54 mask[i] = GL_FALSE; 55 } 56 swrast->StippleCounter++; 57 } 58} 59 60 61/* 62 * To draw a wide line we can simply redraw the span N times, side by side. 63 */ 64static void 65draw_wide_line( GLcontext *ctx, struct sw_span *span, GLboolean xMajor ) 66{ 67 GLint width, start; 68 69 ASSERT(span->end < MAX_WIDTH); 70 71 width = (GLint) CLAMP( ctx->Line.Width, MIN_LINE_WIDTH, MAX_LINE_WIDTH ); 72 73 if (width & 1) 74 start = width / 2; 75 else 76 start = width / 2 - 1; 77 78 if (xMajor) { 79 GLint *y = span->array->y; 80 GLuint i; 81 GLint w; 82 for (w = 0; w < width; w++) { 83 if (w == 0) { 84 for (i = 0; i < span->end; i++) 85 y[i] -= start; 86 } 87 else { 88 for (i = 0; i < span->end; i++) 89 y[i]++; 90 } 91 if ((span->interpMask | span->arrayMask) & SPAN_TEXTURE) 92 _swrast_write_texture_span(ctx, span); 93 else if ((span->interpMask | span->arrayMask) & SPAN_RGBA) 94 _swrast_write_rgba_span(ctx, span); 95 else 96 _swrast_write_index_span(ctx, span); 97 } 98 } 99 else { 100 GLint *x = span->array->x; 101 GLuint i; 102 GLint w; 103 for (w = 0; w < width; w++) { 104 if (w == 0) { 105 for (i = 0; i < span->end; i++) 106 x[i] -= start; 107 } 108 else { 109 for (i = 0; i < span->end; i++) 110 x[i]++; 111 } 112 if ((span->interpMask | span->arrayMask) & SPAN_TEXTURE) 113 _swrast_write_texture_span(ctx, span); 114 else if ((span->interpMask | span->arrayMask) & SPAN_RGBA) 115 _swrast_write_rgba_span(ctx, span); 116 else 117 _swrast_write_index_span(ctx, span); 118 } 119 } 120} 121 122 123 124/**********************************************************************/ 125/***** Rasterization *****/ 126/**********************************************************************/ 127 128 129/* Simple color index line (no stipple, width=1, no Z, no fog, no tex)*/ 130#define NAME simple_ci_line 131#define INTERP_INDEX 132#define RENDER_SPAN(span) _swrast_write_index_span(ctx, &span) 133#include "s_linetemp.h" 134 135 136/* Simple RGBA index line (no stipple, width=1, no Z, no fog, no tex)*/ 137#define NAME simple_rgba_line 138#define INTERP_RGBA 139#define RENDER_SPAN(span) _swrast_write_rgba_span(ctx, &span); 140#include "s_linetemp.h" 141 142 143/* Z, fog, wide, stipple color index line */ 144#define NAME general_ci_line 145#define INTERP_INDEX 146#define INTERP_Z 147#define INTERP_FOG 148#define RENDER_SPAN(span) \ 149 if (ctx->Line.StippleFlag) { \ 150 span.arrayMask |= SPAN_MASK; \ 151 compute_stipple_mask(ctx, span.end, span.array->mask); \ 152 } \ 153 if (ctx->Line.Width > 1.0) { \ 154 draw_wide_line(ctx, &span, dx > dy); \ 155 } \ 156 else { \ 157 _swrast_write_index_span(ctx, &span); \ 158 } 159#include "s_linetemp.h" 160 161 162/* Z, fog, wide, stipple RGBA line */ 163#define NAME general_rgba_line 164#define INTERP_RGBA 165#define INTERP_Z 166#define INTERP_FOG 167#define RENDER_SPAN(span) \ 168 if (ctx->Line.StippleFlag) { \ 169 span.arrayMask |= SPAN_MASK; \ 170 compute_stipple_mask(ctx, span.end, span.array->mask); \ 171 } \ 172 if (ctx->Line.Width > 1.0) { \ 173 draw_wide_line(ctx, &span, dx > dy); \ 174 } \ 175 else { \ 176 _swrast_write_rgba_span(ctx, &span); \ 177 } 178#include "s_linetemp.h" 179 180 181/* Single-texture line, w/ fog, Z, specular, etc. */ 182#define NAME textured_line 183#define INTERP_RGBA 184#define INTERP_Z 185#define INTERP_FOG 186#define INTERP_TEX 187#define RENDER_SPAN(span) \ 188 if (ctx->Line.StippleFlag) { \ 189 span.arrayMask |= SPAN_MASK; \ 190 compute_stipple_mask(ctx, span.end, span.array->mask); \ 191 } \ 192 if (ctx->Line.Width > 1.0) { \ 193 draw_wide_line(ctx, &span, dx > dy); \ 194 } \ 195 else { \ 196 _swrast_write_texture_span(ctx, &span); \ 197 } 198#include "s_linetemp.h" 199 200 201/* Multi-texture or separate specular line, w/ fog, Z, specular, etc. */ 202#define NAME multitextured_line 203#define INTERP_RGBA 204#define INTERP_SPEC 205#define INTERP_Z 206#define INTERP_FOG 207#define INTERP_MULTITEX 208#define RENDER_SPAN(span) \ 209 if (ctx->Line.StippleFlag) { \ 210 span.arrayMask |= SPAN_MASK; \ 211 compute_stipple_mask(ctx, span.end, span.array->mask); \ 212 } \ 213 if (ctx->Line.Width > 1.0) { \ 214 draw_wide_line(ctx, &span, dx > dy); \ 215 } \ 216 else { \ 217 _swrast_write_texture_span(ctx, &span); \ 218 } 219#include "s_linetemp.h" 220 221 222 223void 224_swrast_add_spec_terms_line( GLcontext *ctx, 225 const SWvertex *v0, 226 const SWvertex *v1 ) 227{ 228 SWvertex *ncv0 = (SWvertex *)v0; 229 SWvertex *ncv1 = (SWvertex *)v1; 230 GLchan c[2][4]; 231 COPY_CHAN4( c[0], ncv0->color ); 232 COPY_CHAN4( c[1], ncv1->color ); 233 ACC_3V( ncv0->color, ncv0->specular ); 234 ACC_3V( ncv1->color, ncv1->specular ); 235 SWRAST_CONTEXT(ctx)->SpecLine( ctx, ncv0, ncv1 ); 236 COPY_CHAN4( ncv0->color, c[0] ); 237 COPY_CHAN4( ncv1->color, c[1] ); 238} 239 240 241#ifdef DEBUG 242extern void 243_mesa_print_line_function(GLcontext *ctx); /* silence compiler warning */ 244void 245_mesa_print_line_function(GLcontext *ctx) 246{ 247 SWcontext *swrast = SWRAST_CONTEXT(ctx); 248 249 _mesa_printf("Line Func == "); 250 if (swrast->Line == simple_ci_line) 251 _mesa_printf("simple_ci_line\n"); 252 else if (swrast->Line == simple_rgba_line) 253 _mesa_printf("simple_rgba_line\n"); 254 else if (swrast->Line == general_ci_line) 255 _mesa_printf("general_ci_line\n"); 256 else if (swrast->Line == general_rgba_line) 257 _mesa_printf("general_rgba_line\n"); 258 else if (swrast->Line == textured_line) 259 _mesa_printf("textured_line\n"); 260 else if (swrast->Line == multitextured_line) 261 _mesa_printf("multitextured_line\n"); 262 else 263 _mesa_printf("Driver func %p\n", (void *) swrast->Line); 264} 265#endif 266 267 268 269#ifdef DEBUG 270 271/* record the current line function name */ 272static const char *lineFuncName = NULL; 273 274#define USE(lineFunc) \ 275do { \ 276 lineFuncName = #lineFunc; \ 277 /*_mesa_printf("%s\n", lineFuncName);*/ \ 278 swrast->Line = lineFunc; \ 279} while (0) 280 281#else 282 283#define USE(lineFunc) swrast->Line = lineFunc 284 285#endif 286 287 288 289/* 290 * Determine which line drawing function to use given the current 291 * rendering context. 292 * 293 * Please update the summary flag _SWRAST_NEW_LINE if you add or remove 294 * tests to this code. 295 */ 296void 297_swrast_choose_line( GLcontext *ctx ) 298{ 299 SWcontext *swrast = SWRAST_CONTEXT(ctx); 300 const GLboolean rgbmode = ctx->Visual.rgbMode; 301 302 if (ctx->RenderMode == GL_RENDER) { 303 if (ctx->Line.SmoothFlag) { 304 /* antialiased lines */ 305 _swrast_choose_aa_line_function(ctx); 306 ASSERT(swrast->Line); 307 } 308 else if (ctx->Texture._EnabledUnits) { 309 /* textured lines */ 310 if (ctx->Texture._EnabledUnits > 0x1 || (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)) { 311 /* multi-texture and/or separate specular color */ 312 USE(multitextured_line); 313 } 314 else { 315 USE(textured_line); 316 } 317 } 318 else if (ctx->Depth.Test || ctx->Fog.Enabled || ctx->Line.Width != 1.0 319 || ctx->Line.StippleFlag) { 320 /* no texture, but Z, fog, width>1, stipple, etc. */ 321 if (rgbmode) 322 USE(general_rgba_line); 323 else 324 USE(general_ci_line); 325 } 326 else { 327 /* simplest lines */ 328 if (rgbmode) 329 USE(simple_rgba_line); 330 else 331 USE(simple_ci_line); 332 } 333 } 334 else if (ctx->RenderMode == GL_FEEDBACK) { 335 USE(_swrast_feedback_line); 336 } 337 else { 338 ASSERT(ctx->RenderMode == GL_SELECT); 339 USE(_swrast_select_line); 340 } 341 342 /*_mesa_print_line_function(ctx);*/ 343} 344