fix typo
[mesa.git] / src / mesa / swrast / s_lines.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 5.1
4 *
5 * Copyright (C) 1999-2003 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 "glheader.h"
27 #include "context.h"
28 #include "colormac.h"
29 #include "macros.h"
30 #include "nvfragprog.h"
31 #include "s_aaline.h"
32 #include "s_context.h"
33 #include "s_depth.h"
34 #include "s_feedback.h"
35 #include "s_lines.h"
36 #include "s_span.h"
37
38
39 /*
40 * Init the mask[] array to implement a line stipple.
41 */
42 static void
43 compute_stipple_mask( GLcontext *ctx, GLuint len, GLubyte mask[] )
44 {
45 SWcontext *swrast = SWRAST_CONTEXT(ctx);
46 GLuint i;
47
48 for (i = 0; i < len; i++) {
49 GLuint bit = (swrast->StippleCounter / ctx->Line.StippleFactor) & 0xf;
50 if ((1 << bit) & ctx->Line.StipplePattern) {
51 mask[i] = GL_TRUE;
52 }
53 else {
54 mask[i] = GL_FALSE;
55 }
56 swrast->StippleCounter++;
57 }
58 }
59
60
61 /*
62 * To draw a wide line we can simply redraw the span N times, side by side.
63 */
64 static void
65 draw_wide_line( GLcontext *ctx, struct sw_span *span, GLboolean xMajor )
66 {
67 GLint width, start;
68
69 ASSERT(span->end < MAX_WIDTH);
70
71 width = (GLint) CLAMP( ctx->Line.Width, MIN_LINE_WIDTH, MAX_LINE_WIDTH );
72
73 if (width & 1)
74 start = width / 2;
75 else
76 start = width / 2 - 1;
77
78 if (xMajor) {
79 GLint *y = span->array->y;
80 GLuint i;
81 GLint w;
82 for (w = 0; w < width; w++) {
83 if (w == 0) {
84 for (i = 0; i < span->end; i++)
85 y[i] -= start;
86 }
87 else {
88 for (i = 0; i < span->end; i++)
89 y[i]++;
90 }
91 if ((span->interpMask | span->arrayMask) & SPAN_TEXTURE)
92 _swrast_write_texture_span(ctx, span);
93 else if ((span->interpMask | span->arrayMask) & SPAN_RGBA)
94 _swrast_write_rgba_span(ctx, span);
95 else
96 _swrast_write_index_span(ctx, span);
97 }
98 }
99 else {
100 GLint *x = span->array->x;
101 GLuint i;
102 GLint w;
103 for (w = 0; w < width; w++) {
104 if (w == 0) {
105 for (i = 0; i < span->end; i++)
106 x[i] -= start;
107 }
108 else {
109 for (i = 0; i < span->end; i++)
110 x[i]++;
111 }
112 if ((span->interpMask | span->arrayMask) & SPAN_TEXTURE)
113 _swrast_write_texture_span(ctx, span);
114 else if ((span->interpMask | span->arrayMask) & SPAN_RGBA)
115 _swrast_write_rgba_span(ctx, span);
116 else
117 _swrast_write_index_span(ctx, span);
118 }
119 }
120 }
121
122
123
124 /**********************************************************************/
125 /***** Rasterization *****/
126 /**********************************************************************/
127
128 /* Simple color index line (no stipple, width=1, no Z, no fog, no tex)*/
129 #define NAME simple_ci_line
130 #define INTERP_INDEX
131 #define RENDER_SPAN(span) _swrast_write_index_span(ctx, &span)
132 #include "s_linetemp.h"
133
134 /* Simple RGBA index line (no stipple, width=1, no Z, no fog, no tex)*/
135 #define NAME simple_rgba_line
136 #define INTERP_RGBA
137 #define RENDER_SPAN(span) _swrast_write_rgba_span(ctx, &span);
138 #include "s_linetemp.h"
139
140
141 /* Z, fog, wide, stipple color index line */
142 #define NAME general_ci_line
143 #define INTERP_INDEX
144 #define INTERP_Z
145 #define INTERP_FOG
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_index_span(ctx, &span); \
156 }
157 #include "s_linetemp.h"
158
159
160 /* Z, fog, wide, stipple RGBA line */
161 #define NAME general_rgba_line
162 #define INTERP_RGBA
163 #define INTERP_Z
164 #define INTERP_FOG
165 #define RENDER_SPAN(span) \
166 if (ctx->Line.StippleFlag) { \
167 span.arrayMask |= SPAN_MASK; \
168 compute_stipple_mask(ctx, span.end, span.array->mask); \
169 } \
170 if (ctx->Line.Width > 1.0) { \
171 draw_wide_line(ctx, &span, (GLboolean)(dx > dy)); \
172 } \
173 else { \
174 _swrast_write_rgba_span(ctx, &span); \
175 }
176 #include "s_linetemp.h"
177
178
179 /* Single-texture line, w/ fog, Z, specular, etc. */
180 #define NAME textured_line
181 #define INTERP_RGBA
182 #define INTERP_Z
183 #define INTERP_FOG
184 #define INTERP_TEX
185 #define RENDER_SPAN(span) \
186 if (ctx->Line.StippleFlag) { \
187 span.arrayMask |= SPAN_MASK; \
188 compute_stipple_mask(ctx, span.end, span.array->mask); \
189 } \
190 if (ctx->Line.Width > 1.0) { \
191 draw_wide_line(ctx, &span, (GLboolean)(dx > dy)); \
192 } \
193 else { \
194 _swrast_write_texture_span(ctx, &span); \
195 }
196 #include "s_linetemp.h"
197
198
199 /* Multi-texture or separate specular line, w/ fog, Z, specular, etc. */
200 #define NAME multitextured_line
201 #define INTERP_RGBA
202 #define INTERP_SPEC
203 #define INTERP_Z
204 #define INTERP_FOG
205 #define INTERP_MULTITEX
206 #define RENDER_SPAN(span) \
207 if (ctx->Line.StippleFlag) { \
208 span.arrayMask |= SPAN_MASK; \
209 compute_stipple_mask(ctx, span.end, span.array->mask); \
210 } \
211 if (ctx->Line.Width > 1.0) { \
212 draw_wide_line(ctx, &span, (GLboolean)(dx > dy)); \
213 } \
214 else { \
215 _swrast_write_texture_span(ctx, &span); \
216 }
217 #include "s_linetemp.h"
218
219
220
221 void
222 _swrast_add_spec_terms_line( GLcontext *ctx,
223 const SWvertex *v0,
224 const SWvertex *v1 )
225 {
226 SWvertex *ncv0 = (SWvertex *)v0;
227 SWvertex *ncv1 = (SWvertex *)v1;
228 GLchan c[2][4];
229 COPY_CHAN4( c[0], ncv0->color );
230 COPY_CHAN4( c[1], ncv1->color );
231 ACC_3V( ncv0->color, ncv0->specular );
232 ACC_3V( ncv1->color, ncv1->specular );
233 SWRAST_CONTEXT(ctx)->SpecLine( ctx, ncv0, ncv1 );
234 COPY_CHAN4( ncv0->color, c[0] );
235 COPY_CHAN4( ncv1->color, c[1] );
236 }
237
238
239 #ifdef DEBUG
240 extern void
241 _mesa_print_line_function(GLcontext *ctx); /* silence compiler warning */
242 void
243 _mesa_print_line_function(GLcontext *ctx)
244 {
245 SWcontext *swrast = SWRAST_CONTEXT(ctx);
246
247 _mesa_printf("Line Func == ");
248 if (swrast->Line == simple_ci_line)
249 _mesa_printf("simple_ci_line\n");
250 else if (swrast->Line == simple_rgba_line)
251 _mesa_printf("simple_rgba_line\n");
252 else if (swrast->Line == general_ci_line)
253 _mesa_printf("general_ci_line\n");
254 else if (swrast->Line == general_rgba_line)
255 _mesa_printf("general_rgba_line\n");
256 else if (swrast->Line == textured_line)
257 _mesa_printf("textured_line\n");
258 else if (swrast->Line == multitextured_line)
259 _mesa_printf("multitextured_line\n");
260 else
261 _mesa_printf("Driver func %p\n", (void *) swrast->Line);
262 }
263 #endif
264
265
266
267 #ifdef DEBUG
268
269 /* record the current line function name */
270 static const char *lineFuncName = NULL;
271
272 #define USE(lineFunc) \
273 do { \
274 lineFuncName = #lineFunc; \
275 /*_mesa_printf("%s\n", lineFuncName);*/ \
276 swrast->Line = lineFunc; \
277 } while (0)
278
279 #else
280
281 #define USE(lineFunc) swrast->Line = lineFunc
282
283 #endif
284
285
286
287 /*
288 * Determine which line drawing function to use given the current
289 * rendering context.
290 *
291 * Please update the summary flag _SWRAST_NEW_LINE if you add or remove
292 * tests to this code.
293 */
294 void
295 _swrast_choose_line( GLcontext *ctx )
296 {
297 SWcontext *swrast = SWRAST_CONTEXT(ctx);
298 const GLboolean rgbmode = ctx->Visual.rgbMode;
299
300 if (ctx->RenderMode == GL_RENDER) {
301 if (ctx->Line.SmoothFlag) {
302 /* antialiased lines */
303 _swrast_choose_aa_line_function(ctx);
304 ASSERT(swrast->Line);
305 }
306 else if (ctx->Texture._EnabledCoordUnits) {
307 /* textured lines */
308 if (ctx->Texture._EnabledCoordUnits > 0x1
309 || NEED_SECONDARY_COLOR(ctx)) {
310 /* multi-texture and/or separate specular color */
311 USE(multitextured_line);
312 }
313 else {
314 USE(textured_line);
315 }
316 }
317 else if (ctx->Depth.Test || ctx->Fog.Enabled || ctx->Line.Width != 1.0
318 || ctx->Line.StippleFlag) {
319 /* no texture, but Z, fog, width>1, stipple, etc. */
320 if (rgbmode)
321 USE(general_rgba_line);
322 else
323 USE(general_ci_line);
324 }
325 else {
326 /* simplest lines */
327 if (rgbmode)
328 USE(simple_rgba_line);
329 else
330 USE(simple_ci_line);
331 }
332 }
333 else if (ctx->RenderMode == GL_FEEDBACK) {
334 USE(_swrast_feedback_line);
335 }
336 else {
337 ASSERT(ctx->RenderMode == GL_SELECT);
338 USE(_swrast_select_line);
339 }
340
341 /*_mesa_print_line_function(ctx);*/
342 }