ES31: Add glGetProgramResourceName API

Add API entry and validation checks(GLES 3.1 section 7.3).
Add the first 2 interfaces(PROGRAM_INPUT and PROGRAM_OUTPUT) implementation.

BUG=angleproject:1920

Change-Id: Ide7d5ad40a611a091c3dffab47fd31da57b69f1d
Reviewed-on: https://chromium-review.googlesource.com/457523
Commit-Queue: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/Program.cpp b/src/libANGLE/Program.cpp
index 567e1d9..366483b 100644
--- a/src/libANGLE/Program.cpp
+++ b/src/libANGLE/Program.cpp
@@ -159,6 +159,18 @@
     return GL_INVALID_INDEX;
 }
 
+void CopyStringToBuffer(GLchar *buffer, const std::string &string, GLsizei bufSize, GLsizei *length)
+{
+    ASSERT(bufSize > 0);
+    strncpy(buffer, string.c_str(), bufSize);
+    buffer[bufSize - 1] = '\0';
+
+    if (length)
+    {
+        *length = static_cast<GLsizei>(strlen(buffer));
+    }
+}
+
 }  // anonymous namespace
 
 const char *const g_fakepath = "C:\\fakepath";
@@ -1196,7 +1208,12 @@
     return mState.mActiveAttribLocationsMask[attribLocation];
 }
 
-void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
+void Program::getActiveAttribute(GLuint index,
+                                 GLsizei bufsize,
+                                 GLsizei *length,
+                                 GLint *size,
+                                 GLenum *type,
+                                 GLchar *name) const
 {
     if (!mLinked)
     {
@@ -1220,15 +1237,7 @@
 
     if (bufsize > 0)
     {
-        const char *string = attrib.name.c_str();
-
-        strncpy(name, string, bufsize);
-        name[bufsize - 1] = '\0';
-
-        if (length)
-        {
-            *length = static_cast<GLsizei>(strlen(name));
-        }
+        CopyStringToBuffer(name, attrib.name, bufsize, length);
     }
 
     // Always a single 'type' instance
@@ -1281,6 +1290,50 @@
     return GetResourceIndexFromName(mState.mOutputVariables, std::string(name));
 }
 
+size_t Program::getOutputResourceCount() const
+{
+    return (mLinked ? mState.mOutputVariables.size() : 0);
+}
+
+void Program::getInputResourceName(GLuint index,
+                                   GLsizei bufSize,
+                                   GLsizei *length,
+                                   GLchar *name) const
+{
+    GLint size;
+    GLenum type;
+    getActiveAttribute(index, bufSize, length, &size, &type, name);
+}
+
+void Program::getOutputResourceName(GLuint index,
+                                    GLsizei bufSize,
+                                    GLsizei *length,
+                                    GLchar *name) const
+{
+    if (length)
+    {
+        *length = 0;
+    }
+
+    if (!mLinked)
+    {
+        if (bufSize > 0)
+        {
+            name[0] = '\0';
+        }
+        return;
+    }
+    ASSERT(index < mState.mOutputVariables.size());
+    const auto &output = mState.mOutputVariables[index];
+
+    if (bufSize > 0)
+    {
+        std::string nameWithArray = (output.isArray() ? output.name + "[0]" : output.name);
+
+        CopyStringToBuffer(name, nameWithArray, bufSize, length);
+    }
+}
+
 GLint Program::getFragDataLocation(const std::string &name) const
 {
     std::string baseName(name);
@@ -1316,14 +1369,7 @@
             {
                 string += "[0]";
             }
-
-            strncpy(name, string.c_str(), bufsize);
-            name[bufsize - 1] = '\0';
-
-            if (length)
-            {
-                *length = static_cast<GLsizei>(strlen(name));
-            }
+            CopyStringToBuffer(name, string, bufsize, length);
         }
 
         *size = uniform.elementCount();
@@ -1699,14 +1745,7 @@
         {
             string += ArrayString(uniformBlock.arrayElement);
         }
-
-        strncpy(uniformBlockName, string.c_str(), bufSize);
-        uniformBlockName[bufSize - 1] = '\0';
-
-        if (length)
-        {
-            *length = static_cast<GLsizei>(strlen(uniformBlockName));
-        }
+        CopyStringToBuffer(uniformBlockName, string, bufSize, length);
     }
 }