Fix shader object reference counting and hash table deallocation.

This commit is contained in:
Brian 2006-12-20 09:27:42 -07:00
parent 65a18442e5
commit 9e4bae9cca
5 changed files with 94 additions and 31 deletions

View file

@ -131,7 +131,7 @@
#include "math/m_xform.h"
#include "math/mathmod.h"
#endif
#include "shaders.h"
#include "shader_api.h"
#ifdef USE_SPARC_ASM
#include "sparc/sparc.h"
@ -877,13 +877,22 @@ delete_arrayobj_cb(GLuint id, void *data, void *userData)
}
/**
* Callback for deleting an shader object. Called by _mesa_HashDeleteAll().
* Callback for deleting shader and shader programs objects.
* Called by _mesa_HashDeleteAll().
*/
static void
delete_shaderobj_cb(GLuint id, void *data, void *userData)
delete_shader_cb(GLuint id, void *data, void *userData)
{
/* XXX probably need to fix this */
_mesa_free(data);
GLcontext *ctx = (GLcontext *) userData;
struct gl_shader *sh = (struct gl_shader *) data;
if (sh->Type == GL_FRAGMENT_SHADER || sh->Type == GL_VERTEX_SHADER) {
_mesa_free_shader(ctx, sh);
}
else {
struct gl_shader_program *shProg = (struct gl_shader_program *) data;
ASSERT(shProg->Type == GL_SHADER_PROGRAM);
_mesa_free_shader_program(ctx, shProg);
}
}
@ -948,11 +957,8 @@ free_shared_state( GLcontext *ctx, struct gl_shared_state *ss )
_mesa_DeleteHashTable(ss->ArrayObjects);
#if FEATURE_ARB_shader_objects
/* XXX SLANG TO-DO */
/*
struct _mesa_HashTable *ShaderObjects;
struct _mesa_HashTable *ProgramObjects;
*/
_mesa_HashDeleteAll(ss->ShaderObjects, delete_shader_cb, ctx);
_mesa_DeleteHashTable(ss->ShaderObjects);
#endif
#if FEATURE_EXT_framebuffer_object

View file

@ -2049,16 +2049,17 @@ struct gl_query_state
/**
* A GLSL shader object
* A GLSL shader object.
*/
struct gl_shader
{
GLenum Type; /**< GL_FRAGMENT_SHADER || GL_VERTEX_SHADER (first field!) */
GLuint Name; /**< AKA the handle */
GLint RefCount;
GLint RefCount; /**< Reference count */
GLboolean DeletePending;
const GLchar *Source; /**< Source code string */
GLboolean CompileStatus;
GLboolean DeletePending;
GLuint NumPrograms; /**< size of Programs[] array */
struct gl_program **Programs; /**< Post-compile assembly code */
GLchar *InfoLog;
@ -2066,15 +2067,19 @@ struct gl_shader
/**
* This corresponds to a GLSL "program" and is basically a linked collection
* of "shaders".
* A GLSL program object. Basically a linked collection of "shaders".
*/
struct gl_shader_program
{
GLenum Type; /**< Always GL_SHADER_PROGRAM (internal token) */
GLuint Name; /**< aka handle or ID */
GLuint NumShaders; /**< total number of shaders in this program */
struct gl_shader **Shaders; /**< List of the shaders */
GLint RefCount; /**< Reference count */
GLboolean DeletePending;
GLuint NumShaders; /**< number of attached shaders */
struct gl_shader **Shaders; /**< List of attached the shaders */
/* post-link info: */
struct gl_vertex_program *VertexProgram; /**< Linked vertex program */
struct gl_fragment_program *FragmentProgram; /**< Linked fragment prog */
struct gl_program_parameter_list *Uniforms; /**< Plus constants, etc */
@ -2082,7 +2087,6 @@ struct gl_shader_program
struct gl_program_parameter_list *Attributes; /**< Vertex attributes */
GLboolean LinkStatus; /**< GL_LINK_STATUS */
GLboolean Validated;
GLboolean DeletePending;
GLchar *InfoLog;
};

View file

@ -233,9 +233,4 @@ _mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose,
const GLfloat *value);
/*** XXXX temporary here ! */
extern void
_mesa_init_shader_state(GLcontext *ctx);
#endif /* SHADERS_H */

View file

@ -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.
*/

View file

@ -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);