glsl: better handling of linker failures
authorBrian Paul <brianp@vmware.com>
Wed, 24 Nov 2010 00:18:44 +0000 (17:18 -0700)
committerBrian Paul <brianp@vmware.com>
Wed, 24 Nov 2010 00:18:48 +0000 (17:18 -0700)
Upon link error, exit translation loop, free program instructions.
Check for null pointers in calling code.

src/mesa/program/ir_to_mesa.cpp

index c5f11e010da136ee705f18da47e2ce311f063007..2561bf0880aa4e069b5216a1566cd9743ae96b1c 100644 (file)
@@ -2609,8 +2609,9 @@ set_uniform_initializers(struct gl_context *ctx,
 /**
  * Convert a shader's GLSL IR into a Mesa gl_program.
  */
-struct gl_program *
-get_mesa_program(struct gl_context *ctx, struct gl_shader_program *shader_program,
+static struct gl_program *
+get_mesa_program(struct gl_context *ctx,
+                 struct gl_shader_program *shader_program,
                 struct gl_shader *shader)
 {
    ir_to_mesa_visitor v;
@@ -2756,6 +2757,15 @@ get_mesa_program(struct gl_context *ctx, struct gl_shader_program *shader_progra
 
       mesa_inst++;
       i++;
+
+      if (!shader_program->LinkStatus)
+         break;
+   }
+
+   if (!shader_program->LinkStatus) {
+      free(mesa_instructions);
+      _mesa_reference_program(ctx, &shader->Program, NULL);
+      return NULL;
    }
 
    set_branchtargets(&v, mesa_instructions, num_instructions);
@@ -2866,30 +2876,34 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
 
    for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
       struct gl_program *linked_prog;
-      bool ok = true;
 
       if (prog->_LinkedShaders[i] == NULL)
         continue;
 
       linked_prog = get_mesa_program(ctx, prog, prog->_LinkedShaders[i]);
 
-      switch (prog->_LinkedShaders[i]->Type) {
-      case GL_VERTEX_SHADER:
-        _mesa_reference_vertprog(ctx, &prog->VertexProgram,
-                                 (struct gl_vertex_program *)linked_prog);
-        ok = ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB,
-                                             linked_prog);
-        break;
-      case GL_FRAGMENT_SHADER:
-        _mesa_reference_fragprog(ctx, &prog->FragmentProgram,
-                                 (struct gl_fragment_program *)linked_prog);
-        ok = ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB,
-                                             linked_prog);
-        break;
-      }
-      if (!ok) {
-        return GL_FALSE;
+      if (linked_prog) {
+         bool ok = true;
+
+         switch (prog->_LinkedShaders[i]->Type) {
+         case GL_VERTEX_SHADER:
+            _mesa_reference_vertprog(ctx, &prog->VertexProgram,
+                                     (struct gl_vertex_program *)linked_prog);
+            ok = ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB,
+                                                 linked_prog);
+            break;
+         case GL_FRAGMENT_SHADER:
+            _mesa_reference_fragprog(ctx, &prog->FragmentProgram,
+                                     (struct gl_fragment_program *)linked_prog);
+            ok = ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB,
+                                                 linked_prog);
+            break;
+         }
+         if (!ok) {
+            return GL_FALSE;
+         }
       }
+
       _mesa_reference_program(ctx, &linked_prog, NULL);
    }