Implement glGetAttachedShaders and glGetShaderPrecisionFormat.
TRAC #11599
Signed-off-by: Andrew Lewycky
Signed-off-by: Daniel Koch

Author:    Nicolas Capens

git-svn-id: http://angleproject.googlecode.com/svn/trunk@85 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index f13db41..3e98ec1 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -298,11 +298,11 @@
 
     if (type == GL_VERTEX_SHADER)
     {
-        mShaderMap[handle] = new VertexShader();
+        mShaderMap[handle] = new VertexShader(handle);
     }
     else if (type == GL_FRAGMENT_SHADER)
     {
-        mShaderMap[handle] = new FragmentShader();
+        mShaderMap[handle] = new FragmentShader(handle);
     }
     else UNREACHABLE();
 
diff --git a/src/libGLESv2/Program.cpp b/src/libGLESv2/Program.cpp
index b950f47..f036a93 100644
--- a/src/libGLESv2/Program.cpp
+++ b/src/libGLESv2/Program.cpp
@@ -1058,6 +1058,36 @@
     }
 }
 
+void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders)
+{
+    int total = 0;
+
+    if (mVertexShader)
+    {
+        if (total < maxCount)
+        {
+            shaders[total] = mVertexShader->getHandle();
+        }
+
+        total++;
+    }
+
+    if (mFragmentShader)
+    {
+        if (total < maxCount)
+        {
+            shaders[total] = mFragmentShader->getHandle();
+        }
+
+        total++;
+    }
+
+    if (count)
+    {
+        *count = total;
+    }
+}
+
 void Program::flagForDeletion()
 {
     mDeleteStatus = true;
diff --git a/src/libGLESv2/Program.h b/src/libGLESv2/Program.h
index 92257eb..9502ca0 100644
--- a/src/libGLESv2/Program.h
+++ b/src/libGLESv2/Program.h
@@ -72,6 +72,7 @@
     bool isLinked();
     int getInfoLogLength() const;
     void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog);
+    void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders);
 
     void flagForDeletion();
     bool isFlaggedForDeletion() const;
diff --git a/src/libGLESv2/Shader.cpp b/src/libGLESv2/Shader.cpp
index b17a6c9..aad124a 100644
--- a/src/libGLESv2/Shader.cpp
+++ b/src/libGLESv2/Shader.cpp
@@ -20,7 +20,7 @@
 void *Shader::mFragmentCompiler = NULL;
 void *Shader::mVertexCompiler = NULL;
 
-Shader::Shader()
+Shader::Shader(GLuint handle) : mHandle(handle)
 {
     mSource = NULL;
     mHlsl = NULL;
@@ -49,6 +49,11 @@
     delete[] mInfoLog;
 }
 
+GLuint Shader::getHandle() const
+{
+    return mHandle;
+}
+
 void Shader::setSource(GLsizei count, const char **string, const GLint *length)
 {
     delete[] mSource;
@@ -282,7 +287,7 @@
     delete[] mAttribute;
 }
 
-VertexShader::VertexShader()
+VertexShader::VertexShader(GLuint handle) : Shader(handle)
 {
 }
 
@@ -396,7 +401,7 @@
     }
 }
 
-FragmentShader::FragmentShader()
+FragmentShader::FragmentShader(GLuint handle) : Shader(handle)
 {
 }
 
diff --git a/src/libGLESv2/Shader.h b/src/libGLESv2/Shader.h
index e555064..6bc9cf5 100644
--- a/src/libGLESv2/Shader.h
+++ b/src/libGLESv2/Shader.h
@@ -23,11 +23,12 @@
 class Shader
 {
   public:
-    Shader();
+    explicit Shader(GLuint handle);
 
     virtual ~Shader();
 
     virtual GLenum getType() = 0;
+    GLuint getHandle() const;
 
     void deleteSource();
     void setSource(GLsizei count, const char **string, const GLint *length);
@@ -54,6 +55,7 @@
 
     void compileToHLSL(void *compiler);
 
+    const GLuint mHandle;
     int mAttachCount;     // Number of program objects this shader is attached to
     bool mDeleteStatus;   // Flag to indicate that the shader can be deleted when no longer in use
 
@@ -82,7 +84,7 @@
 class VertexShader : public Shader
 {
   public:
-    VertexShader();
+    explicit VertexShader(GLuint handle);
 
     ~VertexShader();
 
@@ -104,7 +106,7 @@
 class FragmentShader : public Shader
 {
   public:
-    FragmentShader();
+    explicit FragmentShader(GLuint handle);
 
     ~FragmentShader();
 
diff --git a/src/libGLESv2/libGLESv2.cpp b/src/libGLESv2/libGLESv2.cpp
index 82c9a8c..8deaa9e 100644
--- a/src/libGLESv2/libGLESv2.cpp
+++ b/src/libGLESv2/libGLESv2.cpp
@@ -1667,7 +1667,19 @@
             return error(GL_INVALID_VALUE);
         }
 
-        UNIMPLEMENTED();   // FIXME
+        gl::Context *context = gl::getContext();
+
+        if (context)
+        {
+            gl::Program *programObject = context->getProgram(program);
+
+            if (!programObject)
+            {
+                return error(GL_INVALID_VALUE);
+            }
+
+            return programObject->getAttachedShaders(maxcount, count, shaders);
+        }
     }
     catch(std::bad_alloc&)
     {
@@ -2099,7 +2111,39 @@
 
     try
     {
-        UNIMPLEMENTED();   // FIXME
+        switch (shadertype)
+        {
+          case GL_VERTEX_SHADER:
+          case GL_FRAGMENT_SHADER:
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
+
+        switch (precisiontype)
+        {
+          case GL_LOW_FLOAT:
+          case GL_MEDIUM_FLOAT:
+          case GL_HIGH_FLOAT:
+            // Assume IEEE 754 precision
+            range[0] = 127;
+            range[1] = 127;
+            precision[0] = 23;
+            precision[1] = 23;
+            break;
+          case GL_LOW_INT:
+          case GL_MEDIUM_INT:
+          case GL_HIGH_INT:
+            // Some (most) hardware only supports single-precision floating-point numbers,
+            // which can accurately represent integers up to +/-16777216
+            range[0] = 24;
+            range[1] = 24;
+            precision[0] = 0;
+            precision[1] = 0;
+            break;
+          default:
+            return error(GL_INVALID_ENUM);
+        }
     }
     catch(std::bad_alloc&)
     {