1848b8605Smrg/************************************************************************** 2848b8605Smrg * 3848b8605Smrg * Copyright 2008 VMware, Inc. 4848b8605Smrg * All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg **************************************************************************/ 7848b8605Smrg 8848b8605Smrg 9848b8605Smrg/** 10848b8605Smrg * Code to implement GL_OES_query_matrix. See the spec at: 11848b8605Smrg * http://www.khronos.org/registry/gles/extensions/OES/OES_query_matrix.txt 12848b8605Smrg */ 13848b8605Smrg 14848b8605Smrg 15848b8605Smrg#include <stdlib.h> 16b8e80941Smrg#include "c99_math.h" 17848b8605Smrg#include "glheader.h" 18848b8605Smrg#include "querymatrix.h" 19848b8605Smrg#include "main/get.h" 20b8e80941Smrg#include "util/macros.h" 21848b8605Smrg 22848b8605Smrg 23848b8605Smrg/** 24848b8605Smrg * This is from the GL_OES_query_matrix extension specification: 25848b8605Smrg * 26848b8605Smrg * GLbitfield glQueryMatrixxOES( GLfixed mantissa[16], 27848b8605Smrg * GLint exponent[16] ) 28848b8605Smrg * mantissa[16] contains the contents of the current matrix in GLfixed 29848b8605Smrg * format. exponent[16] contains the unbiased exponents applied to the 30848b8605Smrg * matrix components, so that the internal representation of component i 31848b8605Smrg * is close to mantissa[i] * 2^exponent[i]. The function returns a status 32848b8605Smrg * word which is zero if all the components are valid. If 33848b8605Smrg * status & (1<<i) != 0, the component i is invalid (e.g., NaN, Inf). 34848b8605Smrg * The implementations are not required to keep track of overflows. In 35848b8605Smrg * that case, the invalid bits are never set. 36848b8605Smrg */ 37848b8605Smrg 38848b8605Smrg#define INT_TO_FIXED(x) ((GLfixed) ((x) << 16)) 39848b8605Smrg#define FLOAT_TO_FIXED(x) ((GLfixed) ((x) * 65536.0)) 40848b8605Smrg 41848b8605Smrg 42b8e80941SmrgGLbitfield GLAPIENTRY 43b8e80941Smrg_mesa_QueryMatrixxOES(GLfixed mantissa[16], GLint exponent[16]) 44848b8605Smrg{ 45b8e80941Smrg GLfloat matrix[16]; 46b8e80941Smrg GLint tmp; 47b8e80941Smrg GLenum currentMode = GL_FALSE; 48b8e80941Smrg GLenum desiredMatrix = GL_FALSE; 49b8e80941Smrg /* The bitfield returns 1 for each component that is invalid (i.e. 50b8e80941Smrg * NaN or Inf). In case of error, everything is invalid. 51b8e80941Smrg */ 52b8e80941Smrg GLbitfield rv; 53b8e80941Smrg unsigned i, bit; 54b8e80941Smrg 55b8e80941Smrg /* This data structure defines the mapping between the current matrix 56b8e80941Smrg * mode and the desired matrix identifier. 57b8e80941Smrg */ 58b8e80941Smrg static const struct { 59b8e80941Smrg GLenum currentMode; 60b8e80941Smrg GLenum desiredMatrix; 61b8e80941Smrg } modes[] = { 62b8e80941Smrg {GL_MODELVIEW, GL_MODELVIEW_MATRIX}, 63b8e80941Smrg {GL_PROJECTION, GL_PROJECTION_MATRIX}, 64b8e80941Smrg {GL_TEXTURE, GL_TEXTURE_MATRIX}, 65b8e80941Smrg }; 66b8e80941Smrg 67b8e80941Smrg /* Call Mesa to get the current matrix in floating-point form. First, 68b8e80941Smrg * we have to figure out what the current matrix mode is. 69b8e80941Smrg */ 70b8e80941Smrg _mesa_GetIntegerv(GL_MATRIX_MODE, &tmp); 71b8e80941Smrg currentMode = (GLenum) tmp; 72b8e80941Smrg 73b8e80941Smrg /* The mode is either GL_FALSE, if for some reason we failed to query 74b8e80941Smrg * the mode, or a given mode from the above table. Search for the 75b8e80941Smrg * returned mode to get the desired matrix; if we don't find it, 76b8e80941Smrg * we can return immediately, as _mesa_GetInteger() will have 77b8e80941Smrg * logged the necessary error already. 78b8e80941Smrg */ 79b8e80941Smrg for (i = 0; i < ARRAY_SIZE(modes); i++) { 80b8e80941Smrg if (modes[i].currentMode == currentMode) { 81b8e80941Smrg desiredMatrix = modes[i].desiredMatrix; 82b8e80941Smrg break; 83b8e80941Smrg } 84b8e80941Smrg } 85b8e80941Smrg if (desiredMatrix == GL_FALSE) { 86b8e80941Smrg /* Early error means all values are invalid. */ 87b8e80941Smrg return 0xffff; 88b8e80941Smrg } 89b8e80941Smrg 90b8e80941Smrg /* Now pull the matrix itself. */ 91b8e80941Smrg _mesa_GetFloatv(desiredMatrix, matrix); 92b8e80941Smrg 93b8e80941Smrg rv = 0; 94b8e80941Smrg for (i = 0, bit = 1; i < 16; i++, bit<<=1) { 95b8e80941Smrg float normalizedFraction; 96b8e80941Smrg int exp; 97b8e80941Smrg 98b8e80941Smrg switch (fpclassify(matrix[i])) { 99b8e80941Smrg case FP_SUBNORMAL: 100b8e80941Smrg case FP_NORMAL: 101b8e80941Smrg case FP_ZERO: 102b8e80941Smrg /* A "subnormal" or denormalized number is too small to be 103b8e80941Smrg * represented in normal format; but despite that it's a 104b8e80941Smrg * valid floating point number. FP_ZERO and FP_NORMAL 105b8e80941Smrg * are both valid as well. We should be fine treating 106b8e80941Smrg * these three cases as legitimate floating-point numbers. 107b8e80941Smrg */ 108b8e80941Smrg normalizedFraction = (GLfloat)frexp(matrix[i], &exp); 109b8e80941Smrg mantissa[i] = FLOAT_TO_FIXED(normalizedFraction); 110b8e80941Smrg exponent[i] = (GLint) exp; 111b8e80941Smrg break; 112b8e80941Smrg 113b8e80941Smrg case FP_NAN: 114b8e80941Smrg /* If the entry is not-a-number or an infinity, then the 115b8e80941Smrg * matrix component is invalid. The invalid flag for 116b8e80941Smrg * the component is already set; might as well set the 117b8e80941Smrg * other return values to known values. We'll set 118b8e80941Smrg * distinct values so that a savvy end user could determine 119b8e80941Smrg * whether the matrix component was a NaN or an infinity, 120b8e80941Smrg * but this is more useful for debugging than anything else 121b8e80941Smrg * since the standard doesn't specify any such magic 122b8e80941Smrg * values to return. 123b8e80941Smrg */ 124b8e80941Smrg mantissa[i] = INT_TO_FIXED(0); 125b8e80941Smrg exponent[i] = (GLint) 0; 126b8e80941Smrg rv |= bit; 127b8e80941Smrg break; 128b8e80941Smrg 129b8e80941Smrg case FP_INFINITE: 130b8e80941Smrg /* Return +/- 1 based on whether it's a positive or 131b8e80941Smrg * negative infinity. 132b8e80941Smrg */ 133b8e80941Smrg if (matrix[i] > 0) { 134b8e80941Smrg mantissa[i] = INT_TO_FIXED(1); 135b8e80941Smrg } 136b8e80941Smrg else { 137b8e80941Smrg mantissa[i] = -INT_TO_FIXED(1); 138b8e80941Smrg } 139b8e80941Smrg exponent[i] = (GLint) 0; 140b8e80941Smrg rv |= bit; 141b8e80941Smrg break; 142b8e80941Smrg 143b8e80941Smrg default: 144b8e80941Smrg /* We should never get here; but here's a catching case 145b8e80941Smrg * in case fpclassify() is returnings something unexpected. 146b8e80941Smrg */ 147b8e80941Smrg mantissa[i] = INT_TO_FIXED(2); 148b8e80941Smrg exponent[i] = (GLint) 0; 149b8e80941Smrg rv |= bit; 150b8e80941Smrg break; 151b8e80941Smrg } 152b8e80941Smrg 153b8e80941Smrg } /* for each component */ 154b8e80941Smrg 155b8e80941Smrg /* All done */ 156b8e80941Smrg return rv; 157848b8605Smrg} 158