1//
2// Copyright (c) 2002-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/VariableInfo.h"
8
9static TString arrayBrackets(int index)
10{
11    TStringStream stream;
12    stream << "[" << index << "]";
13    return stream.str();
14}
15
16// Returns the data type for an attribute or uniform.
17static ShDataType getVariableDataType(const TType& type)
18{
19    switch (type.getBasicType()) {
20      case EbtFloat:
21          if (type.isMatrix()) {
22              switch (type.getNominalSize()) {
23                case 2: return SH_FLOAT_MAT2;
24                case 3: return SH_FLOAT_MAT3;
25                case 4: return SH_FLOAT_MAT4;
26                default: UNREACHABLE();
27              }
28          } else if (type.isVector()) {
29              switch (type.getNominalSize()) {
30                case 2: return SH_FLOAT_VEC2;
31                case 3: return SH_FLOAT_VEC3;
32                case 4: return SH_FLOAT_VEC4;
33                default: UNREACHABLE();
34              }
35          } else {
36              return SH_FLOAT;
37          }
38      case EbtInt:
39          if (type.isMatrix()) {
40              UNREACHABLE();
41          } else if (type.isVector()) {
42              switch (type.getNominalSize()) {
43                case 2: return SH_INT_VEC2;
44                case 3: return SH_INT_VEC3;
45                case 4: return SH_INT_VEC4;
46                default: UNREACHABLE();
47              }
48          } else {
49              return SH_INT;
50          }
51      case EbtBool:
52          if (type.isMatrix()) {
53              UNREACHABLE();
54          } else if (type.isVector()) {
55              switch (type.getNominalSize()) {
56                case 2: return SH_BOOL_VEC2;
57                case 3: return SH_BOOL_VEC3;
58                case 4: return SH_BOOL_VEC4;
59                default: UNREACHABLE();
60              }
61          } else {
62              return SH_BOOL;
63          }
64      case EbtSampler2D: return SH_SAMPLER_2D;
65      case EbtSamplerCube: return SH_SAMPLER_CUBE;
66      default: UNREACHABLE();
67    }
68    return SH_NONE;
69}
70
71static void getBuiltInVariableInfo(const TType& type,
72                                   const TString& name,
73                                   TVariableInfoList& infoList);
74static void getUserDefinedVariableInfo(const TType& type,
75                                       const TString& name,
76                                       TVariableInfoList& infoList);
77
78// Returns info for an attribute or uniform.
79static void getVariableInfo(const TType& type,
80                            const TString& name,
81                            TVariableInfoList& infoList)
82{
83    if (type.getBasicType() == EbtStruct) {
84        if (type.isArray()) {
85            for (int i = 0; i < type.getArraySize(); ++i) {
86                TString lname = name + arrayBrackets(i);
87                getUserDefinedVariableInfo(type, lname, infoList);
88            }
89        } else {
90            getUserDefinedVariableInfo(type, name, infoList);
91        }
92    } else {
93        getBuiltInVariableInfo(type, name, infoList);
94    }
95}
96
97void getBuiltInVariableInfo(const TType& type,
98                            const TString& name,
99                            TVariableInfoList& infoList)
100{
101    ASSERT(type.getBasicType() != EbtStruct);
102
103    TVariableInfo varInfo;
104    if (type.isArray()) {
105        varInfo.name = (name + "[0]").c_str();
106        varInfo.size = type.getArraySize();
107    } else {
108        varInfo.name = name.c_str();
109        varInfo.size = 1;
110    }
111    varInfo.type = getVariableDataType(type);
112    infoList.push_back(varInfo);
113}
114
115void getUserDefinedVariableInfo(const TType& type,
116                                const TString& name,
117                                TVariableInfoList& infoList)
118{
119    ASSERT(type.getBasicType() == EbtStruct);
120
121    TString lname = name + ".";
122    const TTypeList* structure = type.getStruct();
123    for (size_t i = 0; i < structure->size(); ++i) {
124        const TType* fieldType = (*structure)[i].type;
125        getVariableInfo(*fieldType,
126                        lname + fieldType->getFieldName(),
127                        infoList);
128    }
129}
130
131CollectAttribsUniforms::CollectAttribsUniforms(TVariableInfoList& attribs,
132                                               TVariableInfoList& uniforms)
133    : mAttribs(attribs),
134      mUniforms(uniforms)
135{
136}
137
138// We are only interested in attribute and uniform variable declaration.
139void CollectAttribsUniforms::visitSymbol(TIntermSymbol*)
140{
141}
142
143void CollectAttribsUniforms::visitConstantUnion(TIntermConstantUnion*)
144{
145}
146
147bool CollectAttribsUniforms::visitBinary(Visit, TIntermBinary*)
148{
149    return false;
150}
151
152bool CollectAttribsUniforms::visitUnary(Visit, TIntermUnary*)
153{
154    return false;
155}
156
157bool CollectAttribsUniforms::visitSelection(Visit, TIntermSelection*)
158{
159    return false;
160}
161
162bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node)
163{
164    bool visitChildren = false;
165
166    switch (node->getOp())
167    {
168    case EOpSequence:
169        // We need to visit sequence children to get to variable declarations.
170        visitChildren = true;
171        break;
172    case EOpDeclaration: {
173        const TIntermSequence& sequence = node->getSequence();
174        TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
175        if (qualifier == EvqAttribute || qualifier == EvqUniform)
176        {
177            TVariableInfoList& infoList = qualifier == EvqAttribute ?
178                mAttribs : mUniforms;
179            for (TIntermSequence::const_iterator i = sequence.begin();
180                 i != sequence.end(); ++i)
181            {
182                const TIntermSymbol* variable = (*i)->getAsSymbolNode();
183                // The only case in which the sequence will not contain a
184                // TIntermSymbol node is initialization. It will contain a
185                // TInterBinary node in that case. Since attributes and unifroms
186                // cannot be initialized in a shader, we must have only
187                // TIntermSymbol nodes in the sequence.
188                ASSERT(variable != NULL);
189                getVariableInfo(variable->getType(), variable->getSymbol(),
190                                infoList);
191            }
192        }
193        break;
194    }
195    default: break;
196    }
197
198    return visitChildren;
199}
200
201bool CollectAttribsUniforms::visitLoop(Visit, TIntermLoop*)
202{
203    return false;
204}
205
206bool CollectAttribsUniforms::visitBranch(Visit, TIntermBranch*)
207{
208    return false;
209}
210
211