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