1 //
2 // Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // queryconversions.cpp: Implementation of state query cast conversions
8 
9 #include "libANGLE/queryconversions.h"
10 
11 #include <vector>
12 
13 #include "libANGLE/Context.h"
14 #include "common/utilities.h"
15 
16 namespace gl
17 {
18 
19 namespace
20 {
21 
ExpandFloatToInteger(GLfloat value)22 GLint64 ExpandFloatToInteger(GLfloat value)
23 {
24     return static_cast<GLint64>((static_cast<double>(0xFFFFFFFFULL) * value - 1.0) / 2.0);
25 }
26 
27 template <typename QueryT>
ClampToQueryRange(GLint64 value)28 QueryT ClampToQueryRange(GLint64 value)
29 {
30     const GLint64 min = static_cast<GLint64>(std::numeric_limits<QueryT>::min());
31     const GLint64 max = static_cast<GLint64>(std::numeric_limits<QueryT>::max());
32     return static_cast<QueryT>(clamp(value, min, max));
33 }
34 
35 template <typename QueryT, typename NativeT>
36 QueryT CastStateValueToInt(GLenum pname, NativeT value)
37 {
38     GLenum queryType  = GLTypeToGLenum<QueryT>::value;
39     GLenum nativeType = GLTypeToGLenum<NativeT>::value;
40 
41     if (nativeType == GL_FLOAT)
42     {
43         // RGBA color values and DepthRangeF values are converted to integer using Equation 2.4 from Table 4.5
44         if (pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
45         {
46             return ClampToQueryRange<QueryT>(ExpandFloatToInteger(static_cast<GLfloat>(value)));
47         }
48         else
49         {
50             return gl::iround<QueryT>(static_cast<GLfloat>(value));
51         }
52     }
53 
54     // Clamp 64-bit int values when casting to int
55     if (nativeType == GL_INT_64_ANGLEX && queryType == GL_INT)
56     {
57         GLint64 minIntValue = static_cast<GLint64>(std::numeric_limits<GLint>::min());
58         GLint64 maxIntValue = static_cast<GLint64>(std::numeric_limits<GLint>::max());
59         GLint64 clampedValue = std::max(std::min(static_cast<GLint64>(value), maxIntValue), minIntValue);
60         return static_cast<QueryT>(clampedValue);
61     }
62 
63     return static_cast<QueryT>(value);
64 }
65 
66 template <typename QueryT, typename NativeT>
67 QueryT CastStateValue(GLenum pname, NativeT value)
68 {
69     GLenum queryType = GLTypeToGLenum<QueryT>::value;
70 
71     switch (queryType)
72     {
73         case GL_INT:
74             return CastStateValueToInt<QueryT, NativeT>(pname, value);
75         case GL_INT_64_ANGLEX:
76             return CastStateValueToInt<QueryT, NativeT>(pname, value);
77         case GL_FLOAT:
78             return static_cast<QueryT>(value);
79         case GL_BOOL:
80             return static_cast<QueryT>(value == static_cast<NativeT>(0) ? GL_FALSE : GL_TRUE);
81         default:
82             UNREACHABLE();
83             return 0;
84     }
85 }
86 
87 }  // anonymous namespace
88 
89 template <typename QueryT>
CastStateValues(Context * context,GLenum nativeType,GLenum pname,unsigned int numParams,QueryT * outParams)90 void CastStateValues(Context *context, GLenum nativeType, GLenum pname,
91                      unsigned int numParams, QueryT *outParams)
92 {
93     if (nativeType == GL_INT)
94     {
95         std::vector<GLint> intParams(numParams, 0);
96         context->getIntegerv(pname, intParams.data());
97 
98         for (unsigned int i = 0; i < numParams; ++i)
99         {
100             outParams[i] = CastStateValue<QueryT>(pname, intParams[i]);
101         }
102     }
103     else if (nativeType == GL_BOOL)
104     {
105         std::vector<GLboolean> boolParams(numParams, GL_FALSE);
106         context->getBooleanv(pname, boolParams.data());
107 
108         for (unsigned int i = 0; i < numParams; ++i)
109         {
110             outParams[i] = (boolParams[i] == GL_FALSE ? static_cast<QueryT>(0) : static_cast<QueryT>(1));
111         }
112     }
113     else if (nativeType == GL_FLOAT)
114     {
115         std::vector<GLfloat> floatParams(numParams, 0.0f);
116         context->getFloatv(pname, floatParams.data());
117 
118         for (unsigned int i = 0; i < numParams; ++i)
119         {
120             outParams[i] = CastStateValue<QueryT>(pname, floatParams[i]);
121         }
122     }
123     else if (nativeType == GL_INT_64_ANGLEX)
124     {
125         std::vector<GLint64> int64Params(numParams, 0);
126         context->getInteger64v(pname, int64Params.data());
127 
128         for (unsigned int i = 0; i < numParams; ++i)
129         {
130             outParams[i] = CastStateValue<QueryT>(pname, int64Params[i]);
131         }
132     }
133     else UNREACHABLE();
134 }
135 
136 // Explicit template instantiation (how we export template functions in different files)
137 // The calls below will make CastStateValues successfully link with the GL state query types
138 // The GL state query API types are: bool, int, uint, float, int64
139 
140 template void CastStateValues<GLboolean>(Context *, GLenum, GLenum, unsigned int, GLboolean *);
141 template void CastStateValues<GLint>(Context *, GLenum, GLenum, unsigned int, GLint *);
142 template void CastStateValues<GLuint>(Context *, GLenum, GLenum, unsigned int, GLuint *);
143 template void CastStateValues<GLfloat>(Context *, GLenum, GLenum, unsigned int, GLfloat *);
144 template void CastStateValues<GLint64>(Context *, GLenum, GLenum, unsigned int, GLint64 *);
145 
146 template <typename QueryT>
CastIndexedStateValues(Context * context,GLenum nativeType,GLenum pname,GLuint index,unsigned int numParams,QueryT * outParams)147 void CastIndexedStateValues(Context *context,
148                             GLenum nativeType,
149                             GLenum pname,
150                             GLuint index,
151                             unsigned int numParams,
152                             QueryT *outParams)
153 {
154     if (nativeType == GL_INT)
155     {
156         std::vector<GLint> intParams(numParams, 0);
157         context->getIntegeri_v(pname, index, intParams.data());
158 
159         for (unsigned int i = 0; i < numParams; ++i)
160         {
161             outParams[i] = CastStateValue<QueryT>(pname, intParams[i]);
162         }
163     }
164     else if (nativeType == GL_BOOL)
165     {
166         std::vector<GLboolean> boolParams(numParams, GL_FALSE);
167         context->getBooleani_v(pname, index, boolParams.data());
168 
169         for (unsigned int i = 0; i < numParams; ++i)
170         {
171             outParams[i] =
172                 (boolParams[i] == GL_FALSE ? static_cast<QueryT>(0) : static_cast<QueryT>(1));
173         }
174     }
175     else if (nativeType == GL_INT_64_ANGLEX)
176     {
177         std::vector<GLint64> int64Params(numParams, 0);
178         context->getInteger64i_v(pname, index, int64Params.data());
179 
180         for (unsigned int i = 0; i < numParams; ++i)
181         {
182             outParams[i] = CastStateValue<QueryT>(pname, int64Params[i]);
183         }
184     }
185     else
186         UNREACHABLE();
187 }
188 
189 template void CastIndexedStateValues<GLboolean>(Context *,
190                                                 GLenum,
191                                                 GLenum,
192                                                 GLuint index,
193                                                 unsigned int,
194                                                 GLboolean *);
195 template void CastIndexedStateValues<GLint>(Context *,
196                                             GLenum,
197                                             GLenum,
198                                             GLuint index,
199                                             unsigned int,
200                                             GLint *);
201 template void CastIndexedStateValues<GLuint>(Context *,
202                                              GLenum,
203                                              GLenum,
204                                              GLuint index,
205                                              unsigned int,
206                                              GLuint *);
207 template void CastIndexedStateValues<GLfloat>(Context *,
208                                               GLenum,
209                                               GLenum,
210                                               GLuint index,
211                                               unsigned int,
212                                               GLfloat *);
213 template void CastIndexedStateValues<GLint64>(Context *,
214                                               GLenum,
215                                               GLenum,
216                                               GLuint index,
217                                               unsigned int,
218                                               GLint64 *);
219 }
220