Fixed includes & added a few hooks for the DRI.
[mesa.git] / src / mesa / main / clip.c
1 /* $Id: clip.c,v 1.3 1999/10/08 09:27:10 keithw Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.1
6 *
7 * Copyright (C) 1999 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
27
28
29
30
31 #ifdef PC_HEADER
32 #include "all.h"
33 #else
34 #ifndef XFree86Server
35 #include <string.h>
36 #include <stdlib.h>
37 #else
38 #include "GL/xf86glx.h"
39 #endif
40 #include "clip.h"
41 #include "context.h"
42 #include "macros.h"
43 #include "matrix.h"
44 #include "mmath.h"
45 #include "types.h"
46 #include "vb.h"
47 #include "xform.h"
48 #ifdef XFree86Server
49 #include "GL/xf86glx.h"
50 #endif
51 #endif
52
53
54
55
56 /* Linear interpolation between A and B: */
57 #define LINTERP( T, A, B ) ( (A) + (T) * ( (B) - (A) ) )
58
59
60
61 #define INTERP_SZ( t, vec, to, a, b, sz ) \
62 do { \
63 switch (sz) { \
64 case 4: vec[to][3] = LINTERP( t, vec[a][3], vec[b][3] ); \
65 case 3: vec[to][2] = LINTERP( t, vec[a][2], vec[b][2] ); \
66 case 2: vec[to][1] = LINTERP( t, vec[a][1], vec[b][1] ); \
67 case 1: vec[to][0] = LINTERP( t, vec[a][0], vec[b][0] ); \
68 } \
69 } while(0)
70
71
72
73
74 #define CLIP_RGBA0 0x1
75 #define CLIP_RGBA1 0x2
76 #define CLIP_TEX0 0x4
77 #define CLIP_TEX1 0x8
78 #define CLIP_INDEX0 0x10
79 #define CLIP_INDEX1 0x20
80
81 static clip_interp_func clip_interp_tab[0x40];
82
83 #define IND 0
84 #define NAME clip_nil
85 #include "interp_tmp.h"
86
87 #define IND (CLIP_RGBA0)
88 #define NAME clipRGBA0
89 #include "interp_tmp.h"
90
91 #define IND (CLIP_RGBA0|CLIP_RGBA1)
92 #define NAME clipRGBA0_RGBA1
93 #include "interp_tmp.h"
94
95 #define IND (CLIP_TEX0|CLIP_RGBA0)
96 #define NAME clipTEX0_RGBA0
97 #include "interp_tmp.h"
98
99 #define IND (CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1)
100 #define NAME clipTEX0_RGBA0_RGBA1
101 #include "interp_tmp.h"
102
103 #define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0)
104 #define NAME clipTEX1_TEX0_RGBA0
105 #include "interp_tmp.h"
106
107 #define IND (CLIP_TEX0)
108 #define NAME clipTEX0
109 #include "interp_tmp.h"
110
111 #define IND (CLIP_TEX1|CLIP_TEX0)
112 #define NAME clipTEX1_TEX0
113 #include "interp_tmp.h"
114
115 #define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1)
116 #define NAME clipTEX1_TEX0_RGBA0_RGBA1
117 #include "interp_tmp.h"
118
119 #define IND (CLIP_INDEX0)
120 #define NAME clipINDEX0
121 #include "interp_tmp.h"
122
123 #define IND (CLIP_INDEX0|CLIP_INDEX1)
124 #define NAME clipINDEX0_INDEX1
125 #include "interp_tmp.h"
126
127
128
129
130 /**********************************************************************/
131 /* Get/Set User clip-planes. */
132 /**********************************************************************/
133
134
135
136 void gl_ClipPlane( GLcontext* ctx, GLenum plane, const GLfloat *equation )
137 {
138 GLint p;
139
140 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glClipPlane");
141
142 p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
143 if (p<0 || p>=MAX_CLIP_PLANES) {
144 gl_error( ctx, GL_INVALID_ENUM, "glClipPlane" );
145 return;
146 }
147
148 /*
149 * The equation is transformed by the transpose of the inverse of the
150 * current modelview matrix and stored in the resulting eye coordinates.
151 *
152 * KW: Eqn is then transformed to the current clip space, where user
153 * clipping now takes place. The clip-space equations are recalculated
154 * whenever the projection matrix changes.
155 */
156 if (ctx->ModelView.flags & MAT_DIRTY_ALL_OVER) {
157 gl_matrix_analyze( &ctx->ModelView );
158 }
159 gl_transform_vector( ctx->Transform.EyeUserPlane[p], equation,
160 ctx->ModelView.inv );
161
162
163 if (ctx->Transform.ClipEnabled[p]) {
164 ctx->NewState |= NEW_USER_CLIP;
165
166 if (ctx->ProjectionMatrix.flags & MAT_DIRTY_ALL_OVER) {
167 gl_matrix_analyze( &ctx->ProjectionMatrix );
168 }
169 gl_transform_vector( ctx->Transform.ClipUserPlane[p],
170 ctx->Transform.EyeUserPlane[p],
171 ctx->ProjectionMatrix.inv );
172 }
173 }
174
175
176 void gl_update_userclip( GLcontext *ctx )
177 {
178 GLuint p;
179
180 for (p = 0 ; p < MAX_CLIP_PLANES ; p++) {
181 if (ctx->Transform.ClipEnabled[p]) {
182 gl_transform_vector( ctx->Transform.ClipUserPlane[p],
183 ctx->Transform.EyeUserPlane[p],
184 ctx->ProjectionMatrix.inv );
185 }
186 }
187 }
188
189 void gl_GetClipPlane( GLcontext* ctx, GLenum plane, GLdouble *equation )
190 {
191 GLint p;
192
193 ASSERT_OUTSIDE_BEGIN_END(ctx, "glGetClipPlane");
194
195
196 p = (GLint) (plane - GL_CLIP_PLANE0);
197 if (p<0 || p>=MAX_CLIP_PLANES) {
198 gl_error( ctx, GL_INVALID_ENUM, "glGetClipPlane" );
199 return;
200 }
201
202 equation[0] = (GLdouble) ctx->Transform.EyeUserPlane[p][0];
203 equation[1] = (GLdouble) ctx->Transform.EyeUserPlane[p][1];
204 equation[2] = (GLdouble) ctx->Transform.EyeUserPlane[p][2];
205 equation[3] = (GLdouble) ctx->Transform.EyeUserPlane[p][3];
206 }
207
208
209
210
211 /**********************************************************************/
212 /* View volume clipping. */
213 /**********************************************************************/
214
215
216 /*
217 * Clip a point against the view volume.
218 * Input: v - vertex-vector describing the point to clip
219 * Return: 0 = outside view volume
220 * 1 = inside view volume
221 */
222 GLuint gl_viewclip_point( const GLfloat v[] )
223 {
224 if ( v[0] > v[3] || v[0] < -v[3]
225 || v[1] > v[3] || v[1] < -v[3]
226 || v[2] > v[3] || v[2] < -v[3] ) {
227 return 0;
228 }
229 else {
230 return 1;
231 }
232 }
233
234 /*
235 * Clip a point against the user clipping planes.
236 * Input: v - vertex-vector describing the point to clip.
237 * Return: 0 = point was clipped
238 * 1 = point not clipped
239 */
240 GLuint gl_userclip_point( GLcontext* ctx, const GLfloat v[] )
241 {
242 GLuint p;
243
244 for (p=0;p<MAX_CLIP_PLANES;p++) {
245 if (ctx->Transform.ClipEnabled[p]) {
246 GLfloat dot = v[0] * ctx->Transform.ClipUserPlane[p][0]
247 + v[1] * ctx->Transform.ClipUserPlane[p][1]
248 + v[2] * ctx->Transform.ClipUserPlane[p][2]
249 + v[3] * ctx->Transform.ClipUserPlane[p][3];
250 if (dot < 0.0F) {
251 return 0;
252 }
253 }
254 }
255
256 return 1;
257 }
258
259
260
261
262 #if defined(__i386__)
263 #define NEGATIVE(x) ((*(int *)&x)<0)
264 #else
265 #define NEGATIVE(x) (x < 0)
266 #endif
267
268
269 static clip_poly_func gl_poly_clip_tab[2][5];
270 static clip_line_func gl_line_clip_tab[2][5];
271
272 #define W(i) coord[i][3]
273 #define Z(i) coord[i][2]
274 #define Y(i) coord[i][1]
275 #define X(i) coord[i][0]
276 #define SIZE 4
277 #define IND 0
278 #define TAG(x) x##_4
279 #include "clip_funcs.h"
280
281 #define W(i) 1.0
282 #define Z(i) coord[i][2]
283 #define Y(i) coord[i][1]
284 #define X(i) coord[i][0]
285 #define SIZE 3
286 #define IND 0
287 #define TAG(x) x##_3
288 #include "clip_funcs.h"
289
290 #define W(i) 1.0
291 #define Z(i) 0.0
292 #define Y(i) coord[i][1]
293 #define X(i) coord[i][0]
294 #define SIZE 2
295 #define IND 0
296 #define TAG(x) x##_2
297 #include "clip_funcs.h"
298
299 #define W(i) coord[i][3]
300 #define Z(i) coord[i][2]
301 #define Y(i) coord[i][1]
302 #define X(i) coord[i][0]
303 #define SIZE 4
304 #define IND CLIP_TAB_EDGEFLAG
305 #define TAG(x) x##_4_edgeflag
306 #include "clip_funcs.h"
307
308 #define W(i) 1.0
309 #define Z(i) coord[i][2]
310 #define Y(i) coord[i][1]
311 #define X(i) coord[i][0]
312 #define SIZE 3
313 #define IND CLIP_TAB_EDGEFLAG
314 #define TAG(x) x##_3_edgeflag
315 #include "clip_funcs.h"
316
317 #define W(i) 1.0
318 #define Z(i) 0.0
319 #define Y(i) coord[i][1]
320 #define X(i) coord[i][0]
321 #define SIZE 2
322 #define IND CLIP_TAB_EDGEFLAG
323 #define TAG(x) x##_2_edgeflag
324 #include "clip_funcs.h"
325
326
327
328
329 void gl_update_clipmask( GLcontext *ctx )
330 {
331 GLuint mask = 0;
332
333 if (ctx->Visual->RGBAflag)
334 {
335 if (ctx->Light.ShadeModel==GL_SMOOTH)
336 {
337 mask |= CLIP_RGBA0;
338
339 if (ctx->TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_SEPERATE_SPECULAR))
340 mask |= CLIP_RGBA1;
341 }
342
343 if (ctx->Texture.ReallyEnabled & 0xf0)
344 mask |= CLIP_TEX1|CLIP_TEX0;
345
346 if (ctx->Texture.ReallyEnabled & 0xf)
347 mask |= CLIP_TEX0;
348 }
349 else if (ctx->Light.ShadeModel==GL_SMOOTH)
350 {
351 mask |= CLIP_INDEX0;
352
353 if (ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE)
354 mask |= CLIP_INDEX1;
355 }
356
357
358 ctx->ClipInterpFunc = clip_interp_tab[mask];
359 ctx->poly_clip_tab = gl_poly_clip_tab[0];
360 ctx->line_clip_tab = gl_line_clip_tab[0];
361
362 if (ctx->TriangleCaps & DD_TRI_UNFILLED) {
363 ctx->poly_clip_tab = gl_poly_clip_tab[1];
364 ctx->line_clip_tab = gl_line_clip_tab[0];
365 }
366 }
367
368
369 #define USER_CLIPTEST(NAME, SZ) \
370 static void NAME( struct vertex_buffer *VB ) \
371 { \
372 GLcontext *ctx = VB->ctx; \
373 GLubyte *clipMask = VB->ClipMask; \
374 GLubyte *userClipMask = VB->UserClipMask; \
375 GLuint start = VB->Start; \
376 GLuint count = VB->Count; \
377 GLuint p, i; \
378 GLubyte bit; \
379 \
380 \
381 for (bit = 1, p = 0; p < MAX_CLIP_PLANES ; p++, bit *=2) \
382 if (ctx->Transform.ClipEnabled[p]) { \
383 GLuint nr = 0; \
384 const GLfloat a = ctx->Transform.ClipUserPlane[p][0]; \
385 const GLfloat b = ctx->Transform.ClipUserPlane[p][1]; \
386 const GLfloat c = ctx->Transform.ClipUserPlane[p][2]; \
387 const GLfloat d = ctx->Transform.ClipUserPlane[p][3]; \
388 GLfloat *coord = VB->ClipPtr->start; \
389 GLuint stride = VB->ClipPtr->stride; \
390 \
391 for (i = start ; i < count ; i++, STRIDE_F(coord, stride)) { \
392 GLfloat dp = coord[0] * a + coord[1] * b; \
393 if (SZ > 2) dp += coord[2] * c; \
394 if (SZ > 3) dp += coord[3] * d; else dp += d; \
395 \
396 if (dp < 0) { \
397 clipMask[i] |= CLIP_USER_BIT; \
398 userClipMask[i] |= bit; \
399 nr++; \
400 } \
401 } \
402 \
403 if (nr > 0) { \
404 VB->ClipOrMask |= CLIP_USER_BIT; \
405 VB->CullMode |= CLIP_MASK_ACTIVE; \
406 if (nr == count - start) { \
407 VB->ClipAndMask |= CLIP_USER_BIT; \
408 VB->Culled = 1; \
409 return; \
410 } \
411 } \
412 } \
413 }
414
415
416 USER_CLIPTEST(userclip2, 2)
417 USER_CLIPTEST(userclip3, 3)
418 USER_CLIPTEST(userclip4, 4)
419
420 static void (*(usercliptab[5]))( struct vertex_buffer * ) = {
421 0,
422 0,
423 userclip2,
424 userclip3,
425 userclip4
426 };
427
428 void gl_user_cliptest( struct vertex_buffer *VB )
429 {
430 usercliptab[VB->ClipPtr->size]( VB );
431 }
432
433
434 void gl_init_clip(void)
435 {
436 init_clip_funcs_4();
437 init_clip_funcs_3();
438 init_clip_funcs_2();
439
440 init_clip_funcs_4_edgeflag();
441 init_clip_funcs_3_edgeflag();
442 init_clip_funcs_2_edgeflag();
443
444 clip_interp_tab[0] = clip_nil;
445 clip_interp_tab[CLIP_RGBA0] = clipRGBA0;
446 clip_interp_tab[CLIP_RGBA0|CLIP_RGBA1] = clipRGBA0_RGBA1;
447 clip_interp_tab[CLIP_TEX0|CLIP_RGBA0] = clipTEX0_RGBA0;
448 clip_interp_tab[CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1] = clipTEX0_RGBA0_RGBA1;
449 clip_interp_tab[CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0] = clipTEX1_TEX0_RGBA0;
450 clip_interp_tab[CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1] =
451 clipTEX1_TEX0_RGBA0_RGBA1;
452
453 clip_interp_tab[CLIP_TEX0] = clipTEX0;
454 clip_interp_tab[CLIP_TEX1|CLIP_TEX0] = clipTEX1_TEX0;
455
456 clip_interp_tab[CLIP_INDEX0] = clipINDEX0;
457 clip_interp_tab[CLIP_INDEX0|CLIP_INDEX1] = clipINDEX0_INDEX1;
458 }
459