Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1901 serge 1
/**************************************************************************
2
 *
3
 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
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 
17
#include "GLES/gl.h"
18
#include "GLES/glext.h"
19
 
20
 
21
/**
22
 * This is from the GL_OES_query_matrix extension specification:
23
 *
24
 *  GLbitfield glQueryMatrixxOES( GLfixed mantissa[16],
25
 *                                GLint   exponent[16] )
26
 *  mantissa[16] contains the contents of the current matrix in GLfixed
27
 *  format.  exponent[16] contains the unbiased exponents applied to the
28
 *  matrix components, so that the internal representation of component i
29
 *  is close to mantissa[i] * 2^exponent[i].  The function returns a status
30
 *  word which is zero if all the components are valid. If
31
 *  status & (1<
32
 *  The implementations are not required to keep track of overflows.  In
33
 *  that case, the invalid bits are never set.
34
 */
35
 
36
#define INT_TO_FIXED(x) ((GLfixed) ((x) << 16))
37
#define FLOAT_TO_FIXED(x) ((GLfixed) ((x) * 65536.0))
38
 
39
#if defined(_MSC_VER)
40
/* Oddly, the fpclassify() function doesn't exist in such a form
41
 * on MSVC.  This is an implementation using slightly different
42
 * lower-level Windows functions.
43
 */
44
#include 
45
 
46
enum {FP_NAN, FP_INFINITE, FP_ZERO, FP_SUBNORMAL, FP_NORMAL}
47
fpclassify(double x)
48
{
49
    switch(_fpclass(x)) {
50
        case _FPCLASS_SNAN: /* signaling NaN */
51
        case _FPCLASS_QNAN: /* quiet NaN */
52
            return FP_NAN;
53
        case _FPCLASS_NINF: /* negative infinity */
54
        case _FPCLASS_PINF: /* positive infinity */
55
            return FP_INFINITE;
56
        case _FPCLASS_NN:   /* negative normal */
57
        case _FPCLASS_PN:   /* positive normal */
58
            return FP_NORMAL;
59
        case _FPCLASS_ND:   /* negative denormalized */
60
        case _FPCLASS_PD:   /* positive denormalized */
61
            return FP_SUBNORMAL;
62
        case _FPCLASS_NZ:   /* negative zero */
63
        case _FPCLASS_PZ:   /* positive zero */
64
            return FP_ZERO;
65
        default:
66
            /* Should never get here; but if we do, this will guarantee
67
             * that the pattern is not treated like a number.
68
             */
69
            return FP_NAN;
70
    }
71
}
72
 
73
#elif defined(__APPLE__) || defined(__CYGWIN__) || defined(__FreeBSD__) || \
74
     defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \
75
     (defined(__sun) && defined(__C99FEATURES__)) || defined(__MINGW32__) || \
76
     (defined(__sun) && defined(__GNUC__))
77
 
78
/* fpclassify is available. */
79
 
80
#elif !defined(_XOPEN_SOURCE) || _XOPEN_SOURCE < 600
81
 
82
enum {FP_NAN, FP_INFINITE, FP_ZERO, FP_SUBNORMAL, FP_NORMAL}
83
fpclassify(double x)
84
{
85
   /* XXX do something better someday */
86
   return FP_NORMAL;
87
}
88
 
89
#endif
90
 
91
extern GLbitfield GL_APIENTRY _es_QueryMatrixxOES(GLfixed mantissa[16], GLint exponent[16]);
92
 
93
/* The Mesa functions we'll need */
94
extern void GL_APIENTRY _mesa_GetIntegerv(GLenum pname, GLint *params);
95
extern void GL_APIENTRY _mesa_GetFloatv(GLenum pname, GLfloat *params);
96
 
97
GLbitfield GL_APIENTRY _es_QueryMatrixxOES(GLfixed mantissa[16], GLint exponent[16])
98
{
99
    GLfloat matrix[16];
100
    GLint tmp;
101
    GLenum currentMode = GL_FALSE;
102
    GLenum desiredMatrix = GL_FALSE;
103
    /* The bitfield returns 1 for each component that is invalid (i.e.
104
     * NaN or Inf).  In case of error, everything is invalid.
105
     */
106
    GLbitfield rv;
107
    register unsigned int i;
108
    unsigned int bit;
109
 
110
    /* This data structure defines the mapping between the current matrix
111
     * mode and the desired matrix identifier.
112
     */
113
    static struct {
114
        GLenum currentMode;
115
        GLenum desiredMatrix;
116
    } modes[] = {
117
        {GL_MODELVIEW, GL_MODELVIEW_MATRIX},
118
        {GL_PROJECTION, GL_PROJECTION_MATRIX},
119
        {GL_TEXTURE, GL_TEXTURE_MATRIX},
120
    };
121
 
122
    /* Call Mesa to get the current matrix in floating-point form.  First,
123
     * we have to figure out what the current matrix mode is.
124
     */
125
    _mesa_GetIntegerv(GL_MATRIX_MODE, &tmp);
126
    currentMode = (GLenum) tmp;
127
 
128
    /* The mode is either GL_FALSE, if for some reason we failed to query
129
     * the mode, or a given mode from the above table.  Search for the
130
     * returned mode to get the desired matrix; if we don't find it,
131
     * we can return immediately, as _mesa_GetInteger() will have
132
     * logged the necessary error already.
133
     */
134
    for (i = 0; i < sizeof(modes)/sizeof(modes[0]); i++) {
135
        if (modes[i].currentMode == currentMode) {
136
            desiredMatrix = modes[i].desiredMatrix;
137
            break;
138
        }
139
    }
140
    if (desiredMatrix == GL_FALSE) {
141
        /* Early error means all values are invalid. */
142
        return 0xffff;
143
    }
144
 
145
    /* Now pull the matrix itself. */
146
    _mesa_GetFloatv(desiredMatrix, matrix);
147
 
148
    rv = 0;
149
    for (i = 0, bit = 1; i < 16; i++, bit<<=1) {
150
        float normalizedFraction;
151
        int exp;
152
 
153
        switch (fpclassify(matrix[i])) {
154
            /* A "subnormal" or denormalized number is too small to be
155
             * represented in normal format; but despite that it's a
156
             * valid floating point number.  FP_ZERO and FP_NORMAL
157
             * are both valid as well.  We should be fine treating
158
             * these three cases as legitimate floating-point numbers.
159
             */
160
            case FP_SUBNORMAL:
161
            case FP_NORMAL:
162
            case FP_ZERO:
163
                normalizedFraction = (GLfloat)frexp(matrix[i], &exp);
164
                mantissa[i] = FLOAT_TO_FIXED(normalizedFraction);
165
                exponent[i] = (GLint) exp;
166
                break;
167
 
168
            /* If the entry is not-a-number or an infinity, then the
169
             * matrix component is invalid.  The invalid flag for
170
             * the component is already set; might as well set the
171
             * other return values to known values.  We'll set
172
             * distinct values so that a savvy end user could determine
173
             * whether the matrix component was a NaN or an infinity,
174
             * but this is more useful for debugging than anything else
175
             * since the standard doesn't specify any such magic
176
             * values to return.
177
             */
178
            case FP_NAN:
179
                mantissa[i] = INT_TO_FIXED(0);
180
                exponent[i] = (GLint) 0;
181
                rv |= bit;
182
                break;
183
 
184
            case FP_INFINITE:
185
                /* Return +/- 1 based on whether it's a positive or
186
                 * negative infinity.
187
                 */
188
                if (matrix[i] > 0) {
189
                    mantissa[i] = INT_TO_FIXED(1);
190
                }
191
                else {
192
                    mantissa[i] = -INT_TO_FIXED(1);
193
                }
194
                exponent[i] = (GLint) 0;
195
                rv |= bit;
196
                break;
197
 
198
            /* We should never get here; but here's a catching case
199
             * in case fpclassify() is returnings something unexpected.
200
             */
201
            default:
202
                mantissa[i] = INT_TO_FIXED(2);
203
                exponent[i] = (GLint) 0;
204
                rv |= bit;
205
                break;
206
        }
207
 
208
    } /* for each component */
209
 
210
    /* All done */
211
    return rv;
212
}