summaryrefslogtreecommitdiff
path: root/src/mesa/program
diff options
context:
space:
mode:
authorBrian Paul <brianp@vmware.com>2010-11-23 17:18:44 -0700
committerBrian Paul <brianp@vmware.com>2010-11-23 17:18:48 -0700
commit6162773ea4b0e84c3ab9c9952fb5e838519c2564 (patch)
tree81603c1b4d08061ccdaa1f767c1f2a5b1a7c5464 /src/mesa/program
parent2900e56f9dda864f2c5b75d3db4dcc452dc91373 (diff)
glsl: better handling of linker failures
Upon link error, exit translation loop, free program instructions. Check for null pointers in calling code.
Diffstat (limited to 'src/mesa/program')
-rw-r--r--src/mesa/program/ir_to_mesa.cpp52
1 files changed, 33 insertions, 19 deletions
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index c5f11e010d..2561bf0880 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -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);
}