2 * Mesa 3-D graphics library
4 * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
25 * Keith Whitwell <keithw@vmware.com>
29 /* Template for building functions to plug into the driver interface
31 * ctx->Driver.QuadFunc
32 * ctx->Driver.TriangleFunc
33 * ctx->Driver.LineFunc
34 * ctx->Driver.PointsFunc
36 * DO_TWOSIDE: Plug back-color values from the VB into backfacing triangles,
37 * and restore vertices afterwards.
38 * DO_OFFSET: Calculate offset for triangles and adjust vertices. Restore
39 * vertices after rendering.
40 * DO_FLAT: For hardware without native flatshading, copy provoking colors
41 * into the other vertices. Restore after rendering.
42 * DO_UNFILLED: Decompose triangles to lines and points where appropriate.
43 * DO_TWOSTENCIL:Gross hack for two-sided stencil.
45 * HAVE_SPEC: Vertices have secondary rgba values.
47 * VERT_X(v): Alias for vertex x value.
48 * VERT_Y(v): Alias for vertex y value.
49 * VERT_Z(v): Alias for vertex z value.
50 * DEPTH_SCALE: Scale for constant offset.
51 * REVERSE_DEPTH: Viewport depth range reversed.
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 SPEC.
63 * LOCAL_VARS(n): (At least) define local vars for save/restore rgba.
68 #define VERT_SET_RGBA( v, c )
72 #define VERT_SET_SPEC( v, c ) (void) c
73 #define VERT_COPY_SPEC( v0, v1 )
74 #define VERT_SAVE_SPEC( idx )
75 #define VERT_RESTORE_SPEC( idx )
77 #define VERT_COPY_SPEC1( v )
81 #define VERT_SET_SPEC( v, c )
86 #define VERT_COPY_SPEC1( v )
87 #define VERT_COPY_RGBA1( v )
90 #ifndef INSANE_VERTICES
91 #define VERT_SET_Z(v,val) VERT_Z(v) = val
92 #define VERT_Z_ADD(v,val) VERT_Z(v) += val
96 #define REVERSE_DEPTH 0
99 /* disable twostencil for un-aware drivers */
100 #ifndef HAVE_STENCIL_TWOSIDE
101 #define HAVE_STENCIL_TWOSIDE 0
103 #ifndef DO_TWOSTENCIL
104 #define DO_TWOSTENCIL 0
106 #ifndef SETUP_STENCIL
107 #define SETUP_STENCIL(f)
109 #ifndef UNSET_STENCIL
110 #define UNSET_STENCIL(f)
114 static void TAG(triangle
)( struct gl_context
*ctx
, GLuint e0
, GLuint e1
, GLuint e2
)
116 struct vertex_buffer
*VB
= &TNL_CONTEXT( ctx
)->vb
;
119 GLfloat z
[3] = { 0 };
120 GLenum mode
= GL_FILL
;
124 /* fprintf(stderr, "%s\n", __func__); */
126 v
[0] = (VERTEX
*)GET_VERTEX(e0
);
127 v
[1] = (VERTEX
*)GET_VERTEX(e1
);
128 v
[2] = (VERTEX
*)GET_VERTEX(e2
);
130 if (DO_TWOSIDE
|| DO_OFFSET
|| DO_UNFILLED
|| DO_TWOSTENCIL
)
132 GLfloat ex
= VERT_X(v
[0]) - VERT_X(v
[2]);
133 GLfloat ey
= VERT_Y(v
[0]) - VERT_Y(v
[2]);
134 GLfloat fx
= VERT_X(v
[1]) - VERT_X(v
[2]);
135 GLfloat fy
= VERT_Y(v
[1]) - VERT_Y(v
[2]);
136 GLfloat cc
= ex
*fy
- ey
*fx
;
138 if (DO_TWOSIDE
|| DO_UNFILLED
|| DO_TWOSTENCIL
)
140 facing
= AREA_IS_CCW( cc
) ^ _mesa_polygon_get_front_bit(ctx
);
144 mode
= ctx
->Polygon
.BackMode
;
145 if (ctx
->Polygon
.CullFlag
&&
146 ctx
->Polygon
.CullFaceMode
!= GL_FRONT
) {
150 mode
= ctx
->Polygon
.FrontMode
;
151 if (ctx
->Polygon
.CullFlag
&&
152 ctx
->Polygon
.CullFaceMode
!= GL_BACK
) {
158 if (DO_TWOSIDE
&& facing
== 1) {
159 if (HAVE_BACK_COLORS
) {
163 VERT_COPY_RGBA1( v
[0] );
164 VERT_COPY_RGBA1( v
[1] );
167 VERT_COPY_RGBA1( v
[2] );
172 VERT_COPY_SPEC1( v
[0] );
173 VERT_COPY_SPEC1( v
[1] );
176 VERT_COPY_SPEC1( v
[2] );
180 GLfloat (*vbcolor
)[4] = VB
->BackfaceColorPtr
->data
;
189 if (VB
->BackfaceColorPtr
->stride
) {
190 assert(VB
->BackfaceColorPtr
->stride
== 4*sizeof(GLfloat
));
193 VERT_SET_RGBA( v
[0], vbcolor
[e0
] );
194 VERT_SET_RGBA( v
[1], vbcolor
[e1
] );
196 VERT_SET_RGBA( v
[2], vbcolor
[e2
] );
200 VERT_SET_RGBA( v
[0], vbcolor
[0] );
201 VERT_SET_RGBA( v
[1], vbcolor
[0] );
203 VERT_SET_RGBA( v
[2], vbcolor
[0] );
206 if (HAVE_SPEC
&& VB
->BackfaceSecondaryColorPtr
) {
207 GLfloat (*vbspec
)[4] = VB
->BackfaceSecondaryColorPtr
->data
;
208 assert(VB
->BackfaceSecondaryColorPtr
->stride
== 4*sizeof(GLfloat
));
213 VERT_SET_SPEC( v
[0], vbspec
[e0
] );
214 VERT_SET_SPEC( v
[1], vbspec
[e1
] );
217 VERT_SET_SPEC( v
[2], vbspec
[e2
] );
226 offset
= ctx
->Polygon
.OffsetUnits
* DEPTH_SCALE
;
230 if (cc
* cc
> 1e-16) {
231 GLfloat ic
= 1.0 / cc
;
232 GLfloat ez
= z
[0] - z
[2];
233 GLfloat fz
= z
[1] - z
[2];
234 GLfloat a
= ey
*fz
- ez
*fy
;
235 GLfloat b
= ez
*fx
- ex
*fz
;
238 if ( ac
< 0.0f
) ac
= -ac
;
239 if ( bc
< 0.0f
) bc
= -bc
;
240 offset
+= MAX2( ac
, bc
) * ctx
->Polygon
.OffsetFactor
/ ctx
->DrawBuffer
->_MRD
;
242 offset
*= ctx
->DrawBuffer
->_MRD
* (REVERSE_DEPTH
? -1.0 : 1.0);
249 VERT_COPY_RGBA( v
[0], v
[2] );
250 VERT_COPY_RGBA( v
[1], v
[2] );
251 if (HAVE_SPEC
&& VB
->AttribPtr
[_TNL_ATTRIB_COLOR1
]) {
254 VERT_COPY_SPEC( v
[0], v
[2] );
255 VERT_COPY_SPEC( v
[1], v
[2] );
259 if (mode
== GL_POINT
) {
260 if (DO_OFFSET
&& ctx
->Polygon
.OffsetPoint
) {
261 VERT_Z_ADD(v
[0], offset
);
262 VERT_Z_ADD(v
[1], offset
);
263 VERT_Z_ADD(v
[2], offset
);
265 if (DO_TWOSTENCIL
&& !HAVE_STENCIL_TWOSIDE
&& ctx
->Stencil
.TestTwoSide
) {
266 SETUP_STENCIL(facing
);
267 UNFILLED_TRI( ctx
, GL_POINT
, e0
, e1
, e2
);
268 UNSET_STENCIL(facing
);
270 UNFILLED_TRI( ctx
, GL_POINT
, e0
, e1
, e2
);
272 } else if (mode
== GL_LINE
) {
273 if (DO_OFFSET
&& ctx
->Polygon
.OffsetLine
) {
274 VERT_Z_ADD(v
[0], offset
);
275 VERT_Z_ADD(v
[1], offset
);
276 VERT_Z_ADD(v
[2], offset
);
278 if (DO_TWOSTENCIL
&& !HAVE_STENCIL_TWOSIDE
&& ctx
->Stencil
.TestTwoSide
) {
279 SETUP_STENCIL(facing
);
280 UNFILLED_TRI( ctx
, GL_LINE
, e0
, e1
, e2
);
281 UNSET_STENCIL(facing
);
283 UNFILLED_TRI( ctx
, GL_LINE
, e0
, e1
, e2
);
286 if (DO_OFFSET
&& ctx
->Polygon
.OffsetFill
) {
287 VERT_Z_ADD(v
[0], offset
);
288 VERT_Z_ADD(v
[1], offset
);
289 VERT_Z_ADD(v
[2], offset
);
292 RASTERIZE( GL_TRIANGLES
);
294 if (DO_TWOSTENCIL
&& !HAVE_STENCIL_TWOSIDE
&& ctx
->Stencil
.TestTwoSide
) {
295 SETUP_STENCIL(facing
);
296 TRI( v
[0], v
[1], v
[2] );
297 UNSET_STENCIL(facing
);
299 TRI( v
[0], v
[1], v
[2] );
305 VERT_SET_Z(v
[0], z
[0]);
306 VERT_SET_Z(v
[1], z
[1]);
307 VERT_SET_Z(v
[2], z
[2]);
310 if (DO_TWOSIDE
&& facing
== 1) {
312 VERT_RESTORE_RGBA( 0 );
313 VERT_RESTORE_RGBA( 1 );
315 VERT_RESTORE_RGBA( 2 );
318 VERT_RESTORE_SPEC( 0 );
319 VERT_RESTORE_SPEC( 1 );
321 VERT_RESTORE_SPEC( 2 );
327 VERT_RESTORE_RGBA( 0 );
328 VERT_RESTORE_RGBA( 1 );
329 if (HAVE_SPEC
&& VB
->AttribPtr
[_TNL_ATTRIB_COLOR1
]) {
330 VERT_RESTORE_SPEC( 0 );
331 VERT_RESTORE_SPEC( 1 );
339 static void TAG(quadr
)( struct gl_context
*ctx
,
340 GLuint e0
, GLuint e1
, GLuint e2
, GLuint e3
)
342 struct vertex_buffer
*VB
= &TNL_CONTEXT( ctx
)->vb
;
345 GLfloat z
[4] = { 0 };
346 GLenum mode
= GL_FILL
;
350 v
[0] = (VERTEX
*)GET_VERTEX(e0
);
351 v
[1] = (VERTEX
*)GET_VERTEX(e1
);
352 v
[2] = (VERTEX
*)GET_VERTEX(e2
);
353 v
[3] = (VERTEX
*)GET_VERTEX(e3
);
355 if (DO_TWOSIDE
|| DO_OFFSET
|| DO_UNFILLED
|| DO_TWOSTENCIL
)
357 GLfloat ex
= VERT_X(v
[2]) - VERT_X(v
[0]);
358 GLfloat ey
= VERT_Y(v
[2]) - VERT_Y(v
[0]);
359 GLfloat fx
= VERT_X(v
[3]) - VERT_X(v
[1]);
360 GLfloat fy
= VERT_Y(v
[3]) - VERT_Y(v
[1]);
361 GLfloat cc
= ex
*fy
- ey
*fx
;
363 if (DO_TWOSIDE
|| DO_UNFILLED
|| DO_TWOSTENCIL
)
365 facing
= AREA_IS_CCW( cc
) ^ _mesa_polygon_get_front_bit(ctx
);
369 mode
= ctx
->Polygon
.BackMode
;
370 if (ctx
->Polygon
.CullFlag
&&
371 ctx
->Polygon
.CullFaceMode
!= GL_FRONT
) {
375 mode
= ctx
->Polygon
.FrontMode
;
376 if (ctx
->Polygon
.CullFlag
&&
377 ctx
->Polygon
.CullFaceMode
!= GL_BACK
) {
383 if (DO_TWOSIDE
&& facing
== 1) {
384 GLfloat (*vbcolor
)[4] = VB
->BackfaceColorPtr
->data
;
387 if (HAVE_BACK_COLORS
) {
392 VERT_COPY_RGBA1( v
[0] );
393 VERT_COPY_RGBA1( v
[1] );
394 VERT_COPY_RGBA1( v
[2] );
397 VERT_COPY_RGBA1( v
[3] );
403 VERT_COPY_SPEC1( v
[0] );
404 VERT_COPY_SPEC1( v
[1] );
405 VERT_COPY_SPEC1( v
[2] );
408 VERT_COPY_SPEC1( v
[3] );
419 if (VB
->BackfaceColorPtr
->stride
) {
421 VERT_SET_RGBA( v
[0], vbcolor
[e0
] );
422 VERT_SET_RGBA( v
[1], vbcolor
[e1
] );
423 VERT_SET_RGBA( v
[2], vbcolor
[e2
] );
425 VERT_SET_RGBA( v
[3], vbcolor
[e3
] );
429 VERT_SET_RGBA( v
[0], vbcolor
[0] );
430 VERT_SET_RGBA( v
[1], vbcolor
[0] );
431 VERT_SET_RGBA( v
[2], vbcolor
[0] );
433 VERT_SET_RGBA( v
[3], vbcolor
[0] );
436 if (HAVE_SPEC
&& VB
->BackfaceSecondaryColorPtr
) {
437 GLfloat (*vbspec
)[4] = VB
->BackfaceSecondaryColorPtr
->data
;
438 assert(VB
->BackfaceSecondaryColorPtr
->stride
==4*sizeof(GLfloat
));
444 VERT_SET_SPEC( v
[0], vbspec
[e0
] );
445 VERT_SET_SPEC( v
[1], vbspec
[e1
] );
446 VERT_SET_SPEC( v
[2], vbspec
[e2
] );
449 VERT_SET_SPEC( v
[3], vbspec
[e3
] );
458 offset
= ctx
->Polygon
.OffsetUnits
* DEPTH_SCALE
;
463 if (cc
* cc
> 1e-16) {
464 GLfloat ez
= z
[2] - z
[0];
465 GLfloat fz
= z
[3] - z
[1];
466 GLfloat a
= ey
*fz
- ez
*fy
;
467 GLfloat b
= ez
*fx
- ex
*fz
;
468 GLfloat ic
= 1.0 / cc
;
471 if ( ac
< 0.0f
) ac
= -ac
;
472 if ( bc
< 0.0f
) bc
= -bc
;
473 offset
+= MAX2( ac
, bc
) * ctx
->Polygon
.OffsetFactor
/ ctx
->DrawBuffer
->_MRD
;
475 offset
*= ctx
->DrawBuffer
->_MRD
* (REVERSE_DEPTH
? -1.0 : 1.0);
483 VERT_COPY_RGBA( v
[0], v
[3] );
484 VERT_COPY_RGBA( v
[1], v
[3] );
485 VERT_COPY_RGBA( v
[2], v
[3] );
486 if (HAVE_SPEC
&& VB
->AttribPtr
[_TNL_ATTRIB_COLOR1
]) {
490 VERT_COPY_SPEC( v
[0], v
[3] );
491 VERT_COPY_SPEC( v
[1], v
[3] );
492 VERT_COPY_SPEC( v
[2], v
[3] );
496 if (mode
== GL_POINT
) {
497 if (( DO_OFFSET
) && ctx
->Polygon
.OffsetPoint
) {
498 VERT_Z_ADD(v
[0], offset
);
499 VERT_Z_ADD(v
[1], offset
);
500 VERT_Z_ADD(v
[2], offset
);
501 VERT_Z_ADD(v
[3], offset
);
503 if (DO_TWOSTENCIL
&& !HAVE_STENCIL_TWOSIDE
&& ctx
->Stencil
.TestTwoSide
) {
504 SETUP_STENCIL(facing
);
505 UNFILLED_QUAD( ctx
, GL_POINT
, e0
, e1
, e2
, e3
);
506 UNSET_STENCIL(facing
);
508 UNFILLED_QUAD( ctx
, GL_POINT
, e0
, e1
, e2
, e3
);
510 } else if (mode
== GL_LINE
) {
511 if (DO_OFFSET
&& ctx
->Polygon
.OffsetLine
) {
512 VERT_Z_ADD(v
[0], offset
);
513 VERT_Z_ADD(v
[1], offset
);
514 VERT_Z_ADD(v
[2], offset
);
515 VERT_Z_ADD(v
[3], offset
);
517 if (DO_TWOSTENCIL
&& !HAVE_STENCIL_TWOSIDE
&& ctx
->Stencil
.TestTwoSide
) {
518 SETUP_STENCIL(facing
);
519 UNFILLED_QUAD( ctx
, GL_LINE
, e0
, e1
, e2
, e3
);
520 UNSET_STENCIL(facing
);
522 UNFILLED_QUAD( ctx
, GL_LINE
, e0
, e1
, e2
, e3
);
525 if (DO_OFFSET
&& ctx
->Polygon
.OffsetFill
) {
526 VERT_Z_ADD(v
[0], offset
);
527 VERT_Z_ADD(v
[1], offset
);
528 VERT_Z_ADD(v
[2], offset
);
529 VERT_Z_ADD(v
[3], offset
);
531 RASTERIZE( GL_QUADS
);
532 if (DO_TWOSTENCIL
&& !HAVE_STENCIL_TWOSIDE
&& ctx
->Stencil
.TestTwoSide
) {
533 SETUP_STENCIL(facing
);
534 QUAD( (v
[0]), (v
[1]), (v
[2]), (v
[3]) );
535 UNSET_STENCIL(facing
);
537 QUAD( (v
[0]), (v
[1]), (v
[2]), (v
[3]) );
543 VERT_SET_Z(v
[0], z
[0]);
544 VERT_SET_Z(v
[1], z
[1]);
545 VERT_SET_Z(v
[2], z
[2]);
546 VERT_SET_Z(v
[3], z
[3]);
549 if (DO_TWOSIDE
&& facing
== 1) {
551 VERT_RESTORE_RGBA( 0 );
552 VERT_RESTORE_RGBA( 1 );
553 VERT_RESTORE_RGBA( 2 );
555 VERT_RESTORE_RGBA( 3 );
558 VERT_RESTORE_SPEC( 0 );
559 VERT_RESTORE_SPEC( 1 );
560 VERT_RESTORE_SPEC( 2 );
562 VERT_RESTORE_SPEC( 3 );
568 VERT_RESTORE_RGBA( 0 );
569 VERT_RESTORE_RGBA( 1 );
570 VERT_RESTORE_RGBA( 2 );
571 if (HAVE_SPEC
&& VB
->AttribPtr
[_TNL_ATTRIB_COLOR1
]) {
572 VERT_RESTORE_SPEC( 0 );
573 VERT_RESTORE_SPEC( 1 );
574 VERT_RESTORE_SPEC( 2 );
579 static void TAG(quadr
)( struct gl_context
*ctx
, GLuint e0
,
580 GLuint e1
, GLuint e2
, GLuint e3
)
583 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
584 GLubyte ef1
= VB
->EdgeFlag
[e1
];
585 GLubyte ef3
= VB
->EdgeFlag
[e3
];
586 VB
->EdgeFlag
[e1
] = 0;
587 TAG(triangle
)( ctx
, e0
, e1
, e3
);
588 VB
->EdgeFlag
[e1
] = ef1
;
589 VB
->EdgeFlag
[e3
] = 0;
590 TAG(triangle
)( ctx
, e1
, e2
, e3
);
591 VB
->EdgeFlag
[e3
] = ef3
;
593 TAG(triangle
)( ctx
, e0
, e1
, e3
);
594 TAG(triangle
)( ctx
, e1
, e2
, e3
);
601 static void TAG(line
)( struct gl_context
*ctx
, GLuint e0
, GLuint e1
)
603 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
607 v
[0] = (VERTEX
*)GET_VERTEX(e0
);
608 v
[1] = (VERTEX
*)GET_VERTEX(e1
);
612 VERT_COPY_RGBA( v
[0], v
[1] );
613 if (HAVE_SPEC
&& VB
->AttribPtr
[_TNL_ATTRIB_COLOR1
]) {
615 VERT_COPY_SPEC( v
[0], v
[1] );
622 VERT_RESTORE_RGBA( 0 );
624 if (HAVE_SPEC
&& VB
->AttribPtr
[_TNL_ATTRIB_COLOR1
]) {
625 VERT_RESTORE_SPEC( 0 );
632 static void TAG(points
)( struct gl_context
*ctx
, GLuint first
, GLuint last
)
634 struct vertex_buffer
*VB
= &TNL_CONTEXT( ctx
)->vb
;
639 for ( i
= first
; i
< last
; i
++ ) {
640 if ( VB
->ClipMask
[i
] == 0 ) {
641 VERTEX
*v
= (VERTEX
*)GET_VERTEX(i
);
646 for ( i
= first
; i
< last
; i
++ ) {
647 GLuint e
= VB
->Elts
[i
];
648 if ( VB
->ClipMask
[e
] == 0 ) {
649 VERTEX
*v
= (VERTEX
*)GET_VERTEX(e
);
657 static void TAG(init
)( void )
660 TAB
[IND
].quad
= TAG(quadr
);
663 TAB
[IND
].triangle
= TAG(triangle
);
666 TAB
[IND
].line
= TAG(line
);
669 TAB
[IND
].points
= TAG(points
);
682 #undef VERT_COPY_SPEC
683 #undef VERT_SAVE_SPEC
684 #undef VERT_RESTORE_SPEC
686 #undef VERT_COPY_SPEC1
694 #if !HAVE_BACK_COLORS
695 #undef VERT_COPY_SPEC1
696 #undef VERT_COPY_RGBA1
699 #ifndef INSANE_VERTICES