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