1 /**************************************************************************
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
6 **************************************************************************/
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
18 #include "GLES/glext.h"
22 * This is from the GL_OES_query_matrix extension specification:
24 * GLbitfield glQueryMatrixxOES( GLfixed mantissa[16],
25 * GLint exponent[16] )
26 * mantissa[16] contains the contents of the current matrix in GLfixed
27 * format. exponent[16] contains the unbiased exponents applied to the
28 * matrix components, so that the internal representation of component i
29 * is close to mantissa[i] * 2^exponent[i]. The function returns a status
30 * word which is zero if all the components are valid. If
31 * status & (1<<i) != 0, the component i is invalid (e.g., NaN, Inf).
32 * The implementations are not required to keep track of overflows. In
33 * that case, the invalid bits are never set.
36 #define INT_TO_FIXED(x) ((GLfixed) ((x) << 16))
37 #define FLOAT_TO_FIXED(x) ((GLfixed) ((x) * 65536.0))
40 /* Oddly, the fpclassify() function doesn't exist in such a form
41 * on MSVC. This is an implementation using slightly different
42 * lower-level Windows functions.
46 enum {FP_NAN
, FP_INFINITE
, FP_ZERO
, FP_SUBNORMAL
, FP_NORMAL
}
50 case _FPCLASS_SNAN
: /* signaling NaN */
51 case _FPCLASS_QNAN
: /* quiet NaN */
53 case _FPCLASS_NINF
: /* negative infinity */
54 case _FPCLASS_PINF
: /* positive infinity */
56 case _FPCLASS_NN
: /* negative normal */
57 case _FPCLASS_PN
: /* positive normal */
59 case _FPCLASS_ND
: /* negative denormalized */
60 case _FPCLASS_PD
: /* positive denormalized */
62 case _FPCLASS_NZ
: /* negative zero */
63 case _FPCLASS_PZ
: /* positive zero */
66 /* Should never get here; but if we do, this will guarantee
67 * that the pattern is not treated like a number.
73 #elif defined(__APPLE__) || defined(__CYGWIN__) || defined(__FreeBSD__) || \
74 defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \
75 (defined(__sun) && defined(__C99FEATURES__)) || defined(__MINGW32__) || \
76 (defined(__sun) && defined(__GNUC__))
78 /* fpclassify is available. */
80 #elif !defined(_XOPEN_SOURCE) || _XOPEN_SOURCE < 600
82 enum {FP_NAN
, FP_INFINITE
, FP_ZERO
, FP_SUBNORMAL
, FP_NORMAL
}
85 /* XXX do something better someday */
91 extern GLbitfield GL_APIENTRY
_es_QueryMatrixxOES(GLfixed mantissa
[16], GLint exponent
[16]);
93 /* The Mesa functions we'll need */
94 extern void GL_APIENTRY
_mesa_GetIntegerv(GLenum pname
, GLint
*params
);
95 extern void GL_APIENTRY
_mesa_GetFloatv(GLenum pname
, GLfloat
*params
);
97 GLbitfield GL_APIENTRY
_es_QueryMatrixxOES(GLfixed mantissa
[16], GLint exponent
[16])
101 GLenum currentMode
= GL_FALSE
;
102 GLenum desiredMatrix
= GL_FALSE
;
103 /* The bitfield returns 1 for each component that is invalid (i.e.
104 * NaN or Inf). In case of error, everything is invalid.
107 register unsigned int i
;
110 /* This data structure defines the mapping between the current matrix
111 * mode and the desired matrix identifier.
115 GLenum desiredMatrix
;
117 {GL_MODELVIEW
, GL_MODELVIEW_MATRIX
},
118 {GL_PROJECTION
, GL_PROJECTION_MATRIX
},
119 {GL_TEXTURE
, GL_TEXTURE_MATRIX
},
122 /* Call Mesa to get the current matrix in floating-point form. First,
123 * we have to figure out what the current matrix mode is.
125 _mesa_GetIntegerv(GL_MATRIX_MODE
, &tmp
);
126 currentMode
= (GLenum
) tmp
;
128 /* The mode is either GL_FALSE, if for some reason we failed to query
129 * the mode, or a given mode from the above table. Search for the
130 * returned mode to get the desired matrix; if we don't find it,
131 * we can return immediately, as _mesa_GetInteger() will have
132 * logged the necessary error already.
134 for (i
= 0; i
< sizeof(modes
)/sizeof(modes
[0]); i
++) {
135 if (modes
[i
].currentMode
== currentMode
) {
136 desiredMatrix
= modes
[i
].desiredMatrix
;
140 if (desiredMatrix
== GL_FALSE
) {
141 /* Early error means all values are invalid. */
145 /* Now pull the matrix itself. */
146 _mesa_GetFloatv(desiredMatrix
, matrix
);
149 for (i
= 0, bit
= 1; i
< 16; i
++, bit
<<=1) {
150 float normalizedFraction
;
153 switch (fpclassify(matrix
[i
])) {
154 /* A "subnormal" or denormalized number is too small to be
155 * represented in normal format; but despite that it's a
156 * valid floating point number. FP_ZERO and FP_NORMAL
157 * are both valid as well. We should be fine treating
158 * these three cases as legitimate floating-point numbers.
163 normalizedFraction
= (GLfloat
)frexp(matrix
[i
], &exp
);
164 mantissa
[i
] = FLOAT_TO_FIXED(normalizedFraction
);
165 exponent
[i
] = (GLint
) exp
;
168 /* If the entry is not-a-number or an infinity, then the
169 * matrix component is invalid. The invalid flag for
170 * the component is already set; might as well set the
171 * other return values to known values. We'll set
172 * distinct values so that a savvy end user could determine
173 * whether the matrix component was a NaN or an infinity,
174 * but this is more useful for debugging than anything else
175 * since the standard doesn't specify any such magic
179 mantissa
[i
] = INT_TO_FIXED(0);
180 exponent
[i
] = (GLint
) 0;
185 /* Return +/- 1 based on whether it's a positive or
189 mantissa
[i
] = INT_TO_FIXED(1);
192 mantissa
[i
] = -INT_TO_FIXED(1);
194 exponent
[i
] = (GLint
) 0;
198 /* We should never get here; but here's a catching case
199 * in case fpclassify() is returnings something unexpected.
202 mantissa
[i
] = INT_TO_FIXED(2);
203 exponent
[i
] = (GLint
) 0;
208 } /* for each component */