3 * Mesa 3-D graphics library
6 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 * Keith Whitwell <keith@tungstengraphics.com>
30 /* Template for building functions to plug into the driver interface
32 * ctx->Driver.QuadFunc
33 * ctx->Driver.TriangleFunc
34 * ctx->Driver.LineFunc
35 * ctx->Driver.PointsFunc
37 * DO_TWOSIDE: Plug back-color values from the VB into backfacing triangles,
38 * and restore vertices afterwards.
39 * DO_OFFSET: Calculate offset for triangles and adjust vertices. Restore
40 * vertices after rendering.
41 * DO_FLAT: For hardware without native flatshading, copy provoking colors
42 * into the other vertices. Restore after rendering.
43 * DO_UNFILLED: Decompose triangles to lines and points where appropriate.
45 * HAVE_RGBA: Vertices have rgba values (otherwise index values).
46 * HAVE_SPEC: Vertices have secondary rgba values.
48 * VERT_X(v): Alias for vertex x value.
49 * VERT_Y(v): Alias for vertex y value.
50 * VERT_Z(v): Alias for vertex z value.
51 * DEPTH_SCALE: Scale for offset.
53 * VERTEX: Hardware vertex type.
54 * GET_VERTEX(n): Retreive vertex with index n.
55 * AREA_IS_CCW(a): Return true if triangle with signed area a is ccw.
57 * VERT_SET_RGBA: Assign vertex rgba from VB color.
58 * VERT_COPY_RGBA: Copy vertex rgba another vertex.
59 * VERT_SAVE_RGBA: Save vertex rgba to a local variable.
60 * VERT_RESTORE_RGBA: Restore vertex rgba from a local variable.
61 * --> Similar for IND and SPEC.
63 * LOCAL_VARS(n): (At least) define local vars for save/restore rgba.
68 #define VERT_SET_IND( v, c ) (void) c
69 #define VERT_COPY_IND( v0, v1 )
70 #define VERT_SAVE_IND( idx )
71 #define VERT_RESTORE_IND( idx )
73 #define VERT_SET_RGBA( v, c )
76 #define VERT_SET_RGBA( v, c ) (void) c
77 #define VERT_COPY_RGBA( v0, v1 )
78 #define VERT_SAVE_RGBA( idx )
79 #define VERT_RESTORE_RGBA( idx )
81 #define VERT_SET_IND( v, c )
86 #define VERT_SET_SPEC( v, c ) (void) c
87 #define VERT_COPY_SPEC( v0, v1 )
88 #define VERT_SAVE_SPEC( idx )
89 #define VERT_RESTORE_SPEC( idx )
91 #define VERT_COPY_SPEC1( v )
95 #define VERT_SET_SPEC( v, c )
100 #define VERT_COPY_SPEC1( v )
101 #define VERT_COPY_IND1( v )
102 #define VERT_COPY_RGBA1( v )
105 #ifndef INSANE_VERTICES
106 #define VERT_SET_Z(v,val) VERT_Z(v) = val
107 #define VERT_Z_ADD(v,val) VERT_Z(v) += val
111 static void TAG(triangle
)( GLcontext
*ctx
, GLuint e0
, GLuint e1
, GLuint e2
)
113 struct vertex_buffer
*VB
= &TNL_CONTEXT( ctx
)->vb
;
117 GLenum mode
= GL_FILL
;
121 /* fprintf(stderr, "%s\n", __FUNCTION__); */
123 v
[0] = (VERTEX
*)GET_VERTEX(e0
);
124 v
[1] = (VERTEX
*)GET_VERTEX(e1
);
125 v
[2] = (VERTEX
*)GET_VERTEX(e2
);
127 if (DO_TWOSIDE
|| DO_OFFSET
|| DO_UNFILLED
)
129 GLfloat ex
= VERT_X(v
[0]) - VERT_X(v
[2]);
130 GLfloat ey
= VERT_Y(v
[0]) - VERT_Y(v
[2]);
131 GLfloat fx
= VERT_X(v
[1]) - VERT_X(v
[2]);
132 GLfloat fy
= VERT_Y(v
[1]) - VERT_Y(v
[2]);
133 GLfloat cc
= ex
*fy
- ey
*fx
;
135 if (DO_TWOSIDE
|| DO_UNFILLED
)
137 facing
= AREA_IS_CCW( cc
) ^ ctx
->Polygon
._FrontBit
;
141 mode
= ctx
->Polygon
.BackMode
;
142 if (ctx
->Polygon
.CullFlag
&&
143 ctx
->Polygon
.CullFaceMode
!= GL_FRONT
) {
147 mode
= ctx
->Polygon
.FrontMode
;
148 if (ctx
->Polygon
.CullFlag
&&
149 ctx
->Polygon
.CullFaceMode
!= GL_BACK
) {
155 if (DO_TWOSIDE
&& facing
== 1)
158 if (HAVE_BACK_COLORS
) {
162 VERT_COPY_RGBA1( v
[0] );
163 VERT_COPY_RGBA1( v
[1] );
166 VERT_COPY_RGBA1( v
[2] );
171 VERT_COPY_SPEC1( v
[0] );
172 VERT_COPY_SPEC1( v
[1] );
175 VERT_COPY_SPEC1( v
[2] );
179 GLfloat (*vbcolor
)[4] = VB
->ColorPtr
[1]->data
;
180 ASSERT(VB
->ColorPtr
[1]->stride
== 4*sizeof(GLfloat
));
186 VERT_SET_RGBA( v
[0], vbcolor
[e0
] );
187 VERT_SET_RGBA( v
[1], vbcolor
[e1
] );
190 VERT_SET_RGBA( v
[2], vbcolor
[e2
] );
192 if (HAVE_SPEC
&& VB
->SecondaryColorPtr
[1]) {
193 GLfloat (*vbspec
)[4] = VB
->SecondaryColorPtr
[1]->data
;
198 VERT_SET_SPEC( v
[0], vbspec
[e0
] );
199 VERT_SET_SPEC( v
[1], vbspec
[e1
] );
202 VERT_SET_SPEC( v
[2], vbspec
[e2
] );
207 GLfloat (*vbindex
) = (GLfloat
*)VB
->IndexPtr
[1]->data
;
211 VERT_SET_IND( v
[0], vbindex
[e0
] );
212 VERT_SET_IND( v
[1], vbindex
[e1
] );
215 VERT_SET_IND( v
[2], vbindex
[e2
] );
223 offset
= ctx
->Polygon
.OffsetUnits
* DEPTH_SCALE
;
227 if (cc
* cc
> 1e-16) {
228 GLfloat ic
= 1.0 / cc
;
229 GLfloat ez
= z
[0] - z
[2];
230 GLfloat fz
= z
[1] - z
[2];
231 GLfloat a
= ey
*fz
- ez
*fy
;
232 GLfloat b
= ez
*fx
- ex
*fz
;
235 if ( ac
< 0.0f
) ac
= -ac
;
236 if ( bc
< 0.0f
) bc
= -bc
;
237 offset
+= MAX2( ac
, bc
) * ctx
->Polygon
.OffsetFactor
;
247 VERT_COPY_RGBA( v
[0], v
[2] );
248 VERT_COPY_RGBA( v
[1], v
[2] );
249 if (HAVE_SPEC
&& VB
->SecondaryColorPtr
[0]) {
252 VERT_COPY_SPEC( v
[0], v
[2] );
253 VERT_COPY_SPEC( v
[1], v
[2] );
259 VERT_COPY_IND( v
[0], v
[2] );
260 VERT_COPY_IND( v
[1], v
[2] );
264 if (mode
== GL_POINT
) {
265 if (DO_OFFSET
&& ctx
->Polygon
.OffsetPoint
) {
266 VERT_Z_ADD(v
[0], offset
);
267 VERT_Z_ADD(v
[1], offset
);
268 VERT_Z_ADD(v
[2], offset
);
270 UNFILLED_TRI( ctx
, GL_POINT
, e0
, e1
, e2
);
271 } else if (mode
== GL_LINE
) {
272 if (DO_OFFSET
&& ctx
->Polygon
.OffsetLine
) {
273 VERT_Z_ADD(v
[0], offset
);
274 VERT_Z_ADD(v
[1], offset
);
275 VERT_Z_ADD(v
[2], offset
);
277 UNFILLED_TRI( ctx
, GL_LINE
, e0
, e1
, e2
);
279 if (DO_OFFSET
&& ctx
->Polygon
.OffsetFill
) {
280 VERT_Z_ADD(v
[0], offset
);
281 VERT_Z_ADD(v
[1], offset
);
282 VERT_Z_ADD(v
[2], offset
);
285 RASTERIZE( GL_TRIANGLES
);
286 TRI( v
[0], v
[1], v
[2] );
291 VERT_SET_Z(v
[0], z
[0]);
292 VERT_SET_Z(v
[1], z
[1]);
293 VERT_SET_Z(v
[2], z
[2]);
296 if (DO_TWOSIDE
&& facing
== 1)
300 VERT_RESTORE_RGBA( 0 );
301 VERT_RESTORE_RGBA( 1 );
303 VERT_RESTORE_RGBA( 2 );
306 VERT_RESTORE_SPEC( 0 );
307 VERT_RESTORE_SPEC( 1 );
309 VERT_RESTORE_SPEC( 2 );
314 VERT_RESTORE_IND( 0 );
315 VERT_RESTORE_IND( 1 );
317 VERT_RESTORE_IND( 2 );
324 VERT_RESTORE_RGBA( 0 );
325 VERT_RESTORE_RGBA( 1 );
326 if (HAVE_SPEC
&& VB
->SecondaryColorPtr
[0]) {
327 VERT_RESTORE_SPEC( 0 );
328 VERT_RESTORE_SPEC( 1 );
332 VERT_RESTORE_IND( 0 );
333 VERT_RESTORE_IND( 1 );
341 static void TAG(quad
)( GLcontext
*ctx
,
342 GLuint e0
, GLuint e1
, GLuint e2
, GLuint e3
)
344 struct vertex_buffer
*VB
= &TNL_CONTEXT( ctx
)->vb
;
348 GLenum mode
= GL_FILL
;
352 v
[0] = (VERTEX
*)GET_VERTEX(e0
);
353 v
[1] = (VERTEX
*)GET_VERTEX(e1
);
354 v
[2] = (VERTEX
*)GET_VERTEX(e2
);
355 v
[3] = (VERTEX
*)GET_VERTEX(e3
);
357 if (DO_TWOSIDE
|| DO_OFFSET
|| DO_UNFILLED
)
359 GLfloat ex
= VERT_X(v
[2]) - VERT_X(v
[0]);
360 GLfloat ey
= VERT_Y(v
[2]) - VERT_Y(v
[0]);
361 GLfloat fx
= VERT_X(v
[3]) - VERT_X(v
[1]);
362 GLfloat fy
= VERT_Y(v
[3]) - VERT_Y(v
[1]);
363 GLfloat cc
= ex
*fy
- ey
*fx
;
365 if (DO_TWOSIDE
|| DO_UNFILLED
)
367 facing
= AREA_IS_CCW( cc
) ^ ctx
->Polygon
._FrontBit
;
371 mode
= ctx
->Polygon
.BackMode
;
372 if (ctx
->Polygon
.CullFlag
&&
373 ctx
->Polygon
.CullFaceMode
!= GL_FRONT
) {
377 mode
= ctx
->Polygon
.FrontMode
;
378 if (ctx
->Polygon
.CullFlag
&&
379 ctx
->Polygon
.CullFaceMode
!= GL_BACK
) {
385 if (DO_TWOSIDE
&& facing
== 1)
388 GLfloat (*vbcolor
)[4] = VB
->ColorPtr
[1]->data
;
391 if (HAVE_BACK_COLORS
) {
396 VERT_COPY_RGBA1( v
[0] );
397 VERT_COPY_RGBA1( v
[1] );
398 VERT_COPY_RGBA1( v
[2] );
401 VERT_COPY_RGBA1( v
[3] );
407 VERT_COPY_SPEC1( v
[0] );
408 VERT_COPY_SPEC1( v
[1] );
409 VERT_COPY_SPEC1( v
[2] );
412 VERT_COPY_SPEC1( v
[3] );
420 VERT_SET_RGBA( v
[0], vbcolor
[e0
] );
421 VERT_SET_RGBA( v
[1], vbcolor
[e1
] );
422 VERT_SET_RGBA( v
[2], vbcolor
[e2
] );
425 VERT_SET_RGBA( v
[3], vbcolor
[e3
] );
427 if (HAVE_SPEC
&& VB
->SecondaryColorPtr
[1]) {
428 GLfloat (*vbspec
)[4] = VB
->SecondaryColorPtr
[1]->data
;
429 ASSERT(VB
->SecondaryColorPtr
[1]->stride
==4*sizeof(GLfloat
));
435 VERT_SET_SPEC( v
[0], vbspec
[e0
] );
436 VERT_SET_SPEC( v
[1], vbspec
[e1
] );
437 VERT_SET_SPEC( v
[2], vbspec
[e2
] );
440 VERT_SET_SPEC( v
[3], vbspec
[e3
] );
445 GLfloat
*vbindex
= (GLfloat
*)VB
->IndexPtr
[1]->data
;
450 VERT_SET_IND( v
[0], vbindex
[e0
] );
451 VERT_SET_IND( v
[1], vbindex
[e1
] );
452 VERT_SET_IND( v
[2], vbindex
[e2
] );
455 VERT_SET_IND( v
[3], vbindex
[e3
] );
463 offset
= ctx
->Polygon
.OffsetUnits
* DEPTH_SCALE
;
468 if (cc
* cc
> 1e-16) {
469 GLfloat ez
= z
[2] - z
[0];
470 GLfloat fz
= z
[3] - z
[1];
471 GLfloat a
= ey
*fz
- ez
*fy
;
472 GLfloat b
= ez
*fx
- ex
*fz
;
473 GLfloat ic
= 1.0 / cc
;
476 if ( ac
< 0.0f
) ac
= -ac
;
477 if ( bc
< 0.0f
) bc
= -bc
;
478 offset
+= MAX2( ac
, bc
) * ctx
->Polygon
.OffsetFactor
;
489 VERT_COPY_RGBA( v
[0], v
[3] );
490 VERT_COPY_RGBA( v
[1], v
[3] );
491 VERT_COPY_RGBA( v
[2], v
[3] );
492 if (HAVE_SPEC
&& VB
->SecondaryColorPtr
[0]) {
496 VERT_COPY_SPEC( v
[0], v
[3] );
497 VERT_COPY_SPEC( v
[1], v
[3] );
498 VERT_COPY_SPEC( v
[2], v
[3] );
505 VERT_COPY_IND( v
[0], v
[3] );
506 VERT_COPY_IND( v
[1], v
[3] );
507 VERT_COPY_IND( v
[2], v
[3] );
511 if (mode
== GL_POINT
) {
512 if (( DO_OFFSET
) && ctx
->Polygon
.OffsetPoint
) {
513 VERT_Z_ADD(v
[0], offset
);
514 VERT_Z_ADD(v
[1], offset
);
515 VERT_Z_ADD(v
[2], offset
);
516 VERT_Z_ADD(v
[3], offset
);
518 UNFILLED_QUAD( ctx
, GL_POINT
, e0
, e1
, e2
, e3
);
519 } else if (mode
== GL_LINE
) {
520 if (DO_OFFSET
&& ctx
->Polygon
.OffsetLine
) {
521 VERT_Z_ADD(v
[0], offset
);
522 VERT_Z_ADD(v
[1], offset
);
523 VERT_Z_ADD(v
[2], offset
);
524 VERT_Z_ADD(v
[3], offset
);
526 UNFILLED_QUAD( ctx
, GL_LINE
, e0
, e1
, e2
, e3
);
528 if (DO_OFFSET
&& ctx
->Polygon
.OffsetFill
) {
529 VERT_Z_ADD(v
[0], offset
);
530 VERT_Z_ADD(v
[1], offset
);
531 VERT_Z_ADD(v
[2], offset
);
532 VERT_Z_ADD(v
[3], offset
);
534 RASTERIZE( GL_TRIANGLES
);
535 QUAD( (v
[0]), (v
[1]), (v
[2]), (v
[3]) );
540 VERT_SET_Z(v
[0], z
[0]);
541 VERT_SET_Z(v
[1], z
[1]);
542 VERT_SET_Z(v
[2], z
[2]);
543 VERT_SET_Z(v
[3], z
[3]);
546 if (DO_TWOSIDE
&& facing
== 1)
550 VERT_RESTORE_RGBA( 0 );
551 VERT_RESTORE_RGBA( 1 );
552 VERT_RESTORE_RGBA( 2 );
554 VERT_RESTORE_RGBA( 3 );
557 VERT_RESTORE_SPEC( 0 );
558 VERT_RESTORE_SPEC( 1 );
559 VERT_RESTORE_SPEC( 2 );
561 VERT_RESTORE_SPEC( 3 );
566 VERT_RESTORE_IND( 0 );
567 VERT_RESTORE_IND( 1 );
568 VERT_RESTORE_IND( 2 );
570 VERT_RESTORE_IND( 3 );
577 VERT_RESTORE_RGBA( 0 );
578 VERT_RESTORE_RGBA( 1 );
579 VERT_RESTORE_RGBA( 2 );
580 if (HAVE_SPEC
&& VB
->SecondaryColorPtr
[0]) {
581 VERT_RESTORE_SPEC( 0 );
582 VERT_RESTORE_SPEC( 1 );
583 VERT_RESTORE_SPEC( 2 );
587 VERT_RESTORE_IND( 0 );
588 VERT_RESTORE_IND( 1 );
589 VERT_RESTORE_IND( 2 );
594 static void TAG(quad
)( GLcontext
*ctx
, GLuint e0
,
595 GLuint e1
, GLuint e2
, GLuint e3
)
598 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
599 GLubyte ef1
= VB
->EdgeFlag
[e1
];
600 GLubyte ef3
= VB
->EdgeFlag
[e3
];
601 VB
->EdgeFlag
[e1
] = 0;
602 TAG(triangle
)( ctx
, e0
, e1
, e3
);
603 VB
->EdgeFlag
[e1
] = ef1
;
604 VB
->EdgeFlag
[e3
] = 0;
605 TAG(triangle
)( ctx
, e1
, e2
, e3
);
606 VB
->EdgeFlag
[e3
] = ef3
;
608 TAG(triangle
)( ctx
, e0
, e1
, e3
);
609 TAG(triangle
)( ctx
, e1
, e2
, e3
);
616 static void TAG(line
)( GLcontext
*ctx
, GLuint e0
, GLuint e1
)
618 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
622 v
[0] = (VERTEX
*)GET_VERTEX(e0
);
623 v
[1] = (VERTEX
*)GET_VERTEX(e1
);
628 VERT_COPY_RGBA( v
[0], v
[1] );
629 if (HAVE_SPEC
&& VB
->SecondaryColorPtr
[0]) {
631 VERT_COPY_SPEC( v
[0], v
[1] );
636 VERT_COPY_IND( v
[0], v
[1] );
644 VERT_RESTORE_RGBA( 0 );
646 if (HAVE_SPEC
&& VB
->SecondaryColorPtr
[0]) {
647 VERT_RESTORE_SPEC( 0 );
651 VERT_RESTORE_IND( 0 );
658 static void TAG(points
)( GLcontext
*ctx
, GLuint first
, GLuint last
)
660 struct vertex_buffer
*VB
= &TNL_CONTEXT( ctx
)->vb
;
665 for ( i
= first
; i
< last
; i
++ ) {
666 if ( VB
->ClipMask
[i
] == 0 ) {
667 VERTEX
*v
= (VERTEX
*)GET_VERTEX(i
);
672 for ( i
= first
; i
< last
; i
++ ) {
673 GLuint e
= VB
->Elts
[i
];
674 if ( VB
->ClipMask
[e
] == 0 ) {
675 VERTEX
*v
= (VERTEX
*)GET_VERTEX(e
);
683 static void TAG(init
)( void )
686 TAB
[IND
].quad
= TAG(quad
);
689 TAB
[IND
].triangle
= TAG(triangle
);
692 TAB
[IND
].line
= TAG(line
);
695 TAB
[IND
].points
= TAG(points
);
706 #undef VERT_RESTORE_IND
712 #undef VERT_COPY_RGBA
713 #undef VERT_SAVE_RGBA
714 #undef VERT_RESTORE_RGBA
722 #undef VERT_COPY_SPEC
723 #undef VERT_SAVE_SPEC
724 #undef VERT_RESTORE_SPEC
726 #undef VERT_COPY_SPEC1
734 #if !HAVE_BACK_COLORS
735 #undef VERT_COPY_SPEC1
736 #undef VERT_COPY_IND1
737 #undef VERT_COPY_RGBA1
740 #ifndef INSANE_VERTICES