1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS 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
22  * OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 /*
26  * New (3.1) transformation code written by Keith Whitwell.
27  */
28 
29 
30 /* KW: a clever asm implementation would nestle integer versions
31  * of the outcode calculation underneath the division.  Gcc won't
32  * do this, strangely enough, so I only do the divide in
33  * the case where the cliptest passes.  This isn't essential,
34  * and an asm implementation needn't replicate that behaviour.
35  *
36  * \param clip_vec vector of incoming clip-space coords
37  * \param proj_vec vector of resultant NDC-space projected coords
38  * \param clipMask resulting array of clip flags
39  * \param orMask bitwise-OR of clipMask values
40  * \param andMask bitwise-AND of clipMask values
41  * \return proj_vec pointer
42  */
TAG(cliptest_points4)43 static GLvector4f * TAG(cliptest_points4)( GLvector4f *clip_vec,
44                                                      GLvector4f *proj_vec,
45                                                      GLubyte clipMask[],
46                                                      GLubyte *orMask,
47                                                      GLubyte *andMask,
48 						     GLboolean viewport_z_clip )
49 {
50    const GLuint stride = clip_vec->stride;
51    const GLfloat *from = (GLfloat *)clip_vec->start;
52    const GLuint count = clip_vec->count;
53    GLuint c = 0;
54    GLfloat (*vProj)[4] = (GLfloat (*)[4])proj_vec->start;
55    GLubyte tmpAndMask = *andMask;
56    GLubyte tmpOrMask = *orMask;
57    GLuint i;
58    STRIDE_LOOP {
59       const GLfloat cx = from[0];
60       const GLfloat cy = from[1];
61       const GLfloat cz = from[2];
62       const GLfloat cw = from[3];
63 #if defined(__powerpc__)
64       /* on powerpc cliptest is 17% faster in this way. */
65       GLuint mask;
66       mask = (((cw < cx) << CLIP_RIGHT_SHIFT));
67       mask |= (((cw < -cx) << CLIP_LEFT_SHIFT));
68       mask |= (((cw < cy) << CLIP_TOP_SHIFT));
69       mask |= (((cw < -cy) << CLIP_BOTTOM_SHIFT));
70       if (viewport_z_clip) {
71 	 mask |= (((cw < cz) << CLIP_FAR_SHIFT));
72 	 mask |= (((cw < -cz) << CLIP_NEAR_SHIFT));
73       }
74 #else
75       GLubyte mask = 0;
76       if (-cx + cw < 0) mask |= CLIP_RIGHT_BIT;
77       if ( cx + cw < 0) mask |= CLIP_LEFT_BIT;
78       if (-cy + cw < 0) mask |= CLIP_TOP_BIT;
79       if ( cy + cw < 0) mask |= CLIP_BOTTOM_BIT;
80       if (viewport_z_clip) {
81 	 if (-cz + cw < 0) mask |= CLIP_FAR_BIT;
82 	 if ( cz + cw < 0) mask |= CLIP_NEAR_BIT;
83       }
84 #endif
85 
86       clipMask[i] = mask;
87       if (mask) {
88 	 c++;
89 	 tmpAndMask &= mask;
90 	 tmpOrMask |= mask;
91 	 vProj[i][0] = 0;
92 	 vProj[i][1] = 0;
93 	 vProj[i][2] = 0;
94 	 vProj[i][3] = 1;
95       } else {
96 	 GLfloat oow = 1.0F / cw;
97 	 vProj[i][0] = cx * oow;
98 	 vProj[i][1] = cy * oow;
99 	 vProj[i][2] = cz * oow;
100 	 vProj[i][3] = oow;
101       }
102    }
103 
104    *orMask = tmpOrMask;
105    *andMask = (GLubyte) (c < count ? 0 : tmpAndMask);
106 
107    proj_vec->flags |= VEC_SIZE_4;
108    proj_vec->size = 4;
109    proj_vec->count = clip_vec->count;
110    return proj_vec;
111 }
112 
113 
114 
115 /*
116  * \param clip_vec vector of incoming clip-space coords
117  * \param proj_vec vector of resultant NDC-space projected coords
118  * \param clipMask resulting array of clip flags
119  * \param orMask bitwise-OR of clipMask values
120  * \param andMask bitwise-AND of clipMask values
121  * \return clip_vec pointer
122  */
TAG(cliptest_np_points4)123 static GLvector4f * TAG(cliptest_np_points4)( GLvector4f *clip_vec,
124 							GLvector4f *proj_vec,
125 							GLubyte clipMask[],
126 							GLubyte *orMask,
127 							GLubyte *andMask,
128 							GLboolean viewport_z_clip )
129 {
130    const GLuint stride = clip_vec->stride;
131    const GLuint count = clip_vec->count;
132    const GLfloat *from = (GLfloat *)clip_vec->start;
133    GLuint c = 0;
134    GLubyte tmpAndMask = *andMask;
135    GLubyte tmpOrMask = *orMask;
136    GLuint i;
137    (void) proj_vec;
138    STRIDE_LOOP {
139       const GLfloat cx = from[0];
140       const GLfloat cy = from[1];
141       const GLfloat cz = from[2];
142       const GLfloat cw = from[3];
143 #if defined(__powerpc__)
144       /* on powerpc cliptest is 17% faster in this way. */
145       GLuint mask;
146       mask = (((cw < cx) << CLIP_RIGHT_SHIFT));
147       mask |= (((cw < -cx) << CLIP_LEFT_SHIFT));
148       mask |= (((cw < cy) << CLIP_TOP_SHIFT));
149       mask |= (((cw < -cy) << CLIP_BOTTOM_SHIFT));
150       if (viewport_z_clip) {
151 	 mask |= (((cw < cz) << CLIP_FAR_SHIFT));
152 	 mask |= (((cw < -cz) << CLIP_NEAR_SHIFT));
153       }
154 #else
155       GLubyte mask = 0;
156       if (-cx + cw < 0) mask |= CLIP_RIGHT_BIT;
157       if ( cx + cw < 0) mask |= CLIP_LEFT_BIT;
158       if (-cy + cw < 0) mask |= CLIP_TOP_BIT;
159       if ( cy + cw < 0) mask |= CLIP_BOTTOM_BIT;
160       if (viewport_z_clip) {
161 	 if (-cz + cw < 0) mask |= CLIP_FAR_BIT;
162 	 if ( cz + cw < 0) mask |= CLIP_NEAR_BIT;
163       }
164 #endif
165 
166       clipMask[i] = mask;
167       if (mask) {
168 	 c++;
169 	 tmpAndMask &= mask;
170 	 tmpOrMask |= mask;
171       }
172    }
173 
174    *orMask = tmpOrMask;
175    *andMask = (GLubyte) (c < count ? 0 : tmpAndMask);
176    return clip_vec;
177 }
178 
179 
TAG(cliptest_points3)180 static GLvector4f * TAG(cliptest_points3)( GLvector4f *clip_vec,
181                                                      GLvector4f *proj_vec,
182                                                      GLubyte clipMask[],
183                                                      GLubyte *orMask,
184                                                      GLubyte *andMask,
185 						     GLboolean viewport_z_clip )
186 {
187    const GLuint stride = clip_vec->stride;
188    const GLuint count = clip_vec->count;
189    const GLfloat *from = (GLfloat *)clip_vec->start;
190    GLubyte tmpOrMask = *orMask;
191    GLubyte tmpAndMask = *andMask;
192    GLuint i;
193    (void) proj_vec;
194    STRIDE_LOOP {
195       const GLfloat cx = from[0], cy = from[1], cz = from[2];
196       GLubyte mask = 0;
197       if (cx >  1.0F)       mask |= CLIP_RIGHT_BIT;
198       else if (cx < -1.0F)  mask |= CLIP_LEFT_BIT;
199       if (cy >  1.0F)       mask |= CLIP_TOP_BIT;
200       else if (cy < -1.0F)  mask |= CLIP_BOTTOM_BIT;
201       if (viewport_z_clip) {
202 	 if (cz >  1.0F)       mask |= CLIP_FAR_BIT;
203 	 else if (cz < -1.0F)  mask |= CLIP_NEAR_BIT;
204       }
205       clipMask[i] = mask;
206       tmpOrMask |= mask;
207       tmpAndMask &= mask;
208    }
209 
210    *orMask = tmpOrMask;
211    *andMask = tmpAndMask;
212    return clip_vec;
213 }
214 
215 
TAG(cliptest_points2)216 static GLvector4f * TAG(cliptest_points2)( GLvector4f *clip_vec,
217                                                      GLvector4f *proj_vec,
218                                                      GLubyte clipMask[],
219                                                      GLubyte *orMask,
220                                                      GLubyte *andMask,
221 						     GLboolean viewport_z_clip )
222 {
223    const GLuint stride = clip_vec->stride;
224    const GLuint count = clip_vec->count;
225    const GLfloat *from = (GLfloat *)clip_vec->start;
226    GLubyte tmpOrMask = *orMask;
227    GLubyte tmpAndMask = *andMask;
228    GLuint i;
229    (void) proj_vec;
230    STRIDE_LOOP {
231       const GLfloat cx = from[0], cy = from[1];
232       GLubyte mask = 0;
233       if (cx >  1.0F)       mask |= CLIP_RIGHT_BIT;
234       else if (cx < -1.0F)  mask |= CLIP_LEFT_BIT;
235       if (cy >  1.0F)       mask |= CLIP_TOP_BIT;
236       else if (cy < -1.0F)  mask |= CLIP_BOTTOM_BIT;
237       clipMask[i] = mask;
238       tmpOrMask |= mask;
239       tmpAndMask &= mask;
240    }
241 
242    *orMask = tmpOrMask;
243    *andMask = tmpAndMask;
244    return clip_vec;
245 }
246 
247 
TAG(init_c_cliptest)248 void TAG(init_c_cliptest)( void )
249 {
250    _mesa_clip_tab[4] = TAG(cliptest_points4);
251    _mesa_clip_tab[3] = TAG(cliptest_points3);
252    _mesa_clip_tab[2] = TAG(cliptest_points2);
253 
254    _mesa_clip_np_tab[4] = TAG(cliptest_np_points4);
255    _mesa_clip_np_tab[3] = TAG(cliptest_points3);
256    _mesa_clip_np_tab[2] = TAG(cliptest_points2);
257 }
258