llvmpipe: fix texture reference counting bug
authorBrian Paul <brianp@vmware.com>
Wed, 24 Mar 2010 22:27:31 +0000 (16:27 -0600)
committerBrian Paul <brianp@vmware.com>
Wed, 24 Mar 2010 22:29:17 +0000 (16:29 -0600)
We weren't saving the per-scene texture references at the right point.

Fixes piglit cubemap segfault.  The segfault resulted from referencing
texture memory which was prematurely freed because of a missed reference
count.

Fixes fd.o bug 27276.

src/gallium/drivers/llvmpipe/lp_setup.c
src/gallium/drivers/llvmpipe/lp_setup_context.h

index fbb0d6f8a602de37ae6bcd03c3a0e1ac98a3ba90..76a8b87a3095168e6d8ada7274e8408bd14b09b3 100644 (file)
@@ -489,6 +489,12 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup,
          jit_tex->height = tex->height0;
          jit_tex->depth = tex->depth0;
          jit_tex->last_level = tex->last_level;
+
+         /* We're referencing the texture's internal data, so save a
+          * reference to it.
+          */
+         pipe_texture_reference(&setup->fs.current_tex[i], tex);
+
          if (!lp_tex->dt) {
             /* regular texture - setup array of mipmap level pointers */
             int j;
@@ -511,12 +517,6 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup,
             jit_tex->row_stride[0] = lp_tex->stride[0];
             assert(jit_tex->data[0]);
          }
-
-         /* the scene references this texture */
-         {
-            struct lp_scene *scene = lp_setup_get_current_scene(setup);
-            lp_scene_texture_reference(scene, tex);
-         }
       }
    }
 
@@ -651,6 +651,7 @@ lp_setup_update_state( struct lp_setup_context *setup )
           * the new, current state.  So allocate a new lp_rast_state object
           * and append it to the bin's setup data buffer.
           */
+         uint i;
          struct lp_rast_state *stored =
             (struct lp_rast_state *) lp_scene_alloc(scene, sizeof *stored);
          if(stored) {
@@ -664,6 +665,14 @@ lp_setup_update_state( struct lp_setup_context *setup )
                                        lp_rast_set_state, 
                                        lp_rast_arg_state(setup->fs.stored) );
          }
+
+         /* The scene now references the textures in the rasterization
+          * state record.  Note that now.
+          */
+         for (i = 0; i < Elements(setup->fs.current_tex); i++) {
+            if (setup->fs.current_tex[i])
+               lp_scene_texture_reference(scene, setup->fs.current_tex[i]);
+         }
       }
    }
 
@@ -679,8 +688,14 @@ lp_setup_update_state( struct lp_setup_context *setup )
 void 
 lp_setup_destroy( struct lp_setup_context *setup )
 {
+   uint i;
+
    reset_context( setup );
 
+   for (i = 0; i < Elements(setup->fs.current_tex); i++) {
+      pipe_texture_reference(&setup->fs.current_tex[i], NULL);
+   }
+
    pipe_buffer_reference(&setup->constants.current, NULL);
 
    /* free the scenes in the 'empty' queue */
index 464fb369840260bd92205ec132dd45187dee1bd1..ca0dafab62782c323e046448a77158e7dd938716 100644 (file)
@@ -111,6 +111,7 @@ struct lp_setup_context
 
       const struct lp_rast_state *stored; /**< what's in the scene */
       struct lp_rast_state current;  /**< currently set state */
+      struct pipe_texture *current_tex[PIPE_MAX_SAMPLERS];
    } fs;
 
    /** fragment shader constants */