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