Refactor some entry point stuff.

BUG=angleproject:747

Change-Id: I80634b5e6de8bae1433c49a56a92d3b19c24e11d
Reviewed-on: https://chromium-review.googlesource.com/395568
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
index c4124b3..235a3a5 100644
--- a/src/libANGLE/Context.cpp
+++ b/src/libANGLE/Context.cpp
@@ -817,16 +817,6 @@
     return mResourceManager->getBuffer(handle);
 }
 
-Shader *Context::getShader(GLuint handle) const
-{
-    return mResourceManager->getShader(handle);
-}
-
-Program *Context::getProgram(GLuint handle) const
-{
-    return mResourceManager->getProgram(handle);
-}
-
 Texture *Context::getTexture(GLuint handle) const
 {
     return mResourceManager->getTexture(handle);
@@ -3559,4 +3549,12 @@
     handleError(buffer->bufferSubData(target, data, size, offset));
 }
 
+void Context::attachShader(GLuint program, GLuint shader)
+{
+    auto programObject = mResourceManager->getProgram(program);
+    auto shaderObject  = mResourceManager->getShader(shader);
+    ASSERT(programObject && shaderObject);
+    programObject->attachShader(shaderObject);
+}
+
 }  // namespace gl
diff --git a/src/libANGLE/Context.h b/src/libANGLE/Context.h
index 7fa050d..ae84144 100644
--- a/src/libANGLE/Context.h
+++ b/src/libANGLE/Context.h
@@ -165,8 +165,6 @@
     Buffer *getBuffer(GLuint handle) const;
     FenceNV *getFenceNV(GLuint handle);
     FenceSync *getFenceSync(GLsync handle) const;
-    Shader *getShader(GLuint handle) const;
-    Program *getProgram(GLuint handle) const;
     Texture *getTexture(GLuint handle) const;
     Framebuffer *getFramebuffer(GLuint handle) const;
     Renderbuffer *getRenderbuffer(GLuint handle) const;
@@ -576,6 +574,7 @@
 
     void bufferData(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);
     void bufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data);
+    void attachShader(GLuint program, GLuint shader);
 
     void handleError(const Error &error) override;
 
diff --git a/src/libANGLE/ContextState.cpp b/src/libANGLE/ContextState.cpp
index 56f8d99..dae319c 100644
--- a/src/libANGLE/ContextState.cpp
+++ b/src/libANGLE/ContextState.cpp
@@ -576,4 +576,14 @@
     return false;
 }
 
+Program *ValidationContext::getProgram(GLuint handle) const
+{
+    return mState.mResourceManager->getProgram(handle);
+}
+
+Shader *ValidationContext::getShader(GLuint handle) const
+{
+    return mState.mResourceManager->getShader(handle);
+}
+
 }  // namespace gl
diff --git a/src/libANGLE/ContextState.h b/src/libANGLE/ContextState.h
index ecb3759..24f6ce9 100644
--- a/src/libANGLE/ContextState.h
+++ b/src/libANGLE/ContextState.h
@@ -110,6 +110,9 @@
     bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams);
     bool getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams);
 
+    Program *getProgram(GLuint handle) const;
+    Shader *getShader(GLuint handle) const;
+
   protected:
     ContextState mState;
     bool mSkipValidation;
diff --git a/src/libANGLE/Program.cpp b/src/libANGLE/Program.cpp
index 29be350..961ff3c 100644
--- a/src/libANGLE/Program.cpp
+++ b/src/libANGLE/Program.cpp
@@ -377,39 +377,27 @@
     return mState.mLabel;
 }
 
-bool Program::attachShader(Shader *shader)
+void Program::attachShader(Shader *shader)
 {
     switch (shader->getType())
     {
         case GL_VERTEX_SHADER:
         {
-            if (mState.mAttachedVertexShader)
-            {
-                return false;
-            }
-
+            ASSERT(!mState.mAttachedVertexShader);
             mState.mAttachedVertexShader = shader;
             mState.mAttachedVertexShader->addRef();
             break;
         }
         case GL_FRAGMENT_SHADER:
         {
-            if (mState.mAttachedFragmentShader)
-            {
-                return false;
-            }
-
+            ASSERT(!mState.mAttachedFragmentShader);
             mState.mAttachedFragmentShader = shader;
             mState.mAttachedFragmentShader->addRef();
             break;
         }
         case GL_COMPUTE_SHADER:
         {
-            if (mState.mAttachedComputeShader)
-            {
-                return false;
-            }
-
+            ASSERT(!mState.mAttachedComputeShader);
             mState.mAttachedComputeShader = shader;
             mState.mAttachedComputeShader->addRef();
             break;
@@ -417,8 +405,6 @@
         default:
             UNREACHABLE();
     }
-
-    return true;
 }
 
 bool Program::detachShader(Shader *shader)
diff --git a/src/libANGLE/Program.h b/src/libANGLE/Program.h
index c4befe7..93573ea 100644
--- a/src/libANGLE/Program.h
+++ b/src/libANGLE/Program.h
@@ -243,10 +243,14 @@
 
     rx::ProgramImpl *getImplementation() const { return mProgram; }
 
-    bool attachShader(Shader *shader);
+    void attachShader(Shader *shader);
     bool detachShader(Shader *shader);
     int getAttachedShadersCount() const;
 
+    const Shader *getAttachedVertexShader() const { return mState.mAttachedVertexShader; }
+    const Shader *getAttachedFragmentShader() const { return mState.mAttachedFragmentShader; }
+    const Shader *getAttachedComputeShader() const { return mState.mAttachedComputeShader; }
+
     void bindAttributeLocation(GLuint index, const char *name);
     void bindUniformLocation(GLuint index, const char *name);
 
diff --git a/src/libANGLE/ResourceManager.cpp b/src/libANGLE/ResourceManager.cpp
index 713c104..d3dc102 100644
--- a/src/libANGLE/ResourceManager.cpp
+++ b/src/libANGLE/ResourceManager.cpp
@@ -309,7 +309,7 @@
     }
 }
 
-Shader *ResourceManager::getShader(unsigned int handle)
+Shader *ResourceManager::getShader(unsigned int handle) const
 {
     auto shader = mShaderMap.find(handle);
 
diff --git a/src/libANGLE/ResourceManager.h b/src/libANGLE/ResourceManager.h
index 03df645..f6a0002 100644
--- a/src/libANGLE/ResourceManager.h
+++ b/src/libANGLE/ResourceManager.h
@@ -64,7 +64,7 @@
     void deletePaths(GLuint first, GLsizei range);
 
     Buffer *getBuffer(GLuint handle);
-    Shader *getShader(GLuint handle);
+    Shader *getShader(GLuint handle) const;
     Program *getProgram(GLuint handle) const;
     Texture *getTexture(GLuint handle);
     Renderbuffer *getRenderbuffer(GLuint handle);
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index f92212e..2c84b31 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -722,7 +722,7 @@
     }
 }
 
-Program *GetValidProgram(Context *context, GLuint id)
+Program *GetValidProgram(ValidationContext *context, GLuint id)
 {
     // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the
     // error INVALID_VALUE if the provided name is not the name of either a shader or program object and
@@ -746,7 +746,7 @@
     return validProgram;
 }
 
-Shader *GetValidShader(Context *context, GLuint id)
+Shader *GetValidShader(ValidationContext *context, GLuint id)
 {
     // See ValidProgram for spec details.
 
diff --git a/src/libANGLE/validationES.h b/src/libANGLE/validationES.h
index 95ad637..89eef01 100644
--- a/src/libANGLE/validationES.h
+++ b/src/libANGLE/validationES.h
@@ -65,12 +65,12 @@
 // Returns valid program if id is a valid program name
 // Errors INVALID_OPERATION if valid shader is given and returns NULL
 // Errors INVALID_VALUE otherwise and returns NULL
-Program *GetValidProgram(Context *context, GLuint id);
+Program *GetValidProgram(ValidationContext *context, GLuint id);
 
 // Returns valid shader if id is a valid shader name
 // Errors INVALID_OPERATION if valid program is given and returns NULL
 // Errors INVALID_VALUE otherwise and returns NULL
-Shader *GetValidShader(Context *context, GLuint id);
+Shader *GetValidShader(ValidationContext *context, GLuint id);
 
 bool ValidateAttachmentTarget(Context *context, GLenum attachment);
 bool ValidateRenderbufferStorageParametersBase(Context *context, GLenum target, GLsizei samples,
diff --git a/src/libANGLE/validationES2.cpp b/src/libANGLE/validationES2.cpp
index b98f6b4..28b4f1c 100644
--- a/src/libANGLE/validationES2.cpp
+++ b/src/libANGLE/validationES2.cpp
@@ -10,19 +10,19 @@
 
 #include <cstdint>
 
-#include "libANGLE/validationES.h"
-#include "libANGLE/validationES3.h"
-#include "libANGLE/Context.h"
-#include "libANGLE/Texture.h"
-#include "libANGLE/Framebuffer.h"
-#include "libANGLE/Renderbuffer.h"
-#include "libANGLE/formatutils.h"
-#include "libANGLE/FramebufferAttachment.h"
-#include "libANGLE/Uniform.h"
-
 #include "common/mathutil.h"
 #include "common/string_utils.h"
 #include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/validationES.h"
+#include "libANGLE/validationES3.h"
 
 namespace gl
 {
@@ -3526,4 +3526,67 @@
     return true;
 }
 
+bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
+{
+    if (texture < GL_TEXTURE0 ||
+        texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
+    {
+        context->handleError(Error(GL_INVALID_ENUM));
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
+{
+    Program *programObject = GetValidProgram(context, program);
+    if (!programObject)
+    {
+        return false;
+    }
+
+    Shader *shaderObject = GetValidShader(context, shader);
+    if (!shaderObject)
+    {
+        return false;
+    }
+
+    switch (shaderObject->getType())
+    {
+        case GL_VERTEX_SHADER:
+        {
+            if (programObject->getAttachedVertexShader())
+            {
+                context->handleError(Error(GL_INVALID_OPERATION));
+                return false;
+            }
+            break;
+        }
+        case GL_FRAGMENT_SHADER:
+        {
+            if (programObject->getAttachedFragmentShader())
+            {
+                context->handleError(Error(GL_INVALID_OPERATION));
+                return false;
+            }
+            break;
+        }
+        case GL_COMPUTE_SHADER:
+        {
+            if (programObject->getAttachedComputeShader())
+            {
+                context->handleError(Error(GL_INVALID_OPERATION));
+                return false;
+            }
+            break;
+        }
+        default:
+            UNREACHABLE();
+            break;
+    }
+
+    return true;
+}
+
 }  // namespace gl
diff --git a/src/libANGLE/validationES2.h b/src/libANGLE/validationES2.h
index 705c514..11bf154 100644
--- a/src/libANGLE/validationES2.h
+++ b/src/libANGLE/validationES2.h
@@ -341,6 +341,9 @@
 
 bool ValidateEnableExtensionANGLE(ValidationContext *context, const GLchar *name);
 
+bool ValidateActiveTexture(ValidationContext *context, GLenum texture);
+bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader);
+
 }  // namespace gl
 
 #endif // LIBANGLE_VALIDATION_ES2_H_
diff --git a/src/libGLESv2/entry_points_gles_2_0.cpp b/src/libGLESv2/entry_points_gles_2_0.cpp
index d96f348..8856de8 100644
--- a/src/libGLESv2/entry_points_gles_2_0.cpp
+++ b/src/libGLESv2/entry_points_gles_2_0.cpp
@@ -44,9 +44,8 @@
     Context *context = GetValidGlobalContext();
     if (context)
     {
-        if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
+        if (!context->skipValidation() && !ValidateActiveTexture(context, texture))
         {
-            context->handleError(Error(GL_INVALID_ENUM));
             return;
         }
 
@@ -61,23 +60,12 @@
     Context *context = GetValidGlobalContext();
     if (context)
     {
-        Program *programObject = GetValidProgram(context, program);
-        if (!programObject)
+        if (!context->skipValidation() && !ValidateAttachShader(context, program, shader))
         {
             return;
         }
 
-        Shader *shaderObject = GetValidShader(context, shader);
-        if (!shaderObject)
-        {
-            return;
-        }
-
-        if (!programObject->attachShader(shaderObject))
-        {
-            context->handleError(Error(GL_INVALID_OPERATION));
-            return;
-        }
+        context->attachShader(program, shader);
     }
 }