Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1901 | serge | 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 |
||
16 | #include |
||
17 | #include "GLES/gl.h" |
||
18 | #include "GLES/glext.h" |
||
19 | |||
20 | |||
21 | /** |
||
22 | * This is from the GL_OES_query_matrix extension specification: |
||
23 | * |
||
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< |
||
32 | * The implementations are not required to keep track of overflows. In |
||
33 | * that case, the invalid bits are never set. |
||
34 | */ |
||
35 | |||
36 | #define INT_TO_FIXED(x) ((GLfixed) ((x) << 16)) |
||
37 | #define FLOAT_TO_FIXED(x) ((GLfixed) ((x) * 65536.0)) |
||
38 | |||
39 | #if defined(_MSC_VER) |
||
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. |
||
43 | */ |
||
44 | #include |
||
45 | |||
46 | enum {FP_NAN, FP_INFINITE, FP_ZERO, FP_SUBNORMAL, FP_NORMAL} |
||
47 | fpclassify(double x) |
||
48 | { |
||
49 | switch(_fpclass(x)) { |
||
50 | case _FPCLASS_SNAN: /* signaling NaN */ |
||
51 | case _FPCLASS_QNAN: /* quiet NaN */ |
||
52 | return FP_NAN; |
||
53 | case _FPCLASS_NINF: /* negative infinity */ |
||
54 | case _FPCLASS_PINF: /* positive infinity */ |
||
55 | return FP_INFINITE; |
||
56 | case _FPCLASS_NN: /* negative normal */ |
||
57 | case _FPCLASS_PN: /* positive normal */ |
||
58 | return FP_NORMAL; |
||
59 | case _FPCLASS_ND: /* negative denormalized */ |
||
60 | case _FPCLASS_PD: /* positive denormalized */ |
||
61 | return FP_SUBNORMAL; |
||
62 | case _FPCLASS_NZ: /* negative zero */ |
||
63 | case _FPCLASS_PZ: /* positive zero */ |
||
64 | return FP_ZERO; |
||
65 | default: |
||
66 | /* Should never get here; but if we do, this will guarantee |
||
67 | * that the pattern is not treated like a number. |
||
68 | */ |
||
69 | return FP_NAN; |
||
70 | } |
||
71 | } |
||
72 | |||
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__)) |
||
77 | |||
78 | /* fpclassify is available. */ |
||
79 | |||
80 | #elif !defined(_XOPEN_SOURCE) || _XOPEN_SOURCE < 600 |
||
81 | |||
82 | enum {FP_NAN, FP_INFINITE, FP_ZERO, FP_SUBNORMAL, FP_NORMAL} |
||
83 | fpclassify(double x) |
||
84 | { |
||
85 | /* XXX do something better someday */ |
||
86 | return FP_NORMAL; |
||
87 | } |
||
88 | |||
89 | #endif |
||
90 | |||
91 | extern GLbitfield GL_APIENTRY _es_QueryMatrixxOES(GLfixed mantissa[16], GLint exponent[16]); |
||
92 | |||
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); |
||
96 | |||
97 | GLbitfield GL_APIENTRY _es_QueryMatrixxOES(GLfixed mantissa[16], GLint exponent[16]) |
||
98 | { |
||
99 | GLfloat matrix[16]; |
||
100 | GLint tmp; |
||
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. |
||
105 | */ |
||
106 | GLbitfield rv; |
||
107 | register unsigned int i; |
||
108 | unsigned int bit; |
||
109 | |||
110 | /* This data structure defines the mapping between the current matrix |
||
111 | * mode and the desired matrix identifier. |
||
112 | */ |
||
113 | static struct { |
||
114 | GLenum currentMode; |
||
115 | GLenum desiredMatrix; |
||
116 | } modes[] = { |
||
117 | {GL_MODELVIEW, GL_MODELVIEW_MATRIX}, |
||
118 | {GL_PROJECTION, GL_PROJECTION_MATRIX}, |
||
119 | {GL_TEXTURE, GL_TEXTURE_MATRIX}, |
||
120 | }; |
||
121 | |||
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. |
||
124 | */ |
||
125 | _mesa_GetIntegerv(GL_MATRIX_MODE, &tmp); |
||
126 | currentMode = (GLenum) tmp; |
||
127 | |||
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. |
||
133 | */ |
||
134 | for (i = 0; i < sizeof(modes)/sizeof(modes[0]); i++) { |
||
135 | if (modes[i].currentMode == currentMode) { |
||
136 | desiredMatrix = modes[i].desiredMatrix; |
||
137 | break; |
||
138 | } |
||
139 | } |
||
140 | if (desiredMatrix == GL_FALSE) { |
||
141 | /* Early error means all values are invalid. */ |
||
142 | return 0xffff; |
||
143 | } |
||
144 | |||
145 | /* Now pull the matrix itself. */ |
||
146 | _mesa_GetFloatv(desiredMatrix, matrix); |
||
147 | |||
148 | rv = 0; |
||
149 | for (i = 0, bit = 1; i < 16; i++, bit<<=1) { |
||
150 | float normalizedFraction; |
||
151 | int exp; |
||
152 | |||
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. |
||
159 | */ |
||
160 | case FP_SUBNORMAL: |
||
161 | case FP_NORMAL: |
||
162 | case FP_ZERO: |
||
163 | normalizedFraction = (GLfloat)frexp(matrix[i], &exp); |
||
164 | mantissa[i] = FLOAT_TO_FIXED(normalizedFraction); |
||
165 | exponent[i] = (GLint) exp; |
||
166 | break; |
||
167 | |||
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 |
||
176 | * values to return. |
||
177 | */ |
||
178 | case FP_NAN: |
||
179 | mantissa[i] = INT_TO_FIXED(0); |
||
180 | exponent[i] = (GLint) 0; |
||
181 | rv |= bit; |
||
182 | break; |
||
183 | |||
184 | case FP_INFINITE: |
||
185 | /* Return +/- 1 based on whether it's a positive or |
||
186 | * negative infinity. |
||
187 | */ |
||
188 | if (matrix[i] > 0) { |
||
189 | mantissa[i] = INT_TO_FIXED(1); |
||
190 | } |
||
191 | else { |
||
192 | mantissa[i] = -INT_TO_FIXED(1); |
||
193 | } |
||
194 | exponent[i] = (GLint) 0; |
||
195 | rv |= bit; |
||
196 | break; |
||
197 | |||
198 | /* We should never get here; but here's a catching case |
||
199 | * in case fpclassify() is returnings something unexpected. |
||
200 | */ |
||
201 | default: |
||
202 | mantissa[i] = INT_TO_FIXED(2); |
||
203 | exponent[i] = (GLint) 0; |
||
204 | rv |= bit; |
||
205 | break; |
||
206 | } |
||
207 | |||
208 | } /* for each component */ |
||
209 | |||
210 | /* All done */ |
||
211 | return rv; |
||
212 | }=1)><=1)>>>>><> |