Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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