Implement robust GetShaderiv entry points.

BUG=angleproject:1354

Change-Id: I994b7a596b5b67fadbd91ad0d64054c792523200
Reviewed-on: https://chromium-review.googlesource.com/395111
Commit-Queue: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/libANGLE/queryutils.cpp b/src/libANGLE/queryutils.cpp
index 91dc29d..6468933 100644
--- a/src/libANGLE/queryutils.cpp
+++ b/src/libANGLE/queryutils.cpp
@@ -12,6 +12,7 @@
 #include "libANGLE/Framebuffer.h"
 #include "libANGLE/Program.h"
 #include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Shader.h"
 
 namespace gl
 {
@@ -244,4 +245,34 @@
             break;
     }
 }
+
+void QueryShaderiv(const Shader *shader, GLenum pname, GLint *params)
+{
+    ASSERT(shader != nullptr);
+
+    switch (pname)
+    {
+        case GL_SHADER_TYPE:
+            *params = shader->getType();
+            return;
+        case GL_DELETE_STATUS:
+            *params = shader->isFlaggedForDeletion();
+            return;
+        case GL_COMPILE_STATUS:
+            *params = shader->isCompiled() ? GL_TRUE : GL_FALSE;
+            return;
+        case GL_INFO_LOG_LENGTH:
+            *params = shader->getInfoLogLength();
+            return;
+        case GL_SHADER_SOURCE_LENGTH:
+            *params = shader->getSourceLength();
+            return;
+        case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
+            *params = shader->getTranslatedSourceWithDebugInfoLength();
+            return;
+        default:
+            UNREACHABLE();
+            break;
+    }
+}
 }
diff --git a/src/libANGLE/queryutils.h b/src/libANGLE/queryutils.h
index 1d883ad..17cc44f 100644
--- a/src/libANGLE/queryutils.h
+++ b/src/libANGLE/queryutils.h
@@ -18,6 +18,7 @@
 class Framebuffer;
 class Program;
 class Renderbuffer;
+class Shader;
 
 void QueryFramebufferAttachmentParameteriv(const Framebuffer *framebuffer,
                                            GLenum attachment,
@@ -26,6 +27,7 @@
 void QueryBufferParameteriv(const Buffer *buffer, GLenum pname, GLint *params);
 void QueryProgramiv(const Program *program, GLenum pname, GLint *params);
 void QueryRenderbufferiv(const Renderbuffer *renderbuffer, GLenum pname, GLint *params);
+void QueryShaderiv(const Shader *shader, GLenum pname, GLint *params);
 }
 
 #endif  // LIBANGLE_QUERYUTILS_H_
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index 2c84b31..4904124 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -368,6 +368,48 @@
     return true;
 }
 
+bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
+{
+    if (length)
+    {
+        *length = 0;
+    }
+
+    if (GetValidShader(context, shader) == nullptr)
+    {
+        return false;
+    }
+
+    switch (pname)
+    {
+        case GL_SHADER_TYPE:
+        case GL_DELETE_STATUS:
+        case GL_COMPILE_STATUS:
+        case GL_INFO_LOG_LENGTH:
+        case GL_SHADER_SOURCE_LENGTH:
+            break;
+
+        case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
+            if (!context->getExtensions().translatedShaderSource)
+            {
+                context->handleError(
+                    Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
+                return false;
+            }
+            break;
+
+        default:
+            context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
+            return false;
+    }
+
+    if (length)
+    {
+        *length = 1;
+    }
+    return true;
+}
+
 }  // anonymous namespace
 
 bool ValidTextureTarget(const ValidationContext *context, GLenum target)
@@ -3897,4 +3939,34 @@
     return true;
 }
 
+bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
+{
+    return ValidateGetShaderivBase(context, shader, pname, nullptr);
+}
+
+bool ValidateGetShaderivRobustANGLE(Context *context,
+                                    GLuint shader,
+                                    GLenum pname,
+                                    GLsizei bufSize,
+                                    GLsizei *length,
+                                    GLint *params)
+{
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetShaderivBase(context, shader, pname, length))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
 }  // namespace gl
diff --git a/src/libANGLE/validationES.h b/src/libANGLE/validationES.h
index 89eef01..03be55a 100644
--- a/src/libANGLE/validationES.h
+++ b/src/libANGLE/validationES.h
@@ -351,6 +351,14 @@
                                                    GLsizei *length,
                                                    GLint *params);
 
+bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params);
+bool ValidateGetShaderivRobustANGLE(Context *context,
+                                    GLuint shader,
+                                    GLenum pname,
+                                    GLsizei bufSize,
+                                    GLsizei *length,
+                                    GLint *params);
+
 // Error messages shared here for use in testing.
 extern const char *g_ExceedsMaxElementErrorMessage;
 }  // namespace gl
diff --git a/src/libGLESv2/entry_points_gles_2_0.cpp b/src/libGLESv2/entry_points_gles_2_0.cpp
index 8856de8..f351b4c 100644
--- a/src/libGLESv2/entry_points_gles_2_0.cpp
+++ b/src/libGLESv2/entry_points_gles_2_0.cpp
@@ -1526,37 +1526,13 @@
     Context *context = GetValidGlobalContext();
     if (context)
     {
-        Shader *shaderObject = GetValidShader(context, shader);
-        if (!shaderObject)
+        if (!context->skipValidation() && !ValidateGetShaderiv(context, shader, pname, params))
         {
             return;
         }
 
-        switch (pname)
-        {
-          case GL_SHADER_TYPE:
-            *params = shaderObject->getType();
-            return;
-          case GL_DELETE_STATUS:
-            *params = shaderObject->isFlaggedForDeletion();
-            return;
-          case GL_COMPILE_STATUS:
-            *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
-            return;
-          case GL_INFO_LOG_LENGTH:
-            *params = shaderObject->getInfoLogLength();
-            return;
-          case GL_SHADER_SOURCE_LENGTH:
-            *params = shaderObject->getSourceLength();
-            return;
-          case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
-            *params = shaderObject->getTranslatedSourceWithDebugInfoLength();
-            return;
-
-          default:
-              context->handleError(Error(GL_INVALID_ENUM));
-            return;
-        }
+        Shader *shaderObject = context->getShader(shader);
+        QueryShaderiv(shaderObject, pname, params);
     }
 }
 
diff --git a/src/libGLESv2/entry_points_gles_2_0_ext.cpp b/src/libGLESv2/entry_points_gles_2_0_ext.cpp
index d790159..cefbeeb 100644
--- a/src/libGLESv2/entry_points_gles_2_0_ext.cpp
+++ b/src/libGLESv2/entry_points_gles_2_0_ext.cpp
@@ -2196,7 +2196,20 @@
         "(GLuint shader = %d, GLenum pname = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
         "GLint* params = 0x%0.8p)",
         shader, pname, bufSize, length, params);
-    UNIMPLEMENTED();
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei numParams = 0;
+        if (!ValidateGetShaderivRobustANGLE(context, shader, pname, bufSize, &numParams, params))
+        {
+            return;
+        }
+
+        Shader *shaderObject = context->getShader(shader);
+        QueryShaderiv(shaderObject, pname, params);
+        SetRobustLengthParam(length, numParams);
+    }
 }
 
 ANGLE_EXPORT void GL_APIENTRY GetTexParameterfvRobustANGLE(GLenum target,