Accept shader version 300 on ES3 contexts.

TRAC #22712
Signed-off-by: Jamie Madill
Signed-off-by: Shannon Woods
Author: Nicolas Capens

git-svn-id: https://angleproject.googlecode.com/svn/branches/es3proto@2121 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/compiler/Compiler.cpp b/src/compiler/Compiler.cpp
index c8c79e7..a602c38 100644
--- a/src/compiler/Compiler.cpp
+++ b/src/compiler/Compiler.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2013 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.
 //
@@ -118,6 +118,7 @@
 
 bool TCompiler::Init(const ShBuiltInResources& resources)
 {
+    shaderVersion = 100;
     maxUniformVectors = (shaderType == SH_VERTEX_SHADER) ?
         resources.MaxVertexUniformVectors :
         resources.MaxFragmentUniformVectors;
@@ -177,6 +178,9 @@
     bool success =
         (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], NULL, &parseContext) == 0) &&
         (parseContext.treeRoot != NULL);
+
+    shaderVersion = parseContext.shaderVersion();
+
     if (success) {
         TIntermNode* root = parseContext.treeRoot;
         success = intermediate.postProcess(root);
diff --git a/src/compiler/Diagnostics.cpp b/src/compiler/Diagnostics.cpp
index 06f370d..41fe811 100644
--- a/src/compiler/Diagnostics.cpp
+++ b/src/compiler/Diagnostics.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2012-2013 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.
 //
@@ -11,6 +11,7 @@
 #include "compiler/preprocessor/SourceLocation.h"
 
 TDiagnostics::TDiagnostics(TInfoSink& infoSink) :
+    mShaderVersion(100),
     mInfoSink(infoSink),
     mNumErrors(0),
     mNumWarnings(0)
@@ -21,6 +22,11 @@
 {
 }
 
+void TDiagnostics::setShaderVersion(int version)
+{
+    mShaderVersion = version;
+}
+
 void TDiagnostics::writeInfo(Severity severity,
                              const pp::SourceLocation& loc,
                              const std::string& reason,
diff --git a/src/compiler/Diagnostics.h b/src/compiler/Diagnostics.h
index cb71bb1..b4409e7 100644
--- a/src/compiler/Diagnostics.h
+++ b/src/compiler/Diagnostics.h
@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2012-2013 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.
 //
@@ -17,11 +17,14 @@
     TDiagnostics(TInfoSink& infoSink);
     virtual ~TDiagnostics();
 
+    int shaderVersion() const { return mShaderVersion; }
     TInfoSink& infoSink() { return mInfoSink; }
 
     int numErrors() const { return mNumErrors; }
     int numWarnings() const { return mNumWarnings; }
 
+    void setShaderVersion(int version);
+
     void writeInfo(Severity severity,
                    const pp::SourceLocation& loc,
                    const std::string& reason,
@@ -36,6 +39,8 @@
                        const std::string& text);
 
   private:
+    int mShaderVersion;
+
     TInfoSink& mInfoSink;
     int mNumErrors;
     int mNumWarnings;
diff --git a/src/compiler/DirectiveHandler.cpp b/src/compiler/DirectiveHandler.cpp
index d1f6ab3..85eac8c 100644
--- a/src/compiler/DirectiveHandler.cpp
+++ b/src/compiler/DirectiveHandler.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2012-2013 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.
 //
@@ -148,9 +148,12 @@
 void TDirectiveHandler::handleVersion(const pp::SourceLocation& loc,
                                       int version)
 {
-    static const int kVersion = 100;
-
-    if (version != kVersion)
+    if (version == 100 ||
+        version == 300)
+    {
+        mDiagnostics.setShaderVersion(version);
+    }
+    else
     {
         std::stringstream stream;
         stream << version;
diff --git a/src/compiler/ParseHelper.h b/src/compiler/ParseHelper.h
index 26a3ea1..1a52ab4 100644
--- a/src/compiler/ParseHelper.h
+++ b/src/compiler/ParseHelper.h
@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2013 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.
 //
@@ -66,6 +66,7 @@
     pp::Preprocessor preprocessor;
     void* scanner;
 
+    int shaderVersion() const { return diagnostics.shaderVersion(); }
     int numErrors() const { return diagnostics.numErrors(); }
     TInfoSink& infoSink() { return diagnostics.infoSink(); }
     void error(TSourceLoc loc, const char *reason, const char* token,
diff --git a/src/compiler/ShHandle.h b/src/compiler/ShHandle.h
index 2804930..5b70307 100644
--- a/src/compiler/ShHandle.h
+++ b/src/compiler/ShHandle.h
@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2013 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.
 //
@@ -67,6 +67,7 @@
                  int compileOptions);
 
     // Get results of the last compilation.
+    int getShaderVersion() const { return shaderVersion; }
     TInfoSink& getInfoSink() { return infoSink; }
     const TVariableInfoList& getAttribs() const { return attribs; }
     const TVariableInfoList& getUniforms() const { return uniforms; }
@@ -135,6 +136,7 @@
     BuiltInFunctionEmulator builtInFunctionEmulator;
 
     // Results of compilation.
+    int shaderVersion;
     TInfoSink infoSink;  // Output sink.
     TVariableInfoList attribs;  // Active attributes in the compiled shader.
     TVariableInfoList uniforms;  // Active uniforms in the compiled shader.
diff --git a/src/compiler/ShaderLang.cpp b/src/compiler/ShaderLang.cpp
index 92f3931..a11b663 100644
--- a/src/compiler/ShaderLang.cpp
+++ b/src/compiler/ShaderLang.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2013 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.
 //
@@ -250,6 +250,9 @@
     case SH_HASHED_NAMES_COUNT:
         *params = compiler->getNameMap().size();
         break;
+    case SH_SHADER_VERSION:
+        *params = compiler->getShaderVersion();
+        break;
     default: UNREACHABLE();
     }
 }
diff --git a/src/compiler/preprocessor/DirectiveParser.cpp b/src/compiler/preprocessor/DirectiveParser.cpp
index 94dfdf5..f28d8af 100644
--- a/src/compiler/preprocessor/DirectiveParser.cpp
+++ b/src/compiler/preprocessor/DirectiveParser.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2011-2013 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.
 //
@@ -708,7 +708,9 @@
 
     enum State
     {
-        VERSION_NUMBER
+        VERSION_NUMBER,
+        VERSION_PROFILE,
+        VERSION_ENDLINE
     };
 
     bool valid = true;
@@ -716,12 +718,12 @@
     int state = VERSION_NUMBER;
 
     mTokenizer->lex(token);
-    while ((token->type != '\n') && (token->type != Token::LAST))
+    while (valid && (token->type != '\n') && (token->type != Token::LAST))
     {
-        switch (state++)
+        switch (state)
         {
           case VERSION_NUMBER:
-            if (valid && (token->type != Token::CONST_INT))
+            if (token->type != Token::CONST_INT)
             {
                 mDiagnostics->report(Diagnostics::INVALID_VERSION_NUMBER,
                                      token->location, token->text);
@@ -733,26 +735,41 @@
                                      token->location, token->text);
                 valid = false;
             }
-            break;
-          default:
             if (valid)
             {
-                mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
+                state = (version < 300) ? VERSION_ENDLINE : VERSION_PROFILE;
+            }
+            break;
+          case VERSION_PROFILE:
+            if (token->type != Token::IDENTIFIER || token->text != "es")
+            {
+                mDiagnostics->report(Diagnostics::INVALID_VERSION_DIRECTIVE,
                                      token->location, token->text);
                 valid = false;
             }
+            state = VERSION_ENDLINE;
+            break;
+          default:
+            mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN,
+                                 token->location, token->text);
+            valid = false;
             break;
         }
+
         mTokenizer->lex(token);
     }
-    if (valid && (state != VERSION_NUMBER + 1))
+
+    if (valid && (state != VERSION_ENDLINE))
     {
         mDiagnostics->report(Diagnostics::INVALID_VERSION_DIRECTIVE,
                              token->location, token->text);
         valid = false;
     }
+
     if (valid)
+    {
         mDirectiveHandler->handleVersion(token->location, version);
+    }
 }
 
 void DirectiveParser::parseLine(Token* token)