Bug 1080266 - Simplify WebGLContext::LinkProgram. - r=kamidphish
authorjdashg <jdashg+github@gmail.com>
Fri, 03 Oct 2014 14:47:00 -0700
changeset 233117 562ae8bddcd5d956e0c4fcc1bb31e83b95e1902b
parent 233116 f2d5fb5e746e11665550ea4c007fdea9cadd925e
child 233118 3e779f1cf1d9c24484844184cbe659cf50d8326f
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskamidphish
bugs1080266
milestone35.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1080266 - Simplify WebGLContext::LinkProgram. - r=kamidphish
dom/canvas/WebGLContextGL.cpp
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -1888,98 +1888,90 @@ bool WebGLContext::BindArrayAttribToLoca
         nsCString& attrName = program->mActiveAttribMap.find(leastArrayLocation)->second;
         const char* attrNameCStr = attrName.get();
         gl->fBindAttribLocation(program->GLName(), 0, attrNameCStr);
         return true;
     }
     return false;
 }
 
+static void
+LinkAndUpdateProgram(GLContext* gl, WebGLProgram* prog)
+{
+    GLuint name = prog->GLName();
+    gl->fLinkProgram(name);
+
+    prog->SetLinkStatus(false);
+
+    GLint ok = 0;
+    gl->fGetProgramiv(name, LOCAL_GL_LINK_STATUS, &ok);
+    if (!ok)
+        return;
+
+    if (!prog->UpdateInfo())
+        return;
+
+    prog->SetLinkStatus(true);
+}
+
 void
 WebGLContext::LinkProgram(WebGLProgram *program)
 {
     if (IsContextLost())
         return;
 
     if (!ValidateObject("linkProgram", program))
         return;
 
     InvalidateBufferFetching(); // we do it early in this function
     // as some of the validation below changes program state
 
-    GLuint progname = program->GLName();
-
     if (!program->NextGeneration()) {
         // XXX throw?
         return;
     }
 
     if (!program->HasBothShaderTypesAttached()) {
-        GenerateWarning("linkProgram: this program doesn't have both a vertex shader"
-                        " and a fragment shader");
+        GenerateWarning("linkProgram: this program doesn't have both a vertex"
+                        " shader and a fragment shader");
+        program->SetLinkStatus(false);
+        return;
+    }
+
+    if (program->HasBadShaderAttached()) {
+        GenerateWarning("linkProgram: The program has bad shaders attached.");
         program->SetLinkStatus(false);
         return;
     }
 
     // bug 777028
     // Mesa can't handle more than 16 samplers per program, counting each array entry.
     if (gl->WorkAroundDriverBugs() &&
         mIsMesa &&
         program->UpperBoundNumSamplerUniforms() > 16)
     {
-        GenerateWarning("Programs with more than 16 samplers are disallowed on Mesa drivers " "to avoid a Mesa crasher.");
+        GenerateWarning("Programs with more than 16 samplers are disallowed on"
+                        " Mesa drivers to avoid a Mesa crasher.");
         program->SetLinkStatus(false);
         return;
     }
 
-    bool updateInfoSucceeded = false;
-    GLint ok = 0;
-    if (gl->WorkAroundDriverBugs() &&
-        program->HasBadShaderAttached())
-    {
-        // it's a common driver bug, caught by program-test.html, that linkProgram doesn't
-        // correctly preserve the state of an in-use program that has been attached a bad shader
-        // see bug 777883
-        ok = false;
-    } else {
-        MakeContextCurrent();
-        gl->fLinkProgram(progname);
-        gl->fGetProgramiv(progname, LOCAL_GL_LINK_STATUS, &ok);
-
-        if (ok) {
-            updateInfoSucceeded = program->UpdateInfo();
-            program->SetLinkStatus(updateInfoSucceeded);
-
-            if (BindArrayAttribToLocation0(program)) {
-                GenerateWarning("linkProgram: relinking program to make attrib0 an "
-                                "array.");
-                gl->fLinkProgram(progname);
-                gl->fGetProgramiv(progname, LOCAL_GL_LINK_STATUS, &ok);
-                if (ok) {
-                    updateInfoSucceeded = program->UpdateInfo();
-                    program->SetLinkStatus(updateInfoSucceeded);
-                }
-            }
+    MakeContextCurrent();
+    LinkAndUpdateProgram(gl, program);
+
+    if (program->LinkStatus()) {
+        if (BindArrayAttribToLocation0(program)) {
+            GenerateWarning("linkProgram: Relinking program to make attrib0 an"
+                            " array.");
+            LinkAndUpdateProgram(gl, program);
         }
     }
 
-    if (ok) {
-        // Bug 750527
-        if (gl->WorkAroundDriverBugs() &&
-            updateInfoSucceeded &&
-            gl->Vendor() == gl::GLVendor::NVIDIA)
-        {
-            if (program == mCurrentProgram)
-                gl->fUseProgram(progname);
-        }
-    } else {
-        program->SetLinkStatus(false);
-
+    if (!program->LinkStatus()) {
         if (ShouldGenerateWarnings()) {
-
             // report shader/program infoLogs as warnings.
             // note that shader compilation errors can be deferred to linkProgram,
             // which is why we can't do anything in compileShader. In practice we could
             // report in compileShader the translation errors generated by ANGLE,
             // but it seems saner to keep a single way of obtaining shader infologs.
 
             nsAutoCString log;
 
@@ -2015,16 +2007,24 @@ WebGLContext::LinkProgram(WebGLProgram *
             if (!alreadyReportedShaderInfoLog) {
                 GetProgramInfoLog(program, log);
                 if (!log.IsEmpty()) {
                     GenerateWarning("linkProgram failed, with this log:\n%s\n",
                                     log.get());
                 }
             }
         }
+        return;
+    }
+
+    if (gl->WorkAroundDriverBugs() &&
+        gl->Vendor() == gl::GLVendor::NVIDIA)
+    {
+        if (program == mCurrentProgram)
+            gl->fUseProgram(program->GLName());
     }
 }
 
 void
 WebGLContext::PixelStorei(GLenum pname, GLint param)
 {
     if (IsContextLost())
         return;