support for N texture units
[mesa.git] / src / mesa / main / lines.c
1 /* $Id: lines.c,v 1.15 2000/09/30 18:42:29 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2000 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 #ifdef PC_HEADER
29 #include "all.h"
30 #else
31 #include "glheader.h"
32 #include "context.h"
33 #include "depth.h"
34 #include "feedback.h"
35 #include "lines.h"
36 #include "macros.h"
37 #include "mmath.h"
38 #include "pb.h"
39 #include "texstate.h"
40 #include "types.h"
41 #include "vb.h"
42 #endif
43
44
45
46 void
47 _mesa_LineWidth( GLfloat width )
48 {
49 GET_CURRENT_CONTEXT(ctx);
50 if (width<=0.0) {
51 gl_error( ctx, GL_INVALID_VALUE, "glLineWidth" );
52 return;
53 }
54 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLineWidth");
55
56 if (ctx->Line.Width != width) {
57 ctx->Line.Width = width;
58 ctx->TriangleCaps &= ~DD_LINE_WIDTH;
59 if (width != 1.0) ctx->TriangleCaps |= DD_LINE_WIDTH;
60 ctx->NewState |= NEW_RASTER_OPS;
61 if (ctx->Driver.LineWidth)
62 (*ctx->Driver.LineWidth)(ctx, width);
63 }
64 }
65
66
67
68 void
69 _mesa_LineStipple( GLint factor, GLushort pattern )
70 {
71 GET_CURRENT_CONTEXT(ctx);
72 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLineStipple");
73 ctx->Line.StippleFactor = CLAMP( factor, 1, 256 );
74 ctx->Line.StipplePattern = pattern;
75 ctx->NewState |= NEW_RASTER_OPS;
76
77 if (ctx->Driver.LineStipple)
78 ctx->Driver.LineStipple( ctx, factor, pattern );
79 }
80
81
82
83 /**********************************************************************/
84 /***** Rasterization *****/
85 /**********************************************************************/
86
87
88 /*
89 * There are 4 pairs (RGBA, CI) of line drawing functions:
90 * 1. simple: width=1 and no special rasterization functions (fastest)
91 * 2. flat: width=1, non-stippled, flat-shaded, any raster operations
92 * 3. smooth: width=1, non-stippled, smooth-shaded, any raster operations
93 * 4. general: any other kind of line (slowest)
94 */
95
96
97 /*
98 * All line drawing functions have the same arguments:
99 * v1, v2 - indexes of first and second endpoints into vertex buffer arrays
100 * pv - provoking vertex: which vertex color/index to use for flat shading.
101 */
102
103
104
105
106
107
108 #if MAX_WIDTH > MAX_HEIGHT
109 # define MAXPOINTS MAX_WIDTH
110 #else
111 # define MAXPOINTS MAX_HEIGHT
112 #endif
113
114
115 /* Flat, color index line */
116 static void flat_ci_line( GLcontext *ctx,
117 GLuint vert0, GLuint vert1, GLuint pvert )
118 {
119 PB_SET_INDEX( ctx->PB, ctx->VB->IndexPtr->data[pvert] );
120
121 #define INTERP_XY 1
122 #define PLOT(X,Y) PB_WRITE_PIXEL(ctx->PB, X, Y, 0);
123
124 #include "linetemp.h"
125
126 gl_flush_pb(ctx);
127 }
128
129
130
131 /* Flat, color index line with Z interpolation/testing */
132 static void flat_ci_z_line( GLcontext *ctx,
133 GLuint vert0, GLuint vert1, GLuint pvert )
134 {
135 PB_SET_INDEX( ctx->PB, ctx->VB->IndexPtr->data[pvert] );
136
137 #define INTERP_XY 1
138 #define INTERP_Z 1
139 #define PLOT(X,Y) PB_WRITE_PIXEL(ctx->PB, X, Y, Z);
140
141 #include "linetemp.h"
142
143 gl_flush_pb(ctx);
144 }
145
146
147
148 /* Flat-shaded, RGBA line */
149 static void flat_rgba_line( GLcontext *ctx,
150 GLuint vert0, GLuint vert1, GLuint pvert )
151 {
152 const GLubyte *color = ctx->VB->ColorPtr->data[pvert];
153 PB_SET_COLOR( ctx->PB, color[0], color[1], color[2], color[3] );
154
155 #define INTERP_XY 1
156 #define PLOT(X,Y) PB_WRITE_PIXEL(ctx->PB, X, Y, 0);
157
158 #include "linetemp.h"
159
160 gl_flush_pb(ctx);
161 }
162
163
164
165 /* Flat-shaded, RGBA line with Z interpolation/testing */
166 static void flat_rgba_z_line( GLcontext *ctx,
167 GLuint vert0, GLuint vert1, GLuint pvert )
168 {
169 const GLubyte *color = ctx->VB->ColorPtr->data[pvert];
170 PB_SET_COLOR( ctx->PB, color[0], color[1], color[2], color[3] );
171
172 #define INTERP_XY 1
173 #define INTERP_Z 1
174 #define PLOT(X,Y) PB_WRITE_PIXEL(ctx->PB, X, Y, Z);
175
176 #include "linetemp.h"
177
178 gl_flush_pb(ctx);
179 }
180
181
182
183 /* Smooth shaded, color index line */
184 static void smooth_ci_line( GLcontext *ctx,
185 GLuint vert0, GLuint vert1, GLuint pvert )
186 {
187 GLint count = ctx->PB->count;
188 GLint *pbx = ctx->PB->x;
189 GLint *pby = ctx->PB->y;
190 GLuint *pbi = ctx->PB->index;
191 (void) pvert;
192
193 ctx->PB->mono = GL_FALSE;
194
195 #define INTERP_XY 1
196 #define INTERP_INDEX 1
197
198 #define PLOT(X,Y) \
199 pbx[count] = X; \
200 pby[count] = Y; \
201 pbi[count] = I; \
202 count++;
203
204 #include "linetemp.h"
205
206 ctx->PB->count = count;
207 gl_flush_pb(ctx);
208 }
209
210
211
212 /* Smooth shaded, color index line with Z interpolation/testing */
213 static void smooth_ci_z_line( GLcontext *ctx,
214 GLuint vert0, GLuint vert1, GLuint pvert )
215 {
216 GLint count = ctx->PB->count;
217 GLint *pbx = ctx->PB->x;
218 GLint *pby = ctx->PB->y;
219 GLdepth *pbz = ctx->PB->z;
220 GLuint *pbi = ctx->PB->index;
221 (void) pvert;
222
223 ctx->PB->mono = GL_FALSE;
224
225 #define INTERP_XY 1
226 #define INTERP_Z 1
227 #define INTERP_INDEX 1
228
229 #define PLOT(X,Y) \
230 pbx[count] = X; \
231 pby[count] = Y; \
232 pbz[count] = Z; \
233 pbi[count] = I; \
234 count++;
235
236 #include "linetemp.h"
237
238 ctx->PB->count = count;
239 gl_flush_pb(ctx);
240 }
241
242
243
244 /* Smooth-shaded, RGBA line */
245 static void smooth_rgba_line( GLcontext *ctx,
246 GLuint vert0, GLuint vert1, GLuint pvert )
247 {
248 GLint count = ctx->PB->count;
249 GLint *pbx = ctx->PB->x;
250 GLint *pby = ctx->PB->y;
251 GLubyte (*pbrgba)[4] = ctx->PB->rgba;
252 (void) pvert;
253
254 ctx->PB->mono = GL_FALSE;
255
256 #define INTERP_XY 1
257 #define INTERP_RGB 1
258 #define INTERP_ALPHA 1
259
260 #define PLOT(X,Y) \
261 pbx[count] = X; \
262 pby[count] = Y; \
263 pbrgba[count][RCOMP] = FixedToInt(r0); \
264 pbrgba[count][GCOMP] = FixedToInt(g0); \
265 pbrgba[count][BCOMP] = FixedToInt(b0); \
266 pbrgba[count][ACOMP] = FixedToInt(a0); \
267 count++;
268
269 #include "linetemp.h"
270
271 ctx->PB->count = count;
272 gl_flush_pb(ctx);
273 }
274
275
276
277 /* Smooth-shaded, RGBA line with Z interpolation/testing */
278 static void smooth_rgba_z_line( GLcontext *ctx,
279 GLuint vert0, GLuint vert1, GLuint pvert )
280 {
281 GLint count = ctx->PB->count;
282 GLint *pbx = ctx->PB->x;
283 GLint *pby = ctx->PB->y;
284 GLdepth *pbz = ctx->PB->z;
285 GLubyte (*pbrgba)[4] = ctx->PB->rgba;
286 (void) pvert;
287
288 ctx->PB->mono = GL_FALSE;
289
290 #define INTERP_XY 1
291 #define INTERP_Z 1
292 #define INTERP_RGB 1
293 #define INTERP_ALPHA 1
294
295 #define PLOT(X,Y) \
296 pbx[count] = X; \
297 pby[count] = Y; \
298 pbz[count] = Z; \
299 pbrgba[count][RCOMP] = FixedToInt(r0); \
300 pbrgba[count][GCOMP] = FixedToInt(g0); \
301 pbrgba[count][BCOMP] = FixedToInt(b0); \
302 pbrgba[count][ACOMP] = FixedToInt(a0); \
303 count++;
304
305 #include "linetemp.h"
306
307 ctx->PB->count = count;
308 gl_flush_pb(ctx);
309 }
310
311
312 #define CHECK_FULL(count) \
313 if (count >= PB_SIZE-MAX_WIDTH) { \
314 ctx->PB->count = count; \
315 gl_flush_pb(ctx); \
316 count = ctx->PB->count; \
317 }
318
319
320
321 /* Smooth shaded, color index, any width, maybe stippled */
322 static void general_smooth_ci_line( GLcontext *ctx,
323 GLuint vert0, GLuint vert1, GLuint pvert )
324 {
325 GLint count = ctx->PB->count;
326 GLint *pbx = ctx->PB->x;
327 GLint *pby = ctx->PB->y;
328 GLdepth *pbz = ctx->PB->z;
329 GLuint *pbi = ctx->PB->index;
330 (void) pvert;
331
332 ctx->PB->mono = GL_FALSE;
333
334 if (ctx->Line.StippleFlag) {
335 /* stippled */
336 #define INTERP_XY 1
337 #define INTERP_Z 1
338 #define INTERP_INDEX 1
339 #define WIDE 1
340 #define STIPPLE 1
341 #define PLOT(X,Y) \
342 pbx[count] = X; \
343 pby[count] = Y; \
344 pbz[count] = Z; \
345 pbi[count] = I; \
346 count++; \
347 CHECK_FULL(count);
348 #include "linetemp.h"
349 }
350 else {
351 /* unstippled */
352 if (ctx->Line.Width==2.0F) {
353 /* special case: unstippled and width=2 */
354 #define INTERP_XY 1
355 #define INTERP_Z 1
356 #define INTERP_INDEX 1
357 #define XMAJOR_PLOT(X,Y) \
358 pbx[count] = X; pbx[count+1] = X; \
359 pby[count] = Y; pby[count+1] = Y+1; \
360 pbz[count] = Z; pbz[count+1] = Z; \
361 pbi[count] = I; pbi[count+1] = I; \
362 count += 2; \
363 CHECK_FULL(count);
364 #define YMAJOR_PLOT(X,Y) \
365 pbx[count] = X; pbx[count+1] = X+1; \
366 pby[count] = Y; pby[count+1] = Y; \
367 pbz[count] = Z; pbz[count+1] = Z; \
368 pbi[count] = I; pbi[count+1] = I; \
369 count += 2; \
370 CHECK_FULL(count);
371 #include "linetemp.h"
372 }
373 else {
374 /* unstippled, any width */
375 #define INTERP_XY 1
376 #define INTERP_Z 1
377 #define INTERP_INDEX 1
378 #define WIDE 1
379 #define PLOT(X,Y) \
380 pbx[count] = X; \
381 pby[count] = Y; \
382 pbz[count] = Z; \
383 pbi[count] = I; \
384 count++; \
385 CHECK_FULL(count);
386 #include "linetemp.h"
387 }
388 }
389
390 ctx->PB->count = count;
391 gl_flush_pb(ctx);
392 }
393
394
395 /* Flat shaded, color index, any width, maybe stippled */
396 static void general_flat_ci_line( GLcontext *ctx,
397 GLuint vert0, GLuint vert1, GLuint pvert )
398 {
399 GLint count;
400 GLint *pbx = ctx->PB->x;
401 GLint *pby = ctx->PB->y;
402 GLdepth *pbz = ctx->PB->z;
403 PB_SET_INDEX( ctx->PB, ctx->VB->IndexPtr->data[pvert] );
404 count = ctx->PB->count;
405
406 if (ctx->Line.StippleFlag) {
407 /* stippled, any width */
408 #define INTERP_XY 1
409 #define INTERP_Z 1
410 #define WIDE 1
411 #define STIPPLE 1
412 #define PLOT(X,Y) \
413 pbx[count] = X; \
414 pby[count] = Y; \
415 pbz[count] = Z; \
416 count++; \
417 CHECK_FULL(count);
418 #include "linetemp.h"
419 }
420 else {
421 /* unstippled */
422 if (ctx->Line.Width==2.0F) {
423 /* special case: unstippled and width=2 */
424 #define INTERP_XY 1
425 #define INTERP_Z 1
426 #define XMAJOR_PLOT(X,Y) \
427 pbx[count] = X; pbx[count+1] = X; \
428 pby[count] = Y; pby[count+1] = Y+1; \
429 pbz[count] = Z; pbz[count+1] = Z; \
430 count += 2; \
431 CHECK_FULL(count);
432 #define YMAJOR_PLOT(X,Y) \
433 pbx[count] = X; pbx[count+1] = X+1; \
434 pby[count] = Y; pby[count+1] = Y; \
435 pbz[count] = Z; pbz[count+1] = Z; \
436 count += 2; \
437 CHECK_FULL(count);
438 #include "linetemp.h"
439 }
440 else {
441 /* unstippled, any width */
442 #define INTERP_XY 1
443 #define INTERP_Z 1
444 #define WIDE 1
445 #define PLOT(X,Y) \
446 pbx[count] = X; \
447 pby[count] = Y; \
448 pbz[count] = Z; \
449 count++; \
450 CHECK_FULL(count);
451 #include "linetemp.h"
452 }
453 }
454
455 ctx->PB->count = count;
456 gl_flush_pb(ctx);
457 }
458
459
460
461 static void general_smooth_rgba_line( GLcontext *ctx,
462 GLuint vert0, GLuint vert1, GLuint pvert)
463 {
464 GLint count = ctx->PB->count;
465 GLint *pbx = ctx->PB->x;
466 GLint *pby = ctx->PB->y;
467 GLdepth *pbz = ctx->PB->z;
468 GLubyte (*pbrgba)[4] = ctx->PB->rgba;
469 (void) pvert;
470
471 ctx->PB->mono = GL_FALSE;
472
473 if (ctx->Line.StippleFlag) {
474 /* stippled */
475 #define INTERP_XY 1
476 #define INTERP_Z 1
477 #define INTERP_RGB 1
478 #define INTERP_ALPHA 1
479 #define WIDE 1
480 #define STIPPLE 1
481 #define PLOT(X,Y) \
482 pbx[count] = X; \
483 pby[count] = Y; \
484 pbz[count] = Z; \
485 pbrgba[count][RCOMP] = FixedToInt(r0); \
486 pbrgba[count][GCOMP] = FixedToInt(g0); \
487 pbrgba[count][BCOMP] = FixedToInt(b0); \
488 pbrgba[count][ACOMP] = FixedToInt(a0); \
489 count++; \
490 CHECK_FULL(count);
491 #include "linetemp.h"
492 }
493 else {
494 /* unstippled */
495 if (ctx->Line.Width==2.0F) {
496 /* special case: unstippled and width=2 */
497 #define INTERP_XY 1
498 #define INTERP_Z 1
499 #define INTERP_RGB 1
500 #define INTERP_ALPHA 1
501 #define XMAJOR_PLOT(X,Y) \
502 pbx[count] = X; pbx[count+1] = X; \
503 pby[count] = Y; pby[count+1] = Y+1; \
504 pbz[count] = Z; pbz[count+1] = Z; \
505 pbrgba[count][RCOMP] = FixedToInt(r0); \
506 pbrgba[count][GCOMP] = FixedToInt(g0); \
507 pbrgba[count][BCOMP] = FixedToInt(b0); \
508 pbrgba[count][ACOMP] = FixedToInt(a0); \
509 pbrgba[count+1][RCOMP] = FixedToInt(r0); \
510 pbrgba[count+1][GCOMP] = FixedToInt(g0); \
511 pbrgba[count+1][BCOMP] = FixedToInt(b0); \
512 pbrgba[count+1][ACOMP] = FixedToInt(a0); \
513 count += 2; \
514 CHECK_FULL(count);
515 #define YMAJOR_PLOT(X,Y) \
516 pbx[count] = X; pbx[count+1] = X+1; \
517 pby[count] = Y; pby[count+1] = Y; \
518 pbz[count] = Z; pbz[count+1] = Z; \
519 pbrgba[count][RCOMP] = FixedToInt(r0); \
520 pbrgba[count][GCOMP] = FixedToInt(g0); \
521 pbrgba[count][BCOMP] = FixedToInt(b0); \
522 pbrgba[count][ACOMP] = FixedToInt(a0); \
523 pbrgba[count+1][RCOMP] = FixedToInt(r0); \
524 pbrgba[count+1][GCOMP] = FixedToInt(g0); \
525 pbrgba[count+1][BCOMP] = FixedToInt(b0); \
526 pbrgba[count+1][ACOMP] = FixedToInt(a0); \
527 count += 2; \
528 CHECK_FULL(count);
529 #include "linetemp.h"
530 }
531 else {
532 /* unstippled, any width */
533 #define INTERP_XY 1
534 #define INTERP_Z 1
535 #define INTERP_RGB 1
536 #define INTERP_ALPHA 1
537 #define WIDE 1
538 #define PLOT(X,Y) \
539 pbx[count] = X; \
540 pby[count] = Y; \
541 pbz[count] = Z; \
542 pbrgba[count][RCOMP] = FixedToInt(r0); \
543 pbrgba[count][GCOMP] = FixedToInt(g0); \
544 pbrgba[count][BCOMP] = FixedToInt(b0); \
545 pbrgba[count][ACOMP] = FixedToInt(a0); \
546 count++; \
547 CHECK_FULL(count);
548 #include "linetemp.h"
549 }
550 }
551
552 ctx->PB->count = count;
553 gl_flush_pb(ctx);
554 }
555
556
557 static void general_flat_rgba_line( GLcontext *ctx,
558 GLuint vert0, GLuint vert1, GLuint pvert )
559 {
560 const GLubyte *color = ctx->VB->ColorPtr->data[pvert];
561 PB_SET_COLOR( ctx->PB, color[0], color[1], color[2], color[3] );
562
563 if (ctx->Line.StippleFlag) {
564 /* stippled */
565 #define INTERP_XY 1
566 #define INTERP_Z 1
567 #define WIDE 1
568 #define STIPPLE 1
569 #define PLOT(X,Y) PB_WRITE_PIXEL(ctx->PB, X, Y, Z);
570 #include "linetemp.h"
571 }
572 else {
573 /* unstippled */
574 if (ctx->Line.Width==2.0F) {
575 /* special case: unstippled and width=2 */
576 #define INTERP_XY 1
577 #define INTERP_Z 1
578 #define XMAJOR_PLOT(X,Y) PB_WRITE_PIXEL(ctx->PB, X, Y, Z); \
579 PB_WRITE_PIXEL(ctx->PB, X, Y+1, Z);
580 #define YMAJOR_PLOT(X,Y) PB_WRITE_PIXEL(ctx->PB, X, Y, Z); \
581 PB_WRITE_PIXEL(ctx->PB, X+1, Y, Z);
582 #include "linetemp.h"
583 }
584 else {
585 /* unstippled, any width */
586 #define INTERP_XY 1
587 #define INTERP_Z 1
588 #define WIDE 1
589 #define PLOT(X,Y) PB_WRITE_PIXEL(ctx->PB, X, Y, Z);
590 #include "linetemp.h"
591 }
592 }
593
594 gl_flush_pb(ctx);
595 }
596
597
598 /* Flat-shaded, textured, any width, maybe stippled */
599 static void flat_textured_line( GLcontext *ctx,
600 GLuint vert0, GLuint vert1, GLuint pv )
601 {
602 GLint count;
603 GLint *pbx = ctx->PB->x;
604 GLint *pby = ctx->PB->y;
605 GLdepth *pbz = ctx->PB->z;
606 GLfloat *pbs = ctx->PB->s[0];
607 GLfloat *pbt = ctx->PB->t[0];
608 GLfloat *pbu = ctx->PB->u[0];
609 GLubyte *color = ctx->VB->ColorPtr->data[pv];
610 PB_SET_COLOR( ctx->PB, color[0], color[1], color[2], color[3] );
611 count = ctx->PB->count;
612
613 if (ctx->Line.StippleFlag) {
614 /* stippled */
615 #define INTERP_XY 1
616 #define INTERP_Z 1
617 #define INTERP_TEX 1
618 #define WIDE 1
619 #define STIPPLE 1
620 #define PLOT(X,Y) \
621 { \
622 pbx[count] = X; \
623 pby[count] = Y; \
624 pbz[count] = Z; \
625 pbs[count] = fragTexcoord[0];\
626 pbt[count] = fragTexcoord[1];\
627 pbu[count] = fragTexcoord[2];\
628 count++; \
629 CHECK_FULL(count); \
630 }
631 #include "linetemp.h"
632 }
633 else {
634 /* unstippled */
635 #define INTERP_XY 1
636 #define INTERP_Z 1
637 #define INTERP_TEX 1
638 #define WIDE 1
639 #define PLOT(X,Y) \
640 { \
641 pbx[count] = X; \
642 pby[count] = Y; \
643 pbz[count] = Z; \
644 pbs[count] = fragTexcoord[0];\
645 pbt[count] = fragTexcoord[1];\
646 pbu[count] = fragTexcoord[2];\
647 count++; \
648 CHECK_FULL(count); \
649 }
650 #include "linetemp.h"
651 }
652
653 ctx->PB->count = count;
654 gl_flush_pb(ctx);
655 }
656
657
658
659 /* Smooth-shaded, textured, any width, maybe stippled */
660 static void smooth_textured_line( GLcontext *ctx,
661 GLuint vert0, GLuint vert1, GLuint pvert )
662 {
663 GLint count = ctx->PB->count;
664 GLint *pbx = ctx->PB->x;
665 GLint *pby = ctx->PB->y;
666 GLdepth *pbz = ctx->PB->z;
667 GLfloat *pbs = ctx->PB->s[0];
668 GLfloat *pbt = ctx->PB->t[0];
669 GLfloat *pbu = ctx->PB->u[0];
670 GLubyte (*pbrgba)[4] = ctx->PB->rgba;
671 (void) pvert;
672
673 ctx->PB->mono = GL_FALSE;
674
675 if (ctx->Line.StippleFlag) {
676 /* stippled */
677 #define INTERP_XY 1
678 #define INTERP_Z 1
679 #define INTERP_RGB 1
680 #define INTERP_ALPHA 1
681 #define INTERP_TEX 1
682 #define WIDE 1
683 #define STIPPLE 1
684 #define PLOT(X,Y) \
685 { \
686 pbx[count] = X; \
687 pby[count] = Y; \
688 pbz[count] = Z; \
689 pbs[count] = fragTexcoord[0]; \
690 pbt[count] = fragTexcoord[1]; \
691 pbu[count] = fragTexcoord[2]; \
692 pbrgba[count][RCOMP] = FixedToInt(r0); \
693 pbrgba[count][GCOMP] = FixedToInt(g0); \
694 pbrgba[count][BCOMP] = FixedToInt(b0); \
695 pbrgba[count][ACOMP] = FixedToInt(a0); \
696 count++; \
697 CHECK_FULL(count); \
698 }
699 #include "linetemp.h"
700 }
701 else {
702 /* unstippled */
703 #define INTERP_XY 1
704 #define INTERP_Z 1
705 #define INTERP_RGB 1
706 #define INTERP_ALPHA 1
707 #define INTERP_TEX 1
708 #define WIDE 1
709 #define PLOT(X,Y) \
710 { \
711 pbx[count] = X; \
712 pby[count] = Y; \
713 pbz[count] = Z; \
714 pbs[count] = fragTexcoord[0]; \
715 pbt[count] = fragTexcoord[1]; \
716 pbu[count] = fragTexcoord[2]; \
717 pbrgba[count][RCOMP] = FixedToInt(r0); \
718 pbrgba[count][GCOMP] = FixedToInt(g0); \
719 pbrgba[count][BCOMP] = FixedToInt(b0); \
720 pbrgba[count][ACOMP] = FixedToInt(a0); \
721 count++; \
722 CHECK_FULL(count); \
723 }
724 #include "linetemp.h"
725 }
726
727 ctx->PB->count = count;
728 gl_flush_pb(ctx);
729 }
730
731
732 /* Smooth-shaded, multitextured, any width, maybe stippled, separate specular
733 * color interpolation.
734 */
735 static void smooth_multitextured_line( GLcontext *ctx,
736 GLuint vert0, GLuint vert1, GLuint pvert )
737 {
738 GLint count = ctx->PB->count;
739 GLint *pbx = ctx->PB->x;
740 GLint *pby = ctx->PB->y;
741 GLdepth *pbz = ctx->PB->z;
742 GLubyte (*pbrgba)[4] = ctx->PB->rgba;
743 GLubyte (*pbspec)[3] = ctx->PB->spec;
744 (void) pvert;
745
746 ctx->PB->mono = GL_FALSE;
747
748 if (ctx->Line.StippleFlag) {
749 /* stippled */
750 #define INTERP_XY 1
751 #define INTERP_Z 1
752 #define INTERP_RGB 1
753 #define INTERP_SPEC 1
754 #define INTERP_ALPHA 1
755 #define INTERP_MULTITEX 1
756 #define WIDE 1
757 #define STIPPLE 1
758 #define PLOT(X,Y) \
759 { \
760 GLuint u; \
761 pbx[count] = X; \
762 pby[count] = Y; \
763 pbz[count] = Z; \
764 pbrgba[count][RCOMP] = FixedToInt(r0); \
765 pbrgba[count][GCOMP] = FixedToInt(g0); \
766 pbrgba[count][BCOMP] = FixedToInt(b0); \
767 pbrgba[count][ACOMP] = FixedToInt(a0); \
768 pbspec[count][RCOMP] = FixedToInt(sr0); \
769 pbspec[count][GCOMP] = FixedToInt(sg0); \
770 pbspec[count][BCOMP] = FixedToInt(sb0); \
771 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { \
772 if (ctx->Texture.Unit[u].ReallyEnabled) { \
773 ctx->PB->s[u][0] = fragTexcoord[u][0]; \
774 ctx->PB->s[u][1] = fragTexcoord[u][1]; \
775 ctx->PB->s[u][2] = fragTexcoord[u][2]; \
776 ctx->PB->s[u][3] = fragTexcoord[u][3]; \
777 } \
778 } \
779 count++; \
780 CHECK_FULL(count); \
781 }
782 #include "linetemp.h"
783 }
784 else {
785 /* unstippled */
786 #define INTERP_XY 1
787 #define INTERP_Z 1
788 #define INTERP_RGB 1
789 #define INTERP_SPEC 1
790 #define INTERP_ALPHA 1
791 #define INTERP_MULTITEX 1
792 #define WIDE 1
793 #define PLOT(X,Y) \
794 { \
795 GLuint u; \
796 pbx[count] = X; \
797 pby[count] = Y; \
798 pbz[count] = Z; \
799 pbrgba[count][RCOMP] = FixedToInt(r0); \
800 pbrgba[count][GCOMP] = FixedToInt(g0); \
801 pbrgba[count][BCOMP] = FixedToInt(b0); \
802 pbrgba[count][ACOMP] = FixedToInt(a0); \
803 pbspec[count][RCOMP] = FixedToInt(sr0); \
804 pbspec[count][GCOMP] = FixedToInt(sg0); \
805 pbspec[count][BCOMP] = FixedToInt(sb0); \
806 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { \
807 if (ctx->Texture.Unit[u].ReallyEnabled) { \
808 ctx->PB->s[u][0] = fragTexcoord[u][0]; \
809 ctx->PB->s[u][1] = fragTexcoord[u][1]; \
810 ctx->PB->s[u][2] = fragTexcoord[u][2]; \
811 ctx->PB->s[u][3] = fragTexcoord[u][3]; \
812 } \
813 } \
814 count++; \
815 CHECK_FULL(count); \
816 }
817 #include "linetemp.h"
818 }
819
820 ctx->PB->count = count;
821 gl_flush_pb(ctx);
822 }
823
824
825 /* Flat-shaded, multitextured, any width, maybe stippled, separate specular
826 * color interpolation.
827 */
828 static void flat_multitextured_line( GLcontext *ctx,
829 GLuint vert0, GLuint vert1, GLuint pvert )
830 {
831 GLint count = ctx->PB->count;
832 GLint *pbx = ctx->PB->x;
833 GLint *pby = ctx->PB->y;
834 GLdepth *pbz = ctx->PB->z;
835 GLubyte (*pbrgba)[4] = ctx->PB->rgba;
836 GLubyte (*pbspec)[3] = ctx->PB->spec;
837 GLubyte *color = ctx->VB->ColorPtr->data[pvert];
838 GLubyte sRed = ctx->VB->Specular ? ctx->VB->Specular[pvert][0] : 0;
839 GLubyte sGreen = ctx->VB->Specular ? ctx->VB->Specular[pvert][1] : 0;
840 GLubyte sBlue = ctx->VB->Specular ? ctx->VB->Specular[pvert][2] : 0;
841
842 (void) pvert;
843
844 ctx->PB->mono = GL_FALSE;
845
846 if (ctx->Line.StippleFlag) {
847 /* stippled */
848 #define INTERP_XY 1
849 #define INTERP_Z 1
850 #define INTERP_ALPHA 1
851 #define INTERP_MULTITEX 1
852 #define WIDE 1
853 #define STIPPLE 1
854 #define PLOT(X,Y) \
855 { \
856 GLuint u; \
857 pbx[count] = X; \
858 pby[count] = Y; \
859 pbz[count] = Z; \
860 pbrgba[count][RCOMP] = color[0]; \
861 pbrgba[count][GCOMP] = color[1]; \
862 pbrgba[count][BCOMP] = color[2]; \
863 pbrgba[count][ACOMP] = color[3]; \
864 pbspec[count][RCOMP] = sRed; \
865 pbspec[count][GCOMP] = sGreen; \
866 pbspec[count][BCOMP] = sBlue; \
867 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { \
868 if (ctx->Texture.Unit[u].ReallyEnabled) { \
869 ctx->PB->s[u][0] = fragTexcoord[u][0]; \
870 ctx->PB->s[u][1] = fragTexcoord[u][1]; \
871 ctx->PB->s[u][2] = fragTexcoord[u][2]; \
872 ctx->PB->s[u][3] = fragTexcoord[u][3]; \
873 } \
874 } \
875 count++; \
876 CHECK_FULL(count); \
877 }
878 #include "linetemp.h"
879 }
880 else {
881 /* unstippled */
882 #define INTERP_XY 1
883 #define INTERP_Z 1
884 #define INTERP_ALPHA 1
885 #define INTERP_MULTITEX 1
886 #define WIDE 1
887 #define PLOT(X,Y) \
888 { \
889 GLuint u; \
890 pbx[count] = X; \
891 pby[count] = Y; \
892 pbz[count] = Z; \
893 pbrgba[count][RCOMP] = color[0]; \
894 pbrgba[count][GCOMP] = color[1]; \
895 pbrgba[count][BCOMP] = color[2]; \
896 pbrgba[count][ACOMP] = color[3]; \
897 pbspec[count][RCOMP] = sRed; \
898 pbspec[count][GCOMP] = sGreen; \
899 pbspec[count][BCOMP] = sBlue; \
900 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { \
901 if (ctx->Texture.Unit[u].ReallyEnabled) { \
902 ctx->PB->s[u][0] = fragTexcoord[u][0]; \
903 ctx->PB->s[u][1] = fragTexcoord[u][1]; \
904 ctx->PB->s[u][2] = fragTexcoord[u][2]; \
905 ctx->PB->s[u][3] = fragTexcoord[u][3]; \
906 } \
907 } \
908 count++; \
909 CHECK_FULL(count); \
910 }
911 #include "linetemp.h"
912 }
913
914 ctx->PB->count = count;
915 gl_flush_pb(ctx);
916 }
917
918
919
920
921 /*
922 * Antialiased RGBA line
923 *
924 * This AA line function isn't terribly efficient but it's pretty
925 * straight-forward to understand. Also, it doesn't exactly conform
926 * to the specification.
927 */
928 static void aa_rgba_line( GLcontext *ctx,
929 GLuint vert0, GLuint vert1, GLuint pvert )
930 {
931 #define INTERP_RGBA 1
932 #define PLOT(x, y) \
933 { \
934 PB_WRITE_RGBA_PIXEL( pb, (x), (y), z, \
935 red, green, blue, coverage ); \
936 }
937 #include "lnaatemp.h"
938 }
939
940 /*
941 * Antialiased Textured RGBA line
942 *
943 * This AA line function isn't terribly efficient but it's pretty
944 * straight-forward to understand. Also, it doesn't exactly conform
945 * to the specification.
946 */
947 static void aa_tex_rgba_line( GLcontext *ctx,
948 GLuint vert0, GLuint vert1, GLuint pvert )
949 {
950 #define INTERP_RGBA 1
951 #define INTERP_TEX 1
952 #define PLOT(x, y) \
953 { \
954 PB_WRITE_TEX_PIXEL( pb, (x), (y), z, red, green, blue, coverage, \
955 fragTexcoord[0], fragTexcoord[1], fragTexcoord[2] ); \
956 }
957 #include "lnaatemp.h"
958 }
959
960
961 /*
962 * Antialiased Multitextured RGBA line
963 *
964 * This AA line function isn't terribly efficient but it's pretty
965 * straight-forward to understand. Also, it doesn't exactly conform
966 * to the specification.
967 */
968 static void aa_multitex_rgba_line( GLcontext *ctx,
969 GLuint vert0, GLuint vert1, GLuint pvert )
970 {
971 #define INTERP_RGBA 1
972 #define INTERP_SPEC 1
973 #define INTERP_MULTITEX 1
974 #define PLOT(x, y) \
975 { \
976 PB_WRITE_MULTITEX_SPEC_PIXEL( pb, (x), (y), z, \
977 red, green, blue, coverage, specRed, specGreen, specBlue, \
978 fragTexcoord ); \
979 }
980 #include "lnaatemp.h"
981 }
982
983
984 /*
985 * Antialiased CI line. Same comments for RGBA antialiased lines apply.
986 */
987 static void aa_ci_line( GLcontext *ctx,
988 GLuint vert0, GLuint vert1, GLuint pvert )
989 {
990 #define INTERP_INDEX 1
991 #define PLOT(x, y) \
992 { \
993 PB_WRITE_CI_PIXEL( pb, (x), (y), z, index + coverage ); \
994 }
995 #include "lnaatemp.h"
996 }
997
998
999 /*
1000 * Null rasterizer for measuring transformation speed.
1001 */
1002 static void null_line( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv )
1003 {
1004 (void) ctx;
1005 (void) v1;
1006 (void) v2;
1007 (void) pv;
1008 }
1009
1010
1011
1012 #ifdef DEBUG
1013 void
1014 _mesa_print_line_function(GLcontext *ctx)
1015 {
1016 printf("Line Func == ");
1017 if (ctx->Driver.LineFunc == flat_ci_line)
1018 printf("flat_ci_line\n");
1019 else if (ctx->Driver.LineFunc == flat_ci_z_line)
1020 printf("flat_ci_z_line\n");
1021 else if (ctx->Driver.LineFunc == flat_rgba_line)
1022 printf("flat_rgba_line\n");
1023 else if (ctx->Driver.LineFunc == flat_rgba_z_line)
1024 printf("flat_rgba_z_line\n");
1025 else if (ctx->Driver.LineFunc == smooth_ci_line)
1026 printf("smooth_ci_line\n");
1027 else if (ctx->Driver.LineFunc == smooth_ci_z_line)
1028 printf("smooth_ci_z_line\n");
1029 else if (ctx->Driver.LineFunc == smooth_rgba_line)
1030 printf("smooth_rgba_line\n");
1031 else if (ctx->Driver.LineFunc == smooth_rgba_z_line)
1032 printf("smooth_rgba_z_line\n");
1033 else if (ctx->Driver.LineFunc == general_smooth_ci_line)
1034 printf("general_smooth_ci_line\n");
1035 else if (ctx->Driver.LineFunc == general_flat_ci_line)
1036 printf("general_flat_ci_line\n");
1037 else if (ctx->Driver.LineFunc == general_smooth_rgba_line)
1038 printf("general_smooth_rgba_line\n");
1039 else if (ctx->Driver.LineFunc == general_flat_rgba_line)
1040 printf("general_flat_rgba_line\n");
1041 else if (ctx->Driver.LineFunc == flat_textured_line)
1042 printf("flat_textured_line\n");
1043 else if (ctx->Driver.LineFunc == smooth_textured_line)
1044 printf("smooth_textured_line\n");
1045 else if (ctx->Driver.LineFunc == smooth_multitextured_line)
1046 printf("smooth_multitextured_line\n");
1047 else if (ctx->Driver.LineFunc == flat_multitextured_line)
1048 printf("flat_multitextured_line\n");
1049 else if (ctx->Driver.LineFunc == aa_rgba_line)
1050 printf("aa_rgba_line\n");
1051 else if (ctx->Driver.LineFunc == aa_tex_rgba_line)
1052 printf("aa_tex_rgba_line\n");
1053 else if (ctx->Driver.LineFunc == aa_multitex_rgba_line)
1054 printf("aa_multitex_rgba_line\n");
1055 else if (ctx->Driver.LineFunc == aa_ci_line)
1056 printf("aa_ci_line\n");
1057 else if (ctx->Driver.LineFunc == null_line)
1058 printf("null_line\n");
1059 else
1060 printf("Driver func %p\n", ctx->Driver.PointsFunc);
1061 }
1062 #endif
1063
1064
1065
1066 /*
1067 * Determine which line drawing function to use given the current
1068 * rendering context.
1069 */
1070 void gl_set_line_function( GLcontext *ctx )
1071 {
1072 GLboolean rgbmode = ctx->Visual.RGBAflag;
1073 /* TODO: antialiased lines */
1074
1075 if (ctx->RenderMode==GL_RENDER) {
1076 if (ctx->NoRaster) {
1077 ctx->Driver.LineFunc = null_line;
1078 return;
1079 }
1080 if (ctx->Driver.LineFunc) {
1081 /* Device driver will draw lines. */
1082 return;
1083 }
1084
1085 if (ctx->Line.SmoothFlag) {
1086 /* antialiased lines */
1087 if (rgbmode) {
1088 if (ctx->Texture.ReallyEnabled) {
1089 if (ctx->Texture.ReallyEnabled >= TEXTURE1_1D
1090 || ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR)
1091 /* Multitextured! */
1092 ctx->Driver.LineFunc = aa_multitex_rgba_line;
1093 else
1094 ctx->Driver.LineFunc = aa_tex_rgba_line;
1095 } else {
1096 ctx->Driver.LineFunc = aa_rgba_line;
1097 }
1098 }
1099 else {
1100 ctx->Driver.LineFunc = aa_ci_line;
1101 }
1102 }
1103 else if (ctx->Texture.ReallyEnabled) {
1104 if (ctx->Texture.ReallyEnabled >= TEXTURE1_1D
1105 || ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) {
1106 /* multi-texture and/or separate specular color */
1107 if (ctx->Light.ShadeModel==GL_SMOOTH)
1108 ctx->Driver.LineFunc = smooth_multitextured_line;
1109 else
1110 ctx->Driver.LineFunc = flat_multitextured_line;
1111 }
1112 else {
1113 if (ctx->Light.ShadeModel==GL_SMOOTH) {
1114 ctx->Driver.LineFunc = smooth_textured_line;
1115 }
1116 else {
1117 ctx->Driver.LineFunc = flat_textured_line;
1118 }
1119 }
1120 }
1121 else if (ctx->Line.Width!=1.0 || ctx->Line.StippleFlag
1122 || ctx->Line.SmoothFlag) {
1123 if (ctx->Light.ShadeModel==GL_SMOOTH) {
1124 if (rgbmode)
1125 ctx->Driver.LineFunc = general_smooth_rgba_line;
1126 else
1127 ctx->Driver.LineFunc = general_smooth_ci_line;
1128 }
1129 else {
1130 if (rgbmode)
1131 ctx->Driver.LineFunc = general_flat_rgba_line;
1132 else
1133 ctx->Driver.LineFunc = general_flat_ci_line;
1134 }
1135 }
1136 else {
1137 if (ctx->Light.ShadeModel==GL_SMOOTH) {
1138 /* Width==1, non-stippled, smooth-shaded */
1139 if (ctx->Depth.Test || ctx->FogMode == FOG_FRAGMENT) {
1140 if (rgbmode)
1141 ctx->Driver.LineFunc = smooth_rgba_z_line;
1142 else
1143 ctx->Driver.LineFunc = smooth_ci_z_line;
1144 }
1145 else {
1146 if (rgbmode)
1147 ctx->Driver.LineFunc = smooth_rgba_line;
1148 else
1149 ctx->Driver.LineFunc = smooth_ci_line;
1150 }
1151 }
1152 else {
1153 /* Width==1, non-stippled, flat-shaded */
1154 if (ctx->Depth.Test || ctx->FogMode == FOG_FRAGMENT) {
1155 if (rgbmode)
1156 ctx->Driver.LineFunc = flat_rgba_z_line;
1157 else
1158 ctx->Driver.LineFunc = flat_ci_z_line;
1159 }
1160 else {
1161 if (rgbmode)
1162 ctx->Driver.LineFunc = flat_rgba_line;
1163 else
1164 ctx->Driver.LineFunc = flat_ci_line;
1165 }
1166 }
1167 }
1168 }
1169 else if (ctx->RenderMode==GL_FEEDBACK) {
1170 ctx->Driver.LineFunc = gl_feedback_line;
1171 }
1172 else {
1173 /* GL_SELECT mode */
1174 ctx->Driver.LineFunc = gl_select_line;
1175 }
1176
1177 /*_mesa_print_line_function(ctx);*/
1178 }