Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2008 VMware, Inc.
  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 "c99_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.  
  41. GLbitfield GLAPIENTRY
  42. _mesa_QueryMatrixxOES(GLfixed mantissa[16], GLint exponent[16])
  43. {
  44.    GLfloat matrix[16];
  45.    GLint tmp;
  46.    GLenum currentMode = GL_FALSE;
  47.    GLenum desiredMatrix = GL_FALSE;
  48.    /* The bitfield returns 1 for each component that is invalid (i.e.
  49.     * NaN or Inf).  In case of error, everything is invalid.
  50.     */
  51.    GLbitfield rv;
  52.    unsigned i, bit;
  53.  
  54.    /* This data structure defines the mapping between the current matrix
  55.     * mode and the desired matrix identifier.
  56.     */
  57.    static const struct {
  58.       GLenum currentMode;
  59.       GLenum desiredMatrix;
  60.    } modes[] = {
  61.       {GL_MODELVIEW, GL_MODELVIEW_MATRIX},
  62.       {GL_PROJECTION, GL_PROJECTION_MATRIX},
  63.       {GL_TEXTURE, GL_TEXTURE_MATRIX},
  64.    };
  65.  
  66.    /* Call Mesa to get the current matrix in floating-point form.  First,
  67.     * we have to figure out what the current matrix mode is.
  68.     */
  69.    _mesa_GetIntegerv(GL_MATRIX_MODE, &tmp);
  70.    currentMode = (GLenum) tmp;
  71.  
  72.    /* The mode is either GL_FALSE, if for some reason we failed to query
  73.     * the mode, or a given mode from the above table.  Search for the
  74.     * returned mode to get the desired matrix; if we don't find it,
  75.     * we can return immediately, as _mesa_GetInteger() will have
  76.     * logged the necessary error already.
  77.     */
  78.    for (i = 0; i < ARRAY_SIZE(modes); i++) {
  79.       if (modes[i].currentMode == currentMode) {
  80.          desiredMatrix = modes[i].desiredMatrix;
  81.          break;
  82.       }
  83.    }
  84.    if (desiredMatrix == GL_FALSE) {
  85.       /* Early error means all values are invalid. */
  86.       return 0xffff;
  87.    }
  88.  
  89.    /* Now pull the matrix itself. */
  90.    _mesa_GetFloatv(desiredMatrix, matrix);
  91.  
  92.    rv = 0;
  93.    for (i = 0, bit = 1; i < 16; i++, bit<<=1) {
  94.       float normalizedFraction;
  95.       int exp;
  96.  
  97.       switch (fpclassify(matrix[i])) {
  98.       case FP_SUBNORMAL:
  99.       case FP_NORMAL:
  100.       case FP_ZERO:
  101.          /* A "subnormal" or denormalized number is too small to be
  102.           * represented in normal format; but despite that it's a
  103.           * valid floating point number.  FP_ZERO and FP_NORMAL
  104.           * are both valid as well.  We should be fine treating
  105.           * these three cases as legitimate floating-point numbers.
  106.           */
  107.          normalizedFraction = (GLfloat)frexp(matrix[i], &exp);
  108.          mantissa[i] = FLOAT_TO_FIXED(normalizedFraction);
  109.          exponent[i] = (GLint) exp;
  110.          break;
  111.  
  112.       case FP_NAN:
  113.          /* If the entry is not-a-number or an infinity, then the
  114.           * matrix component is invalid.  The invalid flag for
  115.           * the component is already set; might as well set the
  116.           * other return values to known values.  We'll set
  117.           * distinct values so that a savvy end user could determine
  118.           * whether the matrix component was a NaN or an infinity,
  119.           * but this is more useful for debugging than anything else
  120.           * since the standard doesn't specify any such magic
  121.           * values to return.
  122.           */
  123.          mantissa[i] = INT_TO_FIXED(0);
  124.          exponent[i] = (GLint) 0;
  125.          rv |= bit;
  126.          break;
  127.  
  128.       case FP_INFINITE:
  129.          /* Return +/- 1 based on whether it's a positive or
  130.           * negative infinity.
  131.           */
  132.          if (matrix[i] > 0) {
  133.             mantissa[i] = INT_TO_FIXED(1);
  134.          }
  135.          else {
  136.             mantissa[i] = -INT_TO_FIXED(1);
  137.          }
  138.          exponent[i] = (GLint) 0;
  139.          rv |= bit;
  140.          break;
  141.  
  142.       default:
  143.          /* We should never get here; but here's a catching case
  144.           * in case fpclassify() is returnings something unexpected.
  145.           */
  146.          mantissa[i] = INT_TO_FIXED(2);
  147.          exponent[i] = (GLint) 0;
  148.          rv |= bit;
  149.          break;
  150.       }
  151.  
  152.    } /* for each component */
  153.  
  154.    /* All done */
  155.    return rv;
  156. }
  157.