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 */ 39static void 40compute_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 */ 61static void 62draw_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 161void 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 */ 199static const char *lineFuncName = NULL; 200 201#define USE(lineFunc) \ 202do { \ 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 */ 223void 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