Add support for querying number of active uniform blocks/block name max length from a program object.

TRAC #22858

Signed-off-by: Geoff Lang
Signed-off-by: Nicolas Capens
Author: Jamie Madill

git-svn-id: https://angleproject.googlecode.com/svn/branches/es3proto@2311 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/Program.cpp b/src/libGLESv2/Program.cpp
index cfaddf0..a59a0f9 100644
--- a/src/libGLESv2/Program.cpp
+++ b/src/libGLESv2/Program.cpp
@@ -525,6 +525,32 @@
     }
 }
 
+GLint Program::getActiveUniformBlockCount()
+{
+    ProgramBinary *programBinary = getProgramBinary();
+    if (programBinary)
+    {
+        return static_cast<GLint>(programBinary->getActiveUniformBlockCount());
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+GLint Program::getActiveUniformBlockMaxLength()
+{
+    ProgramBinary *programBinary = getProgramBinary();
+    if (programBinary)
+    {
+        return static_cast<GLint>(programBinary->getActiveUniformBlockMaxLength());
+    }
+    else
+    {
+        return 0;
+    }
+}
+
 void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
 {
     mUniformBlockBindings[uniformBlockIndex] = uniformBlockBinding;
diff --git a/src/libGLESv2/Program.h b/src/libGLESv2/Program.h
index cb12617..6ca5bd2 100644
--- a/src/libGLESv2/Program.h
+++ b/src/libGLESv2/Program.h
@@ -92,6 +92,9 @@
     GLint getActiveUniformCount();
     GLint getActiveUniformMaxLength();
 
+    GLint getActiveUniformBlockCount();
+    GLint getActiveUniformBlockMaxLength();
+
     void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding);
     GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const;
 
diff --git a/src/libGLESv2/ProgramBinary.cpp b/src/libGLESv2/ProgramBinary.cpp
index ee89f84..33fb108 100644
--- a/src/libGLESv2/ProgramBinary.cpp
+++ b/src/libGLESv2/ProgramBinary.cpp
@@ -2421,6 +2421,28 @@
     return mUniformBlocks.size();
 }
 
+GLuint ProgramBinary::getActiveUniformBlockMaxLength() const
+{
+    unsigned int maxLength = 0;
+
+    unsigned int numUniformBlocks = mUniformBlocks.size();
+    for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++)
+    {
+        const UniformBlock &uniformBlock = *mUniformBlocks[uniformBlockIndex];
+        if (!uniformBlock.name.empty())
+        {
+            const unsigned int length = uniformBlock.name.length() + 1;
+
+            // Counting in "[0]".
+            const unsigned int arrayLength = (uniformBlock.isArrayElement() ? 3 : 0);
+
+            maxLength = std::max(length + arrayLength, maxLength);
+        }
+    }
+
+    return maxLength;
+}
+
 void ProgramBinary::validate(InfoLog &infoLog)
 {
     applyUniforms();
diff --git a/src/libGLESv2/ProgramBinary.h b/src/libGLESv2/ProgramBinary.h
index 78d8ed8..328ffe2 100644
--- a/src/libGLESv2/ProgramBinary.h
+++ b/src/libGLESv2/ProgramBinary.h
@@ -127,6 +127,7 @@
     void getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const;
     void getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const;
     GLuint getActiveUniformBlockCount() const;
+    GLuint getActiveUniformBlockMaxLength() const;
 
     void validate(InfoLog &infoLog);
     bool validateSamplers(InfoLog *infoLog);
diff --git a/src/libGLESv2/libGLESv2.cpp b/src/libGLESv2/libGLESv2.cpp
index 7251bd9..6d0305a 100644
--- a/src/libGLESv2/libGLESv2.cpp
+++ b/src/libGLESv2/libGLESv2.cpp
@@ -3984,6 +3984,16 @@
                 return gl::error(GL_INVALID_VALUE);
             }
 
+            if (context->getClientVersion() < 3)
+            {
+                switch (pname)
+                {
+                  case GL_ACTIVE_UNIFORM_BLOCKS:
+                  case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
+                    return gl::error(GL_INVALID_ENUM);
+                }
+            }
+
             switch (pname)
             {
               case GL_DELETE_STATUS:
@@ -4016,6 +4026,12 @@
               case GL_PROGRAM_BINARY_LENGTH_OES:
                 *params = programObject->getProgramBinaryLength();
                 return;
+              case GL_ACTIVE_UNIFORM_BLOCKS:
+                *params = programObject->getActiveUniformBlockCount();
+                return;
+              case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
+                *params = programObject->getActiveUniformBlockMaxLength();
+                break;
               default:
                 return gl::error(GL_INVALID_ENUM);
             }