lines.c revision e92dd16605dbad8dbf374ca40b8440ef4034a5d4
1/* $Id: lines.c,v 1.14 2000/09/29 16:58:44 brianp Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version:  3.3
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#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
46void
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
68void
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 */
116static 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 */
132static 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 */
149static 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 */
166static 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 */
184static 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 */
213static 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 */
245static 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 */
278static 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 */
322static 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 */
396static 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
461static 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
557static 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 */
599static 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_STUV0 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] = s;		\
626	   pbt[count] = t;		\
627	   pbu[count] = u;		\
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_STUV0 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] = s;		\
645	   pbt[count] = t;		\
646	   pbu[count] = u;		\
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 */
660static 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_STUV0 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] = s;				\
690	   pbt[count] = t;				\
691	   pbu[count] = u;				\
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_STUV0 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] = s;				\
715	   pbt[count] = t;				\
716	   pbu[count] = u;				\
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 */
735static 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   GLfloat *pbs = ctx->PB->s[0];
743   GLfloat *pbt = ctx->PB->t[0];
744   GLfloat *pbu = ctx->PB->u[0];
745   GLfloat *pbs1 = ctx->PB->s[1];
746   GLfloat *pbt1 = ctx->PB->t[1];
747   GLfloat *pbu1 = ctx->PB->u[1];
748   GLubyte (*pbrgba)[4] = ctx->PB->rgba;
749   GLubyte (*pbspec)[3] = ctx->PB->spec;
750   (void) pvert;
751
752   ctx->PB->mono = GL_FALSE;
753
754   if (ctx->Line.StippleFlag) {
755      /* stippled */
756#define INTERP_XY 1
757#define INTERP_Z 1
758#define INTERP_RGB 1
759#define INTERP_SPEC 1
760#define INTERP_ALPHA 1
761#define INTERP_STUV0 1
762#define INTERP_STUV1 1
763#define WIDE 1
764#define STIPPLE 1
765#define PLOT(X,Y)					\
766	{						\
767	   pbx[count] = X;				\
768	   pby[count] = Y;				\
769	   pbz[count] = Z;				\
770	   pbs[count] = s;				\
771	   pbt[count] = t;				\
772	   pbu[count] = u;				\
773	   pbs1[count] = s1;				\
774	   pbt1[count] = t1;				\
775	   pbu1[count] = u1;				\
776	   pbrgba[count][RCOMP] = FixedToInt(r0);	\
777	   pbrgba[count][GCOMP] = FixedToInt(g0);	\
778	   pbrgba[count][BCOMP] = FixedToInt(b0);	\
779	   pbrgba[count][ACOMP] = FixedToInt(a0);	\
780	   pbspec[count][RCOMP] = FixedToInt(sr0);	\
781	   pbspec[count][GCOMP] = FixedToInt(sg0);	\
782	   pbspec[count][BCOMP] = FixedToInt(sb0);	\
783	   count++;					\
784	   CHECK_FULL(count);				\
785	}
786#include "linetemp.h"
787   }
788   else {
789      /* unstippled */
790#define INTERP_XY 1
791#define INTERP_Z 1
792#define INTERP_RGB 1
793#define INTERP_SPEC 1
794#define INTERP_ALPHA 1
795#define INTERP_STUV0 1
796#define INTERP_STUV1 1
797#define WIDE 1
798#define PLOT(X,Y)					\
799	{						\
800	   pbx[count] = X;				\
801	   pby[count] = Y;				\
802	   pbz[count] = Z;				\
803	   pbs[count] = s;				\
804	   pbt[count] = t;				\
805	   pbu[count] = u;				\
806	   pbs1[count] = s1;				\
807	   pbt1[count] = t1;				\
808	   pbu1[count] = u1;				\
809	   pbrgba[count][RCOMP] = FixedToInt(r0);	\
810	   pbrgba[count][GCOMP] = FixedToInt(g0);	\
811	   pbrgba[count][BCOMP] = FixedToInt(b0);	\
812	   pbrgba[count][ACOMP] = FixedToInt(a0);	\
813	   pbspec[count][RCOMP] = FixedToInt(sr0);	\
814	   pbspec[count][GCOMP] = FixedToInt(sg0);	\
815	   pbspec[count][BCOMP] = FixedToInt(sb0);	\
816	   count++;					\
817	   CHECK_FULL(count);				\
818	}
819#include "linetemp.h"
820   }
821
822   ctx->PB->count = count;
823   gl_flush_pb(ctx);
824}
825
826
827/* Flat-shaded, multitextured, any width, maybe stippled, separate specular
828 * color interpolation.
829 */
830static void flat_multitextured_line( GLcontext *ctx,
831                                     GLuint vert0, GLuint vert1, GLuint pvert )
832{
833   GLint count = ctx->PB->count;
834   GLint *pbx = ctx->PB->x;
835   GLint *pby = ctx->PB->y;
836   GLdepth *pbz = ctx->PB->z;
837   GLfloat *pbs = ctx->PB->s[0];
838   GLfloat *pbt = ctx->PB->t[0];
839   GLfloat *pbu = ctx->PB->u[0];
840   GLfloat *pbs1 = ctx->PB->s[1];
841   GLfloat *pbt1 = ctx->PB->t[1];
842   GLfloat *pbu1 = ctx->PB->u[1];
843   GLubyte (*pbrgba)[4] = ctx->PB->rgba;
844   GLubyte (*pbspec)[3] = ctx->PB->spec;
845   GLubyte *color = ctx->VB->ColorPtr->data[pvert];
846   GLubyte sRed   = ctx->VB->Specular ? ctx->VB->Specular[pvert][0] : 0;
847   GLubyte sGreen = ctx->VB->Specular ? ctx->VB->Specular[pvert][1] : 0;
848   GLubyte sBlue  = ctx->VB->Specular ? ctx->VB->Specular[pvert][2] : 0;
849
850   (void) pvert;
851
852   ctx->PB->mono = GL_FALSE;
853
854   if (ctx->Line.StippleFlag) {
855      /* stippled */
856#define INTERP_XY 1
857#define INTERP_Z 1
858#define INTERP_ALPHA 1
859#define INTERP_STUV0 1
860#define INTERP_STUV1 1
861#define WIDE 1
862#define STIPPLE 1
863#define PLOT(X,Y)					\
864	{						\
865	   pbx[count] = X;				\
866	   pby[count] = Y;				\
867	   pbz[count] = Z;				\
868	   pbs[count] = s;				\
869	   pbt[count] = t;				\
870	   pbu[count] = u;				\
871	   pbs1[count] = s1;				\
872	   pbt1[count] = t1;				\
873	   pbu1[count] = u1;				\
874	   pbrgba[count][RCOMP] = color[0];		\
875	   pbrgba[count][GCOMP] = color[1];		\
876	   pbrgba[count][BCOMP] = color[2];		\
877	   pbrgba[count][ACOMP] = color[3];		\
878	   pbspec[count][RCOMP] = sRed;			\
879	   pbspec[count][GCOMP] = sGreen;		\
880	   pbspec[count][BCOMP] = sBlue;		\
881	   count++;					\
882	   CHECK_FULL(count);				\
883	}
884#include "linetemp.h"
885   }
886   else {
887      /* unstippled */
888#define INTERP_XY 1
889#define INTERP_Z 1
890#define INTERP_ALPHA 1
891#define INTERP_STUV0 1
892#define INTERP_STUV1 1
893#define WIDE 1
894#define PLOT(X,Y)					\
895	{						\
896	   pbx[count] = X;				\
897	   pby[count] = Y;				\
898	   pbz[count] = Z;				\
899	   pbs[count] = s;				\
900	   pbt[count] = t;				\
901	   pbu[count] = u;				\
902	   pbs1[count] = s1;				\
903	   pbt1[count] = t1;				\
904	   pbu1[count] = u1;				\
905	   pbrgba[count][RCOMP] = color[0];		\
906	   pbrgba[count][GCOMP] = color[1];		\
907	   pbrgba[count][BCOMP] = color[2];		\
908	   pbrgba[count][ACOMP] = color[3];		\
909	   pbspec[count][RCOMP] = sRed;			\
910	   pbspec[count][GCOMP] = sGreen;		\
911	   pbspec[count][BCOMP] = sBlue;		\
912	   count++;					\
913	   CHECK_FULL(count);				\
914	}
915#include "linetemp.h"
916   }
917
918   ctx->PB->count = count;
919   gl_flush_pb(ctx);
920}
921
922
923
924
925/*
926 * Antialiased RGBA line
927 *
928 * This AA line function isn't terribly efficient but it's pretty
929 * straight-forward to understand.  Also, it doesn't exactly conform
930 * to the specification.
931 */
932static void aa_rgba_line( GLcontext *ctx,
933                          GLuint vert0, GLuint vert1, GLuint pvert )
934{
935#define INTERP_RGBA 1
936#define PLOT(x, y)  { PB_WRITE_RGBA_PIXEL( pb, (x), (y), z, red, green, blue, coverage ); }
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 */
947static void aa_tex_rgba_line( GLcontext *ctx,
948                              GLuint vert0, GLuint vert1, GLuint pvert )
949{
950#define INTERP_RGBA 1
951#define INTERP_STUV0 1
952#define PLOT(x, y)							\
953   {									\
954      PB_WRITE_TEX_PIXEL( pb, (x), (y), z, red, green, blue, coverage,	\
955                          s, t, u );					\
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 */
968static 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_STUV0 1
974#define INTERP_STUV1 1
975#define PLOT(x, y)							\
976   {									\
977      GLfloat texcoord[MAX_TEXTURE_UNITS][4];				\
978      texcoord[0][0] = s;						\
979      texcoord[0][1] = t;						\
980      texcoord[0][2] = u;						\
981      texcoord[1][0] = s1;						\
982      texcoord[1][1] = t1;						\
983      texcoord[1][2] = u1;						\
984      PB_WRITE_MULTITEX_SPEC_PIXEL( pb, (x), (y), z,			\
985            red, green, blue, coverage, specRed, specGreen, specBlue,	\
986            texcoord );							\
987   }
988#include "lnaatemp.h"
989}
990
991
992/*
993 * Antialiased CI line.  Same comments for RGBA antialiased lines apply.
994 */
995static void aa_ci_line( GLcontext *ctx,
996                        GLuint vert0, GLuint vert1, GLuint pvert )
997{
998#define INTERP_INDEX 1
999#define PLOT(x, y)						\
1000   {								\
1001      PB_WRITE_CI_PIXEL( pb, (x), (y), z, index + coverage );	\
1002   }
1003#include "lnaatemp.h"
1004}
1005
1006
1007/*
1008 * Null rasterizer for measuring transformation speed.
1009 */
1010static void null_line( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv )
1011{
1012   (void) ctx;
1013   (void) v1;
1014   (void) v2;
1015   (void) pv;
1016}
1017
1018
1019
1020#ifdef DEBUG
1021void
1022_mesa_print_line_function(GLcontext *ctx)
1023{
1024   printf("Line Func == ");
1025   if (ctx->Driver.LineFunc == flat_ci_line)
1026      printf("flat_ci_line\n");
1027   else if (ctx->Driver.LineFunc == flat_ci_z_line)
1028      printf("flat_ci_z_line\n");
1029   else if (ctx->Driver.LineFunc == flat_rgba_line)
1030      printf("flat_rgba_line\n");
1031   else if (ctx->Driver.LineFunc == flat_rgba_z_line)
1032      printf("flat_rgba_z_line\n");
1033   else if (ctx->Driver.LineFunc == smooth_ci_line)
1034      printf("smooth_ci_line\n");
1035   else if (ctx->Driver.LineFunc == smooth_ci_z_line)
1036      printf("smooth_ci_z_line\n");
1037   else if (ctx->Driver.LineFunc == smooth_rgba_line)
1038      printf("smooth_rgba_line\n");
1039   else if (ctx->Driver.LineFunc == smooth_rgba_z_line)
1040      printf("smooth_rgba_z_line\n");
1041   else if (ctx->Driver.LineFunc == general_smooth_ci_line)
1042      printf("general_smooth_ci_line\n");
1043   else if (ctx->Driver.LineFunc == general_flat_ci_line)
1044      printf("general_flat_ci_line\n");
1045   else if (ctx->Driver.LineFunc == general_smooth_rgba_line)
1046      printf("general_smooth_rgba_line\n");
1047   else if (ctx->Driver.LineFunc == general_flat_rgba_line)
1048      printf("general_flat_rgba_line\n");
1049   else if (ctx->Driver.LineFunc == flat_textured_line)
1050      printf("flat_textured_line\n");
1051   else if (ctx->Driver.LineFunc == smooth_textured_line)
1052      printf("smooth_textured_line\n");
1053   else if (ctx->Driver.LineFunc == smooth_multitextured_line)
1054      printf("smooth_multitextured_line\n");
1055   else if (ctx->Driver.LineFunc == flat_multitextured_line)
1056      printf("flat_multitextured_line\n");
1057   else if (ctx->Driver.LineFunc == aa_rgba_line)
1058      printf("aa_rgba_line\n");
1059   else if (ctx->Driver.LineFunc == aa_tex_rgba_line)
1060      printf("aa_tex_rgba_line\n");
1061   else if (ctx->Driver.LineFunc == aa_multitex_rgba_line)
1062      printf("aa_multitex_rgba_line\n");
1063   else if (ctx->Driver.LineFunc == aa_ci_line)
1064      printf("aa_ci_line\n");
1065   else if (ctx->Driver.LineFunc == null_line)
1066      printf("null_line\n");
1067   else
1068      printf("Driver func %p\n", ctx->Driver.PointsFunc);
1069}
1070#endif
1071
1072
1073
1074/*
1075 * Determine which line drawing function to use given the current
1076 * rendering context.
1077 */
1078void gl_set_line_function( GLcontext *ctx )
1079{
1080   GLboolean rgbmode = ctx->Visual.RGBAflag;
1081   /* TODO: antialiased lines */
1082
1083   if (ctx->RenderMode==GL_RENDER) {
1084      if (ctx->NoRaster) {
1085         ctx->Driver.LineFunc = null_line;
1086         return;
1087      }
1088      if (ctx->Driver.LineFunc) {
1089         /* Device driver will draw lines. */
1090	 return;
1091      }
1092
1093      if (ctx->Line.SmoothFlag) {
1094         /* antialiased lines */
1095         if (rgbmode) {
1096            if (ctx->Texture.ReallyEnabled) {
1097               if (ctx->Texture.ReallyEnabled >= TEXTURE1_1D
1098                  || ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR)
1099                  /* Multitextured! */
1100                  ctx->Driver.LineFunc = aa_multitex_rgba_line;
1101               else
1102                  ctx->Driver.LineFunc = aa_tex_rgba_line;
1103            } else {
1104               ctx->Driver.LineFunc = aa_rgba_line;
1105            }
1106         }
1107         else {
1108            ctx->Driver.LineFunc = aa_ci_line;
1109         }
1110      }
1111      else if (ctx->Texture.ReallyEnabled) {
1112         if (ctx->Texture.ReallyEnabled >= TEXTURE1_1D
1113             || ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) {
1114            /* multi-texture and/or separate specular color */
1115            if (ctx->Light.ShadeModel==GL_SMOOTH)
1116               ctx->Driver.LineFunc = smooth_multitextured_line;
1117            else
1118               ctx->Driver.LineFunc = flat_multitextured_line;
1119         }
1120         else {
1121            if (ctx->Light.ShadeModel==GL_SMOOTH) {
1122                ctx->Driver.LineFunc = smooth_textured_line;
1123            }
1124            else {
1125                ctx->Driver.LineFunc = flat_textured_line;
1126            }
1127         }
1128      }
1129      else if (ctx->Line.Width!=1.0 || ctx->Line.StippleFlag
1130               || ctx->Line.SmoothFlag) {
1131         if (ctx->Light.ShadeModel==GL_SMOOTH) {
1132            if (rgbmode)
1133               ctx->Driver.LineFunc = general_smooth_rgba_line;
1134            else
1135               ctx->Driver.LineFunc = general_smooth_ci_line;
1136         }
1137         else {
1138            if (rgbmode)
1139               ctx->Driver.LineFunc = general_flat_rgba_line;
1140            else
1141               ctx->Driver.LineFunc = general_flat_ci_line;
1142         }
1143      }
1144      else {
1145	 if (ctx->Light.ShadeModel==GL_SMOOTH) {
1146	    /* Width==1, non-stippled, smooth-shaded */
1147            if (ctx->Depth.Test || ctx->FogMode == FOG_FRAGMENT) {
1148               if (rgbmode)
1149                  ctx->Driver.LineFunc = smooth_rgba_z_line;
1150               else
1151                  ctx->Driver.LineFunc = smooth_ci_z_line;
1152            }
1153            else {
1154               if (rgbmode)
1155                  ctx->Driver.LineFunc = smooth_rgba_line;
1156               else
1157                  ctx->Driver.LineFunc = smooth_ci_line;
1158            }
1159	 }
1160         else {
1161	    /* Width==1, non-stippled, flat-shaded */
1162            if (ctx->Depth.Test || ctx->FogMode == FOG_FRAGMENT) {
1163               if (rgbmode)
1164                  ctx->Driver.LineFunc = flat_rgba_z_line;
1165               else
1166                  ctx->Driver.LineFunc = flat_ci_z_line;
1167            }
1168            else {
1169               if (rgbmode)
1170                  ctx->Driver.LineFunc = flat_rgba_line;
1171               else
1172                  ctx->Driver.LineFunc = flat_ci_line;
1173            }
1174         }
1175      }
1176   }
1177   else if (ctx->RenderMode==GL_FEEDBACK) {
1178      ctx->Driver.LineFunc = gl_feedback_line;
1179   }
1180   else {
1181      /* GL_SELECT mode */
1182      ctx->Driver.LineFunc = gl_select_line;
1183   }
1184
1185   /*_mesa_print_line_function(ctx);*/
1186}
1187