2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS 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 OTHER
22 * DEALINGS IN THE SOFTWARE.
26 #define CLIP_DOTPROD(K, A, B, C, D) X(K) * A + Y(K) * B + Z(K) * C + W(K) * D
28 #define POLY_CLIP(PLANE, A, B, C, D) \
31 GLuint idxPrev = inlist[0]; \
32 GLfloat dpPrev = CLIP_DOTPROD(idxPrev, A, B, C, D); \
33 GLuint outcount = 0; \
36 inlist[n] = inlist[0]; /* prevent rotation of vertices */ \
37 for (i = 1; i <= n; i++) { \
38 GLuint idx = inlist[i]; \
39 GLfloat dp = CLIP_DOTPROD(idx, A, B, C, D); \
41 clipmask[idxPrev] |= PLANE; \
42 if (!NEGATIVE(dpPrev)) { \
43 outlist[outcount++] = idxPrev; \
44 clipmask[idxPrev] &= ~PLANE; \
47 if (DIFFERENT_SIGNS(dp, dpPrev)) { \
48 GLuint newvert = VB->LastClipped++; \
49 VB->ClipMask[newvert] = 0; \
50 outlist[outcount++] = newvert; \
52 /* Going out of bounds. Avoid division by zero as we \
53 * know dp != dpPrev from DIFFERENT_SIGNS, above. \
55 GLfloat t = dp / (dp - dpPrev); \
56 INTERP_4F(t, coord[newvert], coord[idx], coord[idxPrev]); \
57 interp(ctx, t, newvert, idx, idxPrev, GL_TRUE); \
62 GLfloat t = dpPrev / (dpPrev - dp); \
63 INTERP_4F(t, coord[newvert], coord[idxPrev], coord[idx]); \
64 interp(ctx, t, newvert, idxPrev, idx, GL_FALSE); \
76 GLuint *tmp = inlist; \
85 #define LINE_CLIP(PLANE, A, B, C, D) \
88 GLfloat dpI = CLIP_DOTPROD(ii, A, B, C, D); \
89 GLfloat dpJ = CLIP_DOTPROD(jj, A, B, C, D); \
91 if (DIFFERENT_SIGNS(dpI, dpJ)) { \
92 GLuint newvert = VB->LastClipped++; \
93 VB->ClipMask[newvert] = 0; \
94 if (NEGATIVE(dpJ)) { \
95 GLfloat t = dpI / (dpI - dpJ); \
96 VB->ClipMask[jj] |= PLANE; \
97 INTERP_4F(t, coord[newvert], coord[ii], coord[jj]); \
98 interp(ctx, t, newvert, ii, jj, GL_FALSE); \
102 GLfloat t = dpJ / (dpJ - dpI); \
103 VB->ClipMask[ii] |= PLANE; \
104 INTERP_4F(t, coord[newvert], coord[jj], coord[ii]); \
105 interp(ctx, t, newvert, jj, ii, GL_FALSE); \
109 else if (NEGATIVE(dpI)) \
115 /* Clip a line against the viewport and user clip planes.
118 TAG(clip_line
)(GLcontext
*ctx
, GLuint i
, GLuint j
, GLubyte mask
)
120 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
121 struct vertex_buffer
*VB
= &tnl
->vb
;
122 tnl_interp_func interp
= tnl
->Driver
.Render
.Interp
;
123 GLfloat (*coord
)[4] = VB
->ClipPtr
->data
;
124 GLuint ii
= i
, jj
= j
, p
;
126 if (VIA_DEBUG
) fprintf(stderr
, "%s - in\n", __FUNCTION__
);
128 #ifdef PERFORMANCE_MEASURE
129 if (VIA_PERFORMANCE
) P_M
;
131 VB
->LastClipped
= VB
->Count
;
134 LINE_CLIP(CLIP_RIGHT_BIT
, -1, 0, 0, 1);
135 LINE_CLIP(CLIP_LEFT_BIT
, 1, 0, 0, 1);
136 LINE_CLIP(CLIP_TOP_BIT
, 0, -1, 0, 1);
137 LINE_CLIP(CLIP_BOTTOM_BIT
, 0, 1, 0, 1);
138 LINE_CLIP(CLIP_FAR_BIT
, 0, 0, -1, 1);
139 LINE_CLIP(CLIP_NEAR_BIT
, 0, 0, 1, 1);
142 if (mask
& CLIP_USER_BIT
) {
143 for (p
= 0; p
< MAX_CLIP_PLANES
; p
++) {
144 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << p
)) {
145 GLfloat a
= ctx
->Transform
._ClipUserPlane
[p
][0];
146 GLfloat b
= ctx
->Transform
._ClipUserPlane
[p
][1];
147 GLfloat c
= ctx
->Transform
._ClipUserPlane
[p
][2];
148 GLfloat d
= ctx
->Transform
._ClipUserPlane
[p
][3];
149 LINE_CLIP(CLIP_USER_BIT
, a
, b
, c
, d
);
154 if ((ctx
->_TriangleCaps
& DD_FLATSHADE
) && j
!= jj
)
155 tnl
->Driver
.Render
.CopyPV(ctx
, jj
, j
);
157 tnl
->Driver
.Render
.ClippedLine(ctx
, ii
, jj
);
159 if (VIA_DEBUG
) fprintf(stderr
, "%s - out\n", __FUNCTION__
);
164 /* Clip a triangle against the viewport and user clip planes.
167 TAG(clip_tri
)(GLcontext
*ctx
, GLuint v0
, GLuint v1
, GLuint v2
, GLubyte mask
)
169 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
170 struct vertex_buffer
*VB
= &tnl
->vb
;
171 tnl_interp_func interp
= tnl
->Driver
.Render
.Interp
;
172 GLfloat (*coord
)[4] = VB
->ClipPtr
->data
;
174 GLuint vlist
[2][MAX_CLIPPED_VERTICES
];
175 GLuint
*inlist
= vlist
[0], *outlist
= vlist
[1];
177 GLubyte
*clipmask
= VB
->ClipMask
;
180 #ifdef PERFORMANCE_MEASURE
181 if (VIA_PERFORMANCE
) P_M
;
183 ASSIGN_3V(inlist
, v2
, v0
, v1
); /* pv rotated to slot zero */
185 VB
->LastClipped
= VB
->Count
;
188 POLY_CLIP(CLIP_RIGHT_BIT
, -1, 0, 0, 1);
189 POLY_CLIP(CLIP_LEFT_BIT
, 1, 0, 0, 1);
190 POLY_CLIP(CLIP_TOP_BIT
, 0, -1, 0, 1);
191 POLY_CLIP(CLIP_BOTTOM_BIT
, 0, 1, 0, 1);
192 POLY_CLIP(CLIP_FAR_BIT
, 0, 0, -1, 1);
193 POLY_CLIP(CLIP_NEAR_BIT
, 0, 0, 1, 1);
196 if (mask
& CLIP_USER_BIT
) {
197 for (p
= 0; p
< MAX_CLIP_PLANES
; p
++) {
198 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << p
)) {
199 GLfloat a
= ctx
->Transform
._ClipUserPlane
[p
][0];
200 GLfloat b
= ctx
->Transform
._ClipUserPlane
[p
][1];
201 GLfloat c
= ctx
->Transform
._ClipUserPlane
[p
][2];
202 GLfloat d
= ctx
->Transform
._ClipUserPlane
[p
][3];
203 POLY_CLIP(CLIP_USER_BIT
, a
, b
, c
, d
);
208 if (ctx
->_TriangleCaps
& DD_FLATSHADE
) {
209 if (pv
!= inlist
[0]) {
210 ASSERT(inlist
[0] >= VB
->Count
);
211 tnl
->Driver
.Render
.CopyPV(ctx
, inlist
[0], pv
);
215 tnl
->Driver
.Render
.ClippedPolygon(ctx
, inlist
, n
);
219 /* Clip a quad against the viewport and user clip planes.
222 TAG(clip_quad
)(GLcontext
*ctx
, GLuint v0
, GLuint v1
, GLuint v2
, GLuint v3
,
225 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
226 struct vertex_buffer
*VB
= &tnl
->vb
;
227 tnl_interp_func interp
= tnl
->Driver
.Render
.Interp
;
228 GLfloat (*coord
)[4] = VB
->ClipPtr
->data
;
230 GLuint vlist
[2][MAX_CLIPPED_VERTICES
];
231 GLuint
*inlist
= vlist
[0], *outlist
= vlist
[1];
233 GLubyte
*clipmask
= VB
->ClipMask
;
236 if (VIA_DEBUG
) fprintf(stderr
, "%s - in\n", __FUNCTION__
);
238 #ifdef PERFORMANCE_MEASURE
239 if (VIA_PERFORMANCE
) P_M
;
241 ASSIGN_4V(inlist
, v3
, v0
, v1
, v2
); /* pv rotated to slot zero */
243 VB
->LastClipped
= VB
->Count
;
246 POLY_CLIP(CLIP_RIGHT_BIT
, -1, 0, 0, 1);
247 POLY_CLIP(CLIP_LEFT_BIT
, 1, 0, 0, 1);
248 POLY_CLIP(CLIP_TOP_BIT
, 0, -1, 0, 1);
249 POLY_CLIP(CLIP_BOTTOM_BIT
, 0, 1, 0, 1);
250 POLY_CLIP(CLIP_FAR_BIT
, 0, 0, -1, 1);
251 POLY_CLIP(CLIP_NEAR_BIT
, 0, 0, 1, 1);
254 if (mask
& CLIP_USER_BIT
) {
255 for (p
= 0; p
< MAX_CLIP_PLANES
; p
++) {
256 if (ctx
->Transform
.ClipPlanesEnabled
& (1 << p
)) {
257 GLfloat a
= ctx
->Transform
._ClipUserPlane
[p
][0];
258 GLfloat b
= ctx
->Transform
._ClipUserPlane
[p
][1];
259 GLfloat c
= ctx
->Transform
._ClipUserPlane
[p
][2];
260 GLfloat d
= ctx
->Transform
._ClipUserPlane
[p
][3];
261 POLY_CLIP(CLIP_USER_BIT
, a
, b
, c
, d
);
266 if (ctx
->_TriangleCaps
& DD_FLATSHADE
) {
267 if (pv
!= inlist
[0]) {
268 ASSERT(inlist
[0] >= VB
->Count
);
269 tnl
->Driver
.Render
.CopyPV(ctx
, inlist
[0], pv
);
273 tnl
->Driver
.Render
.ClippedPolygon(ctx
, inlist
, n
);
275 if (VIA_DEBUG
) fprintf(stderr
, "%s - out\n", __FUNCTION__
);