Rev 4358 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | 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 "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< |
||
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) |
||
4401 | Serge | 41 | #if _MSC_VER < 1800 /* Not required on VS2013 and above. */ |
4358 | Serge | 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 |
||
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 | } |
||
4401 | Serge | 74 | #endif /* _MSC_VER < 1800 */ |
4358 | Serge | 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 | }=1)><=1)>>>>>>><> |