blob: 219909eb7abc01d15b07a13b2e9e01e86599558f [file] [log] [blame]
alokp@chromium.org76b82082010-03-24 17:59:39 +00001//
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
daniel@transgaming.combbf56f72010-04-20 18:52:13 +00007#include "compiler/OutputGLSL.h"
8
alokp@chromium.org76b82082010-03-24 17:59:39 +00009#include "common/debug.h"
10
11namespace
12{
13TString getTypeName(const TType& type)
14{
15 TInfoSinkBase out;
16 if (type.isMatrix())
17 {
18 out << "mat";
19 out << type.getNominalSize();
20 }
alokp@chromium.org76b82082010-03-24 17:59:39 +000021 else if (type.isVector())
22 {
23 switch (type.getBasicType())
24 {
25 case EbtFloat: out << "vec"; break;
26 case EbtInt: out << "ivec"; break;
27 case EbtBool: out << "bvec"; break;
28 default: UNREACHABLE(); break;
29 }
30 out << type.getNominalSize();
31 }
32 else
33 {
34 if (type.getBasicType() == EbtStruct)
35 out << type.getTypeName();
36 else
37 out << type.getBasicString();
38 }
39 return TString(out.c_str());
40}
alokp@chromium.org76b82082010-03-24 17:59:39 +000041} // namespace
42
alokp@chromium.orga499cfc2010-05-03 23:14:49 +000043TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink)
alokp@chromium.org76b82082010-03-24 17:59:39 +000044 : TIntermTraverser(true, true, true),
alokp@chromium.orga499cfc2010-05-03 23:14:49 +000045 mObjSink(objSink),
alokp@chromium.orgb3f7fb62010-05-05 18:21:51 +000046 mWriteFullSymbol(false),
47 mScopeSequences(false)
alokp@chromium.org76b82082010-03-24 17:59:39 +000048{
49}
50
alokp@chromium.org76b82082010-03-24 17:59:39 +000051void TOutputGLSL::writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr)
52{
53 TInfoSinkBase& out = objSink();
54 if (visit == PreVisit && preStr)
55 {
56 out << preStr;
57 }
58 else if (visit == InVisit && inStr)
59 {
60 out << inStr;
61 }
62 else if (visit == PostVisit && postStr)
63 {
64 out << postStr;
65 }
66}
67
alokp@chromium.orgb3f7fb62010-05-05 18:21:51 +000068const ConstantUnion* TOutputGLSL::writeConstantUnion(const TType& type, const ConstantUnion* pConstUnion)
69{
70 TInfoSinkBase& out = objSink();
71
72 if (type.getBasicType() == EbtStruct)
73 {
74 out << type.getTypeName() << "(";
75 const TTypeList* structure = type.getStruct();
76 ASSERT(structure != NULL);
77 for (size_t i = 0; i < structure->size(); ++i)
78 {
79 const TType* fieldType = (*structure)[i].type;
80 ASSERT(fieldType != NULL);
81 pConstUnion = writeConstantUnion(*fieldType, pConstUnion);
82 if (i != structure->size() - 1) out << ", ";
83 }
84 out << ")";
85 }
86 else
87 {
88 int size = type.getObjectSize();
89 bool writeType = size > 1;
90 if (writeType) out << getTypeName(type) << "(";
91 for (int i = 0; i < size; ++i, ++pConstUnion)
92 {
93 switch (pConstUnion->getType())
94 {
95 case EbtFloat: out << pConstUnion->getFConst(); break;
96 case EbtInt: out << pConstUnion->getIConst(); break;
97 case EbtBool:
98 if (pConstUnion->getBConst())
99 out << "true";
100 else
101 out << "false";
102 break;
103 default: UNREACHABLE();
104 }
105 if (i != size - 1) out << ", ";
106 }
107 if (writeType) out << ")";
108 }
109 return pConstUnion;
110}
111
alokp@chromium.org76b82082010-03-24 17:59:39 +0000112void TOutputGLSL::visitSymbol(TIntermSymbol* node)
113{
114 TInfoSinkBase& out = objSink();
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000115 const TType& type = node->getType();
116
117 if (mWriteFullSymbol)
alokp@chromium.org76b82082010-03-24 17:59:39 +0000118 {
119 TQualifier qualifier = node->getQualifier();
120 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal))
121 out << node->getQualifierString() << " ";
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000122
123 // Declare the struct if we have not done so already.
124 if ((type.getBasicType() == EbtStruct) && (mDeclaredStructs.find(type.getTypeName()) == mDeclaredStructs.end()))
125 {
126 out << "struct " << type.getTypeName() << "{\n";
127 const TTypeList* structure = type.getStruct();
128 ASSERT(structure != NULL);
129 for (size_t i = 0; i < structure->size(); ++i)
130 {
131 const TType* fieldType = (*structure)[i].type;
132 ASSERT(fieldType != NULL);
133 out << getTypeName(*fieldType) << " " << fieldType->getFieldName() << ";\n";
134 }
135 out << "} ";
136 mDeclaredStructs.insert(type.getTypeName());
137 }
138 else
139 {
140 out << getTypeName(type) << " ";
141 }
alokp@chromium.org76b82082010-03-24 17:59:39 +0000142 }
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000143
alokp@chromium.org76b82082010-03-24 17:59:39 +0000144 out << node->getSymbol();
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000145
146 if (mWriteFullSymbol && node->getType().isArray())
alokp@chromium.org3d270782010-03-30 20:33:38 +0000147 {
148 out << "[" << node->getType().getArraySize() << "]";
149 }
alokp@chromium.org76b82082010-03-24 17:59:39 +0000150}
151
152void TOutputGLSL::visitConstantUnion(TIntermConstantUnion* node)
153{
alokp@chromium.orgb3f7fb62010-05-05 18:21:51 +0000154 writeConstantUnion(node->getType(), node->getUnionArrayPointer());
alokp@chromium.org76b82082010-03-24 17:59:39 +0000155}
156
157bool TOutputGLSL::visitBinary(Visit visit, TIntermBinary* node)
158{
159 bool visitChildren = true;
160 TInfoSinkBase& out = objSink();
161 switch (node->getOp())
162 {
163 case EOpAssign: writeTriplet(visit, NULL, " = ", NULL); break;
164 case EOpInitialize:
165 if (visit == InVisit) {
166 out << " = ";
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000167 mWriteFullSymbol= false;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000168 }
169 break;
170 case EOpAddAssign: writeTriplet(visit, NULL, " += ", NULL); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000171 case EOpSubAssign: writeTriplet(visit, NULL, " -= ", NULL); break;
172 case EOpDivAssign: writeTriplet(visit, NULL, " /= ", NULL); break;
173 case EOpMulAssign:
174 case EOpVectorTimesMatrixAssign:
175 case EOpVectorTimesScalarAssign:
176 case EOpMatrixTimesScalarAssign:
177 case EOpMatrixTimesMatrixAssign:
178 writeTriplet(visit, NULL, " *= ", NULL);
179 break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000180
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000181 case EOpIndexDirect:
182 case EOpIndexIndirect:
183 writeTriplet(visit, NULL, "[", "]");
184 break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000185 case EOpIndexDirectStruct:
186 if (visit == InVisit)
187 {
188 out << ".";
189 // TODO(alokp): ASSERT
190 out << node->getType().getFieldName();
191 visitChildren = false;
192 }
193 break;
194 case EOpVectorSwizzle:
195 if (visit == InVisit)
196 {
197 out << ".";
198 TIntermAggregate* rightChild = node->getRight()->getAsAggregate();
199 TIntermSequence& sequence = rightChild->getSequence();
200 for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); ++sit)
201 {
202 TIntermConstantUnion* element = (*sit)->getAsConstantUnion();
203 ASSERT(element->getBasicType() == EbtInt);
204 ASSERT(element->getNominalSize() == 1);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000205 const ConstantUnion& data = element->getUnionArrayPointer()[0];
alokp@chromium.org76b82082010-03-24 17:59:39 +0000206 ASSERT(data.getType() == EbtInt);
207 switch (data.getIConst())
208 {
209 case 0: out << "x"; break;
210 case 1: out << "y"; break;
211 case 2: out << "z"; break;
212 case 3: out << "w"; break;
213 default: UNREACHABLE(); break;
214 }
215 }
216 visitChildren = false;
217 }
218 break;
219
220 case EOpAdd: writeTriplet(visit, "(", " + ", ")"); break;
221 case EOpSub: writeTriplet(visit, "(", " - ", ")"); break;
222 case EOpMul: writeTriplet(visit, "(", " * ", ")"); break;
223 case EOpDiv: writeTriplet(visit, "(", " / ", ")"); break;
224 case EOpMod: UNIMPLEMENTED(); break;
alokp@chromium.org3d270782010-03-30 20:33:38 +0000225 case EOpEqual: writeTriplet(visit, "(", " == ", ")"); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000226 case EOpNotEqual: writeTriplet(visit, "(", " != ", ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000227 case EOpLessThan: writeTriplet(visit, "(", " < ", ")"); break;
alokp@chromium.orgdd037b22010-03-30 18:47:20 +0000228 case EOpGreaterThan: writeTriplet(visit, "(", " > ", ")"); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000229 case EOpLessThanEqual: writeTriplet(visit, "(", " <= ", ")"); break;
230 case EOpGreaterThanEqual: writeTriplet(visit, "(", " >= ", ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000231
232 // Notice the fall-through.
233 case EOpVectorTimesScalar:
234 case EOpVectorTimesMatrix:
235 case EOpMatrixTimesVector:
236 case EOpMatrixTimesScalar:
237 case EOpMatrixTimesMatrix:
238 writeTriplet(visit, "(", " * ", ")");
239 break;
240
241 case EOpLogicalOr: writeTriplet(visit, "(", " || ", ")"); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000242 case EOpLogicalXor: writeTriplet(visit, "(", " ^^ ", ")"); break;
243 case EOpLogicalAnd: writeTriplet(visit, "(", " && ", ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000244 default: UNREACHABLE(); break;
245 }
246
247 return visitChildren;
248}
249
250bool TOutputGLSL::visitUnary(Visit visit, TIntermUnary* node)
251{
252 TInfoSinkBase& out = objSink();
253
254 switch (node->getOp())
255 {
256 case EOpNegative: writeTriplet(visit, "(-", NULL, ")"); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000257 case EOpVectorLogicalNot: writeTriplet(visit, "(!", NULL, ")"); break;
258 case EOpLogicalNot: writeTriplet(visit, "(!", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000259
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000260 case EOpPostIncrement: writeTriplet(visit, "(", NULL, "++)"); break;
261 case EOpPostDecrement: writeTriplet(visit, "(", NULL, "--)"); break;
262 case EOpPreIncrement: writeTriplet(visit, "(++", NULL, ")"); break;
263 case EOpPreDecrement: writeTriplet(visit, "(--", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000264
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000265 case EOpConvIntToBool:
266 case EOpConvFloatToBool:
267 switch (node->getOperand()->getType().getNominalSize())
268 {
269 case 1: writeTriplet(visit, "bool(", NULL, ")"); break;
270 case 2: writeTriplet(visit, "bvec2(", NULL, ")"); break;
271 case 3: writeTriplet(visit, "bvec3(", NULL, ")"); break;
272 case 4: writeTriplet(visit, "bvec4(", NULL, ")"); break;
273 default: UNREACHABLE();
274 }
275 break;
276 case EOpConvBoolToFloat:
277 case EOpConvIntToFloat:
278 switch (node->getOperand()->getType().getNominalSize())
279 {
280 case 1: writeTriplet(visit, "float(", NULL, ")"); break;
281 case 2: writeTriplet(visit, "vec2(", NULL, ")"); break;
282 case 3: writeTriplet(visit, "vec3(", NULL, ")"); break;
283 case 4: writeTriplet(visit, "vec4(", NULL, ")"); break;
284 default: UNREACHABLE();
285 }
286 break;
287 case EOpConvFloatToInt:
288 case EOpConvBoolToInt:
289 switch (node->getOperand()->getType().getNominalSize())
290 {
291 case 1: writeTriplet(visit, "int(", NULL, ")"); break;
292 case 2: writeTriplet(visit, "ivec2(", NULL, ")"); break;
293 case 3: writeTriplet(visit, "ivec3(", NULL, ")"); break;
294 case 4: writeTriplet(visit, "ivec4(", NULL, ")"); break;
295 default: UNREACHABLE();
296 }
297 break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000298
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000299 case EOpRadians: writeTriplet(visit, "radians(", NULL, ")"); break;
300 case EOpDegrees: writeTriplet(visit, "degrees(", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000301 case EOpSin: writeTriplet(visit, "sin(", NULL, ")"); break;
302 case EOpCos: writeTriplet(visit, "cos(", NULL, ")"); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000303 case EOpTan: writeTriplet(visit, "tan(", NULL, ")"); break;
304 case EOpAsin: writeTriplet(visit, "asin(", NULL, ")"); break;
alokp@chromium.org3d270782010-03-30 20:33:38 +0000305 case EOpAcos: writeTriplet(visit, "acos(", NULL, ")"); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000306 case EOpAtan: writeTriplet(visit, "atan(", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000307
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000308 case EOpExp: writeTriplet(visit, "exp(", NULL, ")"); break;
309 case EOpLog: writeTriplet(visit, "log(", NULL, ")"); break;
310 case EOpExp2: writeTriplet(visit, "exp2(", NULL, ")"); break;
311 case EOpLog2: writeTriplet(visit, "log2(", NULL, ")"); break;
312 case EOpSqrt: writeTriplet(visit, "sqrt(", NULL, ")"); break;
313 case EOpInverseSqrt: writeTriplet(visit, "inversesqrt(", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000314
alokp@chromium.org3d270782010-03-30 20:33:38 +0000315 case EOpAbs: writeTriplet(visit, "abs(", NULL, ")"); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000316 case EOpSign: writeTriplet(visit, "sign(", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000317 case EOpFloor: writeTriplet(visit, "floor(", NULL, ")"); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000318 case EOpCeil: writeTriplet(visit, "ceil(", NULL, ")"); break;
319 case EOpFract: writeTriplet(visit, "fract(", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000320
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000321 case EOpLength: writeTriplet(visit, "length(", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000322 case EOpNormalize: writeTriplet(visit, "normalize(", NULL, ")"); break;
323
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000324 case EOpAny: writeTriplet(visit, "any(", NULL, ")"); break;
325 case EOpAll: writeTriplet(visit, "all(", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000326
327 default: UNREACHABLE(); break;
328 }
329
330 return true;
331}
332
333bool TOutputGLSL::visitSelection(Visit visit, TIntermSelection* node)
334{
335 TInfoSinkBase& out = objSink();
336
alokp@chromium.org60fe4072010-03-29 20:58:29 +0000337 if (node->usesTernaryOperator())
alokp@chromium.org76b82082010-03-24 17:59:39 +0000338 {
alokp@chromium.org60fe4072010-03-29 20:58:29 +0000339 out << "(";
340 node->getCondition()->traverse(this);
341 out << ") ? (";
342 node->getTrueBlock()->traverse(this);
343 out << ") : (";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000344 node->getFalseBlock()->traverse(this);
alokp@chromium.org60fe4072010-03-29 20:58:29 +0000345 out << ")";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000346 }
alokp@chromium.org60fe4072010-03-29 20:58:29 +0000347 else
348 {
349 out << "if (";
350 node->getCondition()->traverse(this);
351 out << ") {\n";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000352
alokp@chromium.org60fe4072010-03-29 20:58:29 +0000353 incrementDepth();
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000354 if (node->getTrueBlock())
355 {
356 node->getTrueBlock()->traverse(this);
357 }
alokp@chromium.orgb3f7fb62010-05-05 18:21:51 +0000358 out << ";\n}";
alokp@chromium.org60fe4072010-03-29 20:58:29 +0000359
360 if (node->getFalseBlock())
361 {
362 out << " else {\n";
363 node->getFalseBlock()->traverse(this);
alokp@chromium.orgb3f7fb62010-05-05 18:21:51 +0000364 out << ";\n}";
alokp@chromium.org60fe4072010-03-29 20:58:29 +0000365 }
366 decrementDepth();
367 out << "\n";
368 }
alokp@chromium.org76b82082010-03-24 17:59:39 +0000369 return false;
370}
371
372bool TOutputGLSL::visitAggregate(Visit visit, TIntermAggregate* node)
373{
alokp@chromium.orgb3f7fb62010-05-05 18:21:51 +0000374 bool visitChildren = true;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000375 TInfoSinkBase& out = objSink();
376 switch (node->getOp())
377 {
378 case EOpSequence:
alokp@chromium.orgb3f7fb62010-05-05 18:21:51 +0000379 if (visit == PreVisit)
380 {
381 if (mScopeSequences)
382 out << "{\n";
383 }
384 else if (visit == InVisit)
385 {
386 out << ";\n";
387 }
388 else if (visit == PostVisit)
389 {
390 out << ";\n";
391 if (mScopeSequences)
392 out << "}\n";
393 }
alokp@chromium.org76b82082010-03-24 17:59:39 +0000394 break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000395 case EOpPrototype:
396 // Function declaration.
397 if (visit == PreVisit)
398 {
399 TString returnType = getTypeName(node->getType());
400 out << returnType << " " << node->getName() << "(";
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000401 mWriteFullSymbol = true;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000402 }
403 else if (visit == InVisit)
404 {
405 // Called in between function arguments.
406 out << ", ";
407 }
408 else if (visit == PostVisit)
409 {
410 // Called after fucntion arguments.
411 out << ")";
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000412 mWriteFullSymbol = false;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000413 }
414 break;
alokp@chromium.orgb3f7fb62010-05-05 18:21:51 +0000415 case EOpFunction: {
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000416 // Function definition.
alokp@chromium.orgb3f7fb62010-05-05 18:21:51 +0000417 TString returnType = getTypeName(node->getType());
418 TString functionName = TFunction::unmangleName(node->getName());
419 out << returnType << " " << functionName;
420
421 // Function definition node contains one or two children nodes
422 // representing function parameters and function body. The latter
423 // is not present in case of empty function bodies.
424 const TIntermSequence& sequence = node->getSequence();
425 ASSERT((sequence.size() == 1) || (sequence.size() == 2));
426 TIntermSequence::const_iterator seqIter = sequence.begin();
427
428 // Traverse function parameters.
429 TIntermAggregate* params = (*seqIter)->getAsAggregate();
430 ASSERT(params != NULL);
431 ASSERT(params->getOp() == EOpParameters);
432 params->traverse(this);
433
434 // Traverse function body.
435 TIntermAggregate* body = ++seqIter != sequence.end() ?
436 (*seqIter)->getAsAggregate() : NULL;
437 if (body != NULL)
alokp@chromium.org76b82082010-03-24 17:59:39 +0000438 {
alokp@chromium.orgb3f7fb62010-05-05 18:21:51 +0000439 ASSERT(body->getOp() == EOpSequence);
440 // Sequences are scoped with {} inside function body so that
441 // variables are declared in the correct scope.
442 mScopeSequences = true;
443 body->traverse(this);
444 mScopeSequences = false;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000445 }
alokp@chromium.orgb3f7fb62010-05-05 18:21:51 +0000446 else
alokp@chromium.org76b82082010-03-24 17:59:39 +0000447 {
alokp@chromium.orgb3f7fb62010-05-05 18:21:51 +0000448 // Empty function body.
449 out << "{}\n";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000450 }
alokp@chromium.orgb3f7fb62010-05-05 18:21:51 +0000451
452 // Fully processed; no need to visit children.
453 visitChildren = false;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000454 break;
alokp@chromium.orgb3f7fb62010-05-05 18:21:51 +0000455 }
alokp@chromium.org76b82082010-03-24 17:59:39 +0000456 case EOpFunctionCall:
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000457 // Function call.
alokp@chromium.org76b82082010-03-24 17:59:39 +0000458 if (visit == PreVisit)
459 {
alokp@chromium.org43884872010-03-30 00:08:52 +0000460 TString functionName = TFunction::unmangleName(node->getName());
alokp@chromium.org76b82082010-03-24 17:59:39 +0000461 out << functionName << "(";
462 }
463 else if (visit == InVisit)
464 {
465 out << ", ";
466 }
467 else
468 {
469 out << ")";
470 }
471 break;
472 case EOpParameters:
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000473 // Function parameters.
alokp@chromium.org76b82082010-03-24 17:59:39 +0000474 if (visit == PreVisit)
475 {
476 out << "(";
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000477 mWriteFullSymbol = true;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000478 }
479 else if (visit == InVisit)
480 {
481 out << ", ";
482 }
483 else
484 {
485 out << ")";
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000486 mWriteFullSymbol = false;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000487 }
488 break;
489 case EOpDeclaration:
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000490 // Variable declaration.
alokp@chromium.org76b82082010-03-24 17:59:39 +0000491 if (visit == PreVisit)
492 {
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000493 mWriteFullSymbol = true;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000494 }
495 else if (visit == InVisit)
496 {
497 out << ", ";
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000498 mWriteFullSymbol = false;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000499 }
500 else
501 {
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000502 mWriteFullSymbol = false;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000503 }
504 break;
505
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000506 case EOpConstructFloat: writeTriplet(visit, "float(", NULL, ")"); break;
507 case EOpConstructVec2: writeTriplet(visit, "vec2(", ", ", ")"); break;
508 case EOpConstructVec3: writeTriplet(visit, "vec3(", ", ", ")"); break;
509 case EOpConstructVec4: writeTriplet(visit, "vec4(", ", ", ")"); break;
510 case EOpConstructBool: writeTriplet(visit, "bool(", NULL, ")"); break;
511 case EOpConstructBVec2: writeTriplet(visit, "bvec2(", ", ", ")"); break;
512 case EOpConstructBVec3: writeTriplet(visit, "bvec3(", ", ", ")"); break;
513 case EOpConstructBVec4: writeTriplet(visit, "bvec4(", ", ", ")"); break;
514 case EOpConstructInt: writeTriplet(visit, "int(", NULL, ")"); break;
515 case EOpConstructIVec2: writeTriplet(visit, "ivec2(", ", ", ")"); break;
516 case EOpConstructIVec3: writeTriplet(visit, "ivec3(", ", ", ")"); break;
517 case EOpConstructIVec4: writeTriplet(visit, "ivec4(", ", ", ")"); break;
518 case EOpConstructMat2: writeTriplet(visit, "mat2(", ", ", ")"); break;
519 case EOpConstructMat3: writeTriplet(visit, "mat3(", ", ", ")"); break;
520 case EOpConstructMat4: writeTriplet(visit, "mat4(", ", ", ")"); break;
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000521 case EOpConstructStruct:
522 if (visit == PreVisit)
523 {
524 const TType& type = node->getType();
525 ASSERT(type.getBasicType() == EbtStruct);
526 out << type.getTypeName() << "(";
527 }
528 else if (visit == InVisit)
529 {
530 out << ", ";
531 }
532 else
533 {
534 out << ")";
535 }
536 break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000537
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000538 case EOpLessThan: writeTriplet(visit, "lessThan(", ", ", ")"); break;
539 case EOpGreaterThan: writeTriplet(visit, "greaterThan(", ", ", ")"); break;
540 case EOpLessThanEqual: writeTriplet(visit, "lessThanEqual(", ", ", ")"); break;
541 case EOpGreaterThanEqual: writeTriplet(visit, "greaterThanEqual(", ", ", ")"); break;
542 case EOpVectorEqual: writeTriplet(visit, "equal(", ", ", ")"); break;
543 case EOpVectorNotEqual: writeTriplet(visit, "notEqual(", ", ", ")"); break;
544 case EOpComma: writeTriplet(visit, NULL, ", ", NULL); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000545
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000546 case EOpMod: writeTriplet(visit, "mod(", ", ", ")"); break;
547 case EOpPow: writeTriplet(visit, "pow(", ", ", ")"); break;
548 case EOpAtan: writeTriplet(visit, "atan(", ", ", ")"); break;
549 case EOpMin: writeTriplet(visit, "min(", ", ", ")"); break;
550 case EOpMax: writeTriplet(visit, "max(", ", ", ")"); break;
551 case EOpClamp: writeTriplet(visit, "clamp(", ", ", ")"); break;
552 case EOpMix: writeTriplet(visit, "mix(", ", ", ")"); break;
553 case EOpStep: writeTriplet(visit, "step(", ", ", ")"); break;
554 case EOpSmoothStep: writeTriplet(visit, "smoothstep(", ", ", ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000555
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000556 case EOpDistance: writeTriplet(visit, "distance(", ", ", ")"); break;
557 case EOpDot: writeTriplet(visit, "dot(", ", ", ")"); break;
558 case EOpCross: writeTriplet(visit, "cross(", ", ", ")"); break;
559 case EOpFaceForward: writeTriplet(visit, "faceforward(", ", ", ")"); break;
560 case EOpReflect: writeTriplet(visit, "reflect(", ", ", ")"); break;
561 case EOpRefract: writeTriplet(visit, "refract(", ", ", ")"); break;
562 case EOpMul: writeTriplet(visit, "matrixCompMult(", ", ", ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000563
564 default: UNREACHABLE(); break;
565 }
alokp@chromium.orgb3f7fb62010-05-05 18:21:51 +0000566 return visitChildren;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000567}
568
569bool TOutputGLSL::visitLoop(Visit visit, TIntermLoop* node)
570{
alokp@chromium.org376e1062010-03-31 20:25:53 +0000571 TInfoSinkBase& out = objSink();
572
573 // Loop header.
574 if (node->testFirst()) // for loop
575 {
576 out << "for (";
577 if (node->getInit())
578 node->getInit()->traverse(this);
579 out << "; ";
580
581 ASSERT(node->getTest() != NULL);
582 node->getTest()->traverse(this);
583 out << "; ";
584
585 if (node->getTerminal())
586 node->getTerminal()->traverse(this);
587 out << ") {\n";
588 }
589 else // do-while loop
590 {
591 out << "do {\n";
592 }
593
594 // Loop body.
595 if (node->getBody())
596 node->getBody()->traverse(this);
597
598 // Loop footer.
599 if (node->testFirst()) // for loop
600 {
601 out << "}\n";
602 }
603 else // do-while loop
604 {
605 out << "} while (";
606 ASSERT(node->getTest() != NULL);
607 node->getTest()->traverse(this);
608 out << ");\n";
609 }
610
611 // No need to visit children. They have been already processed in
612 // this function.
613 return false;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000614}
615
616bool TOutputGLSL::visitBranch(Visit visit, TIntermBranch* node)
617{
618 TInfoSinkBase &out = objSink();
619
620 switch (node->getFlowOp())
621 {
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000622 case EOpKill: writeTriplet(visit, "discard", NULL, NULL); break;
623 case EOpBreak: writeTriplet(visit, "break", NULL, NULL); break;
624 case EOpContinue: writeTriplet(visit, "continue", NULL, NULL); break;
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000625 case EOpReturn: writeTriplet(visit, "return ", NULL, NULL); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000626 default: UNREACHABLE(); break;
627 }
628
629 return true;
630}