Restore the explicit isLinked() method for Programs and fix link().

Trac #21270
Bug=351
Signed-off-by: Nicolas Capens

If link fails we still need to keep the failed binary around for information
such as number of active attributes, varyings, etc.
Thus we can no longer use the presence of a binary to tell us if we've successfully
linked a program object.



git-svn-id: https://angleproject.googlecode.com/svn/trunk@1241 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/Program.cpp b/src/libGLESv2/Program.cpp
index b0509ab..3923035 100644
--- a/src/libGLESv2/Program.cpp
+++ b/src/libGLESv2/Program.cpp
@@ -142,6 +142,7 @@
     mVertexShader = NULL;
     mProgramBinary = NULL;
     mDeleteStatus = false;
+    mLinked = false;
     mRefCount = 0;
 }
 
@@ -247,14 +248,9 @@
     mInfoLog.reset();
 
     mProgramBinary = new ProgramBinary;
-    if (!mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader))
-    {
-        unlink(false);
+    mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader);
 
-        return false;
-    }
-
-    return true;
+    return mLinked;
 }
 
 int AttributeBindings::getAttributeBinding(const std::string &name) const
@@ -293,6 +289,12 @@
         delete mProgramBinary;
         mProgramBinary = NULL;
     }
+    mLinked = false;
+}
+
+bool Program::isLinked()
+{
+    return mLinked;
 }
 
 ProgramBinary* Program::getProgramBinary()
@@ -307,15 +309,14 @@
     mInfoLog.reset();
 
     mProgramBinary = new ProgramBinary;
-    if (!mProgramBinary->load(mInfoLog, binary, length))
+    mLinked = mProgramBinary->load(mInfoLog, binary, length);
+    if (!mLinked)
     {
         delete mProgramBinary;
         mProgramBinary = NULL;
-
-        return false;
     }
 
-    return true;
+    return mLinked;
 }
 
 void Program::release()
@@ -498,7 +499,7 @@
 {
     mInfoLog.reset();
 
-    if (mProgramBinary)
+    if (isLinked() && mProgramBinary)
     {
         mProgramBinary->validate(mInfoLog);
     }
diff --git a/src/libGLESv2/Program.h b/src/libGLESv2/Program.h
index 981dc67..b103b1c 100644
--- a/src/libGLESv2/Program.h
+++ b/src/libGLESv2/Program.h
@@ -69,6 +69,7 @@
     void bindAttributeLocation(GLuint index, const char *name);
 
     bool link();
+    bool isLinked();
     bool setProgramBinary(const void *binary, GLsizei length);
     ProgramBinary *getProgramBinary();
 
@@ -106,6 +107,7 @@
     AttributeBindings mAttributeBindings;
 
     ProgramBinary* mProgramBinary;
+    bool mLinked;
     bool mDeleteStatus;   // Flag to indicate that the program can be deleted when no longer in use
 
     unsigned int mRefCount;
diff --git a/src/libGLESv2/libGLESv2.cpp b/src/libGLESv2/libGLESv2.cpp
index 8e22a7f..d48bf76 100644
--- a/src/libGLESv2/libGLESv2.cpp
+++ b/src/libGLESv2/libGLESv2.cpp
@@ -2939,7 +2939,7 @@
             }
 
             gl::ProgramBinary *programBinary = programObject->getProgramBinary();
-            if (!programBinary)
+            if (!programObject->isLinked() || !programBinary)
             {
                 return error(GL_INVALID_OPERATION, -1);
             }
@@ -3398,7 +3398,7 @@
                 *params = programObject->isFlaggedForDeletion();
                 return;
               case GL_LINK_STATUS:
-                *params = programObject->getProgramBinary() != NULL;
+                *params = programObject->isLinked();
                 return;
               case GL_VALIDATE_STATUS:
                 *params = programObject->isValidated();
@@ -3963,7 +3963,7 @@
 
             gl::Program *programObject = context->getProgram(program);
 
-            if (!programObject)
+            if (!programObject || !programObject->isLinked())
             {
                 return error(GL_INVALID_OPERATION);
             }
@@ -4003,7 +4003,7 @@
 
             gl::Program *programObject = context->getProgram(program);
 
-            if (!programObject)
+            if (!programObject || !programObject->isLinked())
             {
                 return error(GL_INVALID_OPERATION);
             }
@@ -4049,7 +4049,7 @@
 
             gl::Program *programObject = context->getProgram(program);
 
-            if (!programObject)
+            if (!programObject || !programObject->isLinked())
             {
                 return error(GL_INVALID_OPERATION);
             }
@@ -4089,7 +4089,7 @@
 
             gl::Program *programObject = context->getProgram(program);
 
-            if (!programObject)
+            if (!programObject || !programObject->isLinked())
             {
                 return error(GL_INVALID_OPERATION);
             }
@@ -4142,7 +4142,7 @@
             }
 
             gl::ProgramBinary *programBinary = programObject->getProgramBinary();
-            if (!programBinary)
+            if (!programObject->isLinked() || !programBinary)
             {
                 return error(GL_INVALID_OPERATION, -1);
             }
@@ -6425,7 +6425,7 @@
                 }
             }
 
-            if (program != 0 && !programObject->getProgramBinary())
+            if (program != 0 && !programObject->isLinked())
             {
                 return error(GL_INVALID_OPERATION);
             }
@@ -6848,7 +6848,7 @@
         {
             gl::Program *programObject = context->getProgram(program);
 
-            if (!programObject)
+            if (!programObject || !programObject->isLinked())
             {
                 return error(GL_INVALID_OPERATION);
             }