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 "libGLESv2/Context.h"
10#include "common/utilities.h"
11
12namespace gl
13{
14
15// Helper class for converting a GL type to a GLenum:
16// We can't use CastStateValueEnum generally, because of GLboolean + GLubyte overlap.
17// We restrict our use to CastStateValue, where it eliminates duplicate parameters.
18
19template <typename GLType>
20struct CastStateValueEnum { static GLenum mEnumForType; };
21
22template <> GLenum CastStateValueEnum<GLint>::mEnumForType      = GL_INT;
23template <> GLenum CastStateValueEnum<GLuint>::mEnumForType     = GL_UNSIGNED_INT;
24template <> GLenum CastStateValueEnum<GLboolean>::mEnumForType  = GL_BOOL;
25template <> GLenum CastStateValueEnum<GLint64>::mEnumForType    = GL_INT_64_ANGLEX;
26template <> GLenum CastStateValueEnum<GLfloat>::mEnumForType    = GL_FLOAT;
27
28template <typename QueryT, typename NativeT>
29QueryT CastStateValueToInt(GLenum pname, NativeT value)
30{
31    GLenum queryType = CastStateValueEnum<QueryT>::mEnumForType;
32    GLenum nativeType = CastStateValueEnum<NativeT>::mEnumForType;
33
34    if (nativeType == GL_FLOAT)
35    {
36        // RGBA color values and DepthRangeF values are converted to integer using Equation 2.4 from Table 4.5
37        if (pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
38        {
39            return static_cast<QueryT>((static_cast<GLfloat>(0xFFFFFFFF) * value - 1.0f) / 2.0f);
40        }
41        else
42        {
43            return gl::iround<QueryT>(value);
44        }
45    }
46
47    // Clamp 64-bit int values when casting to int
48    if (nativeType == GL_INT_64_ANGLEX && queryType == GL_INT)
49    {
50        GLint64 minIntValue = static_cast<GLint64>(std::numeric_limits<GLint>::min());
51        GLint64 maxIntValue = static_cast<GLint64>(std::numeric_limits<GLint>::max());
52        GLint64 clampedValue = std::max(std::min(static_cast<GLint64>(value), maxIntValue), minIntValue);
53        return static_cast<QueryT>(clampedValue);
54    }
55
56    return static_cast<QueryT>(value);
57}
58
59template <typename QueryT, typename NativeT>
60QueryT CastStateValue(GLenum pname, NativeT value)
61{
62    GLenum queryType = CastStateValueEnum<QueryT>::mEnumForType;
63
64    switch (queryType)
65    {
66      case GL_INT:              return CastStateValueToInt<QueryT, NativeT>(pname, value);
67      case GL_INT_64_ANGLEX:    return CastStateValueToInt<QueryT, NativeT>(pname, value);
68      case GL_FLOAT:            return static_cast<QueryT>(value);
69      case GL_BOOL:             return (value == static_cast<NativeT>(0) ? GL_FALSE : GL_TRUE);
70      default: UNREACHABLE();   return 0;
71    }
72}
73
74template <typename QueryT>
75void CastStateValues(Context *context, GLenum nativeType, GLenum pname,
76                     unsigned int numParams, QueryT *outParams)
77{
78    if (nativeType == GL_INT)
79    {
80        GLint *intParams = NULL;
81        intParams = new GLint[numParams];
82
83        context->getIntegerv(pname, intParams);
84
85        for (unsigned int i = 0; i < numParams; ++i)
86        {
87            outParams[i] = CastStateValue<QueryT>(pname, intParams[i]);
88        }
89
90        delete [] intParams;
91    }
92    else if (nativeType == GL_BOOL)
93    {
94        GLboolean *boolParams = NULL;
95        boolParams = new GLboolean[numParams];
96
97        context->getBooleanv(pname, boolParams);
98
99        for (unsigned int i = 0; i < numParams; ++i)
100        {
101            outParams[i] = (boolParams[i] == GL_FALSE ? static_cast<QueryT>(0) : static_cast<QueryT>(1));
102        }
103
104        delete [] boolParams;
105    }
106    else if (nativeType == GL_FLOAT)
107    {
108        GLfloat *floatParams = NULL;
109        floatParams = new GLfloat[numParams];
110
111        context->getFloatv(pname, floatParams);
112
113        for (unsigned int i = 0; i < numParams; ++i)
114        {
115            outParams[i] = CastStateValue<QueryT>(pname, floatParams[i]);
116        }
117
118        delete [] floatParams;
119    }
120    else if (nativeType == GL_INT_64_ANGLEX)
121    {
122        GLint64 *int64Params = NULL;
123        int64Params = new GLint64[numParams];
124
125        context->getInteger64v(pname, int64Params);
126
127        for (unsigned int i = 0; i < numParams; ++i)
128        {
129            outParams[i] = CastStateValue<QueryT>(pname, int64Params[i]);
130        }
131
132        delete [] int64Params;
133    }
134    else UNREACHABLE();
135}
136
137// Explicit template instantiation (how we export template functions in different files)
138// The calls below will make CastStateValues successfully link with the GL state query types
139// The GL state query API types are: bool, int, uint, float, int64
140
141template void CastStateValues<GLboolean>(Context *, GLenum, GLenum, unsigned int, GLboolean *);
142template void CastStateValues<GLint>(Context *, GLenum, GLenum, unsigned int, GLint *);
143template void CastStateValues<GLuint>(Context *, GLenum, GLenum, unsigned int, GLuint *);
144template void CastStateValues<GLfloat>(Context *, GLenum, GLenum, unsigned int, GLfloat *);
145template void CastStateValues<GLint64>(Context *, GLenum, GLenum, unsigned int, GLint64 *);
146
147}
148