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