Add ability to recompile shader source

Trac# 19900
Issue=291

- add an 'uncompile' function to clear all results from any previous compile attempts
- allow compiling to be done multiple times on the same shader
- allow a shader to be compiled with no source specified (to produce an appropriate error).

Signed-off-by: Shannon Woods
Signed-off-by: Nicolas Capens

git-svn-id: https://angleproject.googlecode.com/svn/trunk@991 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/Shader.cpp b/src/libGLESv2/Shader.cpp
index 2c58e2d..9b65301 100644
--- a/src/libGLESv2/Shader.cpp
+++ b/src/libGLESv2/Shader.cpp
@@ -27,6 +27,8 @@
     mHlsl = NULL;
     mInfoLog = NULL;
 
+    uncompile();
+
     // Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler)
     if (!mFragmentCompiler)
     {
@@ -294,36 +296,53 @@
     }
 }
 
-void Shader::compileToHLSL(void *compiler)
+// initialize/clean up previous state
+void Shader::uncompile()
 {
-    if (isCompiled() || !mSource)
-    {
-        return;
-    }
-
+    // set by compileToHLSL
+    delete[] mHlsl;
+    mHlsl = NULL;
     delete[] mInfoLog;
     mInfoLog = NULL;
 
+    // set by parseVaryings
+    mVaryings.clear();
+
+    mUsesFragCoord = false;
+    mUsesFrontFacing = false;
+    mUsesPointSize = false;
+    mUsesPointCoord = false;
+}
+
+void Shader::compileToHLSL(void *compiler)
+{
+    // ensure we don't pass a NULL source to the compiler
+    char *source = "\0";
+    if (mSource)
+    {
+        source = mSource;
+    }
+
     int compileOptions = SH_OBJECT_CODE;
     std::string sourcePath;
     if (perfActive())
     {
         sourcePath = getTempPath();
-        writeFile(sourcePath.c_str(), mSource, strlen(mSource));
+        writeFile(sourcePath.c_str(), source, strlen(source));
         compileOptions |= SH_LINE_DIRECTIVES;
     }
 
     int result;
     if (sourcePath.empty())
     {
-        result = ShCompile(compiler, &mSource, 1, compileOptions);
+        result = ShCompile(compiler, &source, 1, compileOptions);
     }
     else
     {
         const char* sourceStrings[2] =
         {
             sourcePath.c_str(),
-            mSource
+            source
         };
 
         result = ShCompile(compiler, sourceStrings, 2, compileOptions | SH_SOURCE_PATH);
@@ -478,8 +497,18 @@
     return GL_VERTEX_SHADER;
 }
 
+void VertexShader::uncompile()
+{
+    Shader::uncompile();
+
+    // set by ParseAttributes
+    mAttributes.clear();
+};
+
 void VertexShader::compile()
 {
+    uncompile();
+
     compileToHLSL(mVertexCompiler);
     parseAttributes();
     parseVaryings();
@@ -545,6 +574,8 @@
 
 void FragmentShader::compile()
 {
+    uncompile();
+
     compileToHLSL(mFragmentCompiler);
     parseVaryings();
     mVaryings.sort(compareVarying);
diff --git a/src/libGLESv2/Shader.h b/src/libGLESv2/Shader.h
index 2fddbef..5baae71 100644
--- a/src/libGLESv2/Shader.h
+++ b/src/libGLESv2/Shader.h
@@ -62,6 +62,7 @@
     void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer);
 
     virtual void compile() = 0;
+    virtual void uncompile();
     bool isCompiled();
     const char *getHLSL();
 
@@ -134,6 +135,7 @@
 
     virtual GLenum getType();
     virtual void compile();
+    virtual void uncompile();
     int getSemanticIndex(const std::string &attributeName);
 
   private: