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