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