blob: 2b42a814585a4866ce6496bdcdae904e11428ce6 [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}
41
alokp@chromium.org76b82082010-03-24 17:59:39 +000042TString getIndentationString(int depth)
43{
44 TString indentation(depth, ' ');
45 return indentation;
46}
47} // namespace
48
49TOutputGLSL::TOutputGLSL(TParseContext &context)
50 : TIntermTraverser(true, true, true),
51 writeFullSymbol(false),
52 parseContext(context)
53{
54}
55
alokp@chromium.orgdd037b22010-03-30 18:47:20 +000056// Header declares user-defined structs.
alokp@chromium.org76b82082010-03-24 17:59:39 +000057void TOutputGLSL::header()
58{
59 TInfoSinkBase& out = objSink();
60
61 TSymbolTableLevel* symbols = parseContext.symbolTable.getGlobalLevel();
62 for (TSymbolTableLevel::const_iterator symbolIter = symbols->begin(); symbolIter != symbols->end(); ++symbolIter)
63 {
64 const TSymbol* symbol = symbolIter->second;
65 if (!symbol->isVariable())
66 continue;
67
68 const TVariable* variable = static_cast<const TVariable*>(symbol);
alokp@chromium.orgdd037b22010-03-30 18:47:20 +000069 if (!variable->isUserType())
70 continue;
alokp@chromium.org76b82082010-03-24 17:59:39 +000071
alokp@chromium.orgdd037b22010-03-30 18:47:20 +000072 const TType& type = variable->getType();
73 ASSERT(type.getQualifier() == EvqTemporary);
74 ASSERT(type.getBasicType() == EbtStruct);
75
76 out << "struct " << variable->getName() << "{\n";
77 const TTypeList* structure = type.getStruct();
78 ASSERT(structure != NULL);
79 incrementDepth();
80 for (size_t i = 0; i < structure->size(); ++i) {
81 const TType* fieldType = (*structure)[i].type;
82 ASSERT(fieldType != NULL);
83 out << getIndentationString(depth);
84 out << getTypeName(*fieldType) << " " << fieldType->getFieldName() << ";\n";
85 }
86 decrementDepth();
87 out << "};\n";
alokp@chromium.org76b82082010-03-24 17:59:39 +000088 }
89}
90
91void TOutputGLSL::writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr)
92{
93 TInfoSinkBase& out = objSink();
94 if (visit == PreVisit && preStr)
95 {
96 out << preStr;
97 }
98 else if (visit == InVisit && inStr)
99 {
100 out << inStr;
101 }
102 else if (visit == PostVisit && postStr)
103 {
104 out << postStr;
105 }
106}
107
108void TOutputGLSL::visitSymbol(TIntermSymbol* node)
109{
110 TInfoSinkBase& out = objSink();
111 if (writeFullSymbol)
112 {
113 TQualifier qualifier = node->getQualifier();
114 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal))
115 out << node->getQualifierString() << " ";
116
117 out << getTypeName(node->getType()) << " ";
118 }
119 out << node->getSymbol();
alokp@chromium.org3d270782010-03-30 20:33:38 +0000120 if (writeFullSymbol && node->getType().isArray())
121 {
122 out << "[" << node->getType().getArraySize() << "]";
123 }
alokp@chromium.org76b82082010-03-24 17:59:39 +0000124}
125
126void TOutputGLSL::visitConstantUnion(TIntermConstantUnion* node)
127{
128 TInfoSinkBase& out = objSink();
129
130 TType type = node->getType();
131 int size = type.getObjectSize();
132 if (size > 1)
133 out << getTypeName(type) << "(";
134 for (int i = 0; i < size; ++i) {
135 const constUnion& data = node->getUnionArrayPointer()[i];
136 switch (data.getType())
137 {
138 case EbtFloat: out << data.getFConst(); break;
139 case EbtInt: out << data.getIConst(); break;
140 case EbtBool: out << data.getBConst(); break;
141 default: UNREACHABLE(); break;
142 }
143 if (i != size - 1)
144 out << ", ";
145 }
146 if (size > 1)
147 out << ")";
148}
149
150bool TOutputGLSL::visitBinary(Visit visit, TIntermBinary* node)
151{
152 bool visitChildren = true;
153 TInfoSinkBase& out = objSink();
154 switch (node->getOp())
155 {
156 case EOpAssign: writeTriplet(visit, NULL, " = ", NULL); break;
157 case EOpInitialize:
158 if (visit == InVisit) {
159 out << " = ";
160 writeFullSymbol= false;
161 }
162 break;
163 case EOpAddAssign: writeTriplet(visit, NULL, " += ", NULL); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000164 case EOpSubAssign: writeTriplet(visit, NULL, " -= ", NULL); break;
165 case EOpDivAssign: writeTriplet(visit, NULL, " /= ", NULL); break;
166 case EOpMulAssign:
167 case EOpVectorTimesMatrixAssign:
168 case EOpVectorTimesScalarAssign:
169 case EOpMatrixTimesScalarAssign:
170 case EOpMatrixTimesMatrixAssign:
171 writeTriplet(visit, NULL, " *= ", NULL);
172 break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000173
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000174 case EOpIndexDirect:
175 case EOpIndexIndirect:
176 writeTriplet(visit, NULL, "[", "]");
177 break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000178 case EOpIndexDirectStruct:
179 if (visit == InVisit)
180 {
181 out << ".";
182 // TODO(alokp): ASSERT
183 out << node->getType().getFieldName();
184 visitChildren = false;
185 }
186 break;
187 case EOpVectorSwizzle:
188 if (visit == InVisit)
189 {
190 out << ".";
191 TIntermAggregate* rightChild = node->getRight()->getAsAggregate();
192 TIntermSequence& sequence = rightChild->getSequence();
193 for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); ++sit)
194 {
195 TIntermConstantUnion* element = (*sit)->getAsConstantUnion();
196 ASSERT(element->getBasicType() == EbtInt);
197 ASSERT(element->getNominalSize() == 1);
198 const constUnion& data = element->getUnionArrayPointer()[0];
199 ASSERT(data.getType() == EbtInt);
200 switch (data.getIConst())
201 {
202 case 0: out << "x"; break;
203 case 1: out << "y"; break;
204 case 2: out << "z"; break;
205 case 3: out << "w"; break;
206 default: UNREACHABLE(); break;
207 }
208 }
209 visitChildren = false;
210 }
211 break;
212
213 case EOpAdd: writeTriplet(visit, "(", " + ", ")"); break;
214 case EOpSub: writeTriplet(visit, "(", " - ", ")"); break;
215 case EOpMul: writeTriplet(visit, "(", " * ", ")"); break;
216 case EOpDiv: writeTriplet(visit, "(", " / ", ")"); break;
217 case EOpMod: UNIMPLEMENTED(); break;
alokp@chromium.org3d270782010-03-30 20:33:38 +0000218 case EOpEqual: writeTriplet(visit, "(", " == ", ")"); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000219 case EOpNotEqual: writeTriplet(visit, "(", " != ", ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000220 case EOpLessThan: writeTriplet(visit, "(", " < ", ")"); break;
alokp@chromium.orgdd037b22010-03-30 18:47:20 +0000221 case EOpGreaterThan: writeTriplet(visit, "(", " > ", ")"); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000222 case EOpLessThanEqual: writeTriplet(visit, "(", " <= ", ")"); break;
223 case EOpGreaterThanEqual: writeTriplet(visit, "(", " >= ", ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000224
225 // Notice the fall-through.
226 case EOpVectorTimesScalar:
227 case EOpVectorTimesMatrix:
228 case EOpMatrixTimesVector:
229 case EOpMatrixTimesScalar:
230 case EOpMatrixTimesMatrix:
231 writeTriplet(visit, "(", " * ", ")");
232 break;
233
234 case EOpLogicalOr: writeTriplet(visit, "(", " || ", ")"); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000235 case EOpLogicalXor: writeTriplet(visit, "(", " ^^ ", ")"); break;
236 case EOpLogicalAnd: writeTriplet(visit, "(", " && ", ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000237 default: UNREACHABLE(); break;
238 }
239
240 return visitChildren;
241}
242
243bool TOutputGLSL::visitUnary(Visit visit, TIntermUnary* node)
244{
245 TInfoSinkBase& out = objSink();
246
247 switch (node->getOp())
248 {
249 case EOpNegative: writeTriplet(visit, "(-", NULL, ")"); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000250 case EOpVectorLogicalNot: writeTriplet(visit, "(!", NULL, ")"); break;
251 case EOpLogicalNot: writeTriplet(visit, "(!", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000252
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000253 case EOpPostIncrement: writeTriplet(visit, "(", NULL, "++)"); break;
254 case EOpPostDecrement: writeTriplet(visit, "(", NULL, "--)"); break;
255 case EOpPreIncrement: writeTriplet(visit, "(++", NULL, ")"); break;
256 case EOpPreDecrement: writeTriplet(visit, "(--", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000257
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000258 case EOpConvIntToBool: writeTriplet(visit, "bool(", NULL, ")"); break;
259 case EOpConvFloatToBool: writeTriplet(visit, "bool(", NULL, ")"); break;
260 case EOpConvBoolToFloat: writeTriplet(visit, "float(", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000261 case EOpConvIntToFloat: writeTriplet(visit, "float(", NULL, ")"); break;
alokp@chromium.org3d270782010-03-30 20:33:38 +0000262 case EOpConvFloatToInt: writeTriplet(visit, "int(", NULL, ")"); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000263 case EOpConvBoolToInt: writeTriplet(visit, "int(", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000264
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000265 case EOpRadians: writeTriplet(visit, "radians(", NULL, ")"); break;
266 case EOpDegrees: writeTriplet(visit, "degrees(", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000267 case EOpSin: writeTriplet(visit, "sin(", NULL, ")"); break;
268 case EOpCos: writeTriplet(visit, "cos(", NULL, ")"); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000269 case EOpTan: writeTriplet(visit, "tan(", NULL, ")"); break;
270 case EOpAsin: writeTriplet(visit, "asin(", NULL, ")"); break;
alokp@chromium.org3d270782010-03-30 20:33:38 +0000271 case EOpAcos: writeTriplet(visit, "acos(", NULL, ")"); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000272 case EOpAtan: writeTriplet(visit, "atan(", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000273
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000274 case EOpExp: writeTriplet(visit, "exp(", NULL, ")"); break;
275 case EOpLog: writeTriplet(visit, "log(", NULL, ")"); break;
276 case EOpExp2: writeTriplet(visit, "exp2(", NULL, ")"); break;
277 case EOpLog2: writeTriplet(visit, "log2(", NULL, ")"); break;
278 case EOpSqrt: writeTriplet(visit, "sqrt(", NULL, ")"); break;
279 case EOpInverseSqrt: writeTriplet(visit, "inversesqrt(", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000280
alokp@chromium.org3d270782010-03-30 20:33:38 +0000281 case EOpAbs: writeTriplet(visit, "abs(", NULL, ")"); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000282 case EOpSign: writeTriplet(visit, "sign(", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000283 case EOpFloor: writeTriplet(visit, "floor(", NULL, ")"); break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000284 case EOpCeil: writeTriplet(visit, "ceil(", NULL, ")"); break;
285 case EOpFract: writeTriplet(visit, "fract(", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000286
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000287 case EOpLength: writeTriplet(visit, "length(", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000288 case EOpNormalize: writeTriplet(visit, "normalize(", NULL, ")"); break;
289
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000290 case EOpAny: writeTriplet(visit, "any(", NULL, ")"); break;
291 case EOpAll: writeTriplet(visit, "all(", NULL, ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000292
293 default: UNREACHABLE(); break;
294 }
295
296 return true;
297}
298
299bool TOutputGLSL::visitSelection(Visit visit, TIntermSelection* node)
300{
301 TInfoSinkBase& out = objSink();
302
alokp@chromium.org60fe4072010-03-29 20:58:29 +0000303 if (node->usesTernaryOperator())
alokp@chromium.org76b82082010-03-24 17:59:39 +0000304 {
alokp@chromium.org60fe4072010-03-29 20:58:29 +0000305 out << "(";
306 node->getCondition()->traverse(this);
307 out << ") ? (";
308 node->getTrueBlock()->traverse(this);
309 out << ") : (";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000310 node->getFalseBlock()->traverse(this);
alokp@chromium.org60fe4072010-03-29 20:58:29 +0000311 out << ")";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000312 }
alokp@chromium.org60fe4072010-03-29 20:58:29 +0000313 else
314 {
315 out << "if (";
316 node->getCondition()->traverse(this);
317 out << ") {\n";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000318
alokp@chromium.org60fe4072010-03-29 20:58:29 +0000319 incrementDepth();
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000320 if (node->getTrueBlock())
321 {
322 node->getTrueBlock()->traverse(this);
323 }
alokp@chromium.org60fe4072010-03-29 20:58:29 +0000324 out << getIndentationString(depth - 2) << "}";
325
326 if (node->getFalseBlock())
327 {
328 out << " else {\n";
329 node->getFalseBlock()->traverse(this);
330 out << getIndentationString(depth - 2) << "}";
331 }
332 decrementDepth();
333 out << "\n";
334 }
alokp@chromium.org76b82082010-03-24 17:59:39 +0000335 return false;
336}
337
338bool TOutputGLSL::visitAggregate(Visit visit, TIntermAggregate* node)
339{
340 TInfoSinkBase& out = objSink();
341 switch (node->getOp())
342 {
343 case EOpSequence:
344 if (visit == PreVisit)
345 {
346 out << getIndentationString(depth);
347 }
348 else if (visit == InVisit)
349 {
350 out << ";\n";
351 out << getIndentationString(depth - 1);
352 }
353 else
354 {
355 out << ";\n";
356 }
357 break;
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000358 case EOpPrototype:
359 // Function declaration.
360 if (visit == PreVisit)
361 {
362 TString returnType = getTypeName(node->getType());
363 out << returnType << " " << node->getName() << "(";
364 writeFullSymbol = true;
365 }
366 else if (visit == InVisit)
367 {
368 // Called in between function arguments.
369 out << ", ";
370 }
371 else if (visit == PostVisit)
372 {
373 // Called after fucntion arguments.
374 out << ")";
375 writeFullSymbol = false;
376 }
377 break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000378 case EOpFunction:
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000379 // Function definition.
alokp@chromium.org76b82082010-03-24 17:59:39 +0000380 if (visit == PreVisit)
381 {
alokp@chromium.orgdd037b22010-03-30 18:47:20 +0000382 TString returnType = getTypeName(node->getType());
alokp@chromium.org43884872010-03-30 00:08:52 +0000383 TString functionName = TFunction::unmangleName(node->getName());
alokp@chromium.org76b82082010-03-24 17:59:39 +0000384 out << returnType << " " << functionName;
385 }
386 else if (visit == InVisit)
387 {
388 // Called after traversing function arguments (EOpParameters)
389 // but before traversing function body (EOpSequence).
390 out << "{\n";
391 }
392 else if (visit == PostVisit)
393 {
394 // Called after traversing function body (EOpSequence).
395 out << "}\n";
396 }
397 break;
398 case EOpFunctionCall:
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000399 // Function call.
alokp@chromium.org76b82082010-03-24 17:59:39 +0000400 if (visit == PreVisit)
401 {
alokp@chromium.org43884872010-03-30 00:08:52 +0000402 TString functionName = TFunction::unmangleName(node->getName());
alokp@chromium.org76b82082010-03-24 17:59:39 +0000403 out << functionName << "(";
404 }
405 else if (visit == InVisit)
406 {
407 out << ", ";
408 }
409 else
410 {
411 out << ")";
412 }
413 break;
414 case EOpParameters:
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000415 // Function parameters.
alokp@chromium.org76b82082010-03-24 17:59:39 +0000416 if (visit == PreVisit)
417 {
418 out << "(";
419 writeFullSymbol = true;
420 }
421 else if (visit == InVisit)
422 {
423 out << ", ";
424 }
425 else
426 {
427 out << ")";
428 writeFullSymbol = false;
429 }
430 break;
431 case EOpDeclaration:
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000432 // Variable declaration.
alokp@chromium.org76b82082010-03-24 17:59:39 +0000433 if (visit == PreVisit)
434 {
435 writeFullSymbol = true;
436 }
437 else if (visit == InVisit)
438 {
439 out << ", ";
440 writeFullSymbol = false;
441 }
442 else
443 {
444 writeFullSymbol = false;
445 }
446 break;
447
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000448 case EOpConstructFloat: writeTriplet(visit, "float(", NULL, ")"); break;
449 case EOpConstructVec2: writeTriplet(visit, "vec2(", ", ", ")"); break;
450 case EOpConstructVec3: writeTriplet(visit, "vec3(", ", ", ")"); break;
451 case EOpConstructVec4: writeTriplet(visit, "vec4(", ", ", ")"); break;
452 case EOpConstructBool: writeTriplet(visit, "bool(", NULL, ")"); break;
453 case EOpConstructBVec2: writeTriplet(visit, "bvec2(", ", ", ")"); break;
454 case EOpConstructBVec3: writeTriplet(visit, "bvec3(", ", ", ")"); break;
455 case EOpConstructBVec4: writeTriplet(visit, "bvec4(", ", ", ")"); break;
456 case EOpConstructInt: writeTriplet(visit, "int(", NULL, ")"); break;
457 case EOpConstructIVec2: writeTriplet(visit, "ivec2(", ", ", ")"); break;
458 case EOpConstructIVec3: writeTriplet(visit, "ivec3(", ", ", ")"); break;
459 case EOpConstructIVec4: writeTriplet(visit, "ivec4(", ", ", ")"); break;
460 case EOpConstructMat2: writeTriplet(visit, "mat2(", ", ", ")"); break;
461 case EOpConstructMat3: writeTriplet(visit, "mat3(", ", ", ")"); break;
462 case EOpConstructMat4: writeTriplet(visit, "mat4(", ", ", ")"); break;
463 case EOpConstructStruct: UNIMPLEMENTED(); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000464
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000465 case EOpLessThan: writeTriplet(visit, "lessThan(", ", ", ")"); break;
466 case EOpGreaterThan: writeTriplet(visit, "greaterThan(", ", ", ")"); break;
467 case EOpLessThanEqual: writeTriplet(visit, "lessThanEqual(", ", ", ")"); break;
468 case EOpGreaterThanEqual: writeTriplet(visit, "greaterThanEqual(", ", ", ")"); break;
469 case EOpVectorEqual: writeTriplet(visit, "equal(", ", ", ")"); break;
470 case EOpVectorNotEqual: writeTriplet(visit, "notEqual(", ", ", ")"); break;
471 case EOpComma: writeTriplet(visit, NULL, ", ", NULL); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000472
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000473 case EOpMod: writeTriplet(visit, "mod(", ", ", ")"); break;
474 case EOpPow: writeTriplet(visit, "pow(", ", ", ")"); break;
475 case EOpAtan: writeTriplet(visit, "atan(", ", ", ")"); break;
476 case EOpMin: writeTriplet(visit, "min(", ", ", ")"); break;
477 case EOpMax: writeTriplet(visit, "max(", ", ", ")"); break;
478 case EOpClamp: writeTriplet(visit, "clamp(", ", ", ")"); break;
479 case EOpMix: writeTriplet(visit, "mix(", ", ", ")"); break;
480 case EOpStep: writeTriplet(visit, "step(", ", ", ")"); break;
481 case EOpSmoothStep: writeTriplet(visit, "smoothstep(", ", ", ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000482
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000483 case EOpDistance: writeTriplet(visit, "distance(", ", ", ")"); break;
484 case EOpDot: writeTriplet(visit, "dot(", ", ", ")"); break;
485 case EOpCross: writeTriplet(visit, "cross(", ", ", ")"); break;
486 case EOpFaceForward: writeTriplet(visit, "faceforward(", ", ", ")"); break;
487 case EOpReflect: writeTriplet(visit, "reflect(", ", ", ")"); break;
488 case EOpRefract: writeTriplet(visit, "refract(", ", ", ")"); break;
489 case EOpMul: writeTriplet(visit, "matrixCompMult(", ", ", ")"); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000490
491 default: UNREACHABLE(); break;
492 }
493 return true;
494}
495
496bool TOutputGLSL::visitLoop(Visit visit, TIntermLoop* node)
497{
alokp@chromium.org376e1062010-03-31 20:25:53 +0000498 TInfoSinkBase& out = objSink();
499
500 // Loop header.
501 if (node->testFirst()) // for loop
502 {
503 out << "for (";
504 if (node->getInit())
505 node->getInit()->traverse(this);
506 out << "; ";
507
508 ASSERT(node->getTest() != NULL);
509 node->getTest()->traverse(this);
510 out << "; ";
511
512 if (node->getTerminal())
513 node->getTerminal()->traverse(this);
514 out << ") {\n";
515 }
516 else // do-while loop
517 {
518 out << "do {\n";
519 }
520
521 // Loop body.
522 if (node->getBody())
523 node->getBody()->traverse(this);
524
525 // Loop footer.
526 if (node->testFirst()) // for loop
527 {
528 out << "}\n";
529 }
530 else // do-while loop
531 {
532 out << "} while (";
533 ASSERT(node->getTest() != NULL);
534 node->getTest()->traverse(this);
535 out << ");\n";
536 }
537
538 // No need to visit children. They have been already processed in
539 // this function.
540 return false;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000541}
542
543bool TOutputGLSL::visitBranch(Visit visit, TIntermBranch* node)
544{
545 TInfoSinkBase &out = objSink();
546
547 switch (node->getFlowOp())
548 {
alokp@chromium.org2986a8c2010-04-30 22:32:32 +0000549 case EOpKill: writeTriplet(visit, "discard", NULL, NULL); break;
550 case EOpBreak: writeTriplet(visit, "break", NULL, NULL); break;
551 case EOpContinue: writeTriplet(visit, "continue", NULL, NULL); break;
552 case EOpReturn: writeTriplet(visit, "return", NULL, NULL); break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000553 default: UNREACHABLE(); break;
554 }
555
556 return true;
557}