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