Move more draw call validation to the API.

The GL expects us to reject invalid draw calls before we start
doing any work, so we can prevent internal unnecessary state
changes.

BUG=angle:571

Change-Id: Ic71218b3c2d5dc310280d3738bb1387753a10e03
Reviewed-on: https://chromium-review.googlesource.com/203770
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Shannon Woods <shannonwoods@chromium.org>
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index 708c89e..6f08d99 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -1348,6 +1348,11 @@
 
 }
 
+GLuint Context::getCurrentProgram() const
+{
+    return mState.currentProgram;
+}
+
 void Context::bindTransformFeedback(GLuint transformFeedback)
 {
     TransformFeedback *transformFeedbackObject = getTransformFeedback(transformFeedback);
@@ -1491,7 +1496,7 @@
     return getCurrentVertexArray()->getElementArrayBuffer();
 }
 
-ProgramBinary *Context::getCurrentProgramBinary()
+ProgramBinary *Context::getCurrentProgramBinary() const
 {
     return mCurrentProgramBinary.get();
 }
@@ -2846,10 +2851,7 @@
 
 void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances)
 {
-    if (!mState.currentProgram)
-    {
-        return gl::error(GL_INVALID_OPERATION);
-    }
+    ASSERT(mState.currentProgram);
 
     ProgramBinary *programBinary = getCurrentProgramBinary();
     programBinary->applyUniforms();
@@ -2900,11 +2902,6 @@
         return;
     }
 
-    if (!programBinary->validateSamplers(NULL))
-    {
-        return gl::error(GL_INVALID_OPERATION);
-    }
-
     if (!skipDraw(mode))
     {
         mRenderer->drawArrays(mode, count, instances, transformFeedbackActive);
@@ -2918,16 +2915,7 @@
 
 void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances)
 {
-    if (!mState.currentProgram)
-    {
-        return gl::error(GL_INVALID_OPERATION);
-    }
-
-    VertexArray *vao = getCurrentVertexArray();
-    if (!indices && !vao->getElementArrayBuffer())
-    {
-        return gl::error(GL_INVALID_OPERATION);
-    }
+    ASSERT(mState.currentProgram);
 
     ProgramBinary *programBinary = getCurrentProgramBinary();
     programBinary->applyUniforms();
@@ -2957,6 +2945,7 @@
 
     applyState(mode);
 
+    VertexArray *vao = getCurrentVertexArray();
     rx::TranslatedIndexData indexInfo;
     GLenum err = mRenderer->applyIndexBuffer(indices, vao->getElementArrayBuffer(), count, mode, type, &indexInfo);
     if (err != GL_NO_ERROR)
@@ -2989,11 +2978,6 @@
         return;
     }
 
-    if (!programBinary->validateSamplers(NULL))
-    {
-        return gl::error(GL_INVALID_OPERATION);
-    }
-
     if (!skipDraw(mode))
     {
         mRenderer->drawElements(mode, count, type, indices, vao->getElementArrayBuffer(), indexInfo, instances);
diff --git a/src/libGLESv2/Context.h b/src/libGLESv2/Context.h
index ca57a0f..ea25110 100644
--- a/src/libGLESv2/Context.h
+++ b/src/libGLESv2/Context.h
@@ -309,6 +309,7 @@
     void useProgram(GLuint program);
     void linkProgram(GLuint program);
     void setProgramBinary(GLuint program, const void *binary, GLint length);
+    GLuint getCurrentProgram() const;
     void bindTransformFeedback(GLuint transformFeedback);
 
     void beginQuery(GLenum target, GLuint query);
@@ -344,7 +345,7 @@
     Buffer *getTargetBuffer(GLenum target) const;
     Buffer *getArrayBuffer();
     Buffer *getElementArrayBuffer() const;
-    ProgramBinary *getCurrentProgramBinary();
+    ProgramBinary *getCurrentProgramBinary() const;
 
     Texture *getTargetTexture(GLenum target) const;
     Texture2D *getTexture2D() const;
diff --git a/src/libGLESv2/validationES.cpp b/src/libGLESv2/validationES.cpp
index dba2231..ef516d5 100644
--- a/src/libGLESv2/validationES.cpp
+++ b/src/libGLESv2/validationES.cpp
@@ -19,6 +19,7 @@
 #include "libGLESv2/Query.h"
 #include "libGLESv2/ProgramBinary.h"
 #include "libGLESv2/TransformFeedback.h"
+#include "libGLESv2/VertexArray.h"
 
 #include "common/mathutil.h"
 #include "common/utilities.h"
@@ -1314,6 +1315,17 @@
         return gl::error(GL_INVALID_OPERATION, false);
     }
 
+    if (!context->getCurrentProgram())
+    {
+        return gl::error(GL_INVALID_OPERATION, false);
+    }
+
+    gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
+    if (!programBinary->validateSamplers(NULL))
+    {
+        return gl::error(GL_INVALID_OPERATION, false);
+    }
+
     // No-op if zero count
     return (count > 0);
 }
@@ -1390,6 +1402,12 @@
         return gl::error(GL_INVALID_OPERATION, false);
     }
 
+    gl::VertexArray *vao = context->getCurrentVertexArray();
+    if (!indices && !vao->getElementArrayBuffer())
+    {
+        return gl::error(GL_INVALID_OPERATION, false);
+    }
+
     if (!ValidateDrawBase(context, count))
     {
         return false;