Subversion Repositories Kolibri OS

Rev

Rev 4358 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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