Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1.  
  2. /*
  3.  * Mesa 3-D graphics library
  4.  *
  5.  * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining a
  8.  * copy of this software and associated documentation files (the "Software"),
  9.  * to deal in the Software without restriction, including without limitation
  10.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11.  * and/or sell copies of the Software, and to permit persons to whom the
  12.  * Software is furnished to do so, subject to the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice shall be included
  15.  * in all copies or substantial portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  20.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  21.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  22.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23.  * OTHER DEALINGS IN THE SOFTWARE.
  24.  *
  25.  * Authors:
  26.  *    Gareth Hughes
  27.  */
  28.  
  29. #include "c99_math.h"
  30. #include "main/glheader.h"
  31. #include "main/context.h"
  32. #include "main/macros.h"
  33. #include "main/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.  
  42. #ifdef __UNIXOS2__
  43. /* The linker doesn't like empty files */
  44. static char dummy;
  45. #endif
  46.  
  47. #ifdef DEBUG_MATH  /* This code only used for debugging */
  48.  
  49.  
  50. static int m_norm_identity[16] = {
  51.    ONE, NIL, NIL, NIL,
  52.    NIL, ONE, NIL, NIL,
  53.    NIL, NIL, ONE, NIL,
  54.    NIL, NIL, NIL, NIL
  55. };
  56. static int m_norm_general[16] = {
  57.    VAR, VAR, VAR, NIL,
  58.    VAR, VAR, VAR, NIL,
  59.    VAR, VAR, VAR, NIL,
  60.    NIL, NIL, NIL, NIL
  61. };
  62. static int m_norm_no_rot[16] = {
  63.    VAR, NIL, NIL, NIL,
  64.    NIL, VAR, NIL, NIL,
  65.    NIL, NIL, VAR, NIL,
  66.    NIL, NIL, NIL, NIL
  67. };
  68. static int *norm_templates[8] = {
  69.    m_norm_no_rot,
  70.    m_norm_no_rot,
  71.    m_norm_no_rot,
  72.    m_norm_general,
  73.    m_norm_general,
  74.    m_norm_general,
  75.    m_norm_identity,
  76.    m_norm_identity
  77. };
  78. static int norm_types[8] = {
  79.    NORM_TRANSFORM_NO_ROT,
  80.    NORM_TRANSFORM_NO_ROT | NORM_RESCALE,
  81.    NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE,
  82.    NORM_TRANSFORM,
  83.    NORM_TRANSFORM | NORM_RESCALE,
  84.    NORM_TRANSFORM | NORM_NORMALIZE,
  85.    NORM_RESCALE,
  86.    NORM_NORMALIZE
  87. };
  88. static int norm_scale_types[8] = {               /*  rescale factor          */
  89.    NIL,                                          /*  NIL disables rescaling  */
  90.    VAR,
  91.    NIL,
  92.    NIL,
  93.    VAR,
  94.    NIL,
  95.    VAR,
  96.    NIL
  97. };
  98. static int norm_normalize_types[8] = {           /*  normalizing ?? (no = 0) */
  99.    0,
  100.    0,
  101.    1,
  102.    0,
  103.    0,
  104.    1,
  105.    0,
  106.    1
  107. };
  108. static char *norm_strings[8] = {
  109.    "NORM_TRANSFORM_NO_ROT",
  110.    "NORM_TRANSFORM_NO_ROT | NORM_RESCALE",
  111.    "NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE",
  112.    "NORM_TRANSFORM",
  113.    "NORM_TRANSFORM | NORM_RESCALE",
  114.    "NORM_TRANSFORM | NORM_NORMALIZE",
  115.    "NORM_RESCALE",
  116.    "NORM_NORMALIZE"
  117. };
  118.  
  119.  
  120. /* =============================================================
  121.  * Reference transformations
  122.  */
  123.  
  124. static void ref_norm_transform_rescale( const GLmatrix *mat,
  125.                                         GLfloat scale,
  126.                                         const GLvector4f *in,
  127.                                         const GLfloat *lengths,
  128.                                         GLvector4f *dest )
  129. {
  130.    GLuint i;
  131.    const GLfloat *s = in->start;
  132.    const GLfloat *m = mat->inv;
  133.    GLfloat (*out)[4] = (GLfloat (*)[4]) dest->start;
  134.  
  135.    (void) lengths;
  136.  
  137.    for ( i = 0 ; i < in->count ; i++ ) {
  138.       GLfloat t[3];
  139.  
  140.       TRANSFORM_NORMAL( t, s, m );
  141.       SCALE_SCALAR_3V( out[i], scale, t );
  142.  
  143.       s = (GLfloat *)((char *)s + in->stride);
  144.    }
  145. }
  146.  
  147. static void ref_norm_transform_normalize( const GLmatrix *mat,
  148.                                           GLfloat scale,
  149.                                           const GLvector4f *in,
  150.                                           const GLfloat *lengths,
  151.                                           GLvector4f *dest )
  152. {
  153.    GLuint i;
  154.    const GLfloat *s = in->start;
  155.    const GLfloat *m = mat->inv;
  156.    GLfloat (*out)[4] = (GLfloat (*)[4]) dest->start;
  157.  
  158.    for ( i = 0 ; i < in->count ; i++ ) {
  159.       GLfloat t[3];
  160.  
  161.       TRANSFORM_NORMAL( t, s, m );
  162.  
  163.       if ( !lengths ) {
  164.          GLfloat len = LEN_SQUARED_3FV( t );
  165.          if ( len > 1e-20 ) {
  166.             /* Hmmm, don't know how we could test the precalculated
  167.              * length case...
  168.              */
  169.             scale = 1.0f / sqrtf(len);
  170.             SCALE_SCALAR_3V( out[i], scale, t );
  171.          } else {
  172.             out[i][0] = out[i][1] = out[i][2] = 0;
  173.          }
  174.       } else {
  175.          scale = lengths[i];;
  176.          SCALE_SCALAR_3V( out[i], scale, t );
  177.       }
  178.  
  179.       s = (GLfloat *)((char *)s + in->stride);
  180.    }
  181. }
  182.  
  183.  
  184. /* =============================================================
  185.  * Normal transformation tests
  186.  */
  187.  
  188. static void init_matrix( GLfloat *m )
  189. {
  190.    m[0] = 63.0; m[4] = 43.0; m[ 8] = 29.0; m[12] = 43.0;
  191.    m[1] = 55.0; m[5] = 17.0; m[ 9] = 31.0; m[13] =  7.0;
  192.    m[2] = 44.0; m[6] =  9.0; m[10] =  7.0; m[14] =  3.0;
  193.    m[3] = 11.0; m[7] = 23.0; m[11] = 91.0; m[15] =  9.0;
  194. }
  195.  
  196.  
  197. static int test_norm_function( normal_func func, int mtype, long *cycles )
  198. {
  199.    GLvector4f source[1], dest[1], dest2[1], ref[1], ref2[1];
  200.    GLmatrix mat[1];
  201.    GLfloat s[TEST_COUNT][5], d[TEST_COUNT][4], r[TEST_COUNT][4];
  202.    GLfloat d2[TEST_COUNT][4], r2[TEST_COUNT][4], length[TEST_COUNT];
  203.    GLfloat scale;
  204.    GLfloat *m;
  205.    int i, j;
  206. #ifdef  RUN_DEBUG_BENCHMARK
  207.    int cycle_i;         /* the counter for the benchmarks we run */
  208. #endif
  209.  
  210.    (void) cycles;
  211.  
  212.    mat->m = _mesa_align_malloc( 16 * sizeof(GLfloat), 16 );
  213.    mat->inv = m = mat->m;
  214.  
  215.    init_matrix( m );
  216.  
  217.    scale = 1.0F + rnd () * norm_scale_types[mtype];
  218.  
  219.    for ( i = 0 ; i < 4 ; i++ ) {
  220.       for ( j = 0 ; j < 4 ; j++ ) {
  221.          switch ( norm_templates[mtype][i * 4 + j] ) {
  222.          case NIL:
  223.             m[j * 4 + i] = 0.0;
  224.             break;
  225.          case ONE:
  226.             m[j * 4 + i] = 1.0;
  227.             break;
  228.          case NEG:
  229.             m[j * 4 + i] = -1.0;
  230.             break;
  231.          case VAR:
  232.             break;
  233.          default:
  234.             exit(1);
  235.          }
  236.       }
  237.    }
  238.  
  239.    for ( i = 0 ; i < TEST_COUNT ; i++ ) {
  240.       ASSIGN_3V( d[i],  0.0, 0.0, 0.0 );
  241.       ASSIGN_3V( s[i],  0.0, 0.0, 0.0 );
  242.       ASSIGN_3V( d2[i], 0.0, 0.0, 0.0 );
  243.       for ( j = 0 ; j < 3 ; j++ )
  244.          s[i][j] = rnd();
  245.       length[i] = 1.0f / sqrtf( LEN_SQUARED_3FV( s[i] ) );
  246.    }
  247.  
  248.    source->data = (GLfloat(*)[4]) s;
  249.    source->start = (GLfloat *) s;
  250.    source->count = TEST_COUNT;
  251.    source->stride = sizeof(s[0]);
  252.    source->flags = 0;
  253.  
  254.    dest->data = d;
  255.    dest->start = (GLfloat *) d;
  256.    dest->count = TEST_COUNT;
  257.    dest->stride = sizeof(float[4]);
  258.    dest->flags = 0;
  259.  
  260.    dest2->data = d2;
  261.    dest2->start = (GLfloat *) d2;
  262.    dest2->count = TEST_COUNT;
  263.    dest2->stride = sizeof(float[4]);
  264.    dest2->flags = 0;
  265.  
  266.    ref->data = r;
  267.    ref->start = (GLfloat *) r;
  268.    ref->count = TEST_COUNT;
  269.    ref->stride = sizeof(float[4]);
  270.    ref->flags = 0;
  271.  
  272.    ref2->data = r2;
  273.    ref2->start = (GLfloat *) r2;
  274.    ref2->count = TEST_COUNT;
  275.    ref2->stride = sizeof(float[4]);
  276.    ref2->flags = 0;
  277.  
  278.    if ( norm_normalize_types[mtype] == 0 ) {
  279.       ref_norm_transform_rescale( mat, scale, source, NULL, ref );
  280.    } else {
  281.       ref_norm_transform_normalize( mat, scale, source, NULL, ref );
  282.       ref_norm_transform_normalize( mat, scale, source, length, ref2 );
  283.    }
  284.  
  285.    if ( mesa_profile ) {
  286.       BEGIN_RACE( *cycles );
  287.       func( mat, scale, source, NULL, dest );
  288.       END_RACE( *cycles );
  289.       func( mat, scale, source, length, dest2 );
  290.    } else {
  291.       func( mat, scale, source, NULL, dest );
  292.       func( mat, scale, source, length, dest2 );
  293.    }
  294.  
  295.    for ( i = 0 ; i < TEST_COUNT ; i++ ) {
  296.       for ( j = 0 ; j < 3 ; j++ ) {
  297.          if ( significand_match( d[i][j], r[i][j] ) < REQUIRED_PRECISION ) {
  298.             printf( "-----------------------------\n" );
  299.             printf( "(i = %i, j = %i)\n", i, j );
  300.             printf( "%f \t %f \t [ratio = %e - %i bit missed]\n",
  301.                     d[i][0], r[i][0], r[i][0]/d[i][0],
  302.                     MAX_PRECISION - significand_match( d[i][0], r[i][0] ) );
  303.             printf( "%f \t %f \t [ratio = %e - %i bit missed]\n",
  304.                     d[i][1], r[i][1], r[i][1]/d[i][1],
  305.                     MAX_PRECISION - significand_match( d[i][1], r[i][1] ) );
  306.             printf( "%f \t %f \t [ratio = %e - %i bit missed]\n",
  307.                     d[i][2], r[i][2], r[i][2]/d[i][2],
  308.                     MAX_PRECISION - significand_match( d[i][2], r[i][2] ) );
  309.             return 0;
  310.          }
  311.  
  312.          if ( norm_normalize_types[mtype] != 0 ) {
  313.             if ( significand_match( d2[i][j], r2[i][j] ) < REQUIRED_PRECISION ) {
  314.                printf( "------------------- precalculated length case ------\n" );
  315.                printf( "(i = %i, j = %i)\n", i, j );
  316.                printf( "%f \t %f \t [ratio = %e - %i bit missed]\n",
  317.                        d2[i][0], r2[i][0], r2[i][0]/d2[i][0],
  318.                        MAX_PRECISION - significand_match( d2[i][0], r2[i][0] ) );
  319.                printf( "%f \t %f \t [ratio = %e - %i bit missed]\n",
  320.                        d2[i][1], r2[i][1], r2[i][1]/d2[i][1],
  321.                        MAX_PRECISION - significand_match( d2[i][1], r2[i][1] ) );
  322.                printf( "%f \t %f \t [ratio = %e - %i bit missed]\n",
  323.                        d2[i][2], r2[i][2], r2[i][2]/d2[i][2],
  324.                        MAX_PRECISION - significand_match( d2[i][2], r2[i][2] ) );
  325.                return 0;
  326.             }
  327.          }
  328.       }
  329.    }
  330.  
  331.    _mesa_align_free( mat->m );
  332.    return 1;
  333. }
  334.  
  335. void _math_test_all_normal_transform_functions( char *description )
  336. {
  337.    int mtype;
  338.    long benchmark_tab[0xf];
  339.    static int first_time = 1;
  340.  
  341.    if ( first_time ) {
  342.       first_time = 0;
  343.       mesa_profile = getenv( "MESA_PROFILE" );
  344.    }
  345.  
  346. #ifdef RUN_DEBUG_BENCHMARK
  347.    if ( mesa_profile ) {
  348.       if ( !counter_overhead ) {
  349.          INIT_COUNTER();
  350.          printf( "counter overhead: %ld cycles\n\n", counter_overhead );
  351.       }
  352.       printf( "normal transform results after hooking in %s functions:\n",
  353.               description );
  354.       printf( "\n-------------------------------------------------------\n" );
  355.    }
  356. #endif
  357.  
  358.    for ( mtype = 0 ; mtype < 8 ; mtype++ ) {
  359.       normal_func func = _mesa_normal_tab[norm_types[mtype]];
  360.       long *cycles = &benchmark_tab[mtype];
  361.  
  362.       if ( test_norm_function( func, mtype, cycles ) == 0 ) {
  363.          char buf[100];
  364.          sprintf( buf, "_mesa_normal_tab[0][%s] failed test (%s)",
  365.                   norm_strings[mtype], description );
  366.          _mesa_problem( NULL, "%s", buf );
  367.       }
  368.  
  369. #ifdef RUN_DEBUG_BENCHMARK
  370.       if ( mesa_profile ) {
  371.          printf( " %li\t", benchmark_tab[mtype] );
  372.          printf( " | [%s]\n", norm_strings[mtype] );
  373.       }
  374. #endif
  375.    }
  376. #ifdef RUN_DEBUG_BENCHMARK
  377.    if ( mesa_profile ) {
  378.       printf( "\n" );
  379.    }
  380. #endif
  381. }
  382.  
  383.  
  384. #endif /* DEBUG_MATH */
  385.