Subversion Repositories Kolibri OS

Rev

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

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
  4.  * All Rights Reserved.
  5.  *
  6.  **************************************************************************/
  7.  
  8.  
  9. /**
  10.  * Code to implement GL_OES_query_matrix.  See the spec at:
  11.  * http://www.khronos.org/registry/gles/extensions/OES/OES_query_matrix.txt
  12.  */
  13.  
  14.  
  15. #include <stdlib.h>
  16. #include <math.h>
  17. #include "glheader.h"
  18. #include "querymatrix.h"
  19. #include "main/get.h"
  20.  
  21.  
  22. /**
  23.  * This is from the GL_OES_query_matrix extension specification:
  24.  *
  25.  *  GLbitfield glQueryMatrixxOES( GLfixed mantissa[16],
  26.  *                                GLint   exponent[16] )
  27.  *  mantissa[16] contains the contents of the current matrix in GLfixed
  28.  *  format.  exponent[16] contains the unbiased exponents applied to the
  29.  *  matrix components, so that the internal representation of component i
  30.  *  is close to mantissa[i] * 2^exponent[i].  The function returns a status
  31.  *  word which is zero if all the components are valid. If
  32.  *  status & (1<<i) != 0, the component i is invalid (e.g., NaN, Inf).
  33.  *  The implementations are not required to keep track of overflows.  In
  34.  *  that case, the invalid bits are never set.
  35.  */
  36.  
  37. #define INT_TO_FIXED(x) ((GLfixed) ((x) << 16))
  38. #define FLOAT_TO_FIXED(x) ((GLfixed) ((x) * 65536.0))
  39.  
  40. #if defined(_MSC_VER)
  41. /* Oddly, the fpclassify() function doesn't exist in such a form
  42.  * on MSVC.  This is an implementation using slightly different
  43.  * lower-level Windows functions.
  44.  */
  45. #include <float.h>
  46.  
  47. enum {FP_NAN, FP_INFINITE, FP_ZERO, FP_SUBNORMAL, FP_NORMAL}
  48. fpclassify(double x)
  49. {
  50.     switch(_fpclass(x)) {
  51.         case _FPCLASS_SNAN: /* signaling NaN */
  52.         case _FPCLASS_QNAN: /* quiet NaN */
  53.             return FP_NAN;
  54.         case _FPCLASS_NINF: /* negative infinity */
  55.         case _FPCLASS_PINF: /* positive infinity */
  56.             return FP_INFINITE;
  57.         case _FPCLASS_NN:   /* negative normal */
  58.         case _FPCLASS_PN:   /* positive normal */
  59.             return FP_NORMAL;
  60.         case _FPCLASS_ND:   /* negative denormalized */
  61.         case _FPCLASS_PD:   /* positive denormalized */
  62.             return FP_SUBNORMAL;
  63.         case _FPCLASS_NZ:   /* negative zero */
  64.         case _FPCLASS_PZ:   /* positive zero */
  65.             return FP_ZERO;
  66.         default:
  67.             /* Should never get here; but if we do, this will guarantee
  68.              * that the pattern is not treated like a number.
  69.              */
  70.             return FP_NAN;
  71.     }
  72. }
  73.  
  74. #elif defined(__APPLE__) || defined(__CYGWIN__) || defined(__FreeBSD__) || \
  75.      defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \
  76.      (defined(__sun) && defined(__C99FEATURES__)) || defined(__MINGW32__) || \
  77.      (defined(__sun) && defined(__GNUC__)) || defined(ANDROID) || defined(__HAIKU__)
  78.  
  79. /* fpclassify is available. */
  80.  
  81. #elif !defined(_XOPEN_SOURCE) || _XOPEN_SOURCE < 600
  82.  
  83. //enum {FP_NAN, FP_INFINITE, FP_ZERO, FP_SUBNORMAL, FP_NORMAL}
  84. //fpclassify(double x)
  85. //{
  86.    /* XXX do something better someday */
  87. //   return FP_NORMAL;
  88. //}
  89.  
  90. #endif
  91.  
  92. GLbitfield GLAPIENTRY _mesa_QueryMatrixxOES(GLfixed mantissa[16], GLint exponent[16])
  93. {
  94.     GLfloat matrix[16];
  95.     GLint tmp;
  96.     GLenum currentMode = GL_FALSE;
  97.     GLenum desiredMatrix = GL_FALSE;
  98.     /* The bitfield returns 1 for each component that is invalid (i.e.
  99.      * NaN or Inf).  In case of error, everything is invalid.
  100.      */
  101.     GLbitfield rv;
  102.     register unsigned int i;
  103.     unsigned int bit;
  104.  
  105.     /* This data structure defines the mapping between the current matrix
  106.      * mode and the desired matrix identifier.
  107.      */
  108.     static struct {
  109.         GLenum currentMode;
  110.         GLenum desiredMatrix;
  111.     } modes[] = {
  112.         {GL_MODELVIEW, GL_MODELVIEW_MATRIX},
  113.         {GL_PROJECTION, GL_PROJECTION_MATRIX},
  114.         {GL_TEXTURE, GL_TEXTURE_MATRIX},
  115.     };
  116.  
  117.     /* Call Mesa to get the current matrix in floating-point form.  First,
  118.      * we have to figure out what the current matrix mode is.
  119.      */
  120.     _mesa_GetIntegerv(GL_MATRIX_MODE, &tmp);
  121.     currentMode = (GLenum) tmp;
  122.  
  123.     /* The mode is either GL_FALSE, if for some reason we failed to query
  124.      * the mode, or a given mode from the above table.  Search for the
  125.      * returned mode to get the desired matrix; if we don't find it,
  126.      * we can return immediately, as _mesa_GetInteger() will have
  127.      * logged the necessary error already.
  128.      */
  129.     for (i = 0; i < sizeof(modes)/sizeof(modes[0]); i++) {
  130.         if (modes[i].currentMode == currentMode) {
  131.             desiredMatrix = modes[i].desiredMatrix;
  132.             break;
  133.         }
  134.     }
  135.     if (desiredMatrix == GL_FALSE) {
  136.         /* Early error means all values are invalid. */
  137.         return 0xffff;
  138.     }
  139.  
  140.     /* Now pull the matrix itself. */
  141.     _mesa_GetFloatv(desiredMatrix, matrix);
  142.  
  143.     rv = 0;
  144.     for (i = 0, bit = 1; i < 16; i++, bit<<=1) {
  145.         float normalizedFraction;
  146.         int exp;
  147.  
  148.         switch (fpclassify(matrix[i])) {
  149.             /* A "subnormal" or denormalized number is too small to be
  150.              * represented in normal format; but despite that it's a
  151.              * valid floating point number.  FP_ZERO and FP_NORMAL
  152.              * are both valid as well.  We should be fine treating
  153.              * these three cases as legitimate floating-point numbers.
  154.              */
  155.             case FP_SUBNORMAL:
  156.             case FP_NORMAL:
  157.             case FP_ZERO:
  158.                 normalizedFraction = (GLfloat)frexp(matrix[i], &exp);
  159.                 mantissa[i] = FLOAT_TO_FIXED(normalizedFraction);
  160.                 exponent[i] = (GLint) exp;
  161.                 break;
  162.  
  163.             /* If the entry is not-a-number or an infinity, then the
  164.              * matrix component is invalid.  The invalid flag for
  165.              * the component is already set; might as well set the
  166.              * other return values to known values.  We'll set
  167.              * distinct values so that a savvy end user could determine
  168.              * whether the matrix component was a NaN or an infinity,
  169.              * but this is more useful for debugging than anything else
  170.              * since the standard doesn't specify any such magic
  171.              * values to return.
  172.              */
  173.             case FP_NAN:
  174.                 mantissa[i] = INT_TO_FIXED(0);
  175.                 exponent[i] = (GLint) 0;
  176.                 rv |= bit;
  177.                 break;
  178.  
  179.             case FP_INFINITE:
  180.                 /* Return +/- 1 based on whether it's a positive or
  181.                  * negative infinity.
  182.                  */
  183.                 if (matrix[i] > 0) {
  184.                     mantissa[i] = INT_TO_FIXED(1);
  185.                 }
  186.                 else {
  187.                     mantissa[i] = -INT_TO_FIXED(1);
  188.                 }
  189.                 exponent[i] = (GLint) 0;
  190.                 rv |= bit;
  191.                 break;
  192.  
  193.             /* We should never get here; but here's a catching case
  194.              * in case fpclassify() is returnings something unexpected.
  195.              */
  196.             default:
  197.                 mantissa[i] = INT_TO_FIXED(2);
  198.                 exponent[i] = (GLint) 0;
  199.                 rv |= bit;
  200.                 break;
  201.         }
  202.  
  203.     } /* for each component */
  204.  
  205.     /* All done */
  206.     return rv;
  207. }
  208.