mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-07 11:28:05 +02:00
Fix shader object reference counting and hash table deallocation.
This commit is contained in:
parent
65a18442e5
commit
9e4bae9cca
5 changed files with 94 additions and 31 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue