Subversion Repositories Kolibri OS

Rev

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