From 9e4bae9ccac5a76a2361c5c3cbe377a3c6b6a95b Mon Sep 17 00:00:00 2001 From: Brian Date: Wed, 20 Dec 2006 09:27:42 -0700 Subject: Fix shader object reference counting and hash table deallocation. --- src/mesa/shader/shader_api.c | 69 +++++++++++++++++++++++++++++++++++++++----- src/mesa/shader/shader_api.h | 5 +++- 2 files changed, 66 insertions(+), 8 deletions(-) (limited to 'src/mesa/shader') diff --git a/src/mesa/shader/shader_api.c b/src/mesa/shader/shader_api.c index e49feea3d8..2d1056e667 100644 --- a/src/mesa/shader/shader_api.c +++ b/src/mesa/shader/shader_api.c @@ -126,6 +126,15 @@ _mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index, return; } + if (!name) + return; + + if (strncmp(name, "gl_", 3) == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindAttribLocation(illegal name)"); + return; + } + #if 0 /* XXXX */ if (name == NULL || index >= MAX_VERTEX_ATTRIBS) _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocationARB"); @@ -188,20 +197,32 @@ _mesa_delete_program2(GLcontext *ctx, GLuint name) return; } - /* XXX refcounting! */ + /* always remove from hash table */ _mesa_HashRemove(ctx->Shared->ShaderObjects, name); - _mesa_delete_shader_program(ctx, shProg); + + shProg->DeletePending = GL_TRUE; + + /* decrement refcount, delete if zero */ + shProg->RefCount--; + if (shProg->RefCount <= 0) { + _mesa_free_shader_program(ctx, shProg); + } } void _mesa_delete_shader(GLcontext *ctx, GLuint shader) { - /* XXX refcounting! */ + struct gl_shader *sh = _mesa_lookup_shader(ctx, shader); + if (!sh) { + return; + } - /* - _mesa_DeleteObjectARB(shader); - */ + sh->DeletePending = GL_TRUE; + sh->RefCount--; + if (sh->RefCount <= 0) { + _mesa_free_shader(ctx, sh); + } } @@ -223,6 +244,9 @@ _mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader) if (shProg->Shaders[i]->Name == shader) { struct gl_shader **newList; /* found it */ + + shProg->Shaders[i]->RefCount--; + /* alloc new, smaller array */ newList = (struct gl_shader **) _mesa_malloc((n - 1) * sizeof(struct gl_shader *)); @@ -602,6 +626,7 @@ _mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source) _mesa_free((void *) sh->Source); } sh->Source = source; + sh->CompileStatus = GL_FALSE; } @@ -667,6 +692,15 @@ _mesa_link_program(GLcontext *ctx, GLuint program) void _mesa_use_program(GLcontext *ctx, GLuint program) { + /* unbind old */ + if (ctx->Shader.CurrentProgram) { + ctx->Shader.CurrentProgram->RefCount--; + if (ctx->Shader.CurrentProgram->RefCount <= 0) { + _mesa_free_shader_program(ctx, ctx->Shader.CurrentProgram); + } + ctx->Shader.CurrentProgram = NULL; + } + /* XXXX need to handle reference counting here! */ if (program) { struct gl_shader_program *shProg; @@ -677,6 +711,7 @@ _mesa_use_program(GLcontext *ctx, GLuint program) return; } ctx->Shader.CurrentProgram = shProg; + shProg->RefCount++; } else { /* don't use a shader program */ @@ -817,6 +852,7 @@ _mesa_new_shader_program(GLcontext *ctx, GLuint name) if (shProg) { shProg->Type = GL_SHADER_PROGRAM; shProg->Name = name; + shProg->RefCount = 1; } return shProg; } @@ -861,7 +897,7 @@ _mesa_free_shader_program_data(GLcontext *ctx, void -_mesa_delete_shader_program(GLcontext *ctx, struct gl_shader_program *shProg) +_mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg) { _mesa_free_shader_program_data(ctx, shProg); _mesa_free(shProg); @@ -903,11 +939,30 @@ _mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type) if (shader) { shader->Type = type; shader->Name = name; + shader->RefCount = 1; } return shader; } +void +_mesa_free_shader(GLcontext *ctx, struct gl_shader *sh) +{ + GLuint i; + if (sh->Source) + _mesa_free((void *) sh->Source); + if (sh->InfoLog) + _mesa_free(sh->InfoLog); + for (i = 0; i < sh->NumPrograms; i++) { + assert(sh->Programs[i]); + _mesa_delete_program(ctx, sh->Programs[i]); + } + if (sh->Programs) + _mesa_free(sh->Programs); + _mesa_free(sh); +} + + /** * Lookup a GLSL shader object. */ diff --git a/src/mesa/shader/shader_api.h b/src/mesa/shader/shader_api.h index 2f73bb8887..315f60a35f 100644 --- a/src/mesa/shader/shader_api.h +++ b/src/mesa/shader/shader_api.h @@ -46,7 +46,7 @@ _mesa_free_shader_program_data(GLcontext *ctx, struct gl_shader_program *shProg); extern void -_mesa_delete_shader_program(GLcontext *ctx, struct gl_shader_program *shProg); +_mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg); extern struct gl_shader_program * _mesa_lookup_shader_program(GLcontext *ctx, GLuint name); @@ -55,6 +55,9 @@ _mesa_lookup_shader_program(GLcontext *ctx, GLuint name); extern struct gl_shader * _mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type); +extern void +_mesa_free_shader(GLcontext *ctx, struct gl_shader *sh); + extern struct gl_shader * _mesa_lookup_shader(GLcontext *ctx, GLuint name); -- cgit v1.2.3