aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa/main/querymatrix.c
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2010-11-29 22:05:53 +0000
committermarha <marha@users.sourceforge.net>2010-11-29 22:05:53 +0000
commitfed109d6a33c0871291d1bb2f3f6b7a3d1a3e9d7 (patch)
treefa1ba494685a71e28a096990a8707680c7cb378b /mesalib/src/mesa/main/querymatrix.c
parentae340911c1ba1f98b418bd8f1a487fa4d79491b0 (diff)
parent6fda93be42ace9eeab0e82ceebb6798961c9105c (diff)
downloadvcxsrv-fed109d6a33c0871291d1bb2f3f6b7a3d1a3e9d7.tar.gz
vcxsrv-fed109d6a33c0871291d1bb2f3f6b7a3d1a3e9d7.tar.bz2
vcxsrv-fed109d6a33c0871291d1bb2f3f6b7a3d1a3e9d7.zip
svn merge ^/branches/released .
Diffstat (limited to 'mesalib/src/mesa/main/querymatrix.c')
-rw-r--r--mesalib/src/mesa/main/querymatrix.c216
1 files changed, 216 insertions, 0 deletions
diff --git a/mesalib/src/mesa/main/querymatrix.c b/mesalib/src/mesa/main/querymatrix.c
new file mode 100644
index 000000000..36236eb9a
--- /dev/null
+++ b/mesalib/src/mesa/main/querymatrix.c
@@ -0,0 +1,216 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ **************************************************************************/
+
+
+/**
+ * Code to implement GL_OES_query_matrix. See the spec at:
+ * http://www.khronos.org/registry/gles/extensions/OES/OES_query_matrix.txt
+ */
+
+
+#include <stdlib.h>
+#include <math.h>
+#include "GLES/gl.h"
+#include "GLES/glext.h"
+
+
+/**
+ * This is from the GL_OES_query_matrix extension specification:
+ *
+ * GLbitfield glQueryMatrixxOES( GLfixed mantissa[16],
+ * GLint exponent[16] )
+ * mantissa[16] contains the contents of the current matrix in GLfixed
+ * format. exponent[16] contains the unbiased exponents applied to the
+ * matrix components, so that the internal representation of component i
+ * is close to mantissa[i] * 2^exponent[i]. The function returns a status
+ * word which is zero if all the components are valid. If
+ * status & (1<<i) != 0, the component i is invalid (e.g., NaN, Inf).
+ * The implementations are not required to keep track of overflows. In
+ * that case, the invalid bits are never set.
+ */
+
+#define INT_TO_FIXED(x) ((GLfixed) ((x) << 16))
+#define FLOAT_TO_FIXED(x) ((GLfixed) ((x) * 65536.0))
+
+#if defined(_MSC_VER)
+/* Oddly, the fpclassify() function doesn't exist in such a form
+ * on MSVC. This is an implementation using slightly different
+ * lower-level Windows functions.
+ */
+#include <float.h>
+
+enum {FP_NAN, FP_INFINITE, FP_ZERO, FP_SUBNORMAL, FP_NORMAL}
+fpclassify(double x)
+{
+ switch(_fpclass(x)) {
+ case _FPCLASS_SNAN: /* signaling NaN */
+ case _FPCLASS_QNAN: /* quiet NaN */
+ return FP_NAN;
+ case _FPCLASS_NINF: /* negative infinity */
+ case _FPCLASS_PINF: /* positive infinity */
+ return FP_INFINITE;
+ case _FPCLASS_NN: /* negative normal */
+ case _FPCLASS_PN: /* positive normal */
+ return FP_NORMAL;
+ case _FPCLASS_ND: /* negative denormalized */
+ case _FPCLASS_PD: /* positive denormalized */
+ return FP_SUBNORMAL;
+ case _FPCLASS_NZ: /* negative zero */
+ case _FPCLASS_PZ: /* positive zero */
+ return FP_ZERO;
+ default:
+ /* Should never get here; but if we do, this will guarantee
+ * that the pattern is not treated like a number.
+ */
+ return FP_NAN;
+ }
+}
+
+#elif defined(__APPLE__) || defined(__CYGWIN__) || defined(__FreeBSD__) || \
+ defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \
+ (defined(__sun) && defined(__C99FEATURES__)) || defined(__MINGW32__) || \
+ (defined(__sun) && defined(__GNUC__))
+
+/* fpclassify is available. */
+
+#elif !defined(_XOPEN_SOURCE) || _XOPEN_SOURCE < 600
+
+enum {FP_NAN, FP_INFINITE, FP_ZERO, FP_SUBNORMAL, FP_NORMAL}
+fpclassify(double x)
+{
+ /* XXX do something better someday */
+ return FP_NORMAL;
+}
+
+#endif
+
+extern GLbitfield GL_APIENTRY _es_QueryMatrixxOES(GLfixed mantissa[16], GLint exponent[16]);
+
+/* The Mesa functions we'll need */
+extern void GL_APIENTRY _mesa_GetIntegerv(GLenum pname, GLint *params);
+extern void GL_APIENTRY _mesa_GetFloatv(GLenum pname, GLfloat *params);
+
+GLbitfield GL_APIENTRY _es_QueryMatrixxOES(GLfixed mantissa[16], GLint exponent[16])
+{
+ GLfloat matrix[16];
+ GLint tmp;
+ GLenum currentMode = GL_FALSE;
+ GLenum desiredMatrix = GL_FALSE;
+ /* The bitfield returns 1 for each component that is invalid (i.e.
+ * NaN or Inf). In case of error, everything is invalid.
+ */
+ GLbitfield rv;
+ register unsigned int i;
+ unsigned int bit;
+
+ /* This data structure defines the mapping between the current matrix
+ * mode and the desired matrix identifier.
+ */
+ static struct {
+ GLenum currentMode;
+ GLenum desiredMatrix;
+ } modes[] = {
+ {GL_MODELVIEW, GL_MODELVIEW_MATRIX},
+ {GL_PROJECTION, GL_PROJECTION_MATRIX},
+ {GL_TEXTURE, GL_TEXTURE_MATRIX},
+#if 0
+ /* this doesn't exist in GLES */
+ {GL_COLOR, GL_COLOR_MATRIX},
+#endif
+ };
+
+ /* Call Mesa to get the current matrix in floating-point form. First,
+ * we have to figure out what the current matrix mode is.
+ */
+ _mesa_GetIntegerv(GL_MATRIX_MODE, &tmp);
+ currentMode = (GLenum) tmp;
+
+ /* The mode is either GL_FALSE, if for some reason we failed to query
+ * the mode, or a given mode from the above table. Search for the
+ * returned mode to get the desired matrix; if we don't find it,
+ * we can return immediately, as _mesa_GetInteger() will have
+ * logged the necessary error already.
+ */
+ for (i = 0; i < sizeof(modes)/sizeof(modes[0]); i++) {
+ if (modes[i].currentMode == currentMode) {
+ desiredMatrix = modes[i].desiredMatrix;
+ break;
+ }
+ }
+ if (desiredMatrix == GL_FALSE) {
+ /* Early error means all values are invalid. */
+ return 0xffff;
+ }
+
+ /* Now pull the matrix itself. */
+ _mesa_GetFloatv(desiredMatrix, matrix);
+
+ rv = 0;
+ for (i = 0, bit = 1; i < 16; i++, bit<<=1) {
+ float normalizedFraction;
+ int exp;
+
+ switch (fpclassify(matrix[i])) {
+ /* A "subnormal" or denormalized number is too small to be
+ * represented in normal format; but despite that it's a
+ * valid floating point number. FP_ZERO and FP_NORMAL
+ * are both valid as well. We should be fine treating
+ * these three cases as legitimate floating-point numbers.
+ */
+ case FP_SUBNORMAL:
+ case FP_NORMAL:
+ case FP_ZERO:
+ normalizedFraction = (GLfloat)frexp(matrix[i], &exp);
+ mantissa[i] = FLOAT_TO_FIXED(normalizedFraction);
+ exponent[i] = (GLint) exp;
+ break;
+
+ /* If the entry is not-a-number or an infinity, then the
+ * matrix component is invalid. The invalid flag for
+ * the component is already set; might as well set the
+ * other return values to known values. We'll set
+ * distinct values so that a savvy end user could determine
+ * whether the matrix component was a NaN or an infinity,
+ * but this is more useful for debugging than anything else
+ * since the standard doesn't specify any such magic
+ * values to return.
+ */
+ case FP_NAN:
+ mantissa[i] = INT_TO_FIXED(0);
+ exponent[i] = (GLint) 0;
+ rv |= bit;
+ break;
+
+ case FP_INFINITE:
+ /* Return +/- 1 based on whether it's a positive or
+ * negative infinity.
+ */
+ if (matrix[i] > 0) {
+ mantissa[i] = INT_TO_FIXED(1);
+ }
+ else {
+ mantissa[i] = -INT_TO_FIXED(1);
+ }
+ exponent[i] = (GLint) 0;
+ rv |= bit;
+ break;
+
+ /* We should never get here; but here's a catching case
+ * in case fpclassify() is returnings something unexpected.
+ */
+ default:
+ mantissa[i] = INT_TO_FIXED(2);
+ exponent[i] = (GLint) 0;
+ rv |= bit;
+ break;
+ }
+
+ } /* for each component */
+
+ /* All done */
+ return rv;
+}