2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * 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.
44 * DO_TWOSTENCIL:Gross hack for two-sided stencil.
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 constant offset.
52 * REVERSE_DEPTH: Viewport depth range reversed.
54 * VERTEX: Hardware vertex type.
55 * GET_VERTEX(n): Retreive vertex with index n.
56 * AREA_IS_CCW(a): Return true if triangle with signed area a is ccw.
58 * VERT_SET_RGBA: Assign vertex rgba from VB color.
59 * VERT_COPY_RGBA: Copy vertex rgba another vertex.
60 * VERT_SAVE_RGBA: Save vertex rgba to a local variable.
61 * VERT_RESTORE_RGBA: Restore vertex rgba from a local variable.
62 * --> Similar for SPEC.
64 * LOCAL_VARS(n): (At least) define local vars for save/restore rgba.
69 #define VERT_SET_RGBA( v, c )
73 #define VERT_SET_SPEC( v, c ) (void) c
74 #define VERT_COPY_SPEC( v0, v1 )
75 #define VERT_SAVE_SPEC( idx )
76 #define VERT_RESTORE_SPEC( idx )
78 #define VERT_COPY_SPEC1( v )
82 #define VERT_SET_SPEC( v, c )
87 #define VERT_COPY_SPEC1( v )
88 #define VERT_COPY_RGBA1( v )
91 #ifndef INSANE_VERTICES
92 #define VERT_SET_Z(v,val) VERT_Z(v) = val
93 #define VERT_Z_ADD(v,val) VERT_Z(v) += val
97 #define REVERSE_DEPTH 0
100 /* disable twostencil for un-aware drivers */
101 #ifndef HAVE_STENCIL_TWOSIDE
102 #define HAVE_STENCIL_TWOSIDE 0
104 #ifndef DO_TWOSTENCIL
105 #define DO_TWOSTENCIL 0
107 #ifndef SETUP_STENCIL
108 #define SETUP_STENCIL(f)
110 #ifndef UNSET_STENCIL
111 #define UNSET_STENCIL(f)
115 static void TAG(triangle
)( struct gl_context
*ctx
, GLuint e0
, GLuint e1
, GLuint e2
)
117 struct vertex_buffer
*VB
= &TNL_CONTEXT( ctx
)->vb
;
120 GLfloat z
[3] = { 0 };
121 GLenum mode
= GL_FILL
;
125 /* fprintf(stderr, "%s\n", __FUNCTION__); */
127 v
[0] = (VERTEX
*)GET_VERTEX(e0
);
128 v
[1] = (VERTEX
*)GET_VERTEX(e1
);
129 v
[2] = (VERTEX
*)GET_VERTEX(e2
);
131 if (DO_TWOSIDE
|| DO_OFFSET
|| DO_UNFILLED
|| DO_TWOSTENCIL
)
133 GLfloat ex
= VERT_X(v
[0]) - VERT_X(v
[2]);
134 GLfloat ey
= VERT_Y(v
[0]) - VERT_Y(v
[2]);
135 GLfloat fx
= VERT_X(v
[1]) - VERT_X(v
[2]);
136 GLfloat fy
= VERT_Y(v
[1]) - VERT_Y(v
[2]);
137 GLfloat cc
= ex
*fy
- ey
*fx
;
139 if (DO_TWOSIDE
|| DO_UNFILLED
|| DO_TWOSTENCIL
)
141 facing
= AREA_IS_CCW( cc
) ^ ctx
->Polygon
._FrontBit
;
145 mode
= ctx
->Polygon
.BackMode
;
146 if (ctx
->Polygon
.CullFlag
&&
147 ctx
->Polygon
.CullFaceMode
!= GL_FRONT
) {
151 mode
= ctx
->Polygon
.FrontMode
;
152 if (ctx
->Polygon
.CullFlag
&&
153 ctx
->Polygon
.CullFaceMode
!= GL_BACK
) {
159 if (DO_TWOSIDE
&& facing
== 1) {
160 if (HAVE_BACK_COLORS
) {
164 VERT_COPY_RGBA1( v
[0] );
165 VERT_COPY_RGBA1( v
[1] );
168 VERT_COPY_RGBA1( v
[2] );
173 VERT_COPY_SPEC1( v
[0] );
174 VERT_COPY_SPEC1( v
[1] );
177 VERT_COPY_SPEC1( v
[2] );
181 GLfloat (*vbcolor
)[4] = VB
->BackfaceColorPtr
->data
;
190 if (VB
->BackfaceColorPtr
->stride
) {
191 ASSERT(VB
->BackfaceColorPtr
->stride
== 4*sizeof(GLfloat
));
194 VERT_SET_RGBA( v
[0], vbcolor
[e0
] );
195 VERT_SET_RGBA( v
[1], vbcolor
[e1
] );
197 VERT_SET_RGBA( v
[2], vbcolor
[e2
] );
201 VERT_SET_RGBA( v
[0], vbcolor
[0] );
202 VERT_SET_RGBA( v
[1], vbcolor
[0] );
204 VERT_SET_RGBA( v
[2], vbcolor
[0] );
207 if (HAVE_SPEC
&& VB
->BackfaceSecondaryColorPtr
) {
208 GLfloat (*vbspec
)[4] = VB
->BackfaceSecondaryColorPtr
->data
;
209 ASSERT(VB
->BackfaceSecondaryColorPtr
->stride
== 4*sizeof(GLfloat
));
214 VERT_SET_SPEC( v
[0], vbspec
[e0
] );
215 VERT_SET_SPEC( v
[1], vbspec
[e1
] );
218 VERT_SET_SPEC( v
[2], vbspec
[e2
] );
227 offset
= ctx
->Polygon
.OffsetUnits
* DEPTH_SCALE
;
231 if (cc
* cc
> 1e-16) {
232 GLfloat ic
= 1.0 / cc
;
233 GLfloat ez
= z
[0] - z
[2];
234 GLfloat fz
= z
[1] - z
[2];
235 GLfloat a
= ey
*fz
- ez
*fy
;
236 GLfloat b
= ez
*fx
- ex
*fz
;
239 if ( ac
< 0.0f
) ac
= -ac
;
240 if ( bc
< 0.0f
) bc
= -bc
;
241 offset
+= MAX2( ac
, bc
) * ctx
->Polygon
.OffsetFactor
/ ctx
->DrawBuffer
->_MRD
;
243 offset
*= ctx
->DrawBuffer
->_MRD
* (REVERSE_DEPTH
? -1.0 : 1.0);
250 VERT_COPY_RGBA( v
[0], v
[2] );
251 VERT_COPY_RGBA( v
[1], v
[2] );
252 if (HAVE_SPEC
&& VB
->AttribPtr
[_TNL_ATTRIB_COLOR1
]) {
255 VERT_COPY_SPEC( v
[0], v
[2] );
256 VERT_COPY_SPEC( v
[1], v
[2] );
260 if (mode
== GL_POINT
) {
261 if (DO_OFFSET
&& ctx
->Polygon
.OffsetPoint
) {
262 VERT_Z_ADD(v
[0], offset
);
263 VERT_Z_ADD(v
[1], offset
);
264 VERT_Z_ADD(v
[2], offset
);
266 if (DO_TWOSTENCIL
&& !HAVE_STENCIL_TWOSIDE
&& ctx
->Stencil
.TestTwoSide
) {
267 SETUP_STENCIL(facing
);
268 UNFILLED_TRI( ctx
, GL_POINT
, e0
, e1
, e2
);
269 UNSET_STENCIL(facing
);
271 UNFILLED_TRI( ctx
, GL_POINT
, e0
, e1
, e2
);
273 } else if (mode
== GL_LINE
) {
274 if (DO_OFFSET
&& ctx
->Polygon
.OffsetLine
) {
275 VERT_Z_ADD(v
[0], offset
);
276 VERT_Z_ADD(v
[1], offset
);
277 VERT_Z_ADD(v
[2], offset
);
279 if (DO_TWOSTENCIL
&& !HAVE_STENCIL_TWOSIDE
&& ctx
->Stencil
.TestTwoSide
) {
280 SETUP_STENCIL(facing
);
281 UNFILLED_TRI( ctx
, GL_LINE
, e0
, e1
, e2
);
282 UNSET_STENCIL(facing
);
284 UNFILLED_TRI( ctx
, GL_LINE
, e0
, e1
, e2
);
287 if (DO_OFFSET
&& ctx
->Polygon
.OffsetFill
) {
288 VERT_Z_ADD(v
[0], offset
);
289 VERT_Z_ADD(v
[1], offset
);
290 VERT_Z_ADD(v
[2], offset
);
293 RASTERIZE( GL_TRIANGLES
);
295 if (DO_TWOSTENCIL
&& !HAVE_STENCIL_TWOSIDE
&& ctx
->Stencil
.TestTwoSide
) {
296 SETUP_STENCIL(facing
);
297 TRI( v
[0], v
[1], v
[2] );
298 UNSET_STENCIL(facing
);
300 TRI( v
[0], v
[1], v
[2] );
306 VERT_SET_Z(v
[0], z
[0]);
307 VERT_SET_Z(v
[1], z
[1]);
308 VERT_SET_Z(v
[2], z
[2]);
311 if (DO_TWOSIDE
&& facing
== 1) {
313 VERT_RESTORE_RGBA( 0 );
314 VERT_RESTORE_RGBA( 1 );
316 VERT_RESTORE_RGBA( 2 );
319 VERT_RESTORE_SPEC( 0 );
320 VERT_RESTORE_SPEC( 1 );
322 VERT_RESTORE_SPEC( 2 );
328 VERT_RESTORE_RGBA( 0 );
329 VERT_RESTORE_RGBA( 1 );
330 if (HAVE_SPEC
&& VB
->AttribPtr
[_TNL_ATTRIB_COLOR1
]) {
331 VERT_RESTORE_SPEC( 0 );
332 VERT_RESTORE_SPEC( 1 );
340 static void TAG(quadr
)( struct gl_context
*ctx
,
341 GLuint e0
, GLuint e1
, GLuint e2
, GLuint e3
)
343 struct vertex_buffer
*VB
= &TNL_CONTEXT( ctx
)->vb
;
346 GLfloat z
[4] = { 0 };
347 GLenum mode
= GL_FILL
;
351 v
[0] = (VERTEX
*)GET_VERTEX(e0
);
352 v
[1] = (VERTEX
*)GET_VERTEX(e1
);
353 v
[2] = (VERTEX
*)GET_VERTEX(e2
);
354 v
[3] = (VERTEX
*)GET_VERTEX(e3
);
356 if (DO_TWOSIDE
|| DO_OFFSET
|| DO_UNFILLED
|| DO_TWOSTENCIL
)
358 GLfloat ex
= VERT_X(v
[2]) - VERT_X(v
[0]);
359 GLfloat ey
= VERT_Y(v
[2]) - VERT_Y(v
[0]);
360 GLfloat fx
= VERT_X(v
[3]) - VERT_X(v
[1]);
361 GLfloat fy
= VERT_Y(v
[3]) - VERT_Y(v
[1]);
362 GLfloat cc
= ex
*fy
- ey
*fx
;
364 if (DO_TWOSIDE
|| DO_UNFILLED
|| DO_TWOSTENCIL
)
366 facing
= AREA_IS_CCW( cc
) ^ ctx
->Polygon
._FrontBit
;
370 mode
= ctx
->Polygon
.BackMode
;
371 if (ctx
->Polygon
.CullFlag
&&
372 ctx
->Polygon
.CullFaceMode
!= GL_FRONT
) {
376 mode
= ctx
->Polygon
.FrontMode
;
377 if (ctx
->Polygon
.CullFlag
&&
378 ctx
->Polygon
.CullFaceMode
!= GL_BACK
) {
384 if (DO_TWOSIDE
&& facing
== 1) {
385 GLfloat (*vbcolor
)[4] = VB
->BackfaceColorPtr
->data
;
388 if (HAVE_BACK_COLORS
) {
393 VERT_COPY_RGBA1( v
[0] );
394 VERT_COPY_RGBA1( v
[1] );
395 VERT_COPY_RGBA1( v
[2] );
398 VERT_COPY_RGBA1( v
[3] );
404 VERT_COPY_SPEC1( v
[0] );
405 VERT_COPY_SPEC1( v
[1] );
406 VERT_COPY_SPEC1( v
[2] );
409 VERT_COPY_SPEC1( v
[3] );
420 if (VB
->BackfaceColorPtr
->stride
) {
422 VERT_SET_RGBA( v
[0], vbcolor
[e0
] );
423 VERT_SET_RGBA( v
[1], vbcolor
[e1
] );
424 VERT_SET_RGBA( v
[2], vbcolor
[e2
] );
426 VERT_SET_RGBA( v
[3], vbcolor
[e3
] );
430 VERT_SET_RGBA( v
[0], vbcolor
[0] );
431 VERT_SET_RGBA( v
[1], vbcolor
[0] );
432 VERT_SET_RGBA( v
[2], vbcolor
[0] );
434 VERT_SET_RGBA( v
[3], vbcolor
[0] );
437 if (HAVE_SPEC
&& VB
->BackfaceSecondaryColorPtr
) {
438 GLfloat (*vbspec
)[4] = VB
->BackfaceSecondaryColorPtr
->data
;
439 ASSERT(VB
->BackfaceSecondaryColorPtr
->stride
==4*sizeof(GLfloat
));
445 VERT_SET_SPEC( v
[0], vbspec
[e0
] );
446 VERT_SET_SPEC( v
[1], vbspec
[e1
] );
447 VERT_SET_SPEC( v
[2], vbspec
[e2
] );
450 VERT_SET_SPEC( v
[3], vbspec
[e3
] );
459 offset
= ctx
->Polygon
.OffsetUnits
* DEPTH_SCALE
;
464 if (cc
* cc
> 1e-16) {
465 GLfloat ez
= z
[2] - z
[0];
466 GLfloat fz
= z
[3] - z
[1];
467 GLfloat a
= ey
*fz
- ez
*fy
;
468 GLfloat b
= ez
*fx
- ex
*fz
;
469 GLfloat ic
= 1.0 / cc
;
472 if ( ac
< 0.0f
) ac
= -ac
;
473 if ( bc
< 0.0f
) bc
= -bc
;
474 offset
+= MAX2( ac
, bc
) * ctx
->Polygon
.OffsetFactor
/ ctx
->DrawBuffer
->_MRD
;
476 offset
*= ctx
->DrawBuffer
->_MRD
* (REVERSE_DEPTH
? -1.0 : 1.0);
484 VERT_COPY_RGBA( v
[0], v
[3] );
485 VERT_COPY_RGBA( v
[1], v
[3] );
486 VERT_COPY_RGBA( v
[2], v
[3] );
487 if (HAVE_SPEC
&& VB
->AttribPtr
[_TNL_ATTRIB_COLOR1
]) {
491 VERT_COPY_SPEC( v
[0], v
[3] );
492 VERT_COPY_SPEC( v
[1], v
[3] );
493 VERT_COPY_SPEC( v
[2], v
[3] );
497 if (mode
== GL_POINT
) {
498 if (( DO_OFFSET
) && ctx
->Polygon
.OffsetPoint
) {
499 VERT_Z_ADD(v
[0], offset
);
500 VERT_Z_ADD(v
[1], offset
);
501 VERT_Z_ADD(v
[2], offset
);
502 VERT_Z_ADD(v
[3], offset
);
504 if (DO_TWOSTENCIL
&& !HAVE_STENCIL_TWOSIDE
&& ctx
->Stencil
.TestTwoSide
) {
505 SETUP_STENCIL(facing
);
506 UNFILLED_QUAD( ctx
, GL_POINT
, e0
, e1
, e2
, e3
);
507 UNSET_STENCIL(facing
);
509 UNFILLED_QUAD( ctx
, GL_POINT
, e0
, e1
, e2
, e3
);
511 } else if (mode
== GL_LINE
) {
512 if (DO_OFFSET
&& ctx
->Polygon
.OffsetLine
) {
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 if (DO_TWOSTENCIL
&& !HAVE_STENCIL_TWOSIDE
&& ctx
->Stencil
.TestTwoSide
) {
519 SETUP_STENCIL(facing
);
520 UNFILLED_QUAD( ctx
, GL_LINE
, e0
, e1
, e2
, e3
);
521 UNSET_STENCIL(facing
);
523 UNFILLED_QUAD( ctx
, GL_LINE
, e0
, e1
, e2
, e3
);
526 if (DO_OFFSET
&& ctx
->Polygon
.OffsetFill
) {
527 VERT_Z_ADD(v
[0], offset
);
528 VERT_Z_ADD(v
[1], offset
);
529 VERT_Z_ADD(v
[2], offset
);
530 VERT_Z_ADD(v
[3], offset
);
532 RASTERIZE( GL_QUADS
);
533 if (DO_TWOSTENCIL
&& !HAVE_STENCIL_TWOSIDE
&& ctx
->Stencil
.TestTwoSide
) {
534 SETUP_STENCIL(facing
);
535 QUAD( (v
[0]), (v
[1]), (v
[2]), (v
[3]) );
536 UNSET_STENCIL(facing
);
538 QUAD( (v
[0]), (v
[1]), (v
[2]), (v
[3]) );
544 VERT_SET_Z(v
[0], z
[0]);
545 VERT_SET_Z(v
[1], z
[1]);
546 VERT_SET_Z(v
[2], z
[2]);
547 VERT_SET_Z(v
[3], z
[3]);
550 if (DO_TWOSIDE
&& facing
== 1) {
552 VERT_RESTORE_RGBA( 0 );
553 VERT_RESTORE_RGBA( 1 );
554 VERT_RESTORE_RGBA( 2 );
556 VERT_RESTORE_RGBA( 3 );
559 VERT_RESTORE_SPEC( 0 );
560 VERT_RESTORE_SPEC( 1 );
561 VERT_RESTORE_SPEC( 2 );
563 VERT_RESTORE_SPEC( 3 );
569 VERT_RESTORE_RGBA( 0 );
570 VERT_RESTORE_RGBA( 1 );
571 VERT_RESTORE_RGBA( 2 );
572 if (HAVE_SPEC
&& VB
->AttribPtr
[_TNL_ATTRIB_COLOR1
]) {
573 VERT_RESTORE_SPEC( 0 );
574 VERT_RESTORE_SPEC( 1 );
575 VERT_RESTORE_SPEC( 2 );
580 static void TAG(quadr
)( struct gl_context
*ctx
, GLuint e0
,
581 GLuint e1
, GLuint e2
, GLuint e3
)
584 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
585 GLubyte ef1
= VB
->EdgeFlag
[e1
];
586 GLubyte ef3
= VB
->EdgeFlag
[e3
];
587 VB
->EdgeFlag
[e1
] = 0;
588 TAG(triangle
)( ctx
, e0
, e1
, e3
);
589 VB
->EdgeFlag
[e1
] = ef1
;
590 VB
->EdgeFlag
[e3
] = 0;
591 TAG(triangle
)( ctx
, e1
, e2
, e3
);
592 VB
->EdgeFlag
[e3
] = ef3
;
594 TAG(triangle
)( ctx
, e0
, e1
, e3
);
595 TAG(triangle
)( ctx
, e1
, e2
, e3
);
602 static void TAG(line
)( struct gl_context
*ctx
, GLuint e0
, GLuint e1
)
604 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
608 v
[0] = (VERTEX
*)GET_VERTEX(e0
);
609 v
[1] = (VERTEX
*)GET_VERTEX(e1
);
613 VERT_COPY_RGBA( v
[0], v
[1] );
614 if (HAVE_SPEC
&& VB
->AttribPtr
[_TNL_ATTRIB_COLOR1
]) {
616 VERT_COPY_SPEC( v
[0], v
[1] );
623 VERT_RESTORE_RGBA( 0 );
625 if (HAVE_SPEC
&& VB
->AttribPtr
[_TNL_ATTRIB_COLOR1
]) {
626 VERT_RESTORE_SPEC( 0 );
633 static void TAG(points
)( struct gl_context
*ctx
, GLuint first
, GLuint last
)
635 struct vertex_buffer
*VB
= &TNL_CONTEXT( ctx
)->vb
;
640 for ( i
= first
; i
< last
; i
++ ) {
641 if ( VB
->ClipMask
[i
] == 0 ) {
642 VERTEX
*v
= (VERTEX
*)GET_VERTEX(i
);
647 for ( i
= first
; i
< last
; i
++ ) {
648 GLuint e
= VB
->Elts
[i
];
649 if ( VB
->ClipMask
[e
] == 0 ) {
650 VERTEX
*v
= (VERTEX
*)GET_VERTEX(e
);
658 static void TAG(init
)( void )
661 TAB
[IND
].quad
= TAG(quadr
);
664 TAB
[IND
].triangle
= TAG(triangle
);
667 TAB
[IND
].line
= TAG(line
);
670 TAB
[IND
].points
= TAG(points
);
683 #undef VERT_COPY_SPEC
684 #undef VERT_SAVE_SPEC
685 #undef VERT_RESTORE_SPEC
687 #undef VERT_COPY_SPEC1
695 #if !HAVE_BACK_COLORS
696 #undef VERT_COPY_SPEC1
697 #undef VERT_COPY_RGBA1
700 #ifndef INSANE_VERTICES