Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5564 | serge | 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 |
||
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< |
||
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 | }=1)><=1)>>>><> |