1 /**************************************************************************
3 * Copyright 2008 VMware, Inc.
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 "querymatrix.h"
20 #include "util/macros.h"
24 * This is from the GL_OES_query_matrix extension specification:
26 * GLbitfield glQueryMatrixxOES( GLfixed mantissa[16],
27 * GLint exponent[16] )
28 * mantissa[16] contains the contents of the current matrix in GLfixed
29 * format. exponent[16] contains the unbiased exponents applied to the
30 * matrix components, so that the internal representation of component i
31 * is close to mantissa[i] * 2^exponent[i]. The function returns a status
32 * word which is zero if all the components are valid. If
33 * status & (1<<i) != 0, the component i is invalid (e.g., NaN, Inf).
34 * The implementations are not required to keep track of overflows. In
35 * that case, the invalid bits are never set.
38 #define INT_TO_FIXED(x) ((GLfixed) ((x) << 16))
39 #define FLOAT_TO_FIXED(x) ((GLfixed) ((x) * 65536.0))
43 _mesa_QueryMatrixxOES(GLfixed mantissa
[16], GLint exponent
[16])
47 GLenum currentMode
= GL_FALSE
;
48 GLenum desiredMatrix
= GL_FALSE
;
49 /* The bitfield returns 1 for each component that is invalid (i.e.
50 * NaN or Inf). In case of error, everything is invalid.
55 /* This data structure defines the mapping between the current matrix
56 * mode and the desired matrix identifier.
62 {GL_MODELVIEW
, GL_MODELVIEW_MATRIX
},
63 {GL_PROJECTION
, GL_PROJECTION_MATRIX
},
64 {GL_TEXTURE
, GL_TEXTURE_MATRIX
},
67 /* Call Mesa to get the current matrix in floating-point form. First,
68 * we have to figure out what the current matrix mode is.
70 _mesa_GetIntegerv(GL_MATRIX_MODE
, &tmp
);
71 currentMode
= (GLenum
) tmp
;
73 /* The mode is either GL_FALSE, if for some reason we failed to query
74 * the mode, or a given mode from the above table. Search for the
75 * returned mode to get the desired matrix; if we don't find it,
76 * we can return immediately, as _mesa_GetInteger() will have
77 * logged the necessary error already.
79 for (i
= 0; i
< ARRAY_SIZE(modes
); i
++) {
80 if (modes
[i
].currentMode
== currentMode
) {
81 desiredMatrix
= modes
[i
].desiredMatrix
;
85 if (desiredMatrix
== GL_FALSE
) {
86 /* Early error means all values are invalid. */
90 /* Now pull the matrix itself. */
91 _mesa_GetFloatv(desiredMatrix
, matrix
);
94 for (i
= 0, bit
= 1; i
< 16; i
++, bit
<<=1) {
95 float normalizedFraction
;
98 switch (fpclassify(matrix
[i
])) {
102 /* A "subnormal" or denormalized number is too small to be
103 * represented in normal format; but despite that it's a
104 * valid floating point number. FP_ZERO and FP_NORMAL
105 * are both valid as well. We should be fine treating
106 * these three cases as legitimate floating-point numbers.
108 normalizedFraction
= (GLfloat
)frexp(matrix
[i
], &exp
);
109 mantissa
[i
] = FLOAT_TO_FIXED(normalizedFraction
);
110 exponent
[i
] = (GLint
) exp
;
114 /* If the entry is not-a-number or an infinity, then the
115 * matrix component is invalid. The invalid flag for
116 * the component is already set; might as well set the
117 * other return values to known values. We'll set
118 * distinct values so that a savvy end user could determine
119 * whether the matrix component was a NaN or an infinity,
120 * but this is more useful for debugging than anything else
121 * since the standard doesn't specify any such magic
124 mantissa
[i
] = INT_TO_FIXED(0);
125 exponent
[i
] = (GLint
) 0;
130 /* Return +/- 1 based on whether it's a positive or
134 mantissa
[i
] = INT_TO_FIXED(1);
137 mantissa
[i
] = -INT_TO_FIXED(1);
139 exponent
[i
] = (GLint
) 0;
144 /* We should never get here; but here's a catching case
145 * in case fpclassify() is returnings something unexpected.
147 mantissa
[i
] = INT_TO_FIXED(2);
148 exponent
[i
] = (GLint
) 0;
153 } /* for each component */