opengles emulator: fix shader/program info log functions

on some platforms info log length of programs and shaders was
not returned correctly, we now cache the info log for these objects
and calculate info log length intenrally to be both correct and
compliant to the spec and conformance tests.

Change-Id: I017932482ba36f9e2e1858fe372683f7ac3a98ca
diff --git a/tools/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp b/tools/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp
index 76b0e8a..c81b346 100644
--- a/tools/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp
+++ b/tools/emulator/opengl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp
@@ -346,11 +346,19 @@
 GL_APICALL void  GL_APIENTRY glCompileShader(GLuint shader){
     GET_CTX();
     if(ctx->shareGroup().Ptr()) {
-       const GLuint globalShaderName = ctx->shareGroup()->getGlobalName(SHADER,shader);
+        const GLuint globalShaderName = ctx->shareGroup()->getGlobalName(SHADER,shader);
         SET_ERROR_IF(globalShaderName==0, GL_INVALID_VALUE);
         ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,shader);
         SET_ERROR_IF(objData.Ptr()->getDataType()!= SHADER_DATA,GL_INVALID_OPERATION);
-       ctx->dispatcher().glCompileShader(globalShaderName);
+        ShaderParser* sp = (ShaderParser*)objData.Ptr();
+        ctx->dispatcher().glCompileShader(globalShaderName);
+
+        GLsizei infoLogLength=0;
+        GLchar* infoLog;
+        ctx->dispatcher().glGetShaderiv(globalShaderName,GL_INFO_LOG_LENGTH,&infoLogLength);
+        infoLog = new GLchar[infoLogLength+1];
+        ctx->dispatcher().glGetShaderInfoLog(globalShaderName,infoLogLength,NULL,infoLog);
+        sp->setInfoLog(infoLog);
     }
 }
 
@@ -1151,6 +1159,16 @@
                     params[0] = GL_FALSE;
             }
             break;
+        case GL_INFO_LOG_LENGTH:
+            {
+                ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,program);
+                SET_ERROR_IF(!objData.Ptr() ,GL_INVALID_OPERATION);
+                SET_ERROR_IF(objData.Ptr()->getDataType()!=PROGRAM_DATA,GL_INVALID_OPERATION);
+                ProgramData* programData = (ProgramData*)objData.Ptr();
+                GLint logLength = strlen(programData->getInfoLog());
+                params[0] = (logLength>0) ? logLength+1 : 0;
+            }
+            break;   
         default:
             ctx->dispatcher().glGetProgramiv(globalProgramName,pname,params);
         }
@@ -1162,7 +1180,30 @@
     if(ctx->shareGroup().Ptr()) {
         const GLuint globalProgramName = ctx->shareGroup()->getGlobalName(SHADER,program);
         SET_ERROR_IF(globalProgramName==0, GL_INVALID_VALUE);
-        ctx->dispatcher().glGetProgramInfoLog(globalProgramName,bufsize,length,infolog);
+        ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,program);
+        SET_ERROR_IF(!objData.Ptr() ,GL_INVALID_OPERATION);
+        SET_ERROR_IF(objData.Ptr()->getDataType()!=PROGRAM_DATA,GL_INVALID_OPERATION);
+        ProgramData* programData = (ProgramData*)objData.Ptr();
+
+        if (bufsize==0) {
+            if (length) {
+                *length = 0;
+            }
+            return;
+        }
+
+        GLsizei logLength;
+        logLength = strlen(programData->getInfoLog());
+        
+        GLsizei returnLength=0;
+        if (infolog) {
+            returnLength = bufsize-1 < logLength ? bufsize-1 : logLength;
+            strncpy(infolog,programData->getInfoLog(),returnLength+1);
+            infolog[returnLength] = '\0';
+        }
+        if (length) {
+            *length = returnLength;
+        }
     }
 }
 
@@ -1171,16 +1212,53 @@
     if(ctx->shareGroup().Ptr()) {
         const GLuint globalShaderName = ctx->shareGroup()->getGlobalName(SHADER,shader);
         SET_ERROR_IF(globalShaderName==0, GL_INVALID_VALUE);
-        ctx->dispatcher().glGetShaderiv(globalShaderName,pname,params);
+        switch(pname) {
+        case GL_INFO_LOG_LENGTH:
+            {
+                ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,shader);
+                SET_ERROR_IF(!objData.Ptr() ,GL_INVALID_OPERATION);
+                SET_ERROR_IF(objData.Ptr()->getDataType()!=SHADER_DATA,GL_INVALID_OPERATION);
+                ShaderParser* sp = (ShaderParser*)objData.Ptr();
+                GLint logLength = strlen(sp->getInfoLog());
+                params[0] = (logLength>0) ? logLength+1 : 0;
+            }
+            break;
+        default:
+            ctx->dispatcher().glGetShaderiv(globalShaderName,pname,params);
+        }
     }
 }
 
+
 GL_APICALL void  GL_APIENTRY glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog){
     GET_CTX();
     if(ctx->shareGroup().Ptr()) {
         const GLuint globalShaderName = ctx->shareGroup()->getGlobalName(SHADER,shader);
         SET_ERROR_IF(globalShaderName==0, GL_INVALID_VALUE);
-        ctx->dispatcher().glGetShaderInfoLog(globalShaderName,bufsize,length,infolog);
+        ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,shader);
+        SET_ERROR_IF(!objData.Ptr() ,GL_INVALID_OPERATION);
+        SET_ERROR_IF(objData.Ptr()->getDataType()!=SHADER_DATA,GL_INVALID_OPERATION);
+        ShaderParser* sp = (ShaderParser*)objData.Ptr();
+
+        if (bufsize==0) {
+            if (length) {
+                *length = 0;
+            }
+            return;
+        }
+
+        GLsizei logLength;
+        logLength = strlen(sp->getInfoLog());
+        
+        GLsizei returnLength=0;
+        if (infolog) {
+            returnLength = bufsize-1 <logLength ? bufsize-1 : logLength;
+            strncpy(infolog,sp->getInfoLog(),returnLength+1);
+            infolog[returnLength] = '\0';
+        }
+        if (length) {
+            *length = returnLength;
+        }
     }
 }
 
@@ -1501,6 +1579,13 @@
             }
         }
         programData->setLinkStatus(linkStatus);
+        
+        GLsizei infoLogLength=0;
+        GLchar* infoLog;
+        ctx->dispatcher().glGetProgramiv(globalProgramName,GL_INFO_LOG_LENGTH,&infoLogLength);
+        infoLog = new GLchar[infoLogLength+1];
+        ctx->dispatcher().glGetProgramInfoLog(globalProgramName,infoLogLength,NULL,infoLog);
+        programData->setInfoLog(infoLog);
     }
 }
 
@@ -1834,7 +1919,15 @@
         SET_ERROR_IF(globalProgramName==0, GL_INVALID_VALUE);
         ObjectDataPtr objData = ctx->shareGroup()->getObjectData(SHADER,program);
         SET_ERROR_IF(objData.Ptr()->getDataType()!=PROGRAM_DATA,GL_INVALID_OPERATION);
+        ProgramData* programData = (ProgramData*)objData.Ptr();
         ctx->dispatcher().glValidateProgram(globalProgramName);
+
+        GLsizei infoLogLength=0;
+        GLchar* infoLog;
+        ctx->dispatcher().glGetProgramiv(globalProgramName,GL_INFO_LOG_LENGTH,&infoLogLength);
+        infoLog = new GLchar[infoLogLength+1];
+        ctx->dispatcher().glGetProgramInfoLog(globalProgramName,infoLogLength,NULL,infoLog);
+        programData->setInfoLog(infoLog);
     }
 }
 
diff --git a/tools/emulator/opengl/host/libs/Translator/GLES_V2/ProgramData.cpp b/tools/emulator/opengl/host/libs/Translator/GLES_V2/ProgramData.cpp
index b3e4a1e..656c782 100644
--- a/tools/emulator/opengl/host/libs/Translator/GLES_V2/ProgramData.cpp
+++ b/tools/emulator/opengl/host/libs/Translator/GLES_V2/ProgramData.cpp
@@ -20,9 +20,23 @@
 ProgramData::ProgramData() :  ObjectData(PROGRAM_DATA),
                               AttachedVertexShader(0),
                               AttachedFragmentShader(0),
-                              LinkStatus(GL_FALSE) {}
+                              LinkStatus(GL_FALSE) {
+    infoLog = new GLchar[1];
+    infoLog[0] = '\0';
+}
 
-ProgramData::~ProgramData () {};
+ProgramData::~ProgramData () {
+    delete[] infoLog;
+};
+
+void ProgramData::setInfoLog(GLchar* log) {
+    delete[] infoLog;
+    infoLog = log;
+}
+
+GLchar* ProgramData::getInfoLog() {
+    return infoLog;
+}
 
 GLuint ProgramData::getAttachedVertexShader() {
     return AttachedVertexShader;
diff --git a/tools/emulator/opengl/host/libs/Translator/GLES_V2/ProgramData.h b/tools/emulator/opengl/host/libs/Translator/GLES_V2/ProgramData.h
index 2bf7524..a79574a 100644
--- a/tools/emulator/opengl/host/libs/Translator/GLES_V2/ProgramData.h
+++ b/tools/emulator/opengl/host/libs/Translator/GLES_V2/ProgramData.h
@@ -32,9 +32,13 @@
     void setLinkStatus(GLint status);
     GLint getLinkStatus();
 
+    void setInfoLog(GLchar *log);
+    GLchar* getInfoLog();
+
 private:
     GLuint AttachedVertexShader;
     GLuint AttachedFragmentShader;
     GLint  LinkStatus;
+    GLchar* infoLog;
 };
 #endif
diff --git a/tools/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.cpp b/tools/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.cpp
index 2f27639..8e5696a 100644
--- a/tools/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.cpp
+++ b/tools/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.cpp
@@ -3,11 +3,18 @@
 
 ShaderParser::ShaderParser():ObjectData(SHADER_DATA),
                              m_type(0),
-                             m_parsedLines(NULL) {};
+                             m_parsedLines(NULL) {
+    m_infoLog = new GLchar[1];
+    m_infoLog[0] = '\0';
+};
 
 ShaderParser::ShaderParser(GLenum type):ObjectData(SHADER_DATA), 
                                         m_type(type),
-                                        m_parsedLines(NULL) {};
+                                        m_parsedLines(NULL) {
+
+    m_infoLog = new GLchar[1];
+    m_infoLog[0] = '\0';
+};
 
 void ShaderParser::setSrc(const Version& ver,GLsizei count,const GLchar** strings,const GLint* length){
     for(int i = 0;i<count;i++){
@@ -191,6 +198,18 @@
     return m_type;
 }
 
+void ShaderParser::setInfoLog(GLchar* infoLog)
+{
+    delete[] m_infoLog;
+    m_infoLog = infoLog;
+}
+
+GLchar* ShaderParser::getInfoLog()
+{   
+    return m_infoLog;
+}
+
 ShaderParser::~ShaderParser(){
     clearParsedSrc();
+    delete[] m_infoLog;
 }
diff --git a/tools/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.h b/tools/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.h
index 32d3b5f..88e4b2a 100644
--- a/tools/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.h
+++ b/tools/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.h
@@ -16,6 +16,9 @@
     GLenum         getType();
     ~ShaderParser();
 
+    void setInfoLog(GLchar * infoLog);
+    GLchar* getInfoLog();
+
 private:
     void parseOriginalSrc();
     void parseGLSLversion();
@@ -28,5 +31,6 @@
     std::string m_src;
     std::string m_parsedSrc;
     GLchar*     m_parsedLines;
+    GLchar*     m_infoLog;
 };
 #endif