Fix a program refcounting error, don't share program parameter lists.
authorBrian Paul <brian.paul@tungstengraphics.com>
Fri, 16 May 2008 15:56:59 +0000 (09:56 -0600)
committerBrian Paul <brian.paul@tungstengraphics.com>
Fri, 16 May 2008 21:16:06 +0000 (15:16 -0600)
The refcounting bug was causing a memleak (unfreed programs).
The old parameter list sharing is not needed since the change in how
uniforms are handled.

src/mesa/shader/shader_api.c
src/mesa/shader/slang/slang_link.c

index 11450db..08fa9a7 100644 (file)
@@ -75,21 +75,8 @@ void
 _mesa_clear_shader_program_data(GLcontext *ctx,
                                 struct gl_shader_program *shProg)
 {
-   if (shProg->VertexProgram) {
-      /* Set ptr to NULL since the param list is shared with the
-       * original/unlinked program.
-       */
-      shProg->VertexProgram->Base.Parameters = NULL;
-      _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
-   }
-
-   if (shProg->FragmentProgram) {
-      /* Set ptr to NULL since the param list is shared with the
-       * original/unlinked program.
-       */
-      shProg->FragmentProgram->Base.Parameters = NULL;
-      _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
-   }
+   _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
+   _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
 
    if (shProg->Uniforms) {
       _mesa_free_uniform_list(shProg->Uniforms);
@@ -176,8 +163,10 @@ _mesa_reference_shader_program(GLcontext *ctx,
 
       ASSERT(old->RefCount > 0);
       old->RefCount--;
-      /*printf("SHPROG DECR %p (%d) to %d\n",
-        (void*) old, old->Name, old->RefCount);*/
+#if 0
+      printf("ShaderProgram %p ID=%u  RefCount-- to %d\n",
+             (void *) old, old->Name, old->RefCount);
+#endif
       deleteFlag = (old->RefCount == 0);
 
       if (deleteFlag) {
@@ -191,8 +180,10 @@ _mesa_reference_shader_program(GLcontext *ctx,
 
    if (shProg) {
       shProg->RefCount++;
-      /*printf("SHPROG INCR %p (%d) to %d\n",
-        (void*) shProg, shProg->Name, shProg->RefCount);*/
+#if 0
+      printf("ShaderProgram %p ID=%u  RefCount++ to %d\n",
+             (void *) shProg, shProg->Name, shProg->RefCount);
+#endif
       *ptr = shProg;
    }
 }
index 8213b77..80cd4b6 100644 (file)
@@ -406,20 +406,20 @@ _slang_link(GLcontext *ctx,
     * Make copies of the vertex/fragment programs now since we'll be
     * changing src/dst registers after merging the uniforms and varying vars.
     */
+   _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
    if (vertProg) {
-      _mesa_reference_vertprog(ctx, &shProg->VertexProgram,
-                               vertex_program(_mesa_clone_program(ctx, &vertProg->Base)));
-   }
-   else {
-      _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
+      struct gl_vertex_program *linked_vprog =
+         vertex_program(_mesa_clone_program(ctx, &vertProg->Base));
+      shProg->VertexProgram = linked_vprog; /* refcount OK */
+      ASSERT(shProg->VertexProgram->Base.RefCount == 1);
    }
 
+   _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
    if (fragProg) {
-      _mesa_reference_fragprog(ctx, &shProg->FragmentProgram,
-                               fragment_program(_mesa_clone_program(ctx, &fragProg->Base)));
-   }
-   else {
-      _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
+      struct gl_fragment_program *linked_fprog = 
+         fragment_program(_mesa_clone_program(ctx, &fragProg->Base));
+      shProg->FragmentProgram = linked_fprog; /* refcount OK */
+      ASSERT(shProg->FragmentProgram->Base.RefCount == 1);
    }
 
    /* link varying vars */
@@ -437,18 +437,6 @@ _slang_link(GLcontext *ctx,
    /*_mesa_print_uniforms(shProg->Uniforms);*/
 
    if (shProg->VertexProgram) {
-      /* Rather than cloning the parameter list here, just share it.
-       * We need to be careful _mesa_clear_shader_program_data() in
-       * to avoid double-freeing.
-       */
-      shProg->VertexProgram->Base.Parameters = vertProg->Base.Parameters;
-   }
-   if (shProg->FragmentProgram) {
-      /* see comment just above */
-      shProg->FragmentProgram->Base.Parameters = fragProg->Base.Parameters;
-   }
-
-   if (shProg->VertexProgram) {
       if (!_slang_resolve_attributes(shProg, &shProg->VertexProgram->Base)) {
          /*goto cleanup;*/
          _mesa_problem(ctx, "_slang_resolve_attributes() failed");