mesa: separate shader program object from shader object.
authorXiang, Haihao <haihao.xiang@intel.com>
Thu, 28 Feb 2008 13:27:16 +0000 (21:27 +0800)
committerXiang, Haihao <haihao.xiang@intel.com>
Thu, 28 Feb 2008 13:32:36 +0000 (21:32 +0800)
Currently a callback delete_shader_cb is used for deleting shader
and shader program objects. Mesa detaches all attached shaders in
_mesa_free_shader_program_data when deleting shader program objects. However
it is likely that these shaders have been freed in _mesa_free_shader,
which will result in unexpected behaviour. This fix uses a single callback for
shader program objects and deletes shader program objects before shader objects.

src/mesa/main/context.c
src/mesa/main/mtypes.h
src/mesa/shader/shader_api.c

index e3096b5..69c361f 100644 (file)
@@ -444,6 +444,7 @@ alloc_shared_state( GLcontext *ctx )
    ss->ArrayObjects = _mesa_NewHashTable();
 
 #if FEATURE_ARB_shader_objects
+   ss->ShaderProgramObjects = _mesa_NewHashTable();
    ss->ShaderObjects = _mesa_NewHashTable();
 #endif
 
@@ -523,6 +524,8 @@ cleanup:
       _mesa_DeleteHashTable (ss->ArrayObjects);
 
 #if FEATURE_ARB_shader_objects
+   if (ss->ShaderProgramObjects)
+      _mesa_DeleteHashTable (ss->ShaderProgramObjects);
    if (ss->ShaderObjects)
       _mesa_DeleteHashTable (ss->ShaderObjects);
 #endif
@@ -631,14 +634,17 @@ delete_shader_cb(GLuint id, void *data, void *userData)
 {
    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);
-      _mesa_free_shader_program(ctx, shProg);
-   }
+   assert(sh->Type == GL_FRAGMENT_SHADER || sh->Type == GL_VERTEX_SHADER);
+   _mesa_free_shader(ctx, sh);
+}
+
+static void
+delete_shader_program_cb(GLuint id, void *data, void *userData)
+{
+   GLcontext *ctx = (GLcontext *) userData;
+   struct gl_shader_program *shProg = (struct gl_shader_program *) data;
+   assert(shProg->Type == GL_SHADER_PROGRAM_MESA);
+   _mesa_free_shader_program(ctx, shProg);
 }
 
 /**
@@ -721,6 +727,8 @@ free_shared_state( GLcontext *ctx, struct gl_shared_state *ss )
    _mesa_DeleteHashTable(ss->ArrayObjects);
 
 #if FEATURE_ARB_shader_objects
+   _mesa_HashDeleteAll(ss->ShaderProgramObjects, delete_shader_program_cb, ctx);
+   _mesa_DeleteHashTable(ss->ShaderProgramObjects);
    _mesa_HashDeleteAll(ss->ShaderObjects, delete_shader_cb, ctx);
    _mesa_DeleteHashTable(ss->ShaderObjects);
 #endif
index c8718a7..da60a46 100644 (file)
@@ -2202,8 +2202,8 @@ struct gl_shared_state
 #endif
 
 #if FEATURE_ARB_shader_objects
-   /** Table of both gl_shader and gl_shader_program objects */
    struct _mesa_HashTable *ShaderObjects;
+   struct _mesa_HashTable *ShaderProgramObjects;
 #endif
 
 #if FEATURE_EXT_framebuffer_object
index d0c8235..e9c35fc 100644 (file)
@@ -178,7 +178,7 @@ _mesa_reference_shader_program(GLcontext *ctx,
       deleteFlag = (old->RefCount == 0);
 
       if (deleteFlag) {
-         _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
+         _mesa_HashRemove(ctx->Shared->ShaderProgramObjects, old->Name);
          _mesa_free_shader_program(ctx, old);
       }
 
@@ -204,7 +204,7 @@ _mesa_lookup_shader_program(GLcontext *ctx, GLuint name)
    struct gl_shader_program *shProg;
    if (name) {
       shProg = (struct gl_shader_program *)
-         _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
+         _mesa_HashLookup(ctx->Shared->ShaderProgramObjects, name);
       /* Note that both gl_shader and gl_shader_program objects are kept
        * in the same hash table.  Check the object's type to be sure it's
        * what we're expecting.
@@ -536,10 +536,10 @@ _mesa_create_program(GLcontext *ctx)
    GLuint name;
    struct gl_shader_program *shProg;
 
-   name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
+   name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderProgramObjects, 1);
    shProg = _mesa_new_shader_program(ctx, name);
 
-   _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
+   _mesa_HashInsert(ctx->Shared->ShaderProgramObjects, name, shProg);
 
    assert(shProg->RefCount == 1);