1 | // |
2 | // Copyright (c) 2012-2013 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/DirectiveHandler.h" |
8 | |
9 | #include <sstream> |
10 | |
11 | #include "angle_gl.h" |
12 | #include "common/debug.h" |
13 | #include "compiler/translator/Common.h" |
14 | #include "compiler/translator/Diagnostics.h" |
15 | |
16 | namespace sh |
17 | { |
18 | |
19 | static TBehavior getBehavior(const std::string &str) |
20 | { |
21 | const char kRequire[] = "require" ; |
22 | const char kEnable[] = "enable" ; |
23 | const char kDisable[] = "disable" ; |
24 | const char kWarn[] = "warn" ; |
25 | |
26 | if (str == kRequire) |
27 | return EBhRequire; |
28 | else if (str == kEnable) |
29 | return EBhEnable; |
30 | else if (str == kDisable) |
31 | return EBhDisable; |
32 | else if (str == kWarn) |
33 | return EBhWarn; |
34 | return EBhUndefined; |
35 | } |
36 | |
37 | TDirectiveHandler::TDirectiveHandler(TExtensionBehavior &extBehavior, |
38 | TDiagnostics &diagnostics, |
39 | int &shaderVersion, |
40 | sh::GLenum shaderType, |
41 | bool debugShaderPrecisionSupported) |
42 | : mExtensionBehavior(extBehavior), |
43 | mDiagnostics(diagnostics), |
44 | mShaderVersion(shaderVersion), |
45 | mShaderType(shaderType), |
46 | mDebugShaderPrecisionSupported(debugShaderPrecisionSupported) |
47 | {} |
48 | |
49 | TDirectiveHandler::~TDirectiveHandler() {} |
50 | |
51 | void TDirectiveHandler::handleError(const angle::pp::SourceLocation &loc, const std::string &msg) |
52 | { |
53 | mDiagnostics.error(loc, msg.c_str(), "" ); |
54 | } |
55 | |
56 | void TDirectiveHandler::handlePragma(const angle::pp::SourceLocation &loc, |
57 | const std::string &name, |
58 | const std::string &value, |
59 | bool stdgl) |
60 | { |
61 | if (stdgl) |
62 | { |
63 | const char kInvariant[] = "invariant" ; |
64 | const char kAll[] = "all" ; |
65 | |
66 | if (name == kInvariant && value == kAll) |
67 | { |
68 | if (mShaderVersion == 300 && mShaderType == GL_FRAGMENT_SHADER) |
69 | { |
70 | // ESSL 3.00.4 section 4.6.1 |
71 | mDiagnostics.error( |
72 | loc, "#pragma STDGL invariant(all) can not be used in fragment shader" , |
73 | name.c_str()); |
74 | } |
75 | mPragma.stdgl.invariantAll = true; |
76 | } |
77 | // The STDGL pragma is used to reserve pragmas for use by future |
78 | // revisions of GLSL. Do not generate an error on unexpected |
79 | // name and value. |
80 | return; |
81 | } |
82 | else |
83 | { |
84 | const char kOptimize[] = "optimize" ; |
85 | const char kDebug[] = "debug" ; |
86 | const char kDebugShaderPrecision[] = "webgl_debug_shader_precision" ; |
87 | const char kOn[] = "on" ; |
88 | const char kOff[] = "off" ; |
89 | |
90 | bool invalidValue = false; |
91 | if (name == kOptimize) |
92 | { |
93 | if (value == kOn) |
94 | mPragma.optimize = true; |
95 | else if (value == kOff) |
96 | mPragma.optimize = false; |
97 | else |
98 | invalidValue = true; |
99 | } |
100 | else if (name == kDebug) |
101 | { |
102 | if (value == kOn) |
103 | mPragma.debug = true; |
104 | else if (value == kOff) |
105 | mPragma.debug = false; |
106 | else |
107 | invalidValue = true; |
108 | } |
109 | else if (name == kDebugShaderPrecision && mDebugShaderPrecisionSupported) |
110 | { |
111 | if (value == kOn) |
112 | mPragma.debugShaderPrecision = true; |
113 | else if (value == kOff) |
114 | mPragma.debugShaderPrecision = false; |
115 | else |
116 | invalidValue = true; |
117 | } |
118 | else |
119 | { |
120 | mDiagnostics.report(angle::pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name); |
121 | return; |
122 | } |
123 | |
124 | if (invalidValue) |
125 | { |
126 | mDiagnostics.error(loc, "invalid pragma value - 'on' or 'off' expected" , value.c_str()); |
127 | } |
128 | } |
129 | } |
130 | |
131 | void TDirectiveHandler::handleExtension(const angle::pp::SourceLocation &loc, |
132 | const std::string &name, |
133 | const std::string &behavior) |
134 | { |
135 | const char kExtAll[] = "all" ; |
136 | |
137 | TBehavior behaviorVal = getBehavior(behavior); |
138 | if (behaviorVal == EBhUndefined) |
139 | { |
140 | mDiagnostics.error(loc, "behavior invalid" , name.c_str()); |
141 | return; |
142 | } |
143 | |
144 | if (name == kExtAll) |
145 | { |
146 | if (behaviorVal == EBhRequire) |
147 | { |
148 | mDiagnostics.error(loc, "extension cannot have 'require' behavior" , name.c_str()); |
149 | } |
150 | else if (behaviorVal == EBhEnable) |
151 | { |
152 | mDiagnostics.error(loc, "extension cannot have 'enable' behavior" , name.c_str()); |
153 | } |
154 | else |
155 | { |
156 | for (TExtensionBehavior::iterator iter = mExtensionBehavior.begin(); |
157 | iter != mExtensionBehavior.end(); ++iter) |
158 | iter->second = behaviorVal; |
159 | } |
160 | return; |
161 | } |
162 | |
163 | TExtensionBehavior::iterator iter = mExtensionBehavior.find(GetExtensionByName(name.c_str())); |
164 | if (iter != mExtensionBehavior.end()) |
165 | { |
166 | iter->second = behaviorVal; |
167 | return; |
168 | } |
169 | |
170 | switch (behaviorVal) |
171 | { |
172 | case EBhRequire: |
173 | mDiagnostics.error(loc, "extension is not supported" , name.c_str()); |
174 | break; |
175 | case EBhEnable: |
176 | case EBhWarn: |
177 | case EBhDisable: |
178 | mDiagnostics.warning(loc, "extension is not supported" , name.c_str()); |
179 | break; |
180 | default: |
181 | UNREACHABLE(); |
182 | break; |
183 | } |
184 | } |
185 | |
186 | void TDirectiveHandler::handleVersion(const angle::pp::SourceLocation &loc, int version) |
187 | { |
188 | if (version == 100 || version == 300 || version == 310) |
189 | { |
190 | mShaderVersion = version; |
191 | } |
192 | else |
193 | { |
194 | std::stringstream stream = sh::InitializeStream<std::stringstream>(); |
195 | stream << version; |
196 | std::string str = stream.str(); |
197 | mDiagnostics.error(loc, "version number not supported" , str.c_str()); |
198 | } |
199 | } |
200 | |
201 | } // namespace sh |
202 | |