Subversion Repositories Kolibri OS

Rev

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
}