Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / tnl_dd / imm / t_dd_imm_vb.c
1
2 /*
3  * Mesa 3-D graphics library
4  * Version:  3.5
5  *
6  * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
7  *
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:
14  *
15  * The above copyright notice and this permission notice shall be included
16  * in all copies or substantial portions of the Software.
17  *
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.
24  *
25  * Authors:
26  *    Keith Whitwell <keith_whitwell@yahoo.com>
27  */
28
29 /* Template to build clipping routines to support t_dd_imm_primtmp.h.
30  *
31  * The TAG(draw_line) and TAG(draw_triangle) routines are called in
32  * clipping and fallback scenarios, and when the native hardware
33  * primitive (eg polygons) is unavailable.
34  */
35
36
37 #define CLIP_DOTPROD(K, A, B, C, D)             \
38    (CLIP_X(K)*A + CLIP_Y(K)*B +         \
39     CLIP_Z(K)*C + CLIP_W(K)*D)
40
41 #define POLY_CLIP( PLANE, A, B, C, D )                                  \
42 do {                                                                    \
43    if (mask & PLANE) {                                                  \
44       TNL_VERTEX **indata = inlist[in];                                 \
45       TNL_VERTEX **outdata = inlist[in ^= 1];                           \
46       TNL_VERTEX *J = indata[0];                                        \
47       GLfloat dpJ = CLIP_DOTPROD(J, A, B, C, D );                       \
48       GLuint outcount = 0;                                              \
49       GLuint i;                                                         \
50                                                                         \
51       indata[n] = indata[0]; /* prevent rotation of vertices */         \
52       for (i = 1; i <= n; i++) {                                        \
53          TNL_VERTEX *I = indata[i];                                     \
54          GLfloat dpI = CLIP_DOTPROD(idx, A, B, C, D );                  \
55                                                                         \
56          if (!NEGATIVE(dpPrev)) {                                       \
57             outdata[outcount++] = J;                                    \
58          }                                                              \
59                                                                         \
60          if (DIFFERENT_SIGNS(dpI, dpJ)) {                               \
61             TNL_VERTEX *O = verts++;                                    \
62             outdata[outcount++] = O;                                    \
63             if (NEGATIVE(dpI)) {                                        \
64                /* Going out of bounds.  Avoid division by zero as we    \
65                 * know dp != dpPrev from DIFFERENT_SIGNS, above.        \
66                 */                                                      \
67                GLfloat t = dpI / (dpI - dpJ);                           \
68                INTERP( ctx, t, O, I, J );                               \
69             } else {                                                    \
70                /* Coming back in.                                       \
71                 */                                                      \
72                GLfloat t = dpJ / (dpJ - dpI);                           \
73                INTERP( ctx, t, O, J, I );                               \
74             }                                                           \
75          }                                                              \
76                                                                         \
77          J = I;                                                         \
78          dpJ = dpI;                                                     \
79       }                                                                 \
80                                                                         \
81       if (outcount < 3)                                                 \
82          return;                                                        \
83                                                                         \
84       nr = outcount;                                                    \
85    }                                                                    \
86 } while (0)
87
88
89 #define LINE_CLIP(PLANE, A, B, C, D )                   \
90 do {                                                    \
91    if (mask & PLANE) {                                  \
92       GLfloat dpI = CLIP_DOTPROD( I, A, B, C, D );      \
93       GLfloat dpJ = CLIP_DOTPROD( J, A, B, C, D );      \
94                                                         \
95       if (DIFFERENT_SIGNS(dpI, dpJ)) {                  \
96          TNL_VERTEX *O = verts++;                       \
97          if (NEGATIVE(dpJ)) {                           \
98             GLfloat t = dpI / (dpI - dpJ);              \
99             INTERP( ctx, t, O, I, J );  \
100             J = O;                                      \
101          } else {                                       \
102             GLfloat t = dpJ / (dpJ - dpI);              \
103             INTERP( ctx, t, O, J, I );  \
104             I = O;                                      \
105          }                                              \
106       }                                                 \
107       else if (NEGATIVE(dpI))                           \
108          return;                                        \
109   }                                                     \
110 } while (0)
111
112
113
114 /* Clip a line against the viewport and user clip planes.
115  */
116 static void TAG(clip_draw_line)( struct gl_context *ctx,
117                                  TNL_VERTEX *I,
118                                  TNL_VERTEX *J,
119                                  GLuint mask )
120 {
121    LOCAL_VARS;
122    GET_INTERP_FUNC;
123    TNL_VERTEX tmp[MAX_CLIPPED_VERTICES];
124    TNL_VERTEX *verts = tmp;
125    TNL_VERTEX *pv = J;
126
127    LINE_CLIP( CLIP_RIGHT_BIT,  -1,  0,  0, 1 );
128    LINE_CLIP( CLIP_LEFT_BIT,    1,  0,  0, 1 );
129    LINE_CLIP( CLIP_TOP_BIT,     0, -1,  0, 1 );
130    LINE_CLIP( CLIP_BOTTOM_BIT,  0,  1,  0, 1 );
131    LINE_CLIP( CLIP_FAR_BIT,     0,  0, -1, 1 );
132    LINE_CLIP( CLIP_NEAR_BIT,    0,  0,  1, 1 );
133
134    if ((ctx->_TriangleCaps & DD_FLATSHADE) && J != pv)
135       COPY_PV( ctx, J, pv );
136
137    DRAW_LINE( I, J );
138 }
139
140
141 /* Clip a triangle against the viewport and user clip planes.
142  */
143 static void TAG(clip_draw_triangle)( struct gl_context *ctx,
144                                      TNL_VERTEX *v0,
145                                      TNL_VERTEX *v1,
146                                      TNL_VERTEX *v2,
147                                      GLuint mask )
148 {
149    LOCAL_VARS;
150    GET_INTERP_FUNC;
151    TNL_VERTEX tmp[MAX_CLIPPED_VERTICES];
152    TNL_VERTEX *verts = tmp;
153    TNL_VERTEX *(inlist[2][MAX_CLIPPED_VERTICES]);
154    TNL_VERTEX **out;
155    GLuint in = 0;
156    GLuint n = 3;
157    GLuint i;
158
159    ASSIGN_3V(inlist, v2, v0, v1 ); /* pv rotated to slot zero */
160
161    POLY_CLIP( CLIP_RIGHT_BIT,  -1,  0,  0, 1 );
162    POLY_CLIP( CLIP_LEFT_BIT,    1,  0,  0, 1 );
163    POLY_CLIP( CLIP_TOP_BIT,     0, -1,  0, 1 );
164    POLY_CLIP( CLIP_BOTTOM_BIT,  0,  1,  0, 1 );
165    POLY_CLIP( CLIP_FAR_BIT,     0,  0, -1, 1 );
166    POLY_CLIP( CLIP_NEAR_BIT,    0,  0,  1, 1 );
167
168    if ((ctx->_TriangleCaps & DD_FLATSHADE) && v2 != inlist[0]) 
169       COPY_PV( ctx, inlist[0], v2 );
170
171    out = inlist[in];
172    DRAW_POLYGON( out, n );
173 }
174
175
176 static __inline void TAG(draw_triangle)( struct gl_context *ctx,
177                                          TNL_VERTEX *v0,
178                                          TNL_VERTEX *v1,
179                                          TNL_VERTEX *v2 )
180 {
181    LOCAL_VARS;
182    GLubyte ormask = (v0->mask | v1->mask | v2->mask);
183
184    if ( !ormask ) {
185       DRAW_TRI( v0, v1, v2 );
186    } else if ( !(v0->mask & v1->mask & v2->mask) ) {
187       TAG(clip_draw_triangle)( ctx, v0, v1, v2, ormask );
188    }
189 }
190
191 static __inline void TAG(draw_line)( struct gl_context *ctx,
192                                      TNL_VERTEX *v0,
193                                      TNL_VERTEX *v1 )
194 {
195    LOCAL_VARS;
196    GLubyte ormask = (v0->mask | v1->mask);
197
198    if ( !ormask ) {
199       DRAW_LINE( v0, v1 );
200    } else if ( !(v0->mask & v1->mask) ) {
201       TAG(clip_draw_line)( ctx, v0, v1, ormask );
202    }
203 }
204