• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2012 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 
getBehavior(const std::string & str)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 
TDirectiveHandler(TExtensionBehavior & extBehavior,TDiagnostics & diagnostics,int & shaderVersion,sh::GLenum shaderType,bool debugShaderPrecisionSupported)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 
~TDirectiveHandler()49 TDirectiveHandler::~TDirectiveHandler() {}
50 
handleError(const angle::pp::SourceLocation & loc,const std::string & msg)51 void TDirectiveHandler::handleError(const angle::pp::SourceLocation &loc, const std::string &msg)
52 {
53     mDiagnostics.error(loc, msg.c_str(), "");
54 }
55 
handlePragma(const angle::pp::SourceLocation & loc,const std::string & name,const std::string & value,bool stdgl)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 
handleExtension(const angle::pp::SourceLocation & loc,const std::string & name,const std::string & behavior)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         // OVR_multiview is implicitly enabled when OVR_multiview2 is enabled
168         if (name == "GL_OVR_multiview2")
169         {
170             const std::string multiview = "GL_OVR_multiview";
171             TExtensionBehavior::iterator iterMultiview =
172                 mExtensionBehavior.find(GetExtensionByName(multiview.c_str()));
173             if (iterMultiview != mExtensionBehavior.end())
174             {
175                 iterMultiview->second = behaviorVal;
176             }
177         }
178         return;
179     }
180 
181     switch (behaviorVal)
182     {
183         case EBhRequire:
184             mDiagnostics.error(loc, "extension is not supported", name.c_str());
185             break;
186         case EBhEnable:
187         case EBhWarn:
188         case EBhDisable:
189             mDiagnostics.warning(loc, "extension is not supported", name.c_str());
190             break;
191         default:
192             UNREACHABLE();
193             break;
194     }
195 }
196 
handleVersion(const angle::pp::SourceLocation & loc,int version,ShShaderSpec spec)197 void TDirectiveHandler::handleVersion(const angle::pp::SourceLocation &loc,
198                                       int version,
199                                       ShShaderSpec spec)
200 {
201     if (((version == 100 || version == 300 || version == 310) && !IsDesktopGLSpec(spec)) ||
202         IsDesktopGLSpec(spec))
203     {
204         mShaderVersion = version;
205     }
206     else
207     {
208         std::stringstream stream = sh::InitializeStream<std::stringstream>();
209         stream << version;
210         std::string str = stream.str();
211         mDiagnostics.error(loc, "client/version number not supported", str.c_str());
212     }
213 }
214 
215 }  // namespace sh
216