home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / System / Mesa-3.1 / src / debug_xform.c < prev    next >
C/C++ Source or Header  |  2000-01-07  |  23KB  |  796 lines

  1. /* $Id: debug_xform.c,v 1.2 1999/11/08 07:36:43 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.1
  6.  * 
  7.  * Copyright (C) 1999  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.  
  27. #ifndef XFree86Server
  28. #include <limits.h>
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <math.h>
  32. #else
  33. #include "GL/xf86glx.h"
  34. #endif
  35. #include "context.h"
  36. #include "types.h"
  37. #include "xform.h"
  38. #include "debug_xform.h"
  39.  
  40.  
  41. /*  comment this out to deactivate the cycle counter.
  42.  *  NOTE: it works only on CPUs which know the 'rdtsc' command (586 or higher) 
  43.  *  (hope, you don't try to debug Mesa on a 386 ;) 
  44.  */
  45. #if defined(__GNUC__) && defined(__i386__) && defined(USE_X86_ASM)
  46. #define  RUN_XFORM_BENCHMARK
  47. #endif
  48.  
  49. #define  TEST_COUNT  100                 /* size of the tested vector array   */
  50.  
  51. #define  REQUIRED_PRECISION  10          /* allow 4 bits to miss              */
  52. #define  MAX_PRECISION       24          /* max. precision possible           */
  53.  
  54.  
  55. #ifdef  RUN_XFORM_BENCHMARK
  56. /*  Modify the the number of tests if you like.
  57.  *  We take the minimum of all results, because every error should be 
  58.  *  positive (time used by other processes, task switches etc).
  59.  *  It is assumed that all calculations are done in the cache.
  60.  */
  61. #define  BEGIN_RACE(x)                                                        \
  62. x = 16000000;                                         /*  hope it's enough-*/ \
  63. for (cycle_i = 0; cycle_i <10; cycle_i++) {                                   \
  64.    long cycle_tmp1, cycle_tmp2, dummy;                                        \
  65.    __asm__ ("mov %%eax, %0":"=a" (cycle_tmp1));       /*  cache cycle_tmp1 */ \
  66.    __asm__ ("mov %%eax, %0":"=a" (cycle_tmp2));       /*  cache cycle_tmp2 */ \
  67.    __asm__ ("cdq");                                   /*  stall pipeline   */ \
  68.    __asm__ ("cdq");                                   /*  to avoid pairing */ \
  69.    __asm__ ("rdtsc":"=a" (cycle_tmp1), "=d" (dummy)); /*  save timestamp   */
  70.  
  71.  
  72. #define END_RACE(x)                                                           \
  73.    __asm__ ("cdq");                                                           \
  74.    __asm__ ("cdq");                                                           \
  75.    __asm__ ("rdtsc":"=a" (cycle_tmp2), "=d" (dummy));                         \
  76.    if (x > (cycle_tmp2-cycle_tmp1)) x = cycle_tmp2 - cycle_tmp1;              \
  77. }                                                                             \
  78. x -= 13;                      /*   sub the overhead of the counter procedure */
  79.  
  80. #else
  81. #define BEGIN_RACE(x) 
  82. #define END_RACE(x)
  83. #endif
  84.  
  85.  
  86. static char *mesa_profile = NULL;
  87.  
  88.  
  89. static GLfloat rnd(void)
  90. {
  91.    GLfloat f = (GLfloat)rand() / (GLfloat)RAND_MAX;
  92.    GLfloat gran = (GLfloat)(1 << 13);
  93.  
  94.    f = (GLfloat)(GLint)(f * gran) / gran;
  95.  
  96.    return f * 2.0 - 1.0;
  97. }
  98.  
  99.  
  100.  
  101. static int significand_match( GLfloat a, GLfloat b )
  102. {
  103.    GLfloat d = a - b;
  104.    int a_ex, b_ex, d_ex;
  105.  
  106.    if (d == 0.0F) {
  107.       return MAX_PRECISION;   /* Exact match */
  108.    }
  109.  
  110.    if (a == 0.0F || b == 0.0F) {
  111.       /*
  112.        * It would probably be better to check if the
  113.        * non-zero number is denormalized and return
  114.        * the index of the highest set bit here.
  115.        */
  116.       return 0;
  117.    }
  118.  
  119.    frexp(a, &a_ex);
  120.    frexp(b, &b_ex);
  121.    frexp(d, &d_ex);
  122.  
  123.    if (a_ex < b_ex)
  124.       return a_ex - d_ex;
  125.    else
  126.       return b_ex - d_ex;
  127. }
  128.  
  129.  
  130.  
  131.  
  132.  
  133. static void ref_transform( GLvector4f *dst, 
  134.                            const GLmatrix *mat, 
  135.                            const GLvector4f *src,
  136.                            const GLubyte *clipmask, 
  137.                            const GLubyte flag )
  138. {
  139.    int i;
  140.    GLfloat *s = (GLfloat *)src->start;
  141.    GLfloat (*d)[4] = (GLfloat (*)[4])dst->start;
  142.    const GLfloat *m = mat->m;
  143.  
  144.    (void) clipmask;
  145.    (void) flag;
  146.  
  147.    for (i = 0; i < src->count; ++i) {
  148.       GLfloat x = s[0], y = s[1], z = s[2], w = s[3];
  149.       d[i][0] = m[0]*x + m[4]*y + m[ 8]*z + m[12]*w;
  150.       d[i][1] = m[1]*x + m[5]*y + m[ 9]*z + m[13]*w;
  151.       d[i][2] = m[2]*x + m[6]*y + m[10]*z + m[14]*w;
  152.       d[i][3] = m[3]*x + m[7]*y + m[11]*z + m[15]*w;
  153.       s = (GLfloat *)((char *)s + src->stride);
  154.    }
  155. }
  156.  
  157.  
  158. enum { NIL=0, ONE=1, NEG=-1, VAR=2 };
  159.  
  160. static int m_general[16] = {
  161.    VAR, VAR, VAR, VAR,
  162.    VAR, VAR, VAR, VAR,
  163.    VAR, VAR, VAR, VAR,
  164.    VAR, VAR, VAR, VAR
  165. };
  166. static int m_identity[16] = {
  167.    ONE, NIL, NIL, NIL,
  168.    NIL, ONE, NIL, NIL,
  169.    NIL, NIL, ONE, NIL,
  170.    NIL, NIL, NIL, ONE
  171. };
  172. static int m_2d[16] = {
  173.    VAR, VAR, NIL, VAR,
  174.    VAR, VAR, NIL, VAR,
  175.    NIL, NIL, ONE, NIL,
  176.    NIL, NIL, NIL, ONE
  177. };
  178. static int m_2d_no_rot[16] = {
  179.    VAR, NIL, NIL, VAR,
  180.    NIL, VAR, NIL, VAR,
  181.    NIL, NIL, ONE, NIL,
  182.    NIL, NIL, NIL, ONE
  183. };
  184. static int m_3d[16] = {
  185.    VAR, VAR, VAR, VAR,
  186.    VAR, VAR, VAR, VAR,
  187.    VAR, VAR, VAR, VAR,
  188.    NIL, NIL, NIL, ONE
  189. };
  190. static int m_3d_no_rot[16] = {
  191.    VAR, NIL, NIL, VAR,
  192.    NIL, VAR, NIL, VAR,
  193.    NIL, NIL, VAR, VAR,
  194.    NIL, NIL, NIL, ONE
  195. };
  196. static int m_perspective[16] = {
  197.    VAR, NIL, VAR, NIL,
  198.    NIL, VAR, VAR, NIL,
  199.    NIL, NIL, VAR, VAR,
  200.    NIL, NIL, NEG, NIL
  201. };
  202. static int *templates[7] = {
  203.    m_general,
  204.    m_identity,
  205.    m_3d_no_rot,
  206.    m_perspective,
  207.    m_2d,
  208.    m_2d_no_rot,
  209.    m_3d
  210. };
  211. static int mtypes[7] = {
  212.    MATRIX_GENERAL,
  213.    MATRIX_IDENTITY,
  214.    MATRIX_3D_NO_ROT,
  215.    MATRIX_PERSPECTIVE,
  216.    MATRIX_2D,
  217.    MATRIX_2D_NO_ROT,
  218.    MATRIX_3D
  219. };
  220. static char *mstrings[7] = {
  221.    "MATRIX_GENERAL",
  222.    "MATRIX_IDENTITY",
  223.    "MATRIX_3D_NO_ROT",
  224.    "MATRIX_PERSPECTIVE",
  225.    "MATRIX_2D",
  226.    "MATRIX_2D_NO_ROT",
  227.    "MATRIX_3D"
  228. };
  229.  
  230.  
  231. static int test_transform_function( transform_func fn, int psize, int mtype,
  232.                                     int masked, long* cycles )
  233. {
  234.    GLvector4f source[1], dest[1], ref[1];
  235.    GLmatrix mat[1];
  236.    GLfloat s[TEST_COUNT][5], d[TEST_COUNT][4], r[TEST_COUNT][4];
  237.    GLfloat *m = mat->m;
  238.    GLubyte mask[TEST_COUNT];
  239.    int i, j;
  240.  
  241.    int cycle_i;                /* the counter for the benchmarks we run     */
  242.  
  243.    (void) cycles; (void) cycle_i;
  244.  
  245.    if (psize > 4) {
  246.       gl_problem( NULL, "test_transform_function called with psize > 4\n");
  247.       return 0;
  248.    }
  249.  
  250.    mat->type = mtypes[mtype];
  251.  
  252.    m[0] = 63.0; m[4] = 43.0; m[ 8] = 29.0; m[12] = 43.0;
  253.    m[1] = 55.0; m[5] = 17.0; m[ 9] = 31.0; m[13] =  7.0;
  254.    m[2] = 44.0; m[6] =  9.0; m[10] =  7.0; m[14] =  3.0;
  255.    m[3] = 11.0; m[7] = 23.0; m[11] = 91.0; m[15] =  9.0;
  256.  
  257.    for (i = 0; i < 4; i++) {
  258.       for (j = 0; j < 4; j++) {
  259.          switch (templates[mtype][i * 4 + j]) {
  260.          case NIL:
  261.             m[j * 4 + i] = 0.0;
  262.             break;
  263.          case ONE:
  264.             m[j * 4 + i] = 1.0;
  265.             break;
  266.          case NEG:
  267.             m[j * 4 + i] = -1.0;
  268.             break;
  269.          case VAR:
  270.             break;
  271.          default:
  272.             abort();
  273.          }
  274.       }
  275.    }
  276.  
  277.    for (i = 0; i < TEST_COUNT; ++i) {
  278.       mask[i] = i % 2;            /*  mask every 2nd element          */
  279.       d[i][0] = s[i][0] = 0.0;
  280.       d[i][1] = s[i][1] = 0.0;
  281.       d[i][2] = s[i][2] = 0.0;
  282.       d[i][3] = s[i][3] = 1.0;
  283.       for (j = 0; j < psize; j++)
  284.          s[i][j] = rnd();
  285.    }
  286.  
  287.    source->data = (GLfloat(*)[4])s;
  288.    source->start = (GLfloat *)s;
  289.    source->count = TEST_COUNT;
  290.    source->stride = sizeof(s[0]);
  291.    source->size = 4;
  292.    source->flags = 0;
  293.  
  294.    dest->data = (GLfloat(*)[4])d;
  295.    dest->start = (GLfloat *)d;
  296.    dest->count = TEST_COUNT;
  297.    dest->stride = sizeof(float[4]);
  298.    dest->size = 0;
  299.    dest->flags = 0;
  300.  
  301.    ref->data = (GLfloat(*)[4])r;
  302.    ref->start = (GLfloat *)r;
  303.    ref->count = TEST_COUNT;
  304.    ref->stride = sizeof(float[4]);
  305.    ref->size = 0;
  306.    ref->flags = 0;
  307.  
  308.    ref_transform(ref, mat, source, NULL, 0);
  309.  
  310.    if (mesa_profile) {
  311.       if (masked) {
  312.          BEGIN_RACE (*cycles);
  313.          fn(dest, mat, source, mask, 1);
  314.          END_RACE (*cycles);
  315.       } else {
  316.          BEGIN_RACE (*cycles);
  317.          fn(dest, mat, source, NULL, 0);
  318.          END_RACE (*cycles);
  319.       }
  320.    }
  321.    else {
  322.       if (masked) {
  323.          fn(dest, mat, source, mask, 1);
  324.       } else {
  325.          fn(dest, mat, source, NULL, 0);
  326.       }
  327.    }
  328.  
  329.    for (i = 0; i < TEST_COUNT; ++i) {
  330.       if (masked && mask[i] & 1)
  331.          continue;
  332.  
  333.       for (j = 0; j < 4; j++) {
  334.          if (significand_match (d[i][j], r[i][j]) < REQUIRED_PRECISION) {
  335.             printf("-----------------------------\n");
  336.             printf ("(i = %i, j = %i)\n", i, j);
  337.             printf ("%f \t %f \t [diff = %e - %i bit missed]\n",
  338.                          d[i][0], r[i][0], r[i][0]-d[i][0],
  339.                          MAX_PRECISION - significand_match (d[i][0], r[i][0]));
  340.             printf ("%f \t %f \t [diff = %e - %i bit missed]\n",
  341.                          d[i][1], r[i][1], r[i][1]-d[i][1], 
  342.                          MAX_PRECISION - significand_match (d[i][1], r[i][1]));
  343.             printf ("%f \t %f \t [diff = %e - %i bit missed]\n",
  344.                          d[i][2], r[i][2], r[i][2]-d[i][2], 
  345.                          MAX_PRECISION - significand_match (d[i][2], r[i][2]));
  346.             printf ("%f \t %f \t [diff = %e - %i bit missed]\n",
  347.                          d[i][3], r[i][3], r[i][3]-d[i][3], 
  348.                          MAX_PRECISION - significand_match (d[i][3], r[i][3]));
  349.             return 0;
  350.          }
  351.       }
  352.    }
  353.    return 1;
  354. }
  355.  
  356.  
  357.  
  358.  
  359. void gl_test_all_transform_functions( char *description )
  360. {
  361.    int masked, psize, mtype;
  362.    long benchmark_tab [2][4][7];
  363.    static int first_time = 1;
  364.  
  365.    if (first_time) {
  366.       first_time = 0;
  367.       mesa_profile = getenv("MESA_PROFILE");
  368.    }
  369.  
  370. #ifdef RUN_XFORM_BENCHMARK
  371.    if (mesa_profile) {
  372.       printf("transform results after hooking in %s functions:\n", description);
  373.    }
  374. #endif
  375.  
  376.    for (masked = 0; masked <= 1; masked++) {
  377.       int cma = masked ? CULL_MASK_ACTIVE : 0;
  378.       char *cmastring = masked ? "CULL_MASK_ACTIVE" : "0";
  379.  
  380. #ifdef RUN_XFORM_BENCHMARK
  381.       if (mesa_profile) {
  382.          printf ("\n culling: %s \n", masked ? "CULL_MASK_ACTIVE" : "0");
  383.          for (psize = 1; psize <= 4; psize++) {
  384.             printf(" p%d\t", psize );
  385.          }
  386.          printf("\n--------------------------------------------------------\n");
  387.       }
  388. #endif
  389.  
  390.       for (mtype = 0; mtype < 7; mtype++) {
  391.          for (psize = 1; psize <= 4; psize++) {
  392.             transform_func fn = gl_transform_tab[cma][psize][mtypes[mtype]];
  393.             long* cycles = &(benchmark_tab [cma][psize-1][mtype]);
  394.  
  395.             if (test_transform_function (fn,psize,mtype,masked,cycles) == 0 ) {
  396.                char buf[100];
  397.                sprintf( buf, "gl_transform_tab[%s][%d][%s] failed test (%s)",
  398.                         cmastring, psize, mstrings[mtype], description );
  399.                gl_problem( NULL, buf );
  400.             } else {
  401. /*             printf("gl_transform_tab[%s][%d][%s] passed test in %i cycles\n",
  402.            cmastring, psize, mstrings[mtype],
  403.            benchmark_tab [cma][psize-1][mtype]); 
  404. */          }
  405. #ifdef RUN_XFORM_BENCHMARK
  406.             if (mesa_profile)
  407.                printf(" %li\t", benchmark_tab [cma][psize-1][mtype] );
  408. #endif
  409.          }
  410. #ifdef RUN_XFORM_BENCHMARK
  411.          if (mesa_profile)
  412.             printf (" | [%s]\n", mstrings[mtype] );
  413. #endif
  414.       }
  415. #ifdef RUN_XFORM_BENCHMARK
  416.       if (mesa_profile)
  417.          printf ("\n");
  418. #endif
  419.    }
  420. }
  421.  
  422.  
  423.  
  424.  
  425.  
  426.  
  427.  
  428.  
  429. static void ref_norm_transform_rescale ( const GLmatrix *mat,
  430.                                     GLfloat scale,
  431.                                     const GLvector3f *in,
  432.                                     const GLfloat *lengths,
  433.                                     const GLubyte mask[],
  434.                                     GLvector3f *dest )
  435. {
  436.    int i;
  437.    const GLfloat *s = in->start;
  438.    const GLfloat *m = mat->inv;
  439.    GLfloat (*out)[3] = (GLfloat (*)[3])dest->start;
  440.  
  441.    (void) mask;
  442.    (void) lengths;
  443.  
  444.    for (i = 0; i < in->count; ++i) {
  445.       GLfloat x = s[0], y = s[1], z = s[2] ;
  446.       GLfloat tx = m[0]*x + m[1]*y + m[ 2]*z ;
  447.       GLfloat ty = m[4]*x + m[5]*y + m[ 6]*z ;
  448.       GLfloat tz = m[8]*x + m[9]*y + m[10]*z ;
  449.  
  450.       out[i][0] = tx * scale;
  451.       out[i][1] = ty * scale;
  452.       out[i][2] = tz * scale;
  453.  
  454.       s = (GLfloat *)((char *)s + in->stride);
  455.    }
  456. }
  457.  
  458.  
  459. static void ref_norm_transform_normalize ( const GLmatrix *mat,
  460.                                       GLfloat scale,
  461.                                       const GLvector3f *in,
  462.                                       const GLfloat *lengths,
  463.                                       const GLubyte mask[],
  464.                                       GLvector3f *dest )
  465. {
  466.    int i;
  467.    const GLfloat *s = in->start;
  468.    const GLfloat *m = mat->inv;
  469.    GLfloat (*out)[3] = (GLfloat (*)[3])dest->start;
  470.  
  471.    (void) mask;
  472.  
  473.    for (i = 0; i < in->count; ++i) {
  474.       GLfloat x = s[0], y = s[1], z = s[2] ;
  475.       GLfloat tx = m[0]*x + m[1]*y + m[ 2]*z ;
  476.       GLfloat ty = m[4]*x + m[5]*y + m[ 6]*z ;
  477.       GLfloat tz = m[8]*x + m[9]*y + m[10]*z ;
  478.  
  479.       if (!lengths) {
  480.          GLfloat len = tx*tx + ty*ty + tz*tz;
  481.          if (len > 1e-20) {
  482.             scale = 1.0 / sqrt (len);           /*  hmmm, don't know how we   */
  483.                                                 /*  could test the precalcu-  */
  484.                                                 /*  lated length case ...     */
  485.             out[i][0] = tx * scale;
  486.             out[i][1] = ty * scale;
  487.             out[i][2] = tz * scale;
  488.          } else {
  489.             out[i][0] = out[i][1] = out[i][2] = 0;
  490.          }
  491.       } else {
  492.          scale = lengths [i];;
  493.          out[i][0] = tx * scale;
  494.          out[i][1] = ty * scale;
  495.          out[i][2] = tz * scale;
  496.       }
  497.  
  498.       s = (GLfloat *)((char *)s + in->stride);
  499.    }
  500. }
  501.  
  502.  
  503.  
  504. static int m_norm_identity[16] = {
  505.    ONE, NIL, NIL, NIL,
  506.    NIL, ONE, NIL, NIL,
  507.    NIL, NIL, ONE, NIL,
  508.    NIL, NIL, NIL, NIL
  509. };
  510. static int m_norm_general[16] = {
  511.    VAR, VAR, VAR, NIL,
  512.    VAR, VAR, VAR, NIL,
  513.    VAR, VAR, VAR, NIL,
  514.    NIL, NIL, NIL, NIL
  515. };
  516. static int m_norm_no_rot[16] = {
  517.    VAR, NIL, NIL, NIL,
  518.    NIL, VAR, NIL, NIL,
  519.    NIL, NIL, VAR, NIL,
  520.    NIL, NIL, NIL, NIL
  521. };
  522. static int *norm_templates[8] = {
  523.    m_norm_no_rot,
  524.    m_norm_no_rot,
  525.    m_norm_no_rot,
  526.    m_norm_general,
  527.    m_norm_general,
  528.    m_norm_general,
  529.    m_norm_identity,
  530.    m_norm_identity
  531. };
  532. static int norm_types[8] = {
  533.    NORM_TRANSFORM_NO_ROT,
  534.    NORM_TRANSFORM_NO_ROT | NORM_RESCALE,
  535.    NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE,
  536.    NORM_TRANSFORM,
  537.    NORM_TRANSFORM | NORM_RESCALE,
  538.    NORM_TRANSFORM | NORM_NORMALIZE,
  539.    NORM_RESCALE,
  540.    NORM_NORMALIZE
  541. };
  542. static int norm_scale_types[8] = {               /*  rescale factor           */
  543.    NIL,                                          /*  NIL disables rescaling   */
  544.    VAR,
  545.    NIL,
  546.    NIL,
  547.    VAR,
  548.    NIL,
  549.    VAR,
  550.    NIL
  551. };
  552. static int norm_normalize_types[8] = {           /*  normalizing ??  (no = 0) */
  553.    0,
  554.    0,
  555.    1,
  556.    0,
  557.    0,
  558.    1,
  559.    0,
  560.    1
  561. };
  562. static char *norm_strings[8] = {
  563.    "NORM_TRANSFORM_NO_ROT",
  564.    "NORM_TRANSFORM_NO_ROT | NORM_RESCALE",
  565.    "NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE",
  566.    "NORM_TRANSFORM",
  567.    "NORM_TRANSFORM | NORM_RESCALE",
  568.    "NORM_TRANSFORM | NORM_NORMALIZE",
  569.    "NORM_RESCALE",
  570.    "NORM_NORMALIZE"
  571. };
  572.  
  573.  
  574.  
  575.  
  576.  
  577. static int test_norm_function( normal_func fn, int mtype,
  578.                                     int masked, long* cycles )
  579. {
  580.    GLvector3f source[1], dest[1], dest2[1], ref[1], ref2[1];
  581.    GLmatrix mat[1];
  582.    GLfloat s [TEST_COUNT][5], d [TEST_COUNT][3], r [TEST_COUNT][3];
  583.    GLfloat d2 [TEST_COUNT][3], r2 [TEST_COUNT][3], length [TEST_COUNT];
  584.    GLfloat scale;
  585.    GLfloat *m = mat->m;
  586.    GLubyte mask[TEST_COUNT];
  587.    int i, j;
  588.  
  589.    int cycle_i;                /* the counter for the benchmarks we run     */
  590.  
  591.    (void) cycles; (void) cycle_i;
  592.  
  593.    mat->inv = mat->m;
  594.  
  595.    m[0] = 63.0; m[4] = 43.0; m[ 8] = 29.0; m[12] = 43.0;
  596.    m[1] = 55.0; m[5] = 17.0; m[ 9] = 31.0; m[13] =  7.0;
  597.    m[2] = 44.0; m[6] =  9.0; m[10] =  7.0; m[14] =  3.0;
  598.    m[3] = 11.0; m[7] = 23.0; m[11] = 91.0; m[15] =  9.0;
  599.  
  600.    scale = 1.0F + rnd () * norm_scale_types[mtype];
  601.  
  602.    for (i = 0; i < 4; i++) {
  603.       for (j = 0; j < 4; j++) {
  604.          switch (norm_templates[mtype][i * 4 + j]) {
  605.          case NIL:
  606.             m[j * 4 + i] = 0.0;
  607.             break;
  608.          case ONE:
  609.             m[j * 4 + i] = 1.0;
  610.             break;
  611.          case NEG:
  612.             m[j * 4 + i] = -1.0;
  613.             break;
  614.          case VAR:
  615.             break;
  616.          default:
  617.             abort();
  618.          }
  619.       }
  620.    }
  621.  
  622.    for (i = 0; i < TEST_COUNT; ++i) {
  623.       mask[i] = i % 2;                         /*  mask every 2nd element     */
  624.       d[i][0] = s[i][0] = d2[i][0] = 0.0;
  625.       d[i][1] = s[i][1] = d2[i][1] = 0.0;
  626.       d[i][2] = s[i][2] = d2[i][2] = 0.0;
  627.       for (j = 0; j < 3; j++)
  628.          s[i][j] = rnd();
  629.       length[i] = 1 / sqrt(s[i][0]*s[i][0] + s[i][1]*s[i][1] + s[i][2]*s[i][2]);
  630.    }
  631.  
  632.    source->data = (GLfloat(*)[3])s;
  633.    source->start = (GLfloat *)s;
  634.    source->count = TEST_COUNT;
  635.    source->stride = sizeof(s[0]);
  636.    source->flags = 0;
  637.  
  638.    dest->data = (GLfloat(*)[3])d;
  639.    dest->start = (GLfloat *)d;
  640.    dest->count = TEST_COUNT;
  641.    dest->stride = sizeof(float[3]);
  642.    dest->flags = 0;
  643.  
  644.    dest2->data = (GLfloat(*)[3])d2;
  645.    dest2->start = (GLfloat *)d2;
  646.    dest2->count = TEST_COUNT;
  647.    dest2->stride = sizeof(float[3]);
  648.    dest2->flags = 0;
  649.  
  650.    ref->data = (GLfloat(*)[3])r;
  651.    ref->start = (GLfloat *)r;
  652.    ref->count = TEST_COUNT;
  653.    ref->stride = sizeof(float[3]);
  654.    ref->flags = 0;
  655.  
  656.    ref2->data = (GLfloat(*)[3])r2;
  657.    ref2->start = (GLfloat *)r2;
  658.    ref2->count = TEST_COUNT;
  659.    ref2->stride = sizeof(float[3]);
  660.    ref2->flags = 0;
  661.  
  662.    if (norm_normalize_types [mtype] == 0) {
  663.       ref_norm_transform_rescale (mat, scale, source, NULL, NULL, ref);
  664.    } else {
  665.       ref_norm_transform_normalize (mat, scale, source, NULL, NULL, ref);
  666.       ref_norm_transform_normalize (mat, scale, source, length, NULL, ref2);
  667.    }
  668.  
  669.    if (mesa_profile) {
  670.       if (masked) {
  671.          BEGIN_RACE (*cycles);
  672.          fn (mat, scale, source, NULL, mask, dest);
  673.          END_RACE (*cycles);
  674.          fn (mat, scale, source, length, mask, dest2);
  675.       } else {
  676.          BEGIN_RACE (*cycles);
  677.          fn (mat, scale, source, NULL, NULL, dest);
  678.          END_RACE (*cycles);
  679.          fn (mat, scale, source, length, NULL, dest2);
  680.       }
  681.    } else {
  682.       if (masked) {
  683.          fn (mat, scale, source, NULL, mask, dest);
  684.          fn (mat, scale, source, length, mask, dest2);
  685.       } else {
  686.          fn (mat, scale, source, NULL, NULL, dest);
  687.          fn (mat, scale, source, length, NULL, dest2);
  688.       }
  689.    }
  690.  
  691.    for (i = 0; i < TEST_COUNT; ++i) {
  692.       if (masked && !(mask[i] & 1))
  693.          continue;
  694.  
  695.       for (j = 0; j < 3; j++) {
  696.          if (significand_match (d[i][j], r[i][j]) < REQUIRED_PRECISION) {
  697.             printf("-----------------------------\n");
  698.             printf ("(i = %i, j = %i)\n", i, j);
  699.             printf ("%f \t %f \t [ratio = %e - %i bit missed]\n",
  700.                          d[i][0], r[i][0], r[i][0]/d[i][0],
  701.                          MAX_PRECISION - significand_match (d[i][0], r[i][0]));
  702.             printf ("%f \t %f \t [ratio = %e - %i bit missed]\n",
  703.                          d[i][1], r[i][1], r[i][1]/d[i][1],
  704.                          MAX_PRECISION - significand_match (d[i][1], r[i][1]));
  705.             printf ("%f \t %f \t [ratio = %e - %i bit missed]\n",
  706.                          d[i][2], r[i][2], r[i][2]/d[i][2],
  707.                          MAX_PRECISION - significand_match (d[i][2], r[i][2]));
  708.             return 0;
  709.          }
  710.  
  711.          if (norm_normalize_types [mtype] != 0) {
  712.             if (significand_match (d2[i][j], r2[i][j]) < REQUIRED_PRECISION) {
  713.                printf("------------------- precalculated length case ------\n");
  714.                printf ("(i = %i, j = %i)\n", i, j);
  715.                printf ("%f \t %f \t [ratio = %e - %i bit missed]\n",
  716.                          d2[i][0], r2[i][0], r2[i][0]/d2[i][0],
  717.                          MAX_PRECISION - significand_match (d2[i][0],r2[i][0]));
  718.                printf ("%f \t %f \t [ratio = %e - %i bit missed]\n",
  719.                          d2[i][1], r2[i][1], r2[i][1]/d2[i][1], 
  720.                          MAX_PRECISION - significand_match (d2[i][1],r2[i][1]));
  721.                printf ("%f \t %f \t [ratio = %e - %i bit missed]\n",
  722.                          d2[i][2], r2[i][2], r2[i][2]/d2[i][2], 
  723.                          MAX_PRECISION - significand_match (d2[i][2],r2[i][2]));
  724.                return 0;
  725.             }
  726.          }
  727.       }
  728.    }
  729.    return 1;
  730. }
  731.  
  732.  
  733.  
  734. void gl_test_all_normal_transform_functions( char *description )
  735. {
  736.    int masked;
  737.    int mtype;
  738.    long benchmark_tab [0xf][0x4];
  739.    static int first_time = 1;
  740.  
  741.  
  742.    if (first_time) {
  743.       first_time = 0;
  744.       mesa_profile = getenv("MESA_PROFILE");
  745.    }
  746.  
  747. #ifdef RUN_XFORM_BENCHMARK
  748.    if (mesa_profile) {
  749.       printf ("normal transform results after hooking in %s functions:\n", 
  750.                                                                 description);
  751.    }
  752. #endif
  753.  
  754.  
  755.    for (masked = 0; masked <= 1; masked++) {
  756.       int cma = masked ? CULL_MASK_ACTIVE : 0;
  757.       char *cmastring = masked ? "CULL_MASK_ACTIVE" : "0";
  758.  
  759. #ifdef RUN_XFORM_BENCHMARK
  760.       if (mesa_profile) {
  761.          printf ("\n culling: %s \n", masked ? "CULL_MASK_ACTIVE" : "0");
  762.          printf ("\n-------------------------------------------------------\n");
  763.       }
  764. #endif
  765.  
  766.       for (mtype = 0; mtype < 8; mtype++) {
  767.          normal_func fn = gl_normal_tab [norm_types[mtype]][cma];
  768.          long* cycles = &(benchmark_tab [mtype][cma]);
  769.  
  770.          if (test_norm_function (fn, mtype, masked, cycles) == 0 ) {
  771.             char buf[100];
  772.             sprintf( buf, "gl_normal_tab[%s][%s] failed test (%s)",
  773.                      cmastring, norm_strings[mtype], description );
  774.             gl_problem( NULL, buf );
  775.          } else {
  776. /*          printf("gl_normal_tab[%s][%s] passed test in %li cycles (%s)\n",
  777.                      cmastring, norm_strings[mtype],
  778.                      benchmark_tab [mtype][cma], description);
  779. */       }
  780.  
  781. #ifdef RUN_XFORM_BENCHMARK
  782.          if (mesa_profile) {
  783.             printf (" %li\t", benchmark_tab [mtype][cma] );
  784.             printf (" | [%s]\n", norm_strings[mtype] );
  785.          }
  786.       }
  787.       if (mesa_profile) { printf ("\n"); }
  788. #else
  789.       }
  790. #endif
  791.    }
  792. }
  793.  
  794.  
  795.  
  796.