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