glsl: better handling of linker failures

Upon link error, exit translation loop, free program instructions.
Check for null pointers in calling code.
This commit is contained in:
Brian Paul
2010-11-23 17:18:44 -07:00
parent 2900e56f9d
commit 6162773ea4

View File

@@ -2609,8 +2609,9 @@ set_uniform_initializers(struct gl_context *ctx,
/** /**
* Convert a shader's GLSL IR into a Mesa gl_program. * Convert a shader's GLSL IR into a Mesa gl_program.
*/ */
struct gl_program * static struct gl_program *
get_mesa_program(struct gl_context *ctx, struct gl_shader_program *shader_program, get_mesa_program(struct gl_context *ctx,
struct gl_shader_program *shader_program,
struct gl_shader *shader) struct gl_shader *shader)
{ {
ir_to_mesa_visitor v; ir_to_mesa_visitor v;
@@ -2756,6 +2757,15 @@ get_mesa_program(struct gl_context *ctx, struct gl_shader_program *shader_progra
mesa_inst++; mesa_inst++;
i++; 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); 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++) { for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
struct gl_program *linked_prog; struct gl_program *linked_prog;
bool ok = true;
if (prog->_LinkedShaders[i] == NULL) if (prog->_LinkedShaders[i] == NULL)
continue; continue;
linked_prog = get_mesa_program(ctx, prog, prog->_LinkedShaders[i]); linked_prog = get_mesa_program(ctx, prog, prog->_LinkedShaders[i]);
switch (prog->_LinkedShaders[i]->Type) { if (linked_prog) {
case GL_VERTEX_SHADER: bool ok = true;
_mesa_reference_vertprog(ctx, &prog->VertexProgram,
(struct gl_vertex_program *)linked_prog); switch (prog->_LinkedShaders[i]->Type) {
ok = ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB, case GL_VERTEX_SHADER:
linked_prog); _mesa_reference_vertprog(ctx, &prog->VertexProgram,
break; (struct gl_vertex_program *)linked_prog);
case GL_FRAGMENT_SHADER: ok = ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB,
_mesa_reference_fragprog(ctx, &prog->FragmentProgram, linked_prog);
(struct gl_fragment_program *)linked_prog); break;
ok = ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB, case GL_FRAGMENT_SHADER:
linked_prog); _mesa_reference_fragprog(ctx, &prog->FragmentProgram,
break; (struct gl_fragment_program *)linked_prog);
} ok = ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB,
if (!ok) { linked_prog);
return GL_FALSE; break;
}
if (!ok) {
return GL_FALSE;
}
} }
_mesa_reference_program(ctx, &linked_prog, NULL); _mesa_reference_program(ctx, &linked_prog, NULL);
} }