Implemented glGetActiveUniform
TRAC #11929
Signed-off-by: Shannon Woods
Signed-off-by: Daniel Koch

Author:    Nicolas Capens

git-svn-id: https://angleproject.googlecode.com/svn/trunk@181 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/compiler/OutputHLSL.cpp b/src/compiler/OutputHLSL.cpp
index 109b356..a36a856 100644
--- a/src/compiler/OutputHLSL.cpp
+++ b/src/compiler/OutputHLSL.cpp
@@ -124,10 +124,10 @@
             }
         }
 
-        out << "uniform float4 gl_Window;\n"
-               "uniform float2 gl_Depth;\n"
-               "uniform bool gl_PointsOrLines;\n"
-               "uniform bool gl_FrontCCW;\n"
+        out << "uniform float4 dx_Window;\n"
+               "uniform float2 dx_Depth;\n"
+               "uniform bool dx_PointsOrLines;\n"
+               "uniform bool dx_FrontCCW;\n"
                "\n";
         out <<  uniforms;
         out << "\n"
@@ -275,7 +275,7 @@
             }
         }
 
-        out << "uniform float2 gl_HalfPixelSize;\n"
+        out << "uniform float2 dx_HalfPixelSize;\n"
                "\n";
         out <<  uniforms;
         out << "\n"
@@ -617,11 +617,11 @@
         out << "PS_OUTPUT main(PS_INPUT input)\n"
                "{\n"
                "    float rhw = 1.0 / input.gl_FragCoord.w;\n"
-               "    gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * gl_Window.x + gl_Window.z;\n"
-               "    gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * gl_Window.y + gl_Window.w;\n"
-               "    gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * gl_Depth.x + gl_Depth.y;\n"
+               "    gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_Window.x + dx_Window.z;\n"
+               "    gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_Window.y + dx_Window.w;\n"
+               "    gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_Depth.x + dx_Depth.y;\n"
                "    gl_FragCoord.w = rhw;\n"
-               "    gl_FrontFacing = gl_PointsOrLines || (gl_FrontCCW ? (input.vFace >= 0.0) : (input.vFace <= 0.0));\n";
+               "    gl_FrontFacing = dx_PointsOrLines || (dx_FrontCCW ? (input.vFace >= 0.0) : (input.vFace <= 0.0));\n";
 
         for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++)
         {
@@ -680,8 +680,8 @@
                "    gl_main();\n"
                "\n"
                "    VS_OUTPUT output;\n"
-               "    output.gl_Position.x = gl_Position.x - gl_HalfPixelSize.x * gl_Position.w;\n"
-               "    output.gl_Position.y = -(gl_Position.y - gl_HalfPixelSize.y * gl_Position.w);\n"
+               "    output.gl_Position.x = gl_Position.x - dx_HalfPixelSize.x * gl_Position.w;\n"
+               "    output.gl_Position.y = -(gl_Position.y - dx_HalfPixelSize.y * gl_Position.w);\n"
                "    output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
                "    output.gl_Position.w = gl_Position.w;\n"
                "    output.gl_PointSize = gl_PointSize;\n"
@@ -1979,7 +1979,7 @@
 
 TString OutputHLSL::decorate(const TString &string)
 {
-    if (string.substr(0, 3) != "gl_")
+    if (string.substr(0, 3) != "gl_" && string.substr(0, 3) != "dx_")
     {
         return "_" + string;
     }
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index d6df598..c700b4c 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -1230,15 +1230,15 @@
         renderTarget->GetDesc(&description);
         Program *programObject = getCurrentProgram();
 
-        GLint halfPixelSize = programObject->getUniformLocation("gl_HalfPixelSize");
+        GLint halfPixelSize = programObject->getUniformLocation("dx_HalfPixelSize");
         GLfloat xy[2] = {1.0f / description.Width, 1.0f / description.Height};
         programObject->setUniform2fv(halfPixelSize, 1, (GLfloat*)&xy);
 
-        GLint window = programObject->getUniformLocation("gl_Window");
+        GLint window = programObject->getUniformLocation("dx_Window");
         GLfloat whxy[4] = {viewportWidth / 2.0f, viewportHeight / 2.0f, (float)viewportX + viewportWidth / 2.0f, (float)viewportY + viewportHeight / 2.0f};
         programObject->setUniform4fv(window, 1, (GLfloat*)&whxy);
 
-        GLint depth = programObject->getUniformLocation("gl_Depth");
+        GLint depth = programObject->getUniformLocation("dx_Depth");
         GLfloat dz[2] = {(zFar - zNear) / 2.0f, (zNear + zFar) / 2.0f};
         programObject->setUniform2fv(depth, 1, (GLfloat*)&dz);
 
@@ -1262,11 +1262,11 @@
     IDirect3DDevice9 *device = getDevice();
     Program *programObject = getCurrentProgram();
 
-    GLint frontCCW = programObject->getUniformLocation("gl_FrontCCW");
+    GLint frontCCW = programObject->getUniformLocation("dx_FrontCCW");
     GLint ccw = (frontFace == GL_CCW);
     programObject->setUniform1iv(frontCCW, 1, &ccw);
 
-    GLint pointsOrLines = programObject->getUniformLocation("gl_PointsOrLines");
+    GLint pointsOrLines = programObject->getUniformLocation("dx_PointsOrLines");
     GLint alwaysFront = !isTriangleMode(drawMode);
     programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront);
 
diff --git a/src/libGLESv2/Program.cpp b/src/libGLESv2/Program.cpp
index 3dff097..1e2f944 100644
--- a/src/libGLESv2/Program.cpp
+++ b/src/libGLESv2/Program.cpp
@@ -1274,7 +1274,7 @@
 // This methods needs to match OutputHLSL::decorate
 std::string Program::decorate(const std::string &string)
 {
-    if (string.substr(0, 3) != "gl_")
+    if (string.substr(0, 3) != "gl_" && string.substr(0, 3) != "dx_")
     {
         return "_" + string;
     }
@@ -1749,41 +1749,6 @@
     return true;
 }
 
-GLenum Program::parseAttributeType(const std::string &type)
-{
-    if (type == "float")
-    {
-        return GL_FLOAT;
-    }
-    else if (type == "float2")
-    {
-        return GL_FLOAT_VEC2;
-    }
-    else if (type == "float3")
-    {
-        return GL_FLOAT_VEC3;
-    }
-    else if (type == "float4")
-    {
-        return GL_FLOAT_VEC4;
-    }
-    else if (type == "float2x2")
-    {
-        return GL_FLOAT_MAT2;
-    }
-    else if (type == "float3x3")
-    {
-        return GL_FLOAT_MAT3;
-    }
-    else if (type == "float4x4")
-    {
-        return GL_FLOAT_MAT4;
-    }
-    else UNREACHABLE();
-
-    return GL_NONE;
-}
-
 void Program::appendToInfoLog(const char *format, ...)
 {
     if (!format)
@@ -1862,7 +1827,6 @@
     for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
     {
         mLinkedAttribute[index].name.clear();
-        mLinkedAttribute[index].type.clear();
         mSemanticIndex[index] = -1;
     }
 
@@ -1962,7 +1926,7 @@
 
 void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
 {
-    int attribute = 0;
+    unsigned int attribute = 0;
     for (unsigned int i = 0; i < index; i++)
     {
         do
@@ -1989,7 +1953,7 @@
 
     *size = 1;
 
-    *type = parseAttributeType(mLinkedAttribute[attribute].type);
+    *type = mLinkedAttribute[attribute].type;
 }
 
 GLint Program::getActiveAttributeCount()
@@ -2022,6 +1986,73 @@
     return maxLength;
 }
 
+void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
+{
+    unsigned int uniform = 0;
+    for (unsigned int i = 0; i < index; i++)
+    {
+        do
+        {
+            uniform++;
+
+            ASSERT(uniform < mUniforms.size());   // index must be smaller than getActiveUniformCount()
+        }
+        while (mUniforms[uniform]->name.substr(0, 3) == "dx_");
+    }
+
+    if (bufsize > 0)
+    {
+        const char *string = mUniforms[uniform]->name.c_str();
+
+        if(string[0] == '_')   // Undecorate
+        {
+            string++;
+        }
+
+        strncpy(name, string, bufsize);
+        name[bufsize - 1] = '\0';
+
+        if (length)
+        {
+            *length = strlen(name);
+        }
+    }
+
+    *size = 1;
+
+    *type = mUniforms[uniform]->type;
+}
+
+GLint Program::getActiveUniformCount()
+{
+    int count = 0;
+
+    for (unsigned int uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
+    {
+        if (mUniforms[uniformIndex]->name.substr(0, 3) != "dx_")
+        {
+            count++;
+        }
+    }
+
+    return count;
+}
+
+GLint Program::getActiveUniformMaxLength()
+{
+    int maxLength = 0;
+
+    for (unsigned int uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
+    {
+        if (!mUniforms[uniformIndex]->name.empty() && mUniforms[uniformIndex]->name.substr(0, 3) != "dx_")
+        {
+            maxLength = std::max((int)(mUniforms[uniformIndex]->name.length() + 1), maxLength);
+        }
+    }
+
+    return maxLength;
+}
+
 void Program::flagForDeletion()
 {
     mDeleteStatus = true;
diff --git a/src/libGLESv2/Program.h b/src/libGLESv2/Program.h
index 9992a5c..91d04ef 100644
--- a/src/libGLESv2/Program.h
+++ b/src/libGLESv2/Program.h
@@ -85,6 +85,10 @@
     GLint getActiveAttributeCount();
     GLint getActiveAttributeMaxLength();
 
+    void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+    GLint getActiveUniformCount();
+    GLint getActiveUniformMaxLength();
+
     void flagForDeletion();
     bool isFlaggedForDeletion() const;
 
@@ -135,7 +139,6 @@
     bool applyUniform3iv(GLint location, GLsizei count, const GLint *v);
     bool applyUniform4iv(GLint location, GLsizei count, const GLint *v);
 
-    GLenum parseAttributeType(const std::string &type);
     void appendToInfoLog(const char *info, ...);
 
     FragmentShader *mFragmentShader;
diff --git a/src/libGLESv2/Shader.cpp b/src/libGLESv2/Shader.cpp
index 61c8e48..2abbd61 100644
--- a/src/libGLESv2/Shader.cpp
+++ b/src/libGLESv2/Shader.cpp
@@ -216,6 +216,41 @@
     mVertexCompiler = NULL;
 }
 
+GLenum Shader::parseAttributeType(const std::string &type)
+{
+    if (type == "float")
+    {
+        return GL_FLOAT;
+    }
+    else if (type == "float2")
+    {
+        return GL_FLOAT_VEC2;
+    }
+    else if (type == "float3")
+    {
+        return GL_FLOAT_VEC3;
+    }
+    else if (type == "float4")
+    {
+        return GL_FLOAT_VEC4;
+    }
+    else if (type == "float2x2")
+    {
+        return GL_FLOAT_MAT2;
+    }
+    else if (type == "float3x3")
+    {
+        return GL_FLOAT_MAT3;
+    }
+    else if (type == "float4x4")
+    {
+        return GL_FLOAT_MAT4;
+    }
+    else UNREACHABLE();
+
+    return GL_NONE;
+}
+
 void Shader::compileToHLSL(void *compiler)
 {
     if (isCompiled() || !mSource)
@@ -319,7 +354,7 @@
             {
                 if (semanticIndex < MAX_VERTEX_ATTRIBS + 1)
                 {
-                    mAttribute[semanticIndex].type = attributeType;
+                    mAttribute[semanticIndex].type = parseAttributeType(attributeType);
                     mAttribute[semanticIndex].name = attributeName;
                 }
                 else
diff --git a/src/libGLESv2/Shader.h b/src/libGLESv2/Shader.h
index 7872d24..86ead44 100644
--- a/src/libGLESv2/Shader.h
+++ b/src/libGLESv2/Shader.h
@@ -49,6 +49,7 @@
     void flagForDeletion();
 
     static void releaseCompiler();
+    static GLenum parseAttributeType(const std::string &type);
 
   protected:
     DISALLOW_COPY_AND_ASSIGN(Shader);
@@ -69,7 +70,7 @@
 
 struct Attribute
 {
-    std::string type;
+    GLenum type;
     std::string name;
 };
 
diff --git a/src/libGLESv2/libGLESv2.cpp b/src/libGLESv2/libGLESv2.cpp
index 9f70ace..516ec8c 100644
--- a/src/libGLESv2/libGLESv2.cpp
+++ b/src/libGLESv2/libGLESv2.cpp
@@ -1899,7 +1899,7 @@
                 }
             }
 
-            if (index >= programObject->getActiveAttributeCount())
+            if (index >= (GLuint)programObject->getActiveAttributeCount())
             {
                 return error(GL_INVALID_VALUE);
             }
@@ -1926,7 +1926,31 @@
             return error(GL_INVALID_VALUE);
         }
 
-        UNIMPLEMENTED();   // FIXME
+        gl::Context *context = gl::getContext();
+
+        if (context)
+        {
+            gl::Program *programObject = context->getProgram(program);
+
+            if (!programObject)
+            {
+                if (context->getShader(program))
+                {
+                    return error(GL_INVALID_OPERATION);
+                }
+                else
+                {
+                    return error(GL_INVALID_VALUE);
+                }
+            }
+
+            if (index >= (GLuint)programObject->getActiveUniformCount())
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            programObject->getActiveUniform(index, bufsize, length, size, type, name);
+        }
     }
     catch(std::bad_alloc&)
     {
@@ -2330,12 +2354,10 @@
                 *params = programObject->getActiveAttributeMaxLength();
                 return;
               case GL_ACTIVE_UNIFORMS:
-                UNIMPLEMENTED();   // FIXME
-                *params = 0;
+                *params = programObject->getActiveUniformCount();
                 return;
               case GL_ACTIVE_UNIFORM_MAX_LENGTH:
-                UNIMPLEMENTED();   // FIXME
-                *params = 0;
+                *params = programObject->getActiveUniformMaxLength();
                 return;
               default:
                 return error(GL_INVALID_ENUM);