aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Paul <[email protected]>2010-03-24 16:27:31 -0600
committerBrian Paul <[email protected]>2010-03-24 16:29:17 -0600
commit2ad8692aad0f4ad49643d5f697a036afccdeb9f0 (patch)
treea3f34c4390cb0022e343128ac199db5dcfc14b10
parentf0e04b094412d358e913d3d1107d7260047f6fb2 (diff)
llvmpipe: fix texture reference counting bug
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.
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup.c27
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_context.h1
2 files changed, 22 insertions, 6 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c
index fbb0d6f8a60..76a8b87a309 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup.c
@@ -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 */
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_context.h b/src/gallium/drivers/llvmpipe/lp_setup_context.h
index 464fb369840..ca0dafab627 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_context.h
+++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h
@@ -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 */