Rev 134 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
134 | giacomo | 1 | /* $Id: m_clip_debug.c,v 1.1 2003-04-24 13:37:46 giacomo Exp $ */ |
2 | |||
3 | /* |
||
4 | * Mesa 3-D graphics library |
||
5 | * Version: 5.0 |
||
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 | * Gareth Hughes |
||
28 | */ |
||
29 | |||
30 | #include "glheader.h" |
||
31 | #include "context.h" |
||
32 | #include "macros.h" |
||
33 | #include "imports.h" |
||
34 | |||
35 | #include "m_matrix.h" |
||
36 | #include "m_xform.h" |
||
37 | |||
38 | #include "m_debug.h" |
||
39 | #include "m_debug_util.h" |
||
40 | |||
41 | #ifdef DEBUG /* This code only used for debugging */ |
||
42 | |||
43 | static clip_func *clip_tab[2] = { |
||
44 | _mesa_clip_tab, |
||
45 | _mesa_clip_np_tab |
||
46 | }; |
||
47 | static char *cnames[2] = { |
||
48 | "_mesa_clip_tab", |
||
49 | "_mesa_clip_np_tab" |
||
50 | }; |
||
51 | #ifdef RUN_DEBUG_BENCHMARK |
||
52 | static char *cstrings[2] = { |
||
53 | "clip, perspective divide", |
||
54 | "clip, no divide" |
||
55 | }; |
||
56 | #endif |
||
57 | |||
58 | |||
59 | /* ============================================================= |
||
60 | * Reference cliptests |
||
61 | */ |
||
62 | |||
63 | static GLvector4f *ref_cliptest_points4( GLvector4f *clip_vec, |
||
64 | GLvector4f *proj_vec, |
||
65 | GLubyte clipMask[], |
||
66 | GLubyte *orMask, |
||
67 | GLubyte *andMask ) |
||
68 | { |
||
69 | const GLuint stride = clip_vec->stride; |
||
70 | const GLuint count = clip_vec->count; |
||
71 | const GLfloat *from = (GLfloat *)clip_vec->start; |
||
72 | GLuint c = 0; |
||
73 | GLfloat (*vProj)[4] = (GLfloat (*)[4])proj_vec->start; |
||
74 | GLubyte tmpAndMask = *andMask; |
||
75 | GLubyte tmpOrMask = *orMask; |
||
76 | GLuint i; |
||
77 | for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) ) { |
||
78 | const GLfloat cx = from[0]; |
||
79 | const GLfloat cy = from[1]; |
||
80 | const GLfloat cz = from[2]; |
||
81 | const GLfloat cw = from[3]; |
||
82 | GLubyte mask = 0; |
||
83 | if ( -cx + cw < 0 ) mask |= CLIP_RIGHT_BIT; |
||
84 | if ( cx + cw < 0 ) mask |= CLIP_LEFT_BIT; |
||
85 | if ( -cy + cw < 0 ) mask |= CLIP_TOP_BIT; |
||
86 | if ( cy + cw < 0 ) mask |= CLIP_BOTTOM_BIT; |
||
87 | if ( -cz + cw < 0 ) mask |= CLIP_FAR_BIT; |
||
88 | if ( cz + cw < 0 ) mask |= CLIP_NEAR_BIT; |
||
89 | clipMask[i] = mask; |
||
90 | if ( mask ) { |
||
91 | c++; |
||
92 | tmpAndMask &= mask; |
||
93 | tmpOrMask |= mask; |
||
94 | vProj[i][0] = 0; |
||
95 | vProj[i][1] = 0; |
||
96 | vProj[i][2] = 0; |
||
97 | vProj[i][3] = 1; |
||
98 | } else { |
||
99 | GLfloat oow = 1.0F / cw; |
||
100 | vProj[i][0] = cx * oow; |
||
101 | vProj[i][1] = cy * oow; |
||
102 | vProj[i][2] = cz * oow; |
||
103 | vProj[i][3] = oow; |
||
104 | } |
||
105 | } |
||
106 | |||
107 | *orMask = tmpOrMask; |
||
108 | *andMask = (GLubyte) (c < count ? 0 : tmpAndMask); |
||
109 | |||
110 | proj_vec->flags |= VEC_SIZE_4; |
||
111 | proj_vec->size = 4; |
||
112 | proj_vec->count = clip_vec->count; |
||
113 | return proj_vec; |
||
114 | } |
||
115 | |||
116 | /* Keep these here for now, even though we don't use them... |
||
117 | */ |
||
118 | static GLvector4f *ref_cliptest_points3( GLvector4f *clip_vec, |
||
119 | GLvector4f *proj_vec, |
||
120 | GLubyte clipMask[], |
||
121 | GLubyte *orMask, |
||
122 | GLubyte *andMask ) |
||
123 | { |
||
124 | const GLuint stride = clip_vec->stride; |
||
125 | const GLuint count = clip_vec->count; |
||
126 | const GLfloat *from = (GLfloat *)clip_vec->start; |
||
127 | |||
128 | GLubyte tmpOrMask = *orMask; |
||
129 | GLubyte tmpAndMask = *andMask; |
||
130 | GLuint i; |
||
131 | for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) ) { |
||
132 | const GLfloat cx = from[0], cy = from[1], cz = from[2]; |
||
133 | GLubyte mask = 0; |
||
134 | if ( cx > 1.0 ) mask |= CLIP_RIGHT_BIT; |
||
135 | else if ( cx < -1.0 ) mask |= CLIP_LEFT_BIT; |
||
136 | if ( cy > 1.0 ) mask |= CLIP_TOP_BIT; |
||
137 | else if ( cy < -1.0 ) mask |= CLIP_BOTTOM_BIT; |
||
138 | if ( cz > 1.0 ) mask |= CLIP_FAR_BIT; |
||
139 | else if ( cz < -1.0 ) mask |= CLIP_NEAR_BIT; |
||
140 | clipMask[i] = mask; |
||
141 | tmpOrMask |= mask; |
||
142 | tmpAndMask &= mask; |
||
143 | } |
||
144 | |||
145 | *orMask = tmpOrMask; |
||
146 | *andMask = tmpAndMask; |
||
147 | return clip_vec; |
||
148 | } |
||
149 | |||
150 | static GLvector4f * ref_cliptest_points2( GLvector4f *clip_vec, |
||
151 | GLvector4f *proj_vec, |
||
152 | GLubyte clipMask[], |
||
153 | GLubyte *orMask, |
||
154 | GLubyte *andMask ) |
||
155 | { |
||
156 | const GLuint stride = clip_vec->stride; |
||
157 | const GLuint count = clip_vec->count; |
||
158 | const GLfloat *from = (GLfloat *)clip_vec->start; |
||
159 | |||
160 | GLubyte tmpOrMask = *orMask; |
||
161 | GLubyte tmpAndMask = *andMask; |
||
162 | GLuint i; |
||
163 | for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) ) { |
||
164 | const GLfloat cx = from[0], cy = from[1]; |
||
165 | GLubyte mask = 0; |
||
166 | if ( cx > 1.0 ) mask |= CLIP_RIGHT_BIT; |
||
167 | else if ( cx < -1.0 ) mask |= CLIP_LEFT_BIT; |
||
168 | if ( cy > 1.0 ) mask |= CLIP_TOP_BIT; |
||
169 | else if ( cy < -1.0 ) mask |= CLIP_BOTTOM_BIT; |
||
170 | clipMask[i] = mask; |
||
171 | tmpOrMask |= mask; |
||
172 | tmpAndMask &= mask; |
||
173 | } |
||
174 | |||
175 | *orMask = tmpOrMask; |
||
176 | *andMask = tmpAndMask; |
||
177 | return clip_vec; |
||
178 | } |
||
179 | |||
180 | static clip_func ref_cliptest[5] = { |
||
181 | 0, |
||
182 | 0, |
||
183 | ref_cliptest_points2, |
||
184 | ref_cliptest_points3, |
||
185 | ref_cliptest_points4 |
||
186 | }; |
||
187 | |||
188 | |||
189 | /* ============================================================= |
||
190 | * Cliptest tests |
||
191 | */ |
||
192 | |||
193 | static GLfloat s[TEST_COUNT][4] ALIGN16; |
||
194 | static GLfloat d[TEST_COUNT][4] ALIGN16; |
||
195 | static GLfloat r[TEST_COUNT][4] ALIGN16; |
||
196 | |||
197 | static int test_cliptest_function( clip_func func, int np, |
||
198 | int psize, long *cycles ) |
||
199 | { |
||
200 | GLvector4f source[1], dest[1], ref[1]; |
||
201 | GLubyte dm[TEST_COUNT], dco, dca; |
||
202 | GLubyte rm[TEST_COUNT], rco, rca; |
||
203 | int i, j; |
||
204 | #ifdef RUN_DEBUG_BENCHMARK |
||
205 | int cycle_i; /* the counter for the benchmarks we run */ |
||
206 | #endif |
||
207 | |||
208 | (void) cycles; |
||
209 | |||
210 | if ( psize > 4 ) { |
||
211 | _mesa_problem( NULL, "test_cliptest_function called with psize > 4\n" ); |
||
212 | return 0; |
||
213 | } |
||
214 | |||
215 | for ( i = 0 ; i < TEST_COUNT ; i++) { |
||
216 | ASSIGN_4V( d[i], 0.0, 0.0, 0.0, 1.0 ); |
||
217 | ASSIGN_4V( s[i], 0.0, 0.0, 0.0, 1.0 ); |
||
218 | for ( j = 0 ; j < psize ; j++ ) |
||
219 | s[i][j] = rnd(); |
||
220 | } |
||
221 | |||
222 | source->data = (GLfloat(*)[4])s; |
||
223 | source->start = (GLfloat *)s; |
||
224 | source->count = TEST_COUNT; |
||
225 | source->stride = sizeof(s[0]); |
||
226 | source->size = 4; |
||
227 | source->flags = 0; |
||
228 | |||
229 | dest->data = (GLfloat(*)[4])d; |
||
230 | dest->start = (GLfloat *)d; |
||
231 | dest->count = TEST_COUNT; |
||
232 | dest->stride = sizeof(float[4]); |
||
233 | dest->size = 0; |
||
234 | dest->flags = 0; |
||
235 | |||
236 | ref->data = (GLfloat(*)[4])r; |
||
237 | ref->start = (GLfloat *)r; |
||
238 | ref->count = TEST_COUNT; |
||
239 | ref->stride = sizeof(float[4]); |
||
240 | ref->size = 0; |
||
241 | ref->flags = 0; |
||
242 | |||
243 | dco = rco = 0; |
||
244 | dca = rca = CLIP_ALL_BITS; |
||
245 | |||
246 | ref_cliptest[psize]( source, ref, rm, &rco, &rca ); |
||
247 | |||
248 | if ( mesa_profile ) { |
||
249 | BEGIN_RACE( *cycles ); |
||
250 | func( source, dest, dm, &dco, &dca ); |
||
251 | END_RACE( *cycles ); |
||
252 | } |
||
253 | else { |
||
254 | func( source, dest, dm, &dco, &dca ); |
||
255 | } |
||
256 | |||
257 | if ( dco != rco ) { |
||
258 | _mesa_printf(NULL, "\n-----------------------------\n" ); |
||
259 | _mesa_printf(NULL, "dco = 0x%02x rco = 0x%02x\n", dco, rco ); |
||
260 | return 0; |
||
261 | } |
||
262 | if ( dca != rca ) { |
||
263 | _mesa_printf(NULL, "\n-----------------------------\n" ); |
||
264 | _mesa_printf(NULL, "dca = 0x%02x rca = 0x%02x\n", dca, rca ); |
||
265 | return 0; |
||
266 | } |
||
267 | for ( i = 0 ; i < TEST_COUNT ; i++ ) { |
||
268 | if ( dm[i] != rm[i] ) { |
||
269 | _mesa_printf(NULL, "\n-----------------------------\n" ); |
||
270 | _mesa_printf(NULL, "(i = %i)\n", i ); |
||
271 | _mesa_printf(NULL, "dm = 0x%02x rm = 0x%02x\n", dm[i], rm[i] ); |
||
272 | return 0; |
||
273 | } |
||
274 | } |
||
275 | |||
276 | /* Only verify output on projected points4 case. FIXME: Do we need |
||
277 | * to test other cases? |
||
278 | */ |
||
279 | if ( np || psize < 4 ) |
||
280 | return 1; |
||
281 | |||
282 | for ( i = 0 ; i < TEST_COUNT ; i++ ) { |
||
283 | for ( j = 0 ; j < 4 ; j++ ) { |
||
284 | if ( significand_match( d[i][j], r[i][j] ) < REQUIRED_PRECISION ) { |
||
285 | _mesa_printf(NULL, "\n-----------------------------\n" ); |
||
286 | _mesa_printf(NULL, "(i = %i, j = %i) dm = 0x%02x rm = 0x%02x\n", |
||
287 | i, j, dm[i], rm[i] ); |
||
288 | _mesa_printf(NULL, "%f \t %f \t [diff = %e - %i bit missed]\n", |
||
289 | d[i][0], r[i][0], r[i][0]-d[i][0], |
||
290 | MAX_PRECISION - significand_match( d[i][0], r[i][0] ) ); |
||
291 | _mesa_printf(NULL, "%f \t %f \t [diff = %e - %i bit missed]\n", |
||
292 | d[i][1], r[i][1], r[i][1]-d[i][1], |
||
293 | MAX_PRECISION - significand_match( d[i][1], r[i][1] ) ); |
||
294 | _mesa_printf(NULL, "%f \t %f \t [diff = %e - %i bit missed]\n", |
||
295 | d[i][2], r[i][2], r[i][2]-d[i][2], |
||
296 | MAX_PRECISION - significand_match( d[i][2], r[i][2] ) ); |
||
297 | _mesa_printf(NULL, "%f \t %f \t [diff = %e - %i bit missed]\n", |
||
298 | d[i][3], r[i][3], r[i][3]-d[i][3], |
||
299 | MAX_PRECISION - significand_match( d[i][3], r[i][3] ) ); |
||
300 | return 0; |
||
301 | } |
||
302 | } |
||
303 | } |
||
304 | |||
305 | return 1; |
||
306 | } |
||
307 | |||
308 | void _math_test_all_cliptest_functions( char *description ) |
||
309 | { |
||
310 | int np, psize; |
||
311 | long benchmark_tab[2][4]; |
||
312 | static int first_time = 1; |
||
313 | |||
314 | if ( first_time ) { |
||
315 | first_time = 0; |
||
316 | mesa_profile = _mesa_getenv( "MESA_PROFILE" ); |
||
317 | } |
||
318 | |||
319 | #ifdef RUN_DEBUG_BENCHMARK |
||
320 | if ( mesa_profile ) { |
||
321 | if ( !counter_overhead ) { |
||
322 | INIT_COUNTER(); |
||
323 | _mesa_printf(NULL, "counter overhead: %ld cycles\n\n", counter_overhead ); |
||
324 | } |
||
325 | _mesa_printf(NULL, "cliptest results after hooking in %s functions:\n", description ); |
||
326 | } |
||
327 | #endif |
||
328 | |||
329 | #ifdef RUN_DEBUG_BENCHMARK |
||
330 | if ( mesa_profile ) { |
||
331 | _mesa_printf(NULL, "\n\t" ); |
||
332 | for ( psize = 2 ; psize <= 4 ; psize++ ) { |
||
333 | _mesa_printf(NULL, " p%d\t", psize ); |
||
334 | } |
||
335 | _mesa_printf(NULL, "\n--------------------------------------------------------\n\t" ); |
||
336 | } |
||
337 | #endif |
||
338 | |||
339 | for ( np = 0 ; np < 2 ; np++ ) { |
||
340 | for ( psize = 2 ; psize <= 4 ; psize++ ) { |
||
341 | clip_func func = clip_tab[np][psize]; |
||
342 | long *cycles = &(benchmark_tab[np][psize-1]); |
||
343 | |||
344 | if ( test_cliptest_function( func, np, psize, cycles ) == 0 ) { |
||
345 | char buf[100]; |
||
346 | _mesa_sprintf(NULL, buf, "%s[%d] failed test (%s)", |
||
347 | cnames[np], psize, description ); |
||
348 | _mesa_problem( NULL, buf ); |
||
349 | } |
||
350 | #ifdef RUN_DEBUG_BENCHMARK |
||
351 | if ( mesa_profile ) |
||
352 | _mesa_printf(NULL, " %li\t", benchmark_tab[np][psize-1] ); |
||
353 | #endif |
||
354 | } |
||
355 | #ifdef RUN_DEBUG_BENCHMARK |
||
356 | if ( mesa_profile ) |
||
357 | _mesa_printf(NULL, " | [%s]\n\t", cstrings[np] ); |
||
358 | #endif |
||
359 | } |
||
360 | #ifdef RUN_DEBUG_BENCHMARK |
||
361 | if ( mesa_profile ) |
||
362 | _mesa_printf(NULL, "\n" ); |
||
363 | #endif |
||
364 | } |
||
365 | |||
366 | |||
367 | #endif /* DEBUG */ |