• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
40 static void
compute_stipple_mask(struct gl_context * ctx,GLuint len,GLubyte mask[])41 compute_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  */
62 static void
draw_wide_line(struct gl_context * ctx,SWspan * span,GLboolean xMajor)63 draw_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 
162 void
_swrast_add_spec_terms_line(struct gl_context * ctx,const SWvertex * v0,const SWvertex * v1)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 */
200 static const char *lineFuncName = NULL;
201 
202 #define USE(lineFunc)                   \
203 do {                                    \
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  */
224 void
_swrast_choose_line(struct gl_context * ctx)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