s_lines.c revision 9e8a961dd7d7b717a9fb4ecdea1c1b60ea355efe
143c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com/*
243c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com * Mesa 3-D graphics library
343c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com * Version:  6.5.3
443c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com *
543c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
643c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com *
743c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com * Permission is hereby granted, free of charge, to any person obtaining a
843c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com * copy of this software and associated documentation files (the "Software"),
943c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com * to deal in the Software without restriction, including without limitation
1043c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1143c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com * and/or sell copies of the Software, and to permit persons to whom the
1243c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com * Software is furnished to do so, subject to the following conditions:
1343c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com *
1443c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com * The above copyright notice and this permission notice shall be included
1543c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com * in all copies or substantial portions of the Software.
1643c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com *
1743c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1843c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1943c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2043c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2143c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2243c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2343c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com */
2443c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com
2543c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com
2643c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com#include "glheader.h"
2743c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com#include "context.h"
2843c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com#include "colormac.h"
2943c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com#include "macros.h"
3043c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com#include "s_aaline.h"
3143c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com#include "s_context.h"
3243c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com#include "s_depth.h"
3343c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com#include "s_feedback.h"
3443c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com#include "s_lines.h"
3543c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com#include "s_span.h"
3643c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com
3743c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com
3843c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com/*
3943c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com * Init the mask[] array to implement a line stipple.
4043c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com */
4143c27586e8b02243c16649de1cd7d95dcea0a712reed@google.comstatic void
4243c27586e8b02243c16649de1cd7d95dcea0a712reed@google.comcompute_stipple_mask( GLcontext *ctx, GLuint len, GLubyte mask[] )
4343c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com{
4443c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com   SWcontext *swrast = SWRAST_CONTEXT(ctx);
4543c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com   GLuint i;
4643c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com
4743c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com   for (i = 0; i < len; i++) {
4843c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com      GLuint bit = (swrast->StippleCounter / ctx->Line.StippleFactor) & 0xf;
4943c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com      if ((1 << bit) & ctx->Line.StipplePattern) {
5043c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com         mask[i] = GL_TRUE;
5143c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com      }
5243c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com      else {
5343c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com         mask[i] = GL_FALSE;
5443c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com      }
5543c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com      swrast->StippleCounter++;
5643c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com   }
5743c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com}
5843c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com
5943c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com
6043c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com/*
6143c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com * To draw a wide line we can simply redraw the span N times, side by side.
6243c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com */
6343c27586e8b02243c16649de1cd7d95dcea0a712reed@google.comstatic void
6443c27586e8b02243c16649de1cd7d95dcea0a712reed@google.comdraw_wide_line( GLcontext *ctx, SWspan *span, GLboolean xMajor )
6543c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com{
66e1d94437585dad1c195d7cf095f8a5a8219d196askia.committer@gmail.com   GLint width, start;
6743c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com
6843c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com   ASSERT(span->end < MAX_WIDTH);
6943d6d80b49b05c4eec400c8393445397653d9654reed@google.com
7043d6d80b49b05c4eec400c8393445397653d9654reed@google.com   width = (GLint) CLAMP( ctx->Line._Width, MIN_LINE_WIDTH, MAX_LINE_WIDTH );
7143c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com
7243c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com   if (width & 1)
7343c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com      start = width / 2;
7443c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com   else
7543c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com      start = width / 2 - 1;
7643c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com
7743c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com   if (xMajor) {
7843c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com      GLint *y = span->array->y;
7943c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com      GLuint i;
8043c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com      GLint w;
8143c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com      for (w = 0; w < width; w++) {
8243c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com         if (w == 0) {
8343c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com            for (i = 0; i < span->end; i++)
8443c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com               y[i] -= start;
8543c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com         }
8643c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com         else {
8743c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com            for (i = 0; i < span->end; i++)
8843c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com               y[i]++;
8943c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com         }
9043c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com         if (ctx->Visual.rgbMode)
9143c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com            _swrast_write_rgba_span(ctx, span);
9243c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com         else
9343c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com            _swrast_write_index_span(ctx, span);
9443c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com      }
9543c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com   }
9643c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com   else {
9743c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com      GLint *x = span->array->x;
9843c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com      GLuint i;
9943c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com      GLint w;
10043c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com      for (w = 0; w < width; w++) {
1016719d604856e45c789c46703204ae10046e0b448reed@google.com         if (w == 0) {
1026719d604856e45c789c46703204ae10046e0b448reed@google.com            for (i = 0; i < span->end; i++)
103efadb4b63c428b4f99399c097879981e6efa8870reed@google.com               x[i] -= start;
104efadb4b63c428b4f99399c097879981e6efa8870reed@google.com         }
105efadb4b63c428b4f99399c097879981e6efa8870reed@google.com         else {
10643c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com            for (i = 0; i < span->end; i++)
10743c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com               x[i]++;
10843c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com         }
10943c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com         if (ctx->Visual.rgbMode)
11043c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com            _swrast_write_rgba_span(ctx, span);
11143c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com         else
11243c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com            _swrast_write_index_span(ctx, span);
11343c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com      }
11443c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com   }
11543c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com}
11643c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com
11743c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com
11843c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com
11943c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com/**********************************************************************/
12043c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com/*****                    Rasterization                           *****/
12143c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com/**********************************************************************/
12243c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com
12343c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com/* Simple color index line (no stipple, width=1, no Z, no fog, no tex)*/
12443c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com#define NAME simple_no_z_ci_line
12543c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com#define INTERP_INDEX
12643c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com#define RENDER_SPAN(span) _swrast_write_index_span(ctx, &span)
12743c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com#include "s_linetemp.h"
12843c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com
12943c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com/* Simple RGBA index line (no stipple, width=1, no Z, no fog, no tex)*/
13043c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com#define NAME simple_no_z_rgba_line
13143c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com#define INTERP_RGBA
13243c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com#define RENDER_SPAN(span) _swrast_write_rgba_span(ctx, &span);
13343c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com#include "s_linetemp.h"
13443c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com
13543c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com
13643c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com/* Z, fog, wide, stipple color index line */
13743c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com#define NAME ci_line
13843c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com#define INTERP_INDEX
13943c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com#define INTERP_Z
14043c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com#define INTERP_ATTRIBS /* for fog */
14143c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com#define RENDER_SPAN(span)					\
14243c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com   if (ctx->Line.StippleFlag) {					\
14343c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com      span.arrayMask |= SPAN_MASK;				\
14443c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com      compute_stipple_mask(ctx, span.end, span.array->mask);    \
14543c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com   }								\
14643c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com   if (ctx->Line._Width > 1.0) {				\
14743c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com      draw_wide_line(ctx, &span, (GLboolean)(dx > dy));		\
14843c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com   }								\
14943c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com   else {							\
15043c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com      _swrast_write_index_span(ctx, &span);			\
15143c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com   }
15243c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com#include "s_linetemp.h"
15343c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com
15443c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com
15543c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com/* Z, fog, wide, stipple RGBA line */
15643c27586e8b02243c16649de1cd7d95dcea0a712reed@google.com#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            USE(rgba_line);
282         else
283            USE(ci_line);
284      }
285      else {
286         ASSERT(!ctx->Depth.Test);
287         /* simple lines */
288         if (rgbmode)
289            USE(simple_no_z_rgba_line);
290         else
291            USE(simple_no_z_ci_line);
292      }
293   }
294   else if (ctx->RenderMode == GL_FEEDBACK) {
295      USE(_swrast_feedback_line);
296   }
297   else {
298      ASSERT(ctx->RenderMode == GL_SELECT);
299      USE(_swrast_select_line);
300   }
301}
302