replaced __inline with INLINE
[mesa.git] / src / mesa / tnl / t_vb_cliptmp.h
1 /* $Id: t_vb_cliptmp.h,v 1.14 2001/07/13 17:26:39 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2001 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 * Authors:
27 * Keith Whitwell <keithw@valinux.com>
28 */
29
30
31 #define CLIP_DOTPROD(K, A, B, C, D) X(K)*A + Y(K)*B + Z(K)*C + W(K)*D
32
33 #define POLY_CLIP( PLANE, A, B, C, D ) \
34 do { \
35 if (mask & PLANE) { \
36 GLuint idxPrev = inlist[0]; \
37 GLfloat dpPrev = CLIP_DOTPROD(idxPrev, A, B, C, D ); \
38 GLuint outcount = 0; \
39 GLuint i; \
40 \
41 inlist[n] = inlist[0]; /* prevent rotation of vertices */ \
42 for (i = 1; i <= n; i++) { \
43 GLuint idx = inlist[i]; \
44 GLfloat dp = CLIP_DOTPROD(idx, A, B, C, D ); \
45 \
46 clipmask[idxPrev] |= PLANE; \
47 if (!NEGATIVE(dpPrev)) { \
48 outlist[outcount++] = idxPrev; \
49 clipmask[idxPrev] &= ~PLANE; \
50 } \
51 \
52 if (DIFFERENT_SIGNS(dp, dpPrev)) { \
53 GLuint newvert = VB->LastClipped++; \
54 VB->ClipMask[newvert] = 0; \
55 outlist[outcount++] = newvert; \
56 if (NEGATIVE(dp)) { \
57 /* Going out of bounds. Avoid division by zero as we \
58 * know dp != dpPrev from DIFFERENT_SIGNS, above. \
59 */ \
60 GLfloat t = dp / (dp - dpPrev); \
61 INTERP_4F( t, coord[newvert], coord[idx], coord[idxPrev]); \
62 interp( ctx, t, newvert, idx, idxPrev, GL_TRUE ); \
63 } else { \
64 /* Coming back in. \
65 */ \
66 GLfloat t = dpPrev / (dpPrev - dp); \
67 INTERP_4F( t, coord[newvert], coord[idxPrev], coord[idx]); \
68 interp( ctx, t, newvert, idxPrev, idx, GL_FALSE ); \
69 } \
70 } \
71 \
72 idxPrev = idx; \
73 dpPrev = dp; \
74 } \
75 \
76 if (outcount < 3) \
77 return; \
78 \
79 { \
80 GLuint *tmp = inlist; \
81 inlist = outlist; \
82 outlist = tmp; \
83 n = outcount; \
84 } \
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( ii, A, B, C, D ); \
93 GLfloat dpJ = CLIP_DOTPROD( jj, A, B, C, D ); \
94 \
95 if (DIFFERENT_SIGNS(dpI, dpJ)) { \
96 GLuint newvert = VB->LastClipped++; \
97 VB->ClipMask[newvert] = 0; \
98 if (NEGATIVE(dpJ)) { \
99 GLfloat t = dpI / (dpI - dpJ); \
100 VB->ClipMask[jj] |= PLANE; \
101 INTERP_4F( t, coord[newvert], coord[ii], coord[jj] ); \
102 interp( ctx, t, newvert, ii, jj, GL_FALSE ); \
103 jj = newvert; \
104 } else { \
105 GLfloat t = dpJ / (dpJ - dpI); \
106 VB->ClipMask[ii] |= PLANE; \
107 INTERP_4F( t, coord[newvert], coord[jj], coord[ii] ); \
108 interp( ctx, t, newvert, jj, ii, GL_FALSE ); \
109 ii = newvert; \
110 } \
111 } \
112 else if (NEGATIVE(dpI)) \
113 return; \
114 } \
115 } while (0)
116
117
118
119 /* Clip a line against the viewport and user clip planes.
120 */
121 static INLINE void
122 TAG(clip_line)( GLcontext *ctx, GLuint i, GLuint j, GLubyte mask )
123 {
124 TNLcontext *tnl = TNL_CONTEXT(ctx);
125 struct vertex_buffer *VB = &tnl->vb;
126 interp_func interp = tnl->Driver.Render.Interp;
127 GLfloat (*coord)[4] = VB->ClipPtr->data;
128 GLuint ii = i, jj = j, p;
129
130 VB->LastClipped = VB->FirstClipped;
131
132 if (mask & 0x3f) {
133 LINE_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 );
134 LINE_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 );
135 LINE_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 );
136 LINE_CLIP( CLIP_BOTTOM_BIT, 0, 1, 0, 1 );
137 LINE_CLIP( CLIP_FAR_BIT, 0, 0, -1, 1 );
138 LINE_CLIP( CLIP_NEAR_BIT, 0, 0, 1, 1 );
139 }
140
141 if (mask & CLIP_USER_BIT) {
142 for (p=0;p<MAX_CLIP_PLANES;p++) {
143 if (ctx->Transform.ClipEnabled[p]) {
144 GLfloat a = ctx->Transform._ClipUserPlane[p][0];
145 GLfloat b = ctx->Transform._ClipUserPlane[p][1];
146 GLfloat c = ctx->Transform._ClipUserPlane[p][2];
147 GLfloat d = ctx->Transform._ClipUserPlane[p][3];
148 LINE_CLIP( CLIP_USER_BIT, a, b, c, d );
149 }
150 }
151 }
152
153 if ((ctx->_TriangleCaps & DD_FLATSHADE) && j != jj)
154 tnl->Driver.Render.CopyPV( ctx, jj, j );
155
156 tnl->Driver.Render.ClippedLine( ctx, ii, jj );
157 }
158
159
160 /* Clip a triangle against the viewport and user clip planes.
161 */
162 static INLINE void
163 TAG(clip_tri)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLubyte mask )
164 {
165 TNLcontext *tnl = TNL_CONTEXT(ctx);
166 struct vertex_buffer *VB = &tnl->vb;
167 interp_func interp = tnl->Driver.Render.Interp;
168 GLfloat (*coord)[4] = VB->ClipPtr->data;
169 GLuint pv = v2;
170 GLuint vlist[2][MAX_CLIPPED_VERTICES];
171 GLuint *inlist = vlist[0], *outlist = vlist[1];
172 GLuint p;
173 GLubyte *clipmask = VB->ClipMask;
174 GLuint n = 3;
175
176 ASSIGN_3V(inlist, v2, v0, v1 ); /* pv rotated to slot zero */
177
178 VB->LastClipped = VB->FirstClipped;
179
180 if (mask & 0x3f) {
181 POLY_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 );
182 POLY_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 );
183 POLY_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 );
184 POLY_CLIP( CLIP_BOTTOM_BIT, 0, 1, 0, 1 );
185 POLY_CLIP( CLIP_FAR_BIT, 0, 0, -1, 1 );
186 POLY_CLIP( CLIP_NEAR_BIT, 0, 0, 1, 1 );
187 }
188
189 if (mask & CLIP_USER_BIT) {
190 for (p=0;p<MAX_CLIP_PLANES;p++) {
191 if (ctx->Transform.ClipEnabled[p]) {
192 GLfloat a = ctx->Transform._ClipUserPlane[p][0];
193 GLfloat b = ctx->Transform._ClipUserPlane[p][1];
194 GLfloat c = ctx->Transform._ClipUserPlane[p][2];
195 GLfloat d = ctx->Transform._ClipUserPlane[p][3];
196 POLY_CLIP( CLIP_USER_BIT, a, b, c, d );
197 }
198 }
199 }
200
201 if (ctx->_TriangleCaps & DD_FLATSHADE) {
202 if (pv != inlist[0]) {
203 ASSERT( inlist[0] >= VB->FirstClipped );
204 tnl->Driver.Render.CopyPV( ctx, inlist[0], pv );
205 }
206 }
207
208 tnl->Driver.Render.ClippedPolygon( ctx, inlist, n );
209 }
210
211
212 /* Clip a quad against the viewport and user clip planes.
213 */
214 static INLINE void
215 TAG(clip_quad)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3,
216 GLubyte mask )
217 {
218 TNLcontext *tnl = TNL_CONTEXT(ctx);
219 struct vertex_buffer *VB = &tnl->vb;
220 interp_func interp = tnl->Driver.Render.Interp;
221 GLfloat (*coord)[4] = VB->ClipPtr->data;
222 GLuint pv = v3;
223 GLuint vlist[2][MAX_CLIPPED_VERTICES];
224 GLuint *inlist = vlist[0], *outlist = vlist[1];
225 GLuint p;
226 GLubyte *clipmask = VB->ClipMask;
227 GLuint n = 4;
228
229 ASSIGN_4V(inlist, v3, v0, v1, v2 ); /* pv rotated to slot zero */
230
231 VB->LastClipped = VB->FirstClipped;
232
233 if (mask & 0x3f) {
234 POLY_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 );
235 POLY_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 );
236 POLY_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 );
237 POLY_CLIP( CLIP_BOTTOM_BIT, 0, 1, 0, 1 );
238 POLY_CLIP( CLIP_FAR_BIT, 0, 0, -1, 1 );
239 POLY_CLIP( CLIP_NEAR_BIT, 0, 0, 1, 1 );
240 }
241
242 if (mask & CLIP_USER_BIT) {
243 for (p=0;p<MAX_CLIP_PLANES;p++) {
244 if (ctx->Transform.ClipEnabled[p]) {
245 GLfloat a = ctx->Transform._ClipUserPlane[p][0];
246 GLfloat b = ctx->Transform._ClipUserPlane[p][1];
247 GLfloat c = ctx->Transform._ClipUserPlane[p][2];
248 GLfloat d = ctx->Transform._ClipUserPlane[p][3];
249 POLY_CLIP( CLIP_USER_BIT, a, b, c, d );
250 }
251 }
252 }
253
254 if (ctx->_TriangleCaps & DD_FLATSHADE) {
255 if (pv != inlist[0]) {
256 ASSERT( inlist[0] >= VB->FirstClipped );
257 tnl->Driver.Render.CopyPV( ctx, inlist[0], pv );
258 }
259 }
260
261 tnl->Driver.Render.ClippedPolygon( ctx, inlist, n );
262 }
263
264 #undef W
265 #undef Z
266 #undef Y
267 #undef X
268 #undef SIZE
269 #undef TAG
270 #undef POLY_CLIP
271 #undef LINE_CLIP