Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / compiler / translator / VariableInfo.cpp
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/translator/VariableInfo.h"
8
9 namespace {
10
11 TString arrayBrackets(int index)
12 {
13     TStringStream stream;
14     stream << "[" << index << "]";
15     return stream.str();
16 }
17
18 // Returns the data type for an attribute, uniform, or varying.
19 ShDataType getVariableDataType(const TType& type)
20 {
21     switch (type.getBasicType()) {
22       case EbtFloat:
23           if (type.isMatrix()) {
24               switch (type.getNominalSize()) {
25                 case 2: return SH_FLOAT_MAT2;
26                 case 3: return SH_FLOAT_MAT3;
27                 case 4: return SH_FLOAT_MAT4;
28                 default: UNREACHABLE();
29               }
30           } else if (type.isVector()) {
31               switch (type.getNominalSize()) {
32                 case 2: return SH_FLOAT_VEC2;
33                 case 3: return SH_FLOAT_VEC3;
34                 case 4: return SH_FLOAT_VEC4;
35                 default: UNREACHABLE();
36               }
37           } else {
38               return SH_FLOAT;
39           }
40       case EbtInt:
41           if (type.isMatrix()) {
42               UNREACHABLE();
43           } else if (type.isVector()) {
44               switch (type.getNominalSize()) {
45                 case 2: return SH_INT_VEC2;
46                 case 3: return SH_INT_VEC3;
47                 case 4: return SH_INT_VEC4;
48                 default: UNREACHABLE();
49               }
50           } else {
51               return SH_INT;
52           }
53       case EbtBool:
54           if (type.isMatrix()) {
55               UNREACHABLE();
56           } else if (type.isVector()) {
57               switch (type.getNominalSize()) {
58                 case 2: return SH_BOOL_VEC2;
59                 case 3: return SH_BOOL_VEC3;
60                 case 4: return SH_BOOL_VEC4;
61                 default: UNREACHABLE();
62               }
63           } else {
64               return SH_BOOL;
65           }
66       case EbtSampler2D: return SH_SAMPLER_2D;
67       case EbtSamplerCube: return SH_SAMPLER_CUBE;
68       case EbtSamplerExternalOES: return SH_SAMPLER_EXTERNAL_OES;
69       case EbtSampler2DRect: return SH_SAMPLER_2D_RECT_ARB;
70       default: UNREACHABLE();
71     }
72     return SH_NONE;
73 }
74
75 void getBuiltInVariableInfo(const TType& type,
76                             const TString& name,
77                             const TString& mappedName,
78                             TVariableInfoList& infoList);
79 void getUserDefinedVariableInfo(const TType& type,
80                                 const TString& name,
81                                 const TString& mappedName,
82                                 TVariableInfoList& infoList,
83                                 ShHashFunction64 hashFunction);
84
85 // Returns info for an attribute, uniform, or varying.
86 void getVariableInfo(const TType& type,
87                      const TString& name,
88                      const TString& mappedName,
89                      TVariableInfoList& infoList,
90                      ShHashFunction64 hashFunction)
91 {
92     if (type.getBasicType() == EbtStruct) {
93         if (type.isArray()) {
94             for (int i = 0; i < type.getArraySize(); ++i) {
95                 TString lname = name + arrayBrackets(i);
96                 TString lmappedName = mappedName + arrayBrackets(i);
97                 getUserDefinedVariableInfo(type, lname, lmappedName, infoList, hashFunction);
98             }
99         } else {
100             getUserDefinedVariableInfo(type, name, mappedName, infoList, hashFunction);
101         }
102     } else {
103         getBuiltInVariableInfo(type, name, mappedName, infoList);
104     }
105 }
106
107 void getBuiltInVariableInfo(const TType& type,
108                             const TString& name,
109                             const TString& mappedName,
110                             TVariableInfoList& infoList)
111 {
112     ASSERT(type.getBasicType() != EbtStruct);
113
114     TVariableInfo varInfo;
115     if (type.isArray()) {
116         varInfo.name = (name + "[0]").c_str();
117         varInfo.mappedName = (mappedName + "[0]").c_str();
118         varInfo.size = type.getArraySize();
119         varInfo.isArray = true;
120     } else {
121         varInfo.name = name.c_str();
122         varInfo.mappedName = mappedName.c_str();
123         varInfo.size = 1;
124         varInfo.isArray = false;
125     }
126     varInfo.precision = type.getPrecision();
127     varInfo.type = getVariableDataType(type);
128     infoList.push_back(varInfo);
129 }
130
131 void getUserDefinedVariableInfo(const TType& type,
132                                 const TString& name,
133                                 const TString& mappedName,
134                                 TVariableInfoList& infoList,
135                                 ShHashFunction64 hashFunction)
136 {
137     ASSERT(type.getBasicType() == EbtStruct);
138
139     const TFieldList& fields = type.getStruct()->fields();
140     for (size_t i = 0; i < fields.size(); ++i) {
141         const TType& fieldType = *(fields[i]->type());
142         const TString& fieldName = fields[i]->name();
143         getVariableInfo(fieldType,
144                         name + "." + fieldName,
145                         mappedName + "." + TIntermTraverser::hash(fieldName, hashFunction),
146                         infoList,
147                         hashFunction);
148     }
149 }
150
151 TVariableInfo* findVariable(const TType& type,
152                             const TString& name,
153                             TVariableInfoList& infoList)
154 {
155     // TODO(zmo): optimize this function.
156     TString myName = name;
157     if (type.isArray())
158         myName += "[0]";
159     for (size_t ii = 0; ii < infoList.size(); ++ii)
160     {
161         if (infoList[ii].name.c_str() == myName)
162             return &(infoList[ii]);
163     }
164     return NULL;
165 }
166
167 }  // namespace anonymous
168
169 TVariableInfo::TVariableInfo()
170     : type(SH_NONE),
171       size(0),
172       isArray(false),
173       precision(EbpUndefined),
174       staticUse(false)
175 {
176 }
177
178 TVariableInfo::TVariableInfo(ShDataType type, int size)
179     : type(type),
180       size(size),
181       isArray(false),
182       precision(EbpUndefined),
183       staticUse(false)
184 {
185 }
186
187 CollectVariables::CollectVariables(TVariableInfoList& attribs,
188                                    TVariableInfoList& uniforms,
189                                    TVariableInfoList& varyings,
190                                    ShHashFunction64 hashFunction)
191     : mAttribs(attribs),
192       mUniforms(uniforms),
193       mVaryings(varyings),
194       mPointCoordAdded(false),
195       mFrontFacingAdded(false),
196       mFragCoordAdded(false),
197       mHashFunction(hashFunction)
198 {
199 }
200
201 // We want to check whether a uniform/varying is statically used
202 // because we only count the used ones in packing computing.
203 // Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
204 // toward varying counting if they are statically used in a fragment
205 // shader.
206 void CollectVariables::visitSymbol(TIntermSymbol* symbol)
207 {
208     ASSERT(symbol != NULL);
209     TVariableInfo* var = NULL;
210     switch (symbol->getQualifier())
211     {
212     case EvqVaryingOut:
213     case EvqInvariantVaryingOut:
214     case EvqVaryingIn:
215     case EvqInvariantVaryingIn:
216         var = findVariable(symbol->getType(), symbol->getSymbol(), mVaryings);
217         break;
218     case EvqUniform:
219         var = findVariable(symbol->getType(), symbol->getSymbol(), mUniforms);
220         break;
221     case EvqFragCoord:
222         if (!mFragCoordAdded) {
223             TVariableInfo info;
224             info.name = "gl_FragCoord";
225             info.mappedName = "gl_FragCoord";
226             info.type = SH_FLOAT_VEC4;
227             info.size = 1;
228             info.precision = EbpMedium;  // Use mediump as it doesn't really matter.
229             info.staticUse = true;
230             mVaryings.push_back(info);
231             mFragCoordAdded = true;
232         }
233         return;
234     case EvqFrontFacing:
235         if (!mFrontFacingAdded) {
236             TVariableInfo info;
237             info.name = "gl_FrontFacing";
238             info.mappedName = "gl_FrontFacing";
239             info.type = SH_BOOL;
240             info.size = 1;
241             info.precision = EbpUndefined;
242             info.staticUse = true;
243             mVaryings.push_back(info);
244             mFrontFacingAdded = true;
245         }
246         return;
247     case EvqPointCoord:
248         if (!mPointCoordAdded) {
249             TVariableInfo info;
250             info.name = "gl_PointCoord";
251             info.mappedName = "gl_PointCoord";
252             info.type = SH_FLOAT_VEC2;
253             info.size = 1;
254             info.precision = EbpMedium;  // Use mediump as it doesn't really matter.
255             info.staticUse = true;
256             mVaryings.push_back(info);
257             mPointCoordAdded = true;
258         }
259         return;
260     default:
261         break;
262     }
263     if (var)
264         var->staticUse = true;
265 }
266
267 bool CollectVariables::visitAggregate(Visit, TIntermAggregate* node)
268 {
269     bool visitChildren = true;
270
271     switch (node->getOp())
272     {
273     case EOpDeclaration: {
274         const TIntermSequence& sequence = node->getSequence();
275         TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
276         if (qualifier == EvqAttribute || qualifier == EvqUniform ||
277             qualifier == EvqVaryingIn || qualifier == EvqVaryingOut ||
278             qualifier == EvqInvariantVaryingIn || qualifier == EvqInvariantVaryingOut)
279         {
280             TVariableInfoList& infoList = qualifier == EvqAttribute ? mAttribs :
281                 (qualifier == EvqUniform ? mUniforms : mVaryings);
282             for (TIntermSequence::const_iterator i = sequence.begin();
283                  i != sequence.end(); ++i)
284             {
285                 const TIntermSymbol* variable = (*i)->getAsSymbolNode();
286                 // The only case in which the sequence will not contain a
287                 // TIntermSymbol node is initialization. It will contain a
288                 // TInterBinary node in that case. Since attributes, uniforms,
289                 // and varyings cannot be initialized in a shader, we must have
290                 // only TIntermSymbol nodes in the sequence.
291                 ASSERT(variable != NULL);
292                 TString processedSymbol;
293                 if (mHashFunction == NULL)
294                     processedSymbol = variable->getSymbol();
295                 else
296                     processedSymbol = TIntermTraverser::hash(variable->getOriginalSymbol(), mHashFunction);
297                 getVariableInfo(variable->getType(),
298                                 variable->getOriginalSymbol(),
299                                 processedSymbol,
300                                 infoList,
301                                 mHashFunction);
302                 visitChildren = false;
303             }
304         }
305         break;
306     }
307     default: break;
308     }
309
310     return visitChildren;
311 }
312