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