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