Move all uniform validation from ProgramBinary to API layer.

This will have the contract of having a successful API call once we
call into the ANGLE internals, having successfully passed valiation.

BUG=angle:571

Change-Id: Ia8d6eccc1e42bdf9e9cc5c10094a08729b42778a
Reviewed-on: https://chromium-review.googlesource.com/200075
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Shannon Woods <shannonwoods@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libGLESv2/validationES.cpp b/src/libGLESv2/validationES.cpp
index 33ed71e..0fe7d22 100644
--- a/src/libGLESv2/validationES.cpp
+++ b/src/libGLESv2/validationES.cpp
@@ -17,6 +17,7 @@
 #include "libGLESv2/formatutils.h"
 #include "libGLESv2/main.h"
 #include "libGLESv2/Query.h"
+#include "libGLESv2/ProgramBinary.h"
 
 #include "common/mathutil.h"
 #include "common/utilities.h"
@@ -946,7 +947,8 @@
     return true;
 }
 
-static bool ValidateUniformCommonBase(gl::Context *context, GLint location, GLsizei count)
+static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniformType,
+                                      GLint location, GLsizei count, LinkedUniform **uniformOut)
 {
     if (count < 0)
     {
@@ -965,6 +967,20 @@
         return false;
     }
 
+    if (!programBinary->isValidUniformLocation(location))
+    {
+        return gl::error(GL_INVALID_OPERATION, false);
+    }
+
+    LinkedUniform *uniform = programBinary->getUniformByLocation(location);
+
+    // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+    if (uniform->elementCount() == 1 && count > 1)
+    {
+        return gl::error(GL_INVALID_OPERATION, false);
+    }
+
+    *uniformOut = uniform;
     return true;
 }
 
@@ -976,7 +992,20 @@
         return gl::error(GL_INVALID_OPERATION, false);
     }
 
-    return ValidateUniformCommonBase(context, location, count);
+    LinkedUniform *uniform = NULL;
+    if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform))
+    {
+        return false;
+    }
+
+    GLenum targetBoolType = UniformBoolVectorType(uniformType);
+    bool samplerUniformCheck = (IsSampler(uniform->type) && uniformType == GL_INT);
+    if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
+    {
+        return gl::error(GL_INVALID_OPERATION, false);
+    }
+
+    return true;
 }
 
 bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count,
@@ -995,7 +1024,18 @@
         return gl::error(GL_INVALID_VALUE, false);
     }
 
-    return ValidateUniformCommonBase(context, location, count);
+    LinkedUniform *uniform = NULL;
+    if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform))
+    {
+        return false;
+    }
+
+    if (uniform->type != matrixType)
+    {
+        return gl::error(GL_INVALID_OPERATION, false);
+    }
+
+    return true;
 }
 
 }