s/printf/_mesa_printf/
[mesa.git] / src / mesa / swrast / s_lines.c
1 /* $Id: s_lines.c,v 1.32 2002/10/30 19:59:33 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 5.0
6 *
7 * Copyright (C) 1999-2002 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 "mmath.h"
32 #include "s_aaline.h"
33 #include "s_context.h"
34 #include "s_depth.h"
35 #include "s_feedback.h"
36 #include "s_lines.h"
37 #include "s_span.h"
38
39
40 /*
41 * Init the mask[] array to implement a line stipple.
42 */
43 static void
44 compute_stipple_mask( GLcontext *ctx, GLuint len, GLubyte mask[] )
45 {
46 SWcontext *swrast = SWRAST_CONTEXT(ctx);
47 GLuint i;
48
49 for (i = 0; i < len; i++) {
50 GLuint bit = (swrast->StippleCounter / ctx->Line.StippleFactor) & 0xf;
51 if ((1 << bit) & ctx->Line.StipplePattern) {
52 mask[i] = GL_TRUE;
53 }
54 else {
55 mask[i] = GL_FALSE;
56 }
57 swrast->StippleCounter++;
58 }
59 }
60
61
62 /*
63 * To draw a wide line we can simply redraw the span N times, side by side.
64 */
65 static void
66 draw_wide_line( GLcontext *ctx, struct sw_span *span, GLboolean xMajor )
67 {
68 GLint width, start;
69
70 ASSERT(span->end < MAX_WIDTH);
71
72 width = (GLint) CLAMP( ctx->Line.Width, MIN_LINE_WIDTH, MAX_LINE_WIDTH );
73
74 if (width & 1)
75 start = width / 2;
76 else
77 start = width / 2 - 1;
78
79 if (xMajor) {
80 GLint *y = span->array->y;
81 GLuint i;
82 GLint w;
83 for (w = 0; w < width; w++) {
84 if (w == 0) {
85 for (i = 0; i < span->end; i++)
86 y[i] -= start;
87 }
88 else {
89 for (i = 0; i < span->end; i++)
90 y[i]++;
91 }
92 if ((span->interpMask | span->arrayMask) & SPAN_TEXTURE)
93 _mesa_write_texture_span(ctx, span);
94 else if ((span->interpMask | span->arrayMask) & SPAN_RGBA)
95 _mesa_write_rgba_span(ctx, span);
96 else
97 _mesa_write_index_span(ctx, span);
98 }
99 }
100 else {
101 GLint *x = span->array->x;
102 GLuint i;
103 GLint w;
104 for (w = 0; w < width; w++) {
105 if (w == 0) {
106 for (i = 0; i < span->end; i++)
107 x[i] -= start;
108 }
109 else {
110 for (i = 0; i < span->end; i++)
111 x[i]++;
112 }
113 if ((span->interpMask | span->arrayMask) & SPAN_TEXTURE)
114 _mesa_write_texture_span(ctx, span);
115 else if ((span->interpMask | span->arrayMask) & SPAN_RGBA)
116 _mesa_write_rgba_span(ctx, span);
117 else
118 _mesa_write_index_span(ctx, span);
119 }
120 }
121 }
122
123
124
125 /**********************************************************************/
126 /***** Rasterization *****/
127 /**********************************************************************/
128
129
130 /* Flat, color index line */
131 static void flat_ci_line( GLcontext *ctx,
132 const SWvertex *vert0,
133 const SWvertex *vert1 )
134 {
135 GLint *x, *y;
136 struct sw_span span;
137
138 ASSERT(ctx->Light.ShadeModel == GL_FLAT);
139 ASSERT(!ctx->Line.StippleFlag);
140 ASSERT(ctx->Line.Width == 1.0F);
141
142 INIT_SPAN(span, GL_LINE, 0, SPAN_INDEX, SPAN_XY);
143 span.index = IntToFixed(vert1->index);
144 span.indexStep = 0;
145 x = span.array->x;
146 y = span.array->y;
147
148 #define INTERP_XY 1
149 #define PLOT(X,Y) \
150 { \
151 x[span.end] = X; \
152 y[span.end] = Y; \
153 span.end++; \
154 }
155
156 #include "s_linetemp.h"
157
158 _mesa_write_index_span(ctx, &span);
159 }
160
161
162 /* Flat-shaded, RGBA line */
163 static void flat_rgba_line( GLcontext *ctx,
164 const SWvertex *vert0,
165 const SWvertex *vert1 )
166 {
167 struct sw_span span;
168 GLint *x, *y;
169
170 ASSERT(ctx->Light.ShadeModel == GL_FLAT);
171 ASSERT(!ctx->Line.StippleFlag);
172 ASSERT(ctx->Line.Width == 1.0F);
173
174 INIT_SPAN(span, GL_LINE, 0, SPAN_RGBA, SPAN_XY);
175 span.red = ChanToFixed(vert1->color[0]);
176 span.green = ChanToFixed(vert1->color[1]);
177 span.blue = ChanToFixed(vert1->color[2]);
178 span.alpha = ChanToFixed(vert1->color[3]);
179 span.redStep = 0;
180 span.greenStep = 0;
181 span.blueStep = 0;
182 span.alphaStep = 0;
183 x = span.array->x;
184 y = span.array->y;
185
186 #define INTERP_XY 1
187 #define PLOT(X,Y) \
188 { \
189 x[span.end] = X; \
190 y[span.end] = Y; \
191 span.end++; \
192 }
193
194 #include "s_linetemp.h"
195
196 _mesa_write_rgba_span(ctx, &span);
197 }
198
199
200 /* Smooth shaded, color index line */
201 static void smooth_ci_line( GLcontext *ctx,
202 const SWvertex *vert0,
203 const SWvertex *vert1 )
204 {
205 struct sw_span span;
206 GLint *x, *y;
207 GLuint *index;
208
209 ASSERT(ctx->Light.ShadeModel == GL_SMOOTH);
210 ASSERT(!ctx->Line.StippleFlag);
211 ASSERT(ctx->Line.Width == 1.0F);
212
213 INIT_SPAN(span, GL_LINE, 0, 0, SPAN_XY | SPAN_INDEX);
214 x = span.array->x;
215 y = span.array->y;
216 index = span.array->index;
217
218 #define INTERP_XY 1
219 #define INTERP_INDEX 1
220 #define PLOT(X,Y) \
221 { \
222 x[span.end] = X; \
223 y[span.end] = Y; \
224 index[span.end] = I; \
225 span.end++; \
226 }
227
228 #include "s_linetemp.h"
229
230 _mesa_write_index_span(ctx, &span);
231 }
232
233
234 /* Smooth-shaded, RGBA line */
235 static void smooth_rgba_line( GLcontext *ctx,
236 const SWvertex *vert0,
237 const SWvertex *vert1 )
238 {
239 struct sw_span span;
240 GLint *x, *y;
241 GLchan (*rgba)[4];
242
243 ASSERT(ctx->Light.ShadeModel == GL_SMOOTH);
244 ASSERT(!ctx->Line.StippleFlag);
245 ASSERT(ctx->Line.Width == 1.0F);
246
247 INIT_SPAN(span, GL_LINE, 0, 0, SPAN_XY | SPAN_RGBA);
248 x = span.array->x;
249 y = span.array->y;
250 rgba = span.array->rgba;
251
252 #define INTERP_XY 1
253 #define INTERP_RGB 1
254 #define INTERP_ALPHA 1
255 #define PLOT(X,Y) \
256 { \
257 x[span.end] = X; \
258 y[span.end] = Y; \
259 rgba[span.end][RCOMP] = FixedToInt(r0); \
260 rgba[span.end][GCOMP] = FixedToInt(g0); \
261 rgba[span.end][BCOMP] = FixedToInt(b0); \
262 rgba[span.end][ACOMP] = FixedToInt(a0); \
263 span.end++; \
264 }
265
266 #include "s_linetemp.h"
267
268 _mesa_write_rgba_span(ctx, &span);
269 }
270
271
272 /* Smooth shaded, color index, any width, maybe stippled */
273 static void general_smooth_ci_line( GLcontext *ctx,
274 const SWvertex *vert0,
275 const SWvertex *vert1 )
276 {
277 GLboolean xMajor = GL_FALSE;
278 struct sw_span span;
279 GLint *x, *y;
280 GLdepth *z;
281 GLfloat *fog;
282 GLuint *index;
283
284 ASSERT(ctx->Light.ShadeModel == GL_SMOOTH);
285
286 INIT_SPAN(span, GL_LINE, 0, 0,
287 SPAN_XY | SPAN_Z | SPAN_FOG | SPAN_INDEX);
288 x = span.array->x;
289 y = span.array->y;
290 z = span.array->z;
291 fog = span.array->fog;
292 index = span.array->index;
293
294 #define SET_XMAJOR 1
295 #define INTERP_XY 1
296 #define INTERP_Z 1
297 #define INTERP_FOG 1
298 #define INTERP_INDEX 1
299 #define PLOT(X,Y) \
300 { \
301 x[span.end] = X; \
302 y[span.end] = Y; \
303 z[span.end] = Z; \
304 fog[span.end] = fog0; \
305 index[span.end] = I; \
306 span.end++; \
307 }
308 #include "s_linetemp.h"
309
310 if (ctx->Line.StippleFlag) {
311 span.arrayMask |= SPAN_MASK;
312 compute_stipple_mask(ctx, span.end, span.array->mask);
313 }
314
315 if (ctx->Line.Width > 1.0) {
316 draw_wide_line(ctx, &span, xMajor);
317 }
318 else {
319 _mesa_write_index_span(ctx, &span);
320 }
321 }
322
323
324 /* Flat shaded, color index, any width, maybe stippled */
325 static void general_flat_ci_line( GLcontext *ctx,
326 const SWvertex *vert0,
327 const SWvertex *vert1 )
328 {
329 GLboolean xMajor = GL_FALSE;
330 struct sw_span span;
331 GLint *x, *y;
332 GLdepth *z;
333 GLfloat *fog;
334
335 ASSERT(ctx->Light.ShadeModel == GL_FLAT);
336
337 INIT_SPAN(span, GL_LINE, 0, SPAN_INDEX,
338 SPAN_XY | SPAN_Z | SPAN_FOG);
339 span.index = IntToFixed(vert1->index);
340 span.indexStep = 0;
341 x = span.array->x;
342 y = span.array->y;
343 z = span.array->z;
344 fog = span.array->fog;
345
346 #define SET_XMAJOR 1
347 #define INTERP_XY 1
348 #define INTERP_Z 1
349 #define INTERP_FOG 1
350 #define PLOT(X,Y) \
351 { \
352 x[span.end] = X; \
353 y[span.end] = Y; \
354 z[span.end] = Z; \
355 fog[span.end] = fog0; \
356 span.end++; \
357 }
358 #include "s_linetemp.h"
359
360 if (ctx->Line.StippleFlag) {
361 span.arrayMask |= SPAN_MASK;
362 compute_stipple_mask(ctx, span.end, span.array->mask);
363 }
364
365 if (ctx->Line.Width > 1.0) {
366 draw_wide_line(ctx, &span, xMajor);
367 }
368 else {
369 _mesa_write_index_span(ctx, &span);
370 }
371 }
372
373
374
375 static void general_smooth_rgba_line( GLcontext *ctx,
376 const SWvertex *vert0,
377 const SWvertex *vert1 )
378 {
379 GLboolean xMajor = GL_FALSE;
380 struct sw_span span;
381 GLint *x, *y;
382 GLdepth *z;
383 GLchan (*rgba)[4];
384 GLfloat *fog;
385
386 ASSERT(ctx->Light.ShadeModel == GL_SMOOTH);
387
388 INIT_SPAN(span, GL_LINE, 0, 0,
389 SPAN_XY | SPAN_Z | SPAN_FOG | SPAN_RGBA);
390 x = span.array->x;
391 y = span.array->y;
392 z = span.array->z;
393 rgba = span.array->rgba;
394 fog = span.array->fog;
395
396 #define SET_XMAJOR 1
397 #define INTERP_XY 1
398 #define INTERP_Z 1
399 #define INTERP_FOG 1
400 #define INTERP_RGB 1
401 #define INTERP_ALPHA 1
402 #define PLOT(X,Y) \
403 { \
404 x[span.end] = X; \
405 y[span.end] = Y; \
406 z[span.end] = Z; \
407 rgba[span.end][RCOMP] = FixedToInt(r0); \
408 rgba[span.end][GCOMP] = FixedToInt(g0); \
409 rgba[span.end][BCOMP] = FixedToInt(b0); \
410 rgba[span.end][ACOMP] = FixedToInt(a0); \
411 fog[span.end] = fog0; \
412 span.end++; \
413 }
414 #include "s_linetemp.h"
415
416 if (ctx->Line.StippleFlag) {
417 span.arrayMask |= SPAN_MASK;
418 compute_stipple_mask(ctx, span.end, span.array->mask);
419 }
420
421 if (ctx->Line.Width > 1.0) {
422 draw_wide_line(ctx, &span, xMajor);
423 }
424 else {
425 _mesa_write_rgba_span(ctx, &span);
426 }
427 }
428
429
430 static void general_flat_rgba_line( GLcontext *ctx,
431 const SWvertex *vert0,
432 const SWvertex *vert1 )
433 {
434 GLboolean xMajor = GL_FALSE;
435 struct sw_span span;
436 GLint *x, *y;
437 GLdepth *z;
438 GLfloat *fog;
439
440 ASSERT(ctx->Light.ShadeModel == GL_FLAT);
441
442 INIT_SPAN(span, GL_LINE, 0, SPAN_RGBA,
443 SPAN_XY | SPAN_Z | SPAN_FOG);
444 span.red = ChanToFixed(vert1->color[0]);
445 span.green = ChanToFixed(vert1->color[1]);
446 span.blue = ChanToFixed(vert1->color[2]);
447 span.alpha = ChanToFixed(vert1->color[3]);
448 span.redStep = 0;
449 span.greenStep = 0;
450 span.blueStep = 0;
451 span.alphaStep = 0;
452 x = span.array->x;
453 y = span.array->y;
454 z = span.array->z;
455 fog = span.array->fog;
456
457 #define SET_XMAJOR 1
458 #define INTERP_XY 1
459 #define INTERP_Z 1
460 #define INTERP_FOG 1
461 #define PLOT(X,Y) \
462 { \
463 x[span.end] = X; \
464 y[span.end] = Y; \
465 z[span.end] = Z; \
466 fog[span.end] = fog0; \
467 span.end++; \
468 }
469 #include "s_linetemp.h"
470
471 if (ctx->Line.StippleFlag) {
472 span.arrayMask |= SPAN_MASK;
473 compute_stipple_mask(ctx, span.end, span.array->mask);
474 }
475
476 if (ctx->Line.Width > 1.0) {
477 draw_wide_line(ctx, &span, xMajor);
478 }
479 else {
480 _mesa_write_rgba_span(ctx, &span);
481 }
482 }
483
484
485 /* Flat-shaded, textured, any width, maybe stippled */
486 static void flat_textured_line( GLcontext *ctx,
487 const SWvertex *vert0,
488 const SWvertex *vert1 )
489 {
490 GLboolean xMajor = GL_FALSE;
491 struct sw_span span;
492
493 ASSERT(ctx->Light.ShadeModel == GL_FLAT);
494
495 INIT_SPAN(span, GL_LINE, 0, SPAN_RGBA | SPAN_SPEC,
496 SPAN_XY | SPAN_Z | SPAN_FOG | SPAN_TEXTURE | SPAN_LAMBDA);
497 span.red = ChanToFixed(vert1->color[0]);
498 span.green = ChanToFixed(vert1->color[1]);
499 span.blue = ChanToFixed(vert1->color[2]);
500 span.alpha = ChanToFixed(vert1->color[3]);
501 span.redStep = 0;
502 span.greenStep = 0;
503 span.blueStep = 0;
504 span.alphaStep = 0;
505 span.specRed = ChanToFixed(vert1->specular[0]);
506 span.specGreen = ChanToFixed(vert1->specular[1]);
507 span.specBlue = ChanToFixed(vert1->specular[2]);
508 span.specRedStep = 0;
509 span.specGreenStep = 0;
510 span.specBlueStep = 0;
511
512 #define SET_XMAJOR 1
513 #define INTERP_XY 1
514 #define INTERP_Z 1
515 #define INTERP_FOG 1
516 #define INTERP_TEX 1
517 #define PLOT(X,Y) \
518 { \
519 span.array->x[span.end] = X; \
520 span.array->y[span.end] = Y; \
521 span.array->z[span.end] = Z; \
522 span.array->fog[span.end] = fog0; \
523 span.array->texcoords[0][span.end][0] = fragTexcoord[0]; \
524 span.array->texcoords[0][span.end][1] = fragTexcoord[1]; \
525 span.array->texcoords[0][span.end][2] = fragTexcoord[2]; \
526 span.array->lambda[0][span.end] = 0.0; \
527 span.end++; \
528 }
529 #include "s_linetemp.h"
530
531 if (ctx->Line.StippleFlag) {
532 span.arrayMask |= SPAN_MASK;
533 compute_stipple_mask(ctx, span.end, span.array->mask);
534 }
535
536 if (ctx->Line.Width > 1.0) {
537 draw_wide_line(ctx, &span, xMajor);
538 }
539 else {
540 _mesa_write_texture_span(ctx, &span);
541 }
542 }
543
544
545
546 /* Smooth-shaded, textured, any width, maybe stippled */
547 static void smooth_textured_line( GLcontext *ctx,
548 const SWvertex *vert0,
549 const SWvertex *vert1 )
550 {
551 GLboolean xMajor = GL_FALSE;
552 struct sw_span span;
553
554 ASSERT(ctx->Light.ShadeModel == GL_SMOOTH);
555
556 INIT_SPAN(span, GL_LINE, 0, 0,
557 SPAN_XY | SPAN_Z | SPAN_FOG | SPAN_RGBA | SPAN_TEXTURE | SPAN_LAMBDA);
558
559 #define SET_XMAJOR 1
560 #define INTERP_XY 1
561 #define INTERP_Z 1
562 #define INTERP_FOG 1
563 #define INTERP_RGB 1
564 #define INTERP_ALPHA 1
565 #define INTERP_TEX 1
566 #define PLOT(X,Y) \
567 { \
568 span.array->x[span.end] = X; \
569 span.array->y[span.end] = Y; \
570 span.array->z[span.end] = Z; \
571 span.array->fog[span.end] = fog0; \
572 span.array->rgba[span.end][RCOMP] = FixedToInt(r0); \
573 span.array->rgba[span.end][GCOMP] = FixedToInt(g0); \
574 span.array->rgba[span.end][BCOMP] = FixedToInt(b0); \
575 span.array->rgba[span.end][ACOMP] = FixedToInt(a0); \
576 span.array->texcoords[0][span.end][0] = fragTexcoord[0]; \
577 span.array->texcoords[0][span.end][1] = fragTexcoord[1]; \
578 span.array->texcoords[0][span.end][2] = fragTexcoord[2]; \
579 span.array->lambda[0][span.end] = 0.0; \
580 span.end++; \
581 }
582 #include "s_linetemp.h"
583
584 if (ctx->Line.StippleFlag) {
585 span.arrayMask |= SPAN_MASK;
586 compute_stipple_mask(ctx, span.end, span.array->mask);
587 }
588
589 if (ctx->Line.Width > 1.0) {
590 draw_wide_line(ctx, &span, xMajor);
591 }
592 else {
593 _mesa_write_texture_span(ctx, &span);
594 }
595 }
596
597
598 /* Smooth-shaded, multitextured, any width, maybe stippled, separate specular
599 * color interpolation.
600 */
601 static void smooth_multitextured_line( GLcontext *ctx,
602 const SWvertex *vert0,
603 const SWvertex *vert1 )
604 {
605 GLboolean xMajor = GL_FALSE;
606 struct sw_span span;
607 GLuint u;
608
609 ASSERT(ctx->Light.ShadeModel == GL_SMOOTH);
610
611 INIT_SPAN(span, GL_LINE, 0, 0,
612 SPAN_XY | SPAN_Z | SPAN_FOG | SPAN_RGBA | SPAN_SPEC | SPAN_TEXTURE | SPAN_LAMBDA);
613
614 #define SET_XMAJOR 1
615 #define INTERP_XY 1
616 #define INTERP_Z 1
617 #define INTERP_FOG 1
618 #define INTERP_RGB 1
619 #define INTERP_SPEC 1
620 #define INTERP_ALPHA 1
621 #define INTERP_MULTITEX 1
622 #define PLOT(X,Y) \
623 { \
624 span.array->x[span.end] = X; \
625 span.array->y[span.end] = Y; \
626 span.array->z[span.end] = Z; \
627 span.array->fog[span.end] = fog0; \
628 span.array->rgba[span.end][RCOMP] = FixedToInt(r0); \
629 span.array->rgba[span.end][GCOMP] = FixedToInt(g0); \
630 span.array->rgba[span.end][BCOMP] = FixedToInt(b0); \
631 span.array->rgba[span.end][ACOMP] = FixedToInt(a0); \
632 span.array->spec[span.end][RCOMP] = FixedToInt(sr0); \
633 span.array->spec[span.end][GCOMP] = FixedToInt(sg0); \
634 span.array->spec[span.end][BCOMP] = FixedToInt(sb0); \
635 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { \
636 if (ctx->Texture.Unit[u]._ReallyEnabled) { \
637 span.array->texcoords[u][span.end][0] = fragTexcoord[u][0]; \
638 span.array->texcoords[u][span.end][1] = fragTexcoord[u][1]; \
639 span.array->texcoords[u][span.end][2] = fragTexcoord[u][2]; \
640 span.array->lambda[u][span.end] = 0.0; \
641 } \
642 } \
643 span.end++; \
644 }
645 #include "s_linetemp.h"
646
647 if (ctx->Line.StippleFlag) {
648 span.arrayMask |= SPAN_MASK;
649 compute_stipple_mask(ctx, span.end, span.array->mask);
650 }
651
652 if (ctx->Line.Width > 1.0) {
653 draw_wide_line(ctx, &span, xMajor);
654 }
655 else {
656 _mesa_write_texture_span(ctx, &span);
657 }
658 }
659
660
661 /* Flat-shaded, multitextured, any width, maybe stippled, separate specular
662 * color interpolation.
663 */
664 static void flat_multitextured_line( GLcontext *ctx,
665 const SWvertex *vert0,
666 const SWvertex *vert1 )
667 {
668 GLboolean xMajor = GL_FALSE;
669 struct sw_span span;
670 GLuint u;
671
672 ASSERT(ctx->Light.ShadeModel == GL_FLAT);
673
674 INIT_SPAN(span, GL_LINE, 0, SPAN_RGBA | SPAN_SPEC,
675 SPAN_XY | SPAN_Z | SPAN_FOG | SPAN_TEXTURE | SPAN_LAMBDA);
676 span.red = ChanToFixed(vert1->color[0]);
677 span.green = ChanToFixed(vert1->color[1]);
678 span.blue = ChanToFixed(vert1->color[2]);
679 span.alpha = ChanToFixed(vert1->color[3]);
680 span.redStep = 0;
681 span.greenStep = 0;
682 span.blueStep = 0;
683 span.alphaStep = 0;
684 span.specRed = ChanToFixed(vert1->specular[0]);
685 span.specGreen = ChanToFixed(vert1->specular[1]);
686 span.specBlue = ChanToFixed(vert1->specular[2]);
687 span.specRedStep = 0;
688 span.specGreenStep = 0;
689 span.specBlueStep = 0;
690
691 #define SET_XMAJOR 1
692 #define INTERP_XY 1
693 #define INTERP_Z 1
694 #define INTERP_FOG 1
695 #define INTERP_MULTITEX 1
696 #define PLOT(X,Y) \
697 { \
698 span.array->x[span.end] = X; \
699 span.array->y[span.end] = Y; \
700 span.array->z[span.end] = Z; \
701 span.array->fog[span.end] = fog0; \
702 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { \
703 if (ctx->Texture.Unit[u]._ReallyEnabled) { \
704 span.array->texcoords[u][span.end][0] = fragTexcoord[u][0]; \
705 span.array->texcoords[u][span.end][1] = fragTexcoord[u][1]; \
706 span.array->texcoords[u][span.end][2] = fragTexcoord[u][2]; \
707 span.array->lambda[u][span.end] = 0.0; \
708 } \
709 } \
710 span.end++; \
711 }
712 #include "s_linetemp.h"
713
714 if (ctx->Line.StippleFlag) {
715 span.arrayMask |= SPAN_MASK;
716 compute_stipple_mask(ctx, span.end, span.array->mask);
717 }
718
719 if (ctx->Line.Width > 1.0) {
720 draw_wide_line(ctx, &span, xMajor);
721 }
722 else {
723 _mesa_write_texture_span(ctx, &span);
724 }
725 }
726
727
728 void _swrast_add_spec_terms_line( GLcontext *ctx,
729 const SWvertex *v0,
730 const SWvertex *v1 )
731 {
732 SWvertex *ncv0 = (SWvertex *)v0;
733 SWvertex *ncv1 = (SWvertex *)v1;
734 GLchan c[2][4];
735 COPY_CHAN4( c[0], ncv0->color );
736 COPY_CHAN4( c[1], ncv1->color );
737 ACC_3V( ncv0->color, ncv0->specular );
738 ACC_3V( ncv1->color, ncv1->specular );
739 SWRAST_CONTEXT(ctx)->SpecLine( ctx, ncv0, ncv1 );
740 COPY_CHAN4( ncv0->color, c[0] );
741 COPY_CHAN4( ncv1->color, c[1] );
742 }
743
744
745 #ifdef DEBUG
746 extern void
747 _mesa_print_line_function(GLcontext *ctx); /* silence compiler warning */
748 void
749 _mesa_print_line_function(GLcontext *ctx)
750 {
751 SWcontext *swrast = SWRAST_CONTEXT(ctx);
752
753 _mesa_printf("Line Func == ");
754 if (swrast->Line == flat_ci_line)
755 _mesa_printf("flat_ci_line\n");
756 else if (swrast->Line == flat_rgba_line)
757 _mesa_printf("flat_rgba_line\n");
758 else if (swrast->Line == smooth_ci_line)
759 _mesa_printf("smooth_ci_line\n");
760 else if (swrast->Line == smooth_rgba_line)
761 _mesa_printf("smooth_rgba_line\n");
762 else if (swrast->Line == general_smooth_ci_line)
763 _mesa_printf("general_smooth_ci_line\n");
764 else if (swrast->Line == general_flat_ci_line)
765 _mesa_printf("general_flat_ci_line\n");
766 else if (swrast->Line == general_smooth_rgba_line)
767 _mesa_printf("general_smooth_rgba_line\n");
768 else if (swrast->Line == general_flat_rgba_line)
769 _mesa_printf("general_flat_rgba_line\n");
770 else if (swrast->Line == flat_textured_line)
771 _mesa_printf("flat_textured_line\n");
772 else if (swrast->Line == smooth_textured_line)
773 _mesa_printf("smooth_textured_line\n");
774 else if (swrast->Line == smooth_multitextured_line)
775 _mesa_printf("smooth_multitextured_line\n");
776 else if (swrast->Line == flat_multitextured_line)
777 _mesa_printf("flat_multitextured_line\n");
778 else
779 _mesa_printf("Driver func %p\n", (void *) swrast->Line);
780 }
781 #endif
782
783
784
785 #ifdef DEBUG
786
787 /* record the current line function name */
788 static const char *lineFuncName = NULL;
789
790 #define USE(lineFunc) \
791 do { \
792 lineFuncName = #lineFunc; \
793 /*_mesa_printf("%s\n", lineFuncName);*/ \
794 swrast->Line = lineFunc; \
795 } while (0)
796
797 #else
798
799 #define USE(lineFunc) swrast->Line = lineFunc
800
801 #endif
802
803
804
805 /*
806 * Determine which line drawing function to use given the current
807 * rendering context.
808 *
809 * Please update the summary flag _SWRAST_NEW_LINE if you add or remove
810 * tests to this code.
811 */
812 void
813 _swrast_choose_line( GLcontext *ctx )
814 {
815 SWcontext *swrast = SWRAST_CONTEXT(ctx);
816 const GLboolean rgbmode = ctx->Visual.rgbMode;
817
818 if (ctx->RenderMode == GL_RENDER) {
819 if (ctx->Line.SmoothFlag) {
820 /* antialiased lines */
821 _swrast_choose_aa_line_function(ctx);
822 ASSERT(swrast->Triangle);
823 }
824 else if (ctx->Texture._EnabledUnits) {
825 if (ctx->Texture._EnabledUnits > 1 ||
826 (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)) {
827 /* multi-texture and/or separate specular color */
828 if (ctx->Light.ShadeModel == GL_SMOOTH)
829 USE(smooth_multitextured_line);
830 else
831 USE(flat_multitextured_line);
832 }
833 else {
834 if (ctx->Light.ShadeModel == GL_SMOOTH) {
835 USE(smooth_textured_line);
836 }
837 else {
838 USE(flat_textured_line);
839 }
840 }
841 }
842 else {
843 if (ctx->Light.ShadeModel == GL_SMOOTH) {
844 if (ctx->Depth.Test || ctx->Fog.Enabled || ctx->Line.Width != 1.0
845 || ctx->Line.StippleFlag) {
846 if (rgbmode)
847 USE(general_smooth_rgba_line);
848 else
849 USE(general_smooth_ci_line);
850 }
851 else {
852 if (rgbmode)
853 USE(smooth_rgba_line);
854 else
855 USE(smooth_ci_line);
856 }
857 }
858 else {
859 if (ctx->Depth.Test || ctx->Fog.Enabled || ctx->Line.Width != 1.0
860 || ctx->Line.StippleFlag) {
861 if (rgbmode)
862 USE(general_flat_rgba_line);
863 else
864 USE(general_flat_ci_line);
865 }
866 else {
867 if (rgbmode)
868 USE(flat_rgba_line);
869 else
870 USE(flat_ci_line);
871 }
872 }
873 }
874 }
875 else if (ctx->RenderMode == GL_FEEDBACK) {
876 USE(_mesa_feedback_line);
877 }
878 else {
879 ASSERT(ctx->RenderMode == GL_SELECT);
880 USE(_mesa_select_line);
881 }
882
883 /*_mesa_print_line_function(ctx);*/
884 }