| // |
| // Copyright 2012 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| |
| #include "compiler/translator/DirectiveHandler.h" |
| |
| #include <sstream> |
| |
| #include "angle_gl.h" |
| #include "common/debug.h" |
| #include "compiler/translator/Common.h" |
| #include "compiler/translator/Diagnostics.h" |
| |
| namespace sh |
| { |
| |
| static TBehavior getBehavior(const std::string &str) |
| { |
| const char kRequire[] = "require"; |
| const char kEnable[] = "enable"; |
| const char kDisable[] = "disable"; |
| const char kWarn[] = "warn"; |
| |
| if (str == kRequire) |
| return EBhRequire; |
| else if (str == kEnable) |
| return EBhEnable; |
| else if (str == kDisable) |
| return EBhDisable; |
| else if (str == kWarn) |
| return EBhWarn; |
| return EBhUndefined; |
| } |
| |
| TDirectiveHandler::TDirectiveHandler(TExtensionBehavior &extBehavior, |
| TDiagnostics &diagnostics, |
| int &shaderVersion, |
| sh::GLenum shaderType, |
| bool debugShaderPrecisionSupported) |
| : mExtensionBehavior(extBehavior), |
| mDiagnostics(diagnostics), |
| mShaderVersion(shaderVersion), |
| mShaderType(shaderType), |
| mDebugShaderPrecisionSupported(debugShaderPrecisionSupported) |
| {} |
| |
| TDirectiveHandler::~TDirectiveHandler() {} |
| |
| void TDirectiveHandler::handleError(const angle::pp::SourceLocation &loc, const std::string &msg) |
| { |
| mDiagnostics.error(loc, msg.c_str(), ""); |
| } |
| |
| void TDirectiveHandler::handlePragma(const angle::pp::SourceLocation &loc, |
| const std::string &name, |
| const std::string &value, |
| bool stdgl) |
| { |
| if (stdgl) |
| { |
| const char kInvariant[] = "invariant"; |
| const char kAll[] = "all"; |
| |
| if (name == kInvariant && value == kAll) |
| { |
| if (mShaderVersion == 300 && mShaderType == GL_FRAGMENT_SHADER) |
| { |
| // ESSL 3.00.4 section 4.6.1 |
| mDiagnostics.error( |
| loc, "#pragma STDGL invariant(all) can not be used in fragment shader", |
| name.c_str()); |
| } |
| mPragma.stdgl.invariantAll = true; |
| } |
| // The STDGL pragma is used to reserve pragmas for use by future |
| // revisions of GLSL. Do not generate an error on unexpected |
| // name and value. |
| return; |
| } |
| else |
| { |
| const char kOptimize[] = "optimize"; |
| const char kDebug[] = "debug"; |
| const char kDebugShaderPrecision[] = "webgl_debug_shader_precision"; |
| const char kOn[] = "on"; |
| const char kOff[] = "off"; |
| |
| bool invalidValue = false; |
| if (name == kOptimize) |
| { |
| if (value == kOn) |
| mPragma.optimize = true; |
| else if (value == kOff) |
| mPragma.optimize = false; |
| else |
| invalidValue = true; |
| } |
| else if (name == kDebug) |
| { |
| if (value == kOn) |
| mPragma.debug = true; |
| else if (value == kOff) |
| mPragma.debug = false; |
| else |
| invalidValue = true; |
| } |
| else if (name == kDebugShaderPrecision && mDebugShaderPrecisionSupported) |
| { |
| if (value == kOn) |
| mPragma.debugShaderPrecision = true; |
| else if (value == kOff) |
| mPragma.debugShaderPrecision = false; |
| else |
| invalidValue = true; |
| } |
| else |
| { |
| mDiagnostics.report(angle::pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name); |
| return; |
| } |
| |
| if (invalidValue) |
| { |
| mDiagnostics.error(loc, "invalid pragma value - 'on' or 'off' expected", value.c_str()); |
| } |
| } |
| } |
| |
| void TDirectiveHandler::handleExtension(const angle::pp::SourceLocation &loc, |
| const std::string &name, |
| const std::string &behavior) |
| { |
| const char kExtAll[] = "all"; |
| |
| TBehavior behaviorVal = getBehavior(behavior); |
| if (behaviorVal == EBhUndefined) |
| { |
| mDiagnostics.error(loc, "behavior invalid", name.c_str()); |
| return; |
| } |
| |
| if (name == kExtAll) |
| { |
| if (behaviorVal == EBhRequire) |
| { |
| mDiagnostics.error(loc, "extension cannot have 'require' behavior", name.c_str()); |
| } |
| else if (behaviorVal == EBhEnable) |
| { |
| mDiagnostics.error(loc, "extension cannot have 'enable' behavior", name.c_str()); |
| } |
| else |
| { |
| for (TExtensionBehavior::iterator iter = mExtensionBehavior.begin(); |
| iter != mExtensionBehavior.end(); ++iter) |
| iter->second = behaviorVal; |
| } |
| return; |
| } |
| |
| TExtensionBehavior::iterator iter = mExtensionBehavior.find(GetExtensionByName(name.c_str())); |
| if (iter != mExtensionBehavior.end()) |
| { |
| iter->second = behaviorVal; |
| // OVR_multiview is implicitly enabled when OVR_multiview2 is enabled |
| if (name == "GL_OVR_multiview2") |
| { |
| const std::string multiview = "GL_OVR_multiview"; |
| TExtensionBehavior::iterator iterMultiview = |
| mExtensionBehavior.find(GetExtensionByName(multiview.c_str())); |
| if (iterMultiview != mExtensionBehavior.end()) |
| { |
| iterMultiview->second = behaviorVal; |
| } |
| } |
| return; |
| } |
| |
| switch (behaviorVal) |
| { |
| case EBhRequire: |
| mDiagnostics.error(loc, "extension is not supported", name.c_str()); |
| break; |
| case EBhEnable: |
| case EBhWarn: |
| case EBhDisable: |
| mDiagnostics.warning(loc, "extension is not supported", name.c_str()); |
| break; |
| default: |
| UNREACHABLE(); |
| break; |
| } |
| } |
| |
| void TDirectiveHandler::handleVersion(const angle::pp::SourceLocation &loc, |
| int version, |
| ShShaderSpec spec) |
| { |
| if (((version == 100 || version == 300 || version == 310) && !IsDesktopGLSpec(spec)) || |
| IsDesktopGLSpec(spec)) |
| { |
| mShaderVersion = version; |
| } |
| else |
| { |
| std::stringstream stream = sh::InitializeStream<std::stringstream>(); |
| stream << version; |
| std::string str = stream.str(); |
| mDiagnostics.error(loc, "client/version number not supported", str.c_str()); |
| } |
| } |
| |
| } // namespace sh |