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