1//
2// Copyright (c) 2010 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#include "compiler/translator/util.h"
8
9#include <limits>
10
11#include "compiler/preprocessor/numeric_lex.h"
12#include "common/utilities.h"
13
14bool atof_clamp(const char *str, float *value)
15{
16    bool success = pp::numeric_lex_float(str, value);
17    if (!success)
18        *value = std::numeric_limits<float>::max();
19    return success;
20}
21
22bool atoi_clamp(const char *str, int *value)
23{
24    bool success = pp::numeric_lex_int(str, value);
25    if (!success)
26        *value = std::numeric_limits<int>::max();
27    return success;
28}
29
30namespace sh
31{
32
33GLenum GLVariableType(const TType &type)
34{
35    if (type.getBasicType() == EbtFloat)
36    {
37        if (type.isScalar())
38        {
39            return GL_FLOAT;
40        }
41        else if (type.isVector())
42        {
43            switch (type.getNominalSize())
44            {
45              case 2: return GL_FLOAT_VEC2;
46              case 3: return GL_FLOAT_VEC3;
47              case 4: return GL_FLOAT_VEC4;
48              default: UNREACHABLE();
49            }
50        }
51        else if (type.isMatrix())
52        {
53            switch (type.getCols())
54            {
55              case 2:
56                switch (type.getRows())
57                {
58                  case 2: return GL_FLOAT_MAT2;
59                  case 3: return GL_FLOAT_MAT2x3;
60                  case 4: return GL_FLOAT_MAT2x4;
61                  default: UNREACHABLE();
62                }
63
64              case 3:
65                switch (type.getRows())
66                {
67                  case 2: return GL_FLOAT_MAT3x2;
68                  case 3: return GL_FLOAT_MAT3;
69                  case 4: return GL_FLOAT_MAT3x4;
70                  default: UNREACHABLE();
71                }
72
73              case 4:
74                switch (type.getRows())
75                {
76                  case 2: return GL_FLOAT_MAT4x2;
77                  case 3: return GL_FLOAT_MAT4x3;
78                  case 4: return GL_FLOAT_MAT4;
79                  default: UNREACHABLE();
80                }
81
82              default: UNREACHABLE();
83            }
84        }
85        else UNREACHABLE();
86    }
87    else if (type.getBasicType() == EbtInt)
88    {
89        if (type.isScalar())
90        {
91            return GL_INT;
92        }
93        else if (type.isVector())
94        {
95            switch (type.getNominalSize())
96            {
97              case 2: return GL_INT_VEC2;
98              case 3: return GL_INT_VEC3;
99              case 4: return GL_INT_VEC4;
100              default: UNREACHABLE();
101            }
102        }
103        else UNREACHABLE();
104    }
105    else if (type.getBasicType() == EbtUInt)
106    {
107        if (type.isScalar())
108        {
109            return GL_UNSIGNED_INT;
110        }
111        else if (type.isVector())
112        {
113            switch (type.getNominalSize())
114            {
115              case 2: return GL_UNSIGNED_INT_VEC2;
116              case 3: return GL_UNSIGNED_INT_VEC3;
117              case 4: return GL_UNSIGNED_INT_VEC4;
118              default: UNREACHABLE();
119            }
120        }
121        else UNREACHABLE();
122    }
123    else if (type.getBasicType() == EbtBool)
124    {
125        if (type.isScalar())
126        {
127            return GL_BOOL;
128        }
129        else if (type.isVector())
130        {
131            switch (type.getNominalSize())
132            {
133              case 2: return GL_BOOL_VEC2;
134              case 3: return GL_BOOL_VEC3;
135              case 4: return GL_BOOL_VEC4;
136              default: UNREACHABLE();
137            }
138        }
139        else UNREACHABLE();
140    }
141
142    switch (type.getBasicType())
143    {
144      case EbtSampler2D:            return GL_SAMPLER_2D;
145      case EbtSampler3D:            return GL_SAMPLER_3D;
146      case EbtSamplerCube:          return GL_SAMPLER_CUBE;
147      case EbtSamplerExternalOES:   return GL_SAMPLER_EXTERNAL_OES;
148      case EbtSampler2DRect:        return GL_SAMPLER_2D_RECT_ARB;
149      case EbtSampler2DArray:       return GL_SAMPLER_2D_ARRAY;
150      case EbtISampler2D:           return GL_INT_SAMPLER_2D;
151      case EbtISampler3D:           return GL_INT_SAMPLER_3D;
152      case EbtISamplerCube:         return GL_INT_SAMPLER_CUBE;
153      case EbtISampler2DArray:      return GL_INT_SAMPLER_2D_ARRAY;
154      case EbtUSampler2D:           return GL_UNSIGNED_INT_SAMPLER_2D;
155      case EbtUSampler3D:           return GL_UNSIGNED_INT_SAMPLER_3D;
156      case EbtUSamplerCube:         return GL_UNSIGNED_INT_SAMPLER_CUBE;
157      case EbtUSampler2DArray:      return GL_UNSIGNED_INT_SAMPLER_2D_ARRAY;
158      case EbtSampler2DShadow:      return GL_SAMPLER_2D_SHADOW;
159      case EbtSamplerCubeShadow:    return GL_SAMPLER_CUBE_SHADOW;
160      case EbtSampler2DArrayShadow: return GL_SAMPLER_2D_ARRAY_SHADOW;
161      default: UNREACHABLE();
162    }
163
164    return GL_NONE;
165}
166
167GLenum GLVariablePrecision(const TType &type)
168{
169    if (type.getBasicType() == EbtFloat)
170    {
171        switch (type.getPrecision())
172        {
173          case EbpHigh:
174            return GL_HIGH_FLOAT;
175          case EbpMedium:
176            return GL_MEDIUM_FLOAT;
177          case EbpLow:
178            return GL_LOW_FLOAT;
179          case EbpUndefined:
180          // Should be defined as the default precision by the parser
181          default:
182            UNREACHABLE();
183        }
184    }
185    else if (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt)
186    {
187        switch (type.getPrecision())
188        {
189          case EbpHigh:
190            return GL_HIGH_INT;
191          case EbpMedium:
192            return GL_MEDIUM_INT;
193          case EbpLow:
194            return GL_LOW_INT;
195          case EbpUndefined:
196          // Should be defined as the default precision by the parser
197          default:
198            UNREACHABLE();
199        }
200    }
201
202    // Other types (boolean, sampler) don't have a precision
203    return GL_NONE;
204}
205
206TString ArrayString(const TType &type)
207{
208    if (!type.isArray())
209    {
210        return "";
211    }
212
213    return "[" + str(type.getArraySize()) + "]";
214}
215
216bool IsVaryingOut(TQualifier qualifier)
217{
218    switch (qualifier)
219    {
220      case EvqVaryingOut:
221      case EvqInvariantVaryingOut:
222      case EvqSmoothOut:
223      case EvqFlatOut:
224      case EvqCentroidOut:
225      case EvqVertexOut:
226        return true;
227
228      default: break;
229    }
230
231    return false;
232}
233
234bool IsVaryingIn(TQualifier qualifier)
235{
236    switch (qualifier)
237    {
238      case EvqVaryingIn:
239      case EvqInvariantVaryingIn:
240      case EvqSmoothIn:
241      case EvqFlatIn:
242      case EvqCentroidIn:
243      case EvqFragmentIn:
244        return true;
245
246      default: break;
247    }
248
249    return false;
250}
251
252bool IsVarying(TQualifier qualifier)
253{
254    return IsVaryingIn(qualifier) || IsVaryingOut(qualifier);
255}
256
257InterpolationType GetInterpolationType(TQualifier qualifier)
258{
259    switch (qualifier)
260    {
261      case EvqFlatIn:
262      case EvqFlatOut:
263        return INTERPOLATION_FLAT;
264
265      case EvqSmoothIn:
266      case EvqSmoothOut:
267      case EvqVertexOut:
268      case EvqFragmentIn:
269      case EvqVaryingIn:
270      case EvqVaryingOut:
271      case EvqInvariantVaryingIn:
272      case EvqInvariantVaryingOut:
273        return INTERPOLATION_SMOOTH;
274
275      case EvqCentroidIn:
276      case EvqCentroidOut:
277        return INTERPOLATION_CENTROID;
278
279      default: UNREACHABLE();
280        return INTERPOLATION_SMOOTH;
281    }
282}
283
284template <typename VarT>
285void GetVariableTraverser::traverse(const TType &type, const TString &name, std::vector<VarT> *output)
286{
287    const TStructure *structure = type.getStruct();
288
289    VarT variable;
290    variable.name = name.c_str();
291    variable.arraySize = static_cast<unsigned int>(type.getArraySize());
292
293    if (!structure)
294    {
295        variable.type = GLVariableType(type);
296        variable.precision = GLVariablePrecision(type);
297    }
298    else
299    {
300        // Note: this enum value is not exposed outside ANGLE
301        variable.type = GL_STRUCT_ANGLEX;
302        variable.structName = structure->name().c_str();
303
304        const TFieldList &fields = structure->fields();
305
306        for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
307        {
308            TField *field = fields[fieldIndex];
309            traverse(*field->type(), field->name(), &variable.fields);
310        }
311    }
312
313    visitVariable(&variable);
314
315    ASSERT(output);
316    output->push_back(variable);
317}
318
319template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Uniform> *);
320template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Varying> *);
321template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<InterfaceBlockField> *);
322
323}
324