2.0 translator: workaround for nVidia "bug"

This is not really a bug, but the nVidia shader compiler is much more
liberal than the GLSL spec, and allows compilation of shaders which
do not comply with the spec. This is an issue for passing the
conformance tests, but more importantly it will allow bad shader written
by the app developer to pass on the emulator and then to fail on the device.

Adding "#version 100" definition to the head of a shader source disables
this liberal behavior. For now this is activated in run time by the "NV_WAR"
environment variable.

Change-Id: I1c322d4221d313d3ee70592bc15ea0e340853990
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 0a8390f..784c0d3 100644
--- a/tools/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.cpp
+++ b/tools/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.cpp
@@ -3,18 +3,23 @@
 
 ShaderParser::ShaderParser():ObjectData(SHADER_DATA),
                              m_type(0),
-                             m_src(NULL),
-                             m_parsedLines(NULL){};
+                             m_parsedLines(NULL) {};
 
 ShaderParser::ShaderParser(GLenum type):ObjectData(SHADER_DATA), 
                                         m_type(type),
-                                        m_parsedLines(NULL){};
+                                        m_parsedLines(NULL) {};
 
 void ShaderParser::setSrc(const Version& ver,GLsizei count,const GLchar** strings,const GLint* length){
     for(int i = 0;i<count;i++){
         m_src.append(strings[i]);
     }
     clearParsedSrc();
+
+    if(getenv("NV_WAR"))
+    {
+        fprintf(stderr, "Workaround for nVidia's liberal shader compilation - adding #version token to shader\n");
+        parseGLSLversion();
+    }
     /*
       version 1.30.10 is the first version of GLSL Language containing precision qualifiers
       if the glsl version is less than 1.30.10 than we will use a shader parser which omits
@@ -31,12 +36,29 @@
     //XXX: Until proved otherwise, glsl doesn't know/use those precision macros, so we omit then
     parseOmitPrecision();
 #endif
+
+    parseOriginalSrc();
 }
+const GLchar** ShaderParser::parsedLines() {
+      m_parsedLines = (GLchar*)m_parsedSrc.c_str();
+      return const_cast<const GLchar**> (&m_parsedLines);
+};
 
 const char* ShaderParser::getOriginalSrc(){
     return m_src.c_str();
 }
 
+void ShaderParser::parseOriginalSrc() {
+    m_parsedSrc+=m_src;
+}
+
+void ShaderParser::parseGLSLversion() {
+    //if no version definition is found
+    if (m_src.find("#version ", 0) == std::string::npos) {
+        m_parsedSrc += "#version 100\n";
+    }
+}
+
 void ShaderParser::parseOmitPrecision(){
 
     //defines we need to add in order to Omit precisions qualifiers
@@ -47,16 +69,7 @@
                                          "#define highp \n"
                                          "#define precision \n"
                                      };
-
-    //the lengths of defines we need to add in order to Omit precisions qualifiers
-    static GLuint definesLength   = strlen(defines);
-
-    const GLchar* origSrc = m_src.c_str();
-    unsigned int origLength = strlen(origSrc);
-
-    m_parsedLines = new GLchar[origLength + definesLength + 1];
-    strncpy(m_parsedLines,defines,definesLength);
-    strcpy(m_parsedLines+definesLength,origSrc);
+    m_parsedSrc+=defines;
 }
 
 void ShaderParser::parseExtendDefaultPrecision(){
@@ -68,21 +81,11 @@
                                       "precision lowp samplerCube;\n"
                                    };
 
-    //the length of the precision lines which we need to add to the shader
-    static GLint extendLength = strlen(extend);
-
-    const GLchar* origSrc = m_src.c_str();
-    unsigned int origLength = strlen(origSrc);
-
-    m_parsedLines = new GLchar[origLength + extendLength + 1];
-    strncpy(m_parsedLines,extend,extendLength);
-    strcpy(m_parsedLines+extendLength,origSrc);
+    m_parsedSrc+=extend;
 }
 
 void ShaderParser::clearParsedSrc(){
-    if(m_parsedLines){
-        delete[] m_parsedLines;
-    }
+    m_parsedSrc.clear();
 }
 
 GLenum ShaderParser::getType() {
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 4f32f90..ca2c69f 100644
--- a/tools/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.h
+++ b/tools/emulator/opengl/host/libs/Translator/GLES_V2/ShaderParser.h
@@ -12,17 +12,20 @@
     ShaderParser(GLenum type);
     void           setSrc(const Version& ver,GLsizei count,const GLchar** strings,const GLint* length);
     const char*    getOriginalSrc();
-    const GLchar** parsedLines(){return const_cast<const GLchar**>(&m_parsedLines);};
+    const GLchar** parsedLines();
     GLenum         getType();
     ~ShaderParser();
 
 private:
+    void parseOriginalSrc();
+    void parseGLSLversion();
     void parseOmitPrecision();
     void parseExtendDefaultPrecision();
     void clearParsedSrc();
 
     GLenum      m_type;
     std::string m_src;
+    std::string m_parsedSrc;
     GLchar*     m_parsedLines;
 };
 #endif