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