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/third_party/compiler/ArrayBoundsClamper.cpp b/src/third_party/compiler/ArrayBoundsClamper.cpp
index 2229cd2..288f552 100644
--- a/src/third_party/compiler/ArrayBoundsClamper.cpp
+++ b/src/third_party/compiler/ArrayBoundsClamper.cpp
@@ -70,17 +70,14 @@
 }  // anonymous namespace
 
 ArrayBoundsClamper::ArrayBoundsClamper()
-    : mArrayBoundsClampDefinitionNeeded(false)
+    : mClampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC)
+    , mArrayBoundsClampDefinitionNeeded(false)
 {
 }
 
-void ArrayBoundsClamper::OutputClampingFunctionDefinition(TInfoSinkBase& out) const
+void ArrayBoundsClamper::SetClampingStrategy(ShArrayIndexClampingStrategy clampingStrategy)
 {
-    if (!mArrayBoundsClampDefinitionNeeded)
-    {
-        return;
-    }
-    out << kIntClampBegin << kIntClampDefinition << kIntClampEnd;
+    mClampingStrategy = clampingStrategy;
 }
 
 void ArrayBoundsClamper::MarkIndirectArrayBoundsForClamping(TIntermNode* root)
@@ -95,3 +92,15 @@
     }
 }
 
+void ArrayBoundsClamper::OutputClampingFunctionDefinition(TInfoSinkBase& out) const
+{
+    if (!mArrayBoundsClampDefinitionNeeded)
+    {
+        return;
+    }
+    if (mClampingStrategy != SH_CLAMP_WITH_USER_DEFINED_INT_CLAMP_FUNCTION)
+    {
+        return;
+    }
+    out << kIntClampBegin << kIntClampDefinition << kIntClampEnd;
+}
diff --git a/src/third_party/compiler/ArrayBoundsClamper.h b/src/third_party/compiler/ArrayBoundsClamper.h
index b63e6d9..0d4e1a3 100644
--- a/src/third_party/compiler/ArrayBoundsClamper.h
+++ b/src/third_party/compiler/ArrayBoundsClamper.h
@@ -35,13 +35,17 @@
 public:
     ArrayBoundsClamper();
 
-    // Output array clamp function source into the shader source.
-    void OutputClampingFunctionDefinition(TInfoSinkBase& out) const;
+    // Must be set before compiling any shaders to ensure consistency
+    // between the translated shaders and any necessary prequel.
+    void SetClampingStrategy(ShArrayIndexClampingStrategy clampingStrategy);
 
     // Marks nodes in the tree that index arrays indirectly as
     // requiring clamping.
     void MarkIndirectArrayBoundsForClamping(TIntermNode* root);
 
+    // If necessary, output array clamp function source into the shader source.
+    void OutputClampingFunctionDefinition(TInfoSinkBase& out) const;
+
     void Cleanup()
     {
         mArrayBoundsClampDefinitionNeeded = false;
@@ -50,7 +54,8 @@
 private:
     bool GetArrayBoundsClampDefinitionNeeded() const { return mArrayBoundsClampDefinitionNeeded; }
     void SetArrayBoundsClampDefinitionNeeded() { mArrayBoundsClampDefinitionNeeded = true; }
-    
+
+    ShArrayIndexClampingStrategy mClampingStrategy;
     bool mArrayBoundsClampDefinitionNeeded;
 };