replace _mesa_ prefix with _swrast_, remove s_histogram.[ch]
[mesa.git] / src / mesa / swrast / s_lines.c
1 /* $Id: s_lines.c,v 1.36 2003/03/25 02:23:46 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 5.1
6 *
7 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28 #include "glheader.h"
29 #include "colormac.h"
30 #include "macros.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
129 /* Simple color index line (no stipple, width=1, no Z, no fog, no tex)*/
130 #define NAME simple_ci_line
131 #define INTERP_INDEX
132 #define RENDER_SPAN(span) _swrast_write_index_span(ctx, &span)
133 #include "s_linetemp.h"
134
135
136 /* Simple RGBA index line (no stipple, width=1, no Z, no fog, no tex)*/
137 #define NAME simple_rgba_line
138 #define INTERP_RGBA
139 #define RENDER_SPAN(span) _swrast_write_rgba_span(ctx, &span);
140 #include "s_linetemp.h"
141
142
143 /* Z, fog, wide, stipple color index line */
144 #define NAME general_ci_line
145 #define INTERP_INDEX
146 #define INTERP_Z
147 #define INTERP_FOG
148 #define RENDER_SPAN(span) \
149 if (ctx->Line.StippleFlag) { \
150 span.arrayMask |= SPAN_MASK; \
151 compute_stipple_mask(ctx, span.end, span.array->mask); \
152 } \
153 if (ctx->Line.Width > 1.0) { \
154 draw_wide_line(ctx, &span, dx > dy); \
155 } \
156 else { \
157 _swrast_write_index_span(ctx, &span); \
158 }
159 #include "s_linetemp.h"
160
161
162 /* Z, fog, wide, stipple RGBA line */
163 #define NAME general_rgba_line
164 #define INTERP_RGBA
165 #define INTERP_Z
166 #define INTERP_FOG
167 #define RENDER_SPAN(span) \
168 if (ctx->Line.StippleFlag) { \
169 span.arrayMask |= SPAN_MASK; \
170 compute_stipple_mask(ctx, span.end, span.array->mask); \
171 } \
172 if (ctx->Line.Width > 1.0) { \
173 draw_wide_line(ctx, &span, dx > dy); \
174 } \
175 else { \
176 _swrast_write_rgba_span(ctx, &span); \
177 }
178 #include "s_linetemp.h"
179
180
181 /* Single-texture line, w/ fog, Z, specular, etc. */
182 #define NAME textured_line
183 #define INTERP_RGBA
184 #define INTERP_Z
185 #define INTERP_FOG
186 #define INTERP_TEX
187 #define RENDER_SPAN(span) \
188 if (ctx->Line.StippleFlag) { \
189 span.arrayMask |= SPAN_MASK; \
190 compute_stipple_mask(ctx, span.end, span.array->mask); \
191 } \
192 if (ctx->Line.Width > 1.0) { \
193 draw_wide_line(ctx, &span, dx > dy); \
194 } \
195 else { \
196 _swrast_write_texture_span(ctx, &span); \
197 }
198 #include "s_linetemp.h"
199
200
201 /* Multi-texture or separate specular line, w/ fog, Z, specular, etc. */
202 #define NAME multitextured_line
203 #define INTERP_RGBA
204 #define INTERP_SPEC
205 #define INTERP_Z
206 #define INTERP_FOG
207 #define INTERP_MULTITEX
208 #define RENDER_SPAN(span) \
209 if (ctx->Line.StippleFlag) { \
210 span.arrayMask |= SPAN_MASK; \
211 compute_stipple_mask(ctx, span.end, span.array->mask); \
212 } \
213 if (ctx->Line.Width > 1.0) { \
214 draw_wide_line(ctx, &span, dx > dy); \
215 } \
216 else { \
217 _swrast_write_texture_span(ctx, &span); \
218 }
219 #include "s_linetemp.h"
220
221
222
223 void
224 _swrast_add_spec_terms_line( GLcontext *ctx,
225 const SWvertex *v0,
226 const SWvertex *v1 )
227 {
228 SWvertex *ncv0 = (SWvertex *)v0;
229 SWvertex *ncv1 = (SWvertex *)v1;
230 GLchan c[2][4];
231 COPY_CHAN4( c[0], ncv0->color );
232 COPY_CHAN4( c[1], ncv1->color );
233 ACC_3V( ncv0->color, ncv0->specular );
234 ACC_3V( ncv1->color, ncv1->specular );
235 SWRAST_CONTEXT(ctx)->SpecLine( ctx, ncv0, ncv1 );
236 COPY_CHAN4( ncv0->color, c[0] );
237 COPY_CHAN4( ncv1->color, c[1] );
238 }
239
240
241 #ifdef DEBUG
242 extern void
243 _mesa_print_line_function(GLcontext *ctx); /* silence compiler warning */
244 void
245 _mesa_print_line_function(GLcontext *ctx)
246 {
247 SWcontext *swrast = SWRAST_CONTEXT(ctx);
248
249 _mesa_printf("Line Func == ");
250 if (swrast->Line == simple_ci_line)
251 _mesa_printf("simple_ci_line\n");
252 else if (swrast->Line == simple_rgba_line)
253 _mesa_printf("simple_rgba_line\n");
254 else if (swrast->Line == general_ci_line)
255 _mesa_printf("general_ci_line\n");
256 else if (swrast->Line == general_rgba_line)
257 _mesa_printf("general_rgba_line\n");
258 else if (swrast->Line == textured_line)
259 _mesa_printf("textured_line\n");
260 else if (swrast->Line == multitextured_line)
261 _mesa_printf("multitextured_line\n");
262 else
263 _mesa_printf("Driver func %p\n", (void *) swrast->Line);
264 }
265 #endif
266
267
268
269 #ifdef DEBUG
270
271 /* record the current line function name */
272 static const char *lineFuncName = NULL;
273
274 #define USE(lineFunc) \
275 do { \
276 lineFuncName = #lineFunc; \
277 /*_mesa_printf("%s\n", lineFuncName);*/ \
278 swrast->Line = lineFunc; \
279 } while (0)
280
281 #else
282
283 #define USE(lineFunc) swrast->Line = lineFunc
284
285 #endif
286
287
288
289 /*
290 * Determine which line drawing function to use given the current
291 * rendering context.
292 *
293 * Please update the summary flag _SWRAST_NEW_LINE if you add or remove
294 * tests to this code.
295 */
296 void
297 _swrast_choose_line( GLcontext *ctx )
298 {
299 SWcontext *swrast = SWRAST_CONTEXT(ctx);
300 const GLboolean rgbmode = ctx->Visual.rgbMode;
301
302 if (ctx->RenderMode == GL_RENDER) {
303 if (ctx->Line.SmoothFlag) {
304 /* antialiased lines */
305 _swrast_choose_aa_line_function(ctx);
306 ASSERT(swrast->Line);
307 }
308 else if (ctx->Texture._EnabledUnits) {
309 /* textured lines */
310 if (ctx->Texture._EnabledUnits > 0x1 || (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)) {
311 /* multi-texture and/or separate specular color */
312 USE(multitextured_line);
313 }
314 else {
315 USE(textured_line);
316 }
317 }
318 else if (ctx->Depth.Test || ctx->Fog.Enabled || ctx->Line.Width != 1.0
319 || ctx->Line.StippleFlag) {
320 /* no texture, but Z, fog, width>1, stipple, etc. */
321 if (rgbmode)
322 USE(general_rgba_line);
323 else
324 USE(general_ci_line);
325 }
326 else {
327 /* simplest lines */
328 if (rgbmode)
329 USE(simple_rgba_line);
330 else
331 USE(simple_ci_line);
332 }
333 }
334 else if (ctx->RenderMode == GL_FEEDBACK) {
335 USE(_swrast_feedback_line);
336 }
337 else {
338 ASSERT(ctx->RenderMode == GL_SELECT);
339 USE(_swrast_select_line);
340 }
341
342 /*_mesa_print_line_function(ctx);*/
343 }