Incorporated patch from haixia@ changing the default implementation of
array index clamping to use the clamp intrinsic. This works more
reliably on pure OpenGL ES devices and on Windows.

Added a mechanism in ShBuiltInResources to choose the strategy for
array index clamping.

BUG=none
TEST=various out-of-bounds array indexing tests and various WebGL content
Review URL: https://codereview.appspot.com/7194051

git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@1798 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/compiler/Compiler.cpp b/src/compiler/Compiler.cpp
index 1e2c945..f555537 100644
--- a/src/compiler/Compiler.cpp
+++ b/src/compiler/Compiler.cpp
@@ -102,6 +102,7 @@
 TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec)
     : shaderType(type),
       shaderSpec(spec),
+      clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
       builtInFunctionEmulator(type)
 {
     longNameMap = LongNameMap::GetInstance();
@@ -125,6 +126,9 @@
         return false;
     InitExtensionBehavior(resources, extensionBehavior);
 
+    arrayBoundsClamper.SetClampingStrategy(resources.ArrayIndexClampingStrategy);
+    clampingStrategy = resources.ArrayIndexClampingStrategy;
+
     hashFunction = resources.HashFunction;
 
     return true;
@@ -355,13 +359,17 @@
     return extensionBehavior;
 }
 
-const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const
-{
-    return builtInFunctionEmulator;
-}
-
 const ArrayBoundsClamper& TCompiler::getArrayBoundsClamper() const
 {
     return arrayBoundsClamper;
 }
 
+ShArrayIndexClampingStrategy TCompiler::getArrayIndexClampingStrategy() const
+{
+    return clampingStrategy;
+}
+
+const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const
+{
+    return builtInFunctionEmulator;
+}
diff --git a/src/compiler/OutputESSL.cpp b/src/compiler/OutputESSL.cpp
index 0331752..c2048f1 100644
--- a/src/compiler/OutputESSL.cpp
+++ b/src/compiler/OutputESSL.cpp
@@ -7,10 +7,11 @@
 #include "compiler/OutputESSL.h"
 
 TOutputESSL::TOutputESSL(TInfoSinkBase& objSink,
+                         ShArrayIndexClampingStrategy clampingStrategy,
                          ShHashFunction64 hashFunction,
                          NameMap& nameMap,
                          TSymbolTable& symbolTable)
-    : TOutputGLSLBase(objSink, hashFunction, nameMap, symbolTable)
+    : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable)
 {
 }
 
diff --git a/src/compiler/OutputESSL.h b/src/compiler/OutputESSL.h
index dd8c5ab..05db96e 100644
--- a/src/compiler/OutputESSL.h
+++ b/src/compiler/OutputESSL.h
@@ -13,6 +13,7 @@
 {
 public:
     TOutputESSL(TInfoSinkBase& objSink,
+                ShArrayIndexClampingStrategy clampingStrategy,
                 ShHashFunction64 hashFunction,
                 NameMap& nameMap,
                 TSymbolTable& symbolTable);
diff --git a/src/compiler/OutputGLSL.cpp b/src/compiler/OutputGLSL.cpp
index 5873042..206f403 100644
--- a/src/compiler/OutputGLSL.cpp
+++ b/src/compiler/OutputGLSL.cpp
@@ -7,10 +7,11 @@
 #include "compiler/OutputGLSL.h"
 
 TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink,
+                         ShArrayIndexClampingStrategy clampingStrategy,
                          ShHashFunction64 hashFunction,
                          NameMap& nameMap,
                          TSymbolTable& symbolTable)
-    : TOutputGLSLBase(objSink, hashFunction, nameMap, symbolTable)
+    : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable)
 {
 }
 
diff --git a/src/compiler/OutputGLSL.h b/src/compiler/OutputGLSL.h
index 9030212..199b6f3 100644
--- a/src/compiler/OutputGLSL.h
+++ b/src/compiler/OutputGLSL.h
@@ -13,6 +13,7 @@
 {
 public:
     TOutputGLSL(TInfoSinkBase& objSink,
+                ShArrayIndexClampingStrategy clampingStrategy,
                 ShHashFunction64 hashFunction,
                 NameMap& nameMap,
                 TSymbolTable& symbolTable);
diff --git a/src/compiler/OutputGLSLBase.cpp b/src/compiler/OutputGLSLBase.cpp
index 06eae13..45fabed 100644
--- a/src/compiler/OutputGLSLBase.cpp
+++ b/src/compiler/OutputGLSLBase.cpp
@@ -40,12 +40,14 @@
 }  // namespace
 
 TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase& objSink,
+                                 ShArrayIndexClampingStrategy clampingStrategy,
                                  ShHashFunction64 hashFunction,
                                  NameMap& nameMap,
                                  TSymbolTable& symbolTable)
     : TIntermTraverser(true, true, true),
       mObjSink(objSink),
       mDeclaringVariables(false),
+      mClampingStrategy(clampingStrategy),
       mHashFunction(hashFunction),
       mNameMap(nameMap),
       mSymbolTable(symbolTable)
@@ -221,7 +223,11 @@
             {
                 if (visit == InVisit)
                 {
-                    out << "[webgl_int_clamp(";
+                    if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) {
+                        out << "[int(clamp(float(";
+                    } else {
+                        out << "[webgl_int_clamp(";
+                    }
                 }
                 else if (visit == PostVisit)
                 {
@@ -238,7 +244,12 @@
                     {
                         maxSize = leftType.getNominalSize() - 1;
                     }
-                    out << ", 0, " << maxSize << ")]";
+
+                    if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) {
+                        out << "), 0.0, float(" << maxSize << ")))]";
+                    } else {
+                        out << ", 0, " << maxSize << ")]";
+                    }
                 }
             }
             else
diff --git a/src/compiler/OutputGLSLBase.h b/src/compiler/OutputGLSLBase.h
index 01e9d4a..c9f72d5 100644
--- a/src/compiler/OutputGLSLBase.h
+++ b/src/compiler/OutputGLSLBase.h
@@ -17,6 +17,7 @@
 {
 public:
     TOutputGLSLBase(TInfoSinkBase& objSink,
+                    ShArrayIndexClampingStrategy clampingStrategy,
                     ShHashFunction64 hashFunction,
                     NameMap& nameMap,
                     TSymbolTable& symbolTable);
@@ -62,8 +63,11 @@
 
     ForLoopUnroll mLoopUnroll;
 
+    ShArrayIndexClampingStrategy mClampingStrategy;
+
     // name hashing.
     ShHashFunction64 mHashFunction;
+
     NameMap& mNameMap;
 
     TSymbolTable& mSymbolTable;
diff --git a/src/compiler/ShHandle.h b/src/compiler/ShHandle.h
index a50be62..274f792 100644
--- a/src/compiler/ShHandle.h
+++ b/src/compiler/ShHandle.h
@@ -110,6 +110,7 @@
     const TExtensionBehavior& getExtensionBehavior() const;
 
     const ArrayBoundsClamper& getArrayBoundsClamper() const;
+    ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const;
     const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const;
 
 private:
@@ -125,6 +126,7 @@
     TExtensionBehavior extensionBehavior;
 
     ArrayBoundsClamper arrayBoundsClamper;
+    ShArrayIndexClampingStrategy clampingStrategy;
     BuiltInFunctionEmulator builtInFunctionEmulator;
 
     // Results of compilation.
diff --git a/src/compiler/ShaderLang.cpp b/src/compiler/ShaderLang.cpp
index a4a8f6c..8aed31b 100644
--- a/src/compiler/ShaderLang.cpp
+++ b/src/compiler/ShaderLang.cpp
@@ -129,6 +129,8 @@
 
     // Disable name hashing by default.
     resources->HashFunction = NULL;
+
+    resources->ArrayIndexClampingStrategy = SH_CLAMP_WITH_CLAMP_INTRINSIC;
 }
 
 //
@@ -363,4 +365,4 @@
         break;
     default: UNREACHABLE();
     }
-}
\ No newline at end of file
+}
diff --git a/src/compiler/TranslatorESSL.cpp b/src/compiler/TranslatorESSL.cpp
index a4f047a..2900f8a 100644
--- a/src/compiler/TranslatorESSL.cpp
+++ b/src/compiler/TranslatorESSL.cpp
@@ -26,7 +26,7 @@
     getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
 
     // Write translated shader.
-    TOutputESSL outputESSL(sink, getHashFunction(), getNameMap(), getSymbolTable());
+    TOutputESSL outputESSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable());
     root->traverse(&outputESSL);
 }
 
diff --git a/src/compiler/TranslatorGLSL.cpp b/src/compiler/TranslatorGLSL.cpp
index 5f3dbcc..7ca4341 100644
--- a/src/compiler/TranslatorGLSL.cpp
+++ b/src/compiler/TranslatorGLSL.cpp
@@ -39,6 +39,6 @@
     getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
 
     // Write translated shader.
-    TOutputGLSL outputGLSL(sink, getHashFunction(), getNameMap(), getSymbolTable());
+    TOutputGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable());
     root->traverse(&outputGLSL);
 }