blob: 3b639e9ca3ea0af94f2789a83031e73294775978 [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),
46 mWriteFullSymbol(false)
alokp@chromium.org76b82082010-03-24 17:59:39 +000047{
48}
49
alokp@chromium.org76b82082010-03-24 17:59:39 +000050void TOutputGLSL::writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr)
51{
52 TInfoSinkBase& out = objSink();
53 if (visit == PreVisit && preStr)
54 {
55 out << preStr;
56 }
57 else if (visit == InVisit && inStr)
58 {
59 out << inStr;
60 }
61 else if (visit == PostVisit && postStr)
62 {
63 out << postStr;
64 }
65}
66
67void TOutputGLSL::visitSymbol(TIntermSymbol* node)
68{
69 TInfoSinkBase& out = objSink();
alokp@chromium.orga499cfc2010-05-03 23:14:49 +000070 const TType& type = node->getType();
71
72 if (mWriteFullSymbol)
alokp@chromium.org76b82082010-03-24 17:59:39 +000073 {
74 TQualifier qualifier = node->getQualifier();
75 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal))
76 out << node->getQualifierString() << " ";
alokp@chromium.orga499cfc2010-05-03 23:14:49 +000077
78 // Declare the struct if we have not done so already.
79 if ((type.getBasicType() == EbtStruct) && (mDeclaredStructs.find(type.getTypeName()) == mDeclaredStructs.end()))
80 {
81 out << "struct " << type.getTypeName() << "{\n";
82 const TTypeList* structure = type.getStruct();
83 ASSERT(structure != NULL);
84 for (size_t i = 0; i < structure->size(); ++i)
85 {
86 const TType* fieldType = (*structure)[i].type;
87 ASSERT(fieldType != NULL);
88 out << getTypeName(*fieldType) << " " << fieldType->getFieldName() << ";\n";
89 }
90 out << "} ";
91 mDeclaredStructs.insert(type.getTypeName());
92 }
93 else
94 {
95 out << getTypeName(type) << " ";
96 }
alokp@chromium.org76b82082010-03-24 17:59:39 +000097 }
alokp@chromium.orga499cfc2010-05-03 23:14:49 +000098
alokp@chromium.org76b82082010-03-24 17:59:39 +000099 out << node->getSymbol();
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000100
101 if (mWriteFullSymbol && node->getType().isArray())
alokp@chromium.org3d270782010-03-30 20:33:38 +0000102 {
103 out << "[" << node->getType().getArraySize() << "]";
104 }
alokp@chromium.org76b82082010-03-24 17:59:39 +0000105}
106
107void TOutputGLSL::visitConstantUnion(TIntermConstantUnion* node)
108{
109 TInfoSinkBase& out = objSink();
110
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000111 const TType& type = node->getType();
alokp@chromium.org76b82082010-03-24 17:59:39 +0000112 int size = type.getObjectSize();
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000113 bool writeType = (size > 1) || (type.getBasicType() == EbtStruct);
114 if (writeType)
alokp@chromium.org76b82082010-03-24 17:59:39 +0000115 out << getTypeName(type) << "(";
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000116 for (int i = 0; i < size; ++i)
117 {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000118 const ConstantUnion& data = node->getUnionArrayPointer()[i];
alokp@chromium.org76b82082010-03-24 17:59:39 +0000119 switch (data.getType())
120 {
121 case EbtFloat: out << data.getFConst(); break;
122 case EbtInt: out << data.getIConst(); break;
123 case EbtBool: out << data.getBConst(); break;
124 default: UNREACHABLE(); break;
125 }
126 if (i != size - 1)
127 out << ", ";
128 }
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000129 if (writeType)
alokp@chromium.org76b82082010-03-24 17:59:39 +0000130 out << ")";
131}
132
133bool TOutputGLSL::visitBinary(Visit visit, TIntermBinary* node)
134{
135 bool visitChildren = true;
136 TInfoSinkBase& out = objSink();
137 switch (node->getOp())
138 {
139 case EOpAssign: writeTriplet(visit, NULL, " = ", NULL); break;
140 case EOpInitialize:
141 if (visit == InVisit) {
142 out << " = ";
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000143 mWriteFullSymbol= false;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000144 }
145 break;
146 case EOpAddAssign: writeTriplet(visit, NULL, " += ", NULL); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000147 case EOpSubAssign: writeTriplet(visit, NULL, " -= ", NULL); break;
148 case EOpDivAssign: writeTriplet(visit, NULL, " /= ", NULL); break;
149 case EOpMulAssign:
150 case EOpVectorTimesMatrixAssign:
151 case EOpVectorTimesScalarAssign:
152 case EOpMatrixTimesScalarAssign:
153 case EOpMatrixTimesMatrixAssign:
154 writeTriplet(visit, NULL, " *= ", NULL);
155 break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000156
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000157 case EOpIndexDirect:
158 case EOpIndexIndirect:
159 writeTriplet(visit, NULL, "[", "]");
160 break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000161 case EOpIndexDirectStruct:
162 if (visit == InVisit)
163 {
164 out << ".";
165 // TODO(alokp): ASSERT
166 out << node->getType().getFieldName();
167 visitChildren = false;
168 }
169 break;
170 case EOpVectorSwizzle:
171 if (visit == InVisit)
172 {
173 out << ".";
174 TIntermAggregate* rightChild = node->getRight()->getAsAggregate();
175 TIntermSequence& sequence = rightChild->getSequence();
176 for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); ++sit)
177 {
178 TIntermConstantUnion* element = (*sit)->getAsConstantUnion();
179 ASSERT(element->getBasicType() == EbtInt);
180 ASSERT(element->getNominalSize() == 1);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000181 const ConstantUnion& data = element->getUnionArrayPointer()[0];
alokp@chromium.org76b82082010-03-24 17:59:39 +0000182 ASSERT(data.getType() == EbtInt);
183 switch (data.getIConst())
184 {
185 case 0: out << "x"; break;
186 case 1: out << "y"; break;
187 case 2: out << "z"; break;
188 case 3: out << "w"; break;
189 default: UNREACHABLE(); break;
190 }
191 }
192 visitChildren = false;
193 }
194 break;
195
196 case EOpAdd: writeTriplet(visit, "(", " + ", ")"); break;
197 case EOpSub: writeTriplet(visit, "(", " - ", ")"); break;
198 case EOpMul: writeTriplet(visit, "(", " * ", ")"); break;
199 case EOpDiv: writeTriplet(visit, "(", " / ", ")"); break;
200 case EOpMod: UNIMPLEMENTED(); break;
alokp@chromium.org3d270782010-03-30 20:33:38 +0000201 case EOpEqual: writeTriplet(visit, "(", " == ", ")"); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000202 case EOpNotEqual: writeTriplet(visit, "(", " != ", ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000203 case EOpLessThan: writeTriplet(visit, "(", " < ", ")"); break;
alokp@chromium.orgdd037b22010-03-30 18:47:20 +0000204 case EOpGreaterThan: writeTriplet(visit, "(", " > ", ")"); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000205 case EOpLessThanEqual: writeTriplet(visit, "(", " <= ", ")"); break;
206 case EOpGreaterThanEqual: writeTriplet(visit, "(", " >= ", ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000207
208 // Notice the fall-through.
209 case EOpVectorTimesScalar:
210 case EOpVectorTimesMatrix:
211 case EOpMatrixTimesVector:
212 case EOpMatrixTimesScalar:
213 case EOpMatrixTimesMatrix:
214 writeTriplet(visit, "(", " * ", ")");
215 break;
216
217 case EOpLogicalOr: writeTriplet(visit, "(", " || ", ")"); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000218 case EOpLogicalXor: writeTriplet(visit, "(", " ^^ ", ")"); break;
219 case EOpLogicalAnd: writeTriplet(visit, "(", " && ", ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000220 default: UNREACHABLE(); break;
221 }
222
223 return visitChildren;
224}
225
226bool TOutputGLSL::visitUnary(Visit visit, TIntermUnary* node)
227{
228 TInfoSinkBase& out = objSink();
229
230 switch (node->getOp())
231 {
232 case EOpNegative: writeTriplet(visit, "(-", NULL, ")"); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000233 case EOpVectorLogicalNot: writeTriplet(visit, "(!", NULL, ")"); break;
234 case EOpLogicalNot: writeTriplet(visit, "(!", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000235
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000236 case EOpPostIncrement: writeTriplet(visit, "(", NULL, "++)"); break;
237 case EOpPostDecrement: writeTriplet(visit, "(", NULL, "--)"); break;
238 case EOpPreIncrement: writeTriplet(visit, "(++", NULL, ")"); break;
239 case EOpPreDecrement: writeTriplet(visit, "(--", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000240
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000241 case EOpConvIntToBool:
242 case EOpConvFloatToBool:
243 switch (node->getOperand()->getType().getNominalSize())
244 {
245 case 1: writeTriplet(visit, "bool(", NULL, ")"); break;
246 case 2: writeTriplet(visit, "bvec2(", NULL, ")"); break;
247 case 3: writeTriplet(visit, "bvec3(", NULL, ")"); break;
248 case 4: writeTriplet(visit, "bvec4(", NULL, ")"); break;
249 default: UNREACHABLE();
250 }
251 break;
252 case EOpConvBoolToFloat:
253 case EOpConvIntToFloat:
254 switch (node->getOperand()->getType().getNominalSize())
255 {
256 case 1: writeTriplet(visit, "float(", NULL, ")"); break;
257 case 2: writeTriplet(visit, "vec2(", NULL, ")"); break;
258 case 3: writeTriplet(visit, "vec3(", NULL, ")"); break;
259 case 4: writeTriplet(visit, "vec4(", NULL, ")"); break;
260 default: UNREACHABLE();
261 }
262 break;
263 case EOpConvFloatToInt:
264 case EOpConvBoolToInt:
265 switch (node->getOperand()->getType().getNominalSize())
266 {
267 case 1: writeTriplet(visit, "int(", NULL, ")"); break;
268 case 2: writeTriplet(visit, "ivec2(", NULL, ")"); break;
269 case 3: writeTriplet(visit, "ivec3(", NULL, ")"); break;
270 case 4: writeTriplet(visit, "ivec4(", NULL, ")"); break;
271 default: UNREACHABLE();
272 }
273 break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000274
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000275 case EOpRadians: writeTriplet(visit, "radians(", NULL, ")"); break;
276 case EOpDegrees: writeTriplet(visit, "degrees(", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000277 case EOpSin: writeTriplet(visit, "sin(", NULL, ")"); break;
278 case EOpCos: writeTriplet(visit, "cos(", NULL, ")"); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000279 case EOpTan: writeTriplet(visit, "tan(", NULL, ")"); break;
280 case EOpAsin: writeTriplet(visit, "asin(", NULL, ")"); break;
alokp@chromium.org3d270782010-03-30 20:33:38 +0000281 case EOpAcos: writeTriplet(visit, "acos(", NULL, ")"); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000282 case EOpAtan: writeTriplet(visit, "atan(", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000283
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000284 case EOpExp: writeTriplet(visit, "exp(", NULL, ")"); break;
285 case EOpLog: writeTriplet(visit, "log(", NULL, ")"); break;
286 case EOpExp2: writeTriplet(visit, "exp2(", NULL, ")"); break;
287 case EOpLog2: writeTriplet(visit, "log2(", NULL, ")"); break;
288 case EOpSqrt: writeTriplet(visit, "sqrt(", NULL, ")"); break;
289 case EOpInverseSqrt: writeTriplet(visit, "inversesqrt(", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000290
alokp@chromium.org3d270782010-03-30 20:33:38 +0000291 case EOpAbs: writeTriplet(visit, "abs(", NULL, ")"); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000292 case EOpSign: writeTriplet(visit, "sign(", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000293 case EOpFloor: writeTriplet(visit, "floor(", NULL, ")"); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000294 case EOpCeil: writeTriplet(visit, "ceil(", NULL, ")"); break;
295 case EOpFract: writeTriplet(visit, "fract(", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000296
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000297 case EOpLength: writeTriplet(visit, "length(", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000298 case EOpNormalize: writeTriplet(visit, "normalize(", NULL, ")"); break;
299
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000300 case EOpAny: writeTriplet(visit, "any(", NULL, ")"); break;
301 case EOpAll: writeTriplet(visit, "all(", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000302
303 default: UNREACHABLE(); break;
304 }
305
306 return true;
307}
308
309bool TOutputGLSL::visitSelection(Visit visit, TIntermSelection* node)
310{
311 TInfoSinkBase& out = objSink();
312
alokp@chromium.org60fe4072010-03-29 20:58:29 +0000313 if (node->usesTernaryOperator())
alokp@chromium.org76b82082010-03-24 17:59:39 +0000314 {
alokp@chromium.org60fe4072010-03-29 20:58:29 +0000315 out << "(";
316 node->getCondition()->traverse(this);
317 out << ") ? (";
318 node->getTrueBlock()->traverse(this);
319 out << ") : (";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000320 node->getFalseBlock()->traverse(this);
alokp@chromium.org60fe4072010-03-29 20:58:29 +0000321 out << ")";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000322 }
alokp@chromium.org60fe4072010-03-29 20:58:29 +0000323 else
324 {
325 out << "if (";
326 node->getCondition()->traverse(this);
327 out << ") {\n";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000328
alokp@chromium.org60fe4072010-03-29 20:58:29 +0000329 incrementDepth();
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000330 if (node->getTrueBlock())
331 {
332 node->getTrueBlock()->traverse(this);
333 }
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000334 out << "}";
alokp@chromium.org60fe4072010-03-29 20:58:29 +0000335
336 if (node->getFalseBlock())
337 {
338 out << " else {\n";
339 node->getFalseBlock()->traverse(this);
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000340 out << "}";
alokp@chromium.org60fe4072010-03-29 20:58:29 +0000341 }
342 decrementDepth();
343 out << "\n";
344 }
alokp@chromium.org76b82082010-03-24 17:59:39 +0000345 return false;
346}
347
348bool TOutputGLSL::visitAggregate(Visit visit, TIntermAggregate* node)
349{
350 TInfoSinkBase& out = objSink();
351 switch (node->getOp())
352 {
353 case EOpSequence:
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000354 writeTriplet(visit, NULL, ";\n", ";\n");
alokp@chromium.org76b82082010-03-24 17:59:39 +0000355 break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000356 case EOpPrototype:
357 // Function declaration.
358 if (visit == PreVisit)
359 {
360 TString returnType = getTypeName(node->getType());
361 out << returnType << " " << node->getName() << "(";
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000362 mWriteFullSymbol = true;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000363 }
364 else if (visit == InVisit)
365 {
366 // Called in between function arguments.
367 out << ", ";
368 }
369 else if (visit == PostVisit)
370 {
371 // Called after fucntion arguments.
372 out << ")";
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000373 mWriteFullSymbol = false;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000374 }
375 break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000376 case EOpFunction:
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000377 // Function definition.
alokp@chromium.org76b82082010-03-24 17:59:39 +0000378 if (visit == PreVisit)
379 {
alokp@chromium.orgdd037b22010-03-30 18:47:20 +0000380 TString returnType = getTypeName(node->getType());
alokp@chromium.org43884872010-03-30 00:08:52 +0000381 TString functionName = TFunction::unmangleName(node->getName());
alokp@chromium.org76b82082010-03-24 17:59:39 +0000382 out << returnType << " " << functionName;
383 }
384 else if (visit == InVisit)
385 {
386 // Called after traversing function arguments (EOpParameters)
387 // but before traversing function body (EOpSequence).
388 out << "{\n";
389 }
390 else if (visit == PostVisit)
391 {
392 // Called after traversing function body (EOpSequence).
393 out << "}\n";
394 }
395 break;
396 case EOpFunctionCall:
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000397 // Function call.
alokp@chromium.org76b82082010-03-24 17:59:39 +0000398 if (visit == PreVisit)
399 {
alokp@chromium.org43884872010-03-30 00:08:52 +0000400 TString functionName = TFunction::unmangleName(node->getName());
alokp@chromium.org76b82082010-03-24 17:59:39 +0000401 out << functionName << "(";
402 }
403 else if (visit == InVisit)
404 {
405 out << ", ";
406 }
407 else
408 {
409 out << ")";
410 }
411 break;
412 case EOpParameters:
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000413 // Function parameters.
alokp@chromium.org76b82082010-03-24 17:59:39 +0000414 if (visit == PreVisit)
415 {
416 out << "(";
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000417 mWriteFullSymbol = true;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000418 }
419 else if (visit == InVisit)
420 {
421 out << ", ";
422 }
423 else
424 {
425 out << ")";
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000426 mWriteFullSymbol = false;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000427 }
428 break;
429 case EOpDeclaration:
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000430 // Variable declaration.
alokp@chromium.org76b82082010-03-24 17:59:39 +0000431 if (visit == PreVisit)
432 {
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000433 mWriteFullSymbol = true;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000434 }
435 else if (visit == InVisit)
436 {
437 out << ", ";
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000438 mWriteFullSymbol = false;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000439 }
440 else
441 {
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000442 mWriteFullSymbol = false;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000443 }
444 break;
445
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000446 case EOpConstructFloat: writeTriplet(visit, "float(", NULL, ")"); break;
447 case EOpConstructVec2: writeTriplet(visit, "vec2(", ", ", ")"); break;
448 case EOpConstructVec3: writeTriplet(visit, "vec3(", ", ", ")"); break;
449 case EOpConstructVec4: writeTriplet(visit, "vec4(", ", ", ")"); break;
450 case EOpConstructBool: writeTriplet(visit, "bool(", NULL, ")"); break;
451 case EOpConstructBVec2: writeTriplet(visit, "bvec2(", ", ", ")"); break;
452 case EOpConstructBVec3: writeTriplet(visit, "bvec3(", ", ", ")"); break;
453 case EOpConstructBVec4: writeTriplet(visit, "bvec4(", ", ", ")"); break;
454 case EOpConstructInt: writeTriplet(visit, "int(", NULL, ")"); break;
455 case EOpConstructIVec2: writeTriplet(visit, "ivec2(", ", ", ")"); break;
456 case EOpConstructIVec3: writeTriplet(visit, "ivec3(", ", ", ")"); break;
457 case EOpConstructIVec4: writeTriplet(visit, "ivec4(", ", ", ")"); break;
458 case EOpConstructMat2: writeTriplet(visit, "mat2(", ", ", ")"); break;
459 case EOpConstructMat3: writeTriplet(visit, "mat3(", ", ", ")"); break;
460 case EOpConstructMat4: writeTriplet(visit, "mat4(", ", ", ")"); break;
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000461 case EOpConstructStruct:
462 if (visit == PreVisit)
463 {
464 const TType& type = node->getType();
465 ASSERT(type.getBasicType() == EbtStruct);
466 out << type.getTypeName() << "(";
467 }
468 else if (visit == InVisit)
469 {
470 out << ", ";
471 }
472 else
473 {
474 out << ")";
475 }
476 break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000477
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000478 case EOpLessThan: writeTriplet(visit, "lessThan(", ", ", ")"); break;
479 case EOpGreaterThan: writeTriplet(visit, "greaterThan(", ", ", ")"); break;
480 case EOpLessThanEqual: writeTriplet(visit, "lessThanEqual(", ", ", ")"); break;
481 case EOpGreaterThanEqual: writeTriplet(visit, "greaterThanEqual(", ", ", ")"); break;
482 case EOpVectorEqual: writeTriplet(visit, "equal(", ", ", ")"); break;
483 case EOpVectorNotEqual: writeTriplet(visit, "notEqual(", ", ", ")"); break;
484 case EOpComma: writeTriplet(visit, NULL, ", ", NULL); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000485
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000486 case EOpMod: writeTriplet(visit, "mod(", ", ", ")"); break;
487 case EOpPow: writeTriplet(visit, "pow(", ", ", ")"); break;
488 case EOpAtan: writeTriplet(visit, "atan(", ", ", ")"); break;
489 case EOpMin: writeTriplet(visit, "min(", ", ", ")"); break;
490 case EOpMax: writeTriplet(visit, "max(", ", ", ")"); break;
491 case EOpClamp: writeTriplet(visit, "clamp(", ", ", ")"); break;
492 case EOpMix: writeTriplet(visit, "mix(", ", ", ")"); break;
493 case EOpStep: writeTriplet(visit, "step(", ", ", ")"); break;
494 case EOpSmoothStep: writeTriplet(visit, "smoothstep(", ", ", ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000495
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000496 case EOpDistance: writeTriplet(visit, "distance(", ", ", ")"); break;
497 case EOpDot: writeTriplet(visit, "dot(", ", ", ")"); break;
498 case EOpCross: writeTriplet(visit, "cross(", ", ", ")"); break;
499 case EOpFaceForward: writeTriplet(visit, "faceforward(", ", ", ")"); break;
500 case EOpReflect: writeTriplet(visit, "reflect(", ", ", ")"); break;
501 case EOpRefract: writeTriplet(visit, "refract(", ", ", ")"); break;
502 case EOpMul: writeTriplet(visit, "matrixCompMult(", ", ", ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000503
504 default: UNREACHABLE(); break;
505 }
506 return true;
507}
508
509bool TOutputGLSL::visitLoop(Visit visit, TIntermLoop* node)
510{
alokp@chromium.org376e1062010-03-31 20:25:53 +0000511 TInfoSinkBase& out = objSink();
512
513 // Loop header.
514 if (node->testFirst()) // for loop
515 {
516 out << "for (";
517 if (node->getInit())
518 node->getInit()->traverse(this);
519 out << "; ";
520
521 ASSERT(node->getTest() != NULL);
522 node->getTest()->traverse(this);
523 out << "; ";
524
525 if (node->getTerminal())
526 node->getTerminal()->traverse(this);
527 out << ") {\n";
528 }
529 else // do-while loop
530 {
531 out << "do {\n";
532 }
533
534 // Loop body.
535 if (node->getBody())
536 node->getBody()->traverse(this);
537
538 // Loop footer.
539 if (node->testFirst()) // for loop
540 {
541 out << "}\n";
542 }
543 else // do-while loop
544 {
545 out << "} while (";
546 ASSERT(node->getTest() != NULL);
547 node->getTest()->traverse(this);
548 out << ");\n";
549 }
550
551 // No need to visit children. They have been already processed in
552 // this function.
553 return false;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000554}
555
556bool TOutputGLSL::visitBranch(Visit visit, TIntermBranch* node)
557{
558 TInfoSinkBase &out = objSink();
559
560 switch (node->getFlowOp())
561 {
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000562 case EOpKill: writeTriplet(visit, "discard", NULL, NULL); break;
563 case EOpBreak: writeTriplet(visit, "break", NULL, NULL); break;
564 case EOpContinue: writeTriplet(visit, "continue", NULL, NULL); break;
alokp@chromium.orga499cfc2010-05-03 23:14:49 +0000565 case EOpReturn: writeTriplet(visit, "return ", NULL, NULL); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000566 default: UNREACHABLE(); break;
567 }
568
569 return true;
570}