blob: 3f87820263d4e16c0fa71e4d8f09209de1548b69 [file] [log] [blame]
alokp@chromium.org9ecf3952010-10-13 19:28:25 +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
7#include "compiler/VersionGLSL.h"
8
9static const int GLSL_VERSION_110 = 110;
10static const int GLSL_VERSION_120 = 120;
11
12// We need to scan for two things:
13// 1. "invariant" keyword: This can occur in both - vertex and fragment shaders
14// but only at the global scope.
15// 2. "gl_PointCoord" built-in variable: This can only occur in fragment shader
16// but inside any scope.
17// So we need to scan the entire fragment shader but only the global scope
18// of vertex shader.
19//
20// TODO(alokp): The following two cases of invariant decalaration get lost
21// during parsing - they do not get carried over to the intermediate tree.
22// Handle these cases:
23// 1. When a pragma is used to force all output variables to be invariant:
24// - #pragma STDGL invariant(all)
25// 2. When a previously decalared or built-in variable is marked invariant:
26// - invariant gl_Position;
27// - varying vec3 color; invariant color;
28//
29TVersionGLSL::TVersionGLSL(ShShaderType type)
30 : mShaderType(type),
31 mVersion(GLSL_VERSION_110)
32{
33}
34
35void TVersionGLSL::visitSymbol(TIntermSymbol* node)
36{
37 ASSERT(mShaderType == SH_FRAGMENT_SHADER);
38
39 if (node->getSymbol() == "gl_PointCoord")
40 updateVersion(GLSL_VERSION_120);
41}
42
43void TVersionGLSL::visitConstantUnion(TIntermConstantUnion*)
44{
45 ASSERT(mShaderType == SH_FRAGMENT_SHADER);
46}
47
48bool TVersionGLSL::visitBinary(Visit, TIntermBinary*)
49{
50 ASSERT(mShaderType == SH_FRAGMENT_SHADER);
51 return true;
52}
53
54bool TVersionGLSL::visitUnary(Visit, TIntermUnary*)
55{
56 ASSERT(mShaderType == SH_FRAGMENT_SHADER);
57 return true;
58}
59
60bool TVersionGLSL::visitSelection(Visit, TIntermSelection*)
61{
62 ASSERT(mShaderType == SH_FRAGMENT_SHADER);
63 return true;
64}
65
66bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate* node)
67{
68 // We need to scan the entire fragment shader but only the global scope
69 // of vertex shader.
70 bool visitChildren = mShaderType == SH_FRAGMENT_SHADER ? true : false;
71
72 switch (node->getOp()) {
73 case EOpSequence:
74 // We need to visit sequence children to get to global or inner scope.
75 visitChildren = true;
76 break;
77 case EOpDeclaration: {
78 const TIntermSequence& sequence = node->getSequence();
79 TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
80 if ((qualifier == EvqInvariantVaryingIn) ||
81 (qualifier == EvqInvariantVaryingOut)) {
82 updateVersion(GLSL_VERSION_120);
83 }
84 break;
85 }
86 default: break;
87 }
88
89 return visitChildren;
90}
91
92bool TVersionGLSL::visitLoop(Visit, TIntermLoop*)
93{
94 ASSERT(mShaderType == SH_FRAGMENT_SHADER);
95 return true;
96}
97
98bool TVersionGLSL::visitBranch(Visit, TIntermBranch*)
99{
100 ASSERT(mShaderType == SH_FRAGMENT_SHADER);
101 return true;
102}
103
104void TVersionGLSL::updateVersion(int version)
105{
106 mVersion = std::max(version, mVersion);
107}
108