summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian <[email protected]>2006-12-20 09:27:42 -0700
committerBrian <[email protected]>2006-12-20 09:27:42 -0700
commit9e4bae9ccac5a76a2361c5c3cbe377a3c6b6a95b (patch)
tree49457c5d38d27a54d59d3e0429f8dcd46eab6882
parent65a18442e5d846940714bb662f5b1bb47ab60c29 (diff)
Fix shader object reference counting and hash table deallocation.
-rw-r--r--src/mesa/main/context.c26
-rw-r--r--src/mesa/main/mtypes.h20
-rw-r--r--src/mesa/main/shaders.h5
-rw-r--r--src/mesa/shader/shader_api.c69
-rw-r--r--src/mesa/shader/shader_api.h5
5 files changed, 94 insertions, 31 deletions
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index 2196591ba26..0e2a7804769 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -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
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 57f174a7d47..e73c625a825 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -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;
};
diff --git a/src/mesa/main/shaders.h b/src/mesa/main/shaders.h
index a098c4c3315..17339ccf623 100644
--- a/src/mesa/main/shaders.h
+++ b/src/mesa/main/shaders.h
@@ -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 */
diff --git a/src/mesa/shader/shader_api.c b/src/mesa/shader/shader_api.c
index e49feea3d86..2d1056e6674 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 2f73bb88871..315f60a35f7 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);