summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2012-02-21 18:30:18 +0100
committerMarek Olšák <[email protected]>2012-02-23 20:29:55 +0100
commit6a94c9dde0d62b5ccfcbe3dbafdadeab37fd48a6 (patch)
tree7de74977c02177f66a39108b3af58f06226f84a4
parent9670e72f6ef85f0e6f6c9afe136dc67c017e3fae (diff)
r600g: fix possible crashes in destroy_context when failing in create_context
Reviewed-by: Jerome Glisse <[email protected]> Reviewed-by: Alex Deucher <[email protected]>
-rw-r--r--src/gallium/drivers/r600/r600_hw_context.c36
-rw-r--r--src/gallium/drivers/r600/r600_pipe.c27
2 files changed, 38 insertions, 25 deletions
diff --git a/src/gallium/drivers/r600/r600_hw_context.c b/src/gallium/drivers/r600/r600_hw_context.c
index 5738b486e22..fb0923d162d 100644
--- a/src/gallium/drivers/r600/r600_hw_context.c
+++ b/src/gallium/drivers/r600/r600_hw_context.c
@@ -625,6 +625,11 @@ static void r600_free_resource_range(struct r600_context *ctx, struct r600_range
{
struct r600_block *block;
int i;
+
+ if (!range->blocks) {
+ return; /* nothing to do */
+ }
+
for (i = 0; i < nblocks; i++) {
block = range->blocks[i];
if (block) {
@@ -634,7 +639,6 @@ static void r600_free_resource_range(struct r600_context *ctx, struct r600_range
}
}
free(range->blocks);
-
}
/* initialize */
@@ -643,23 +647,25 @@ void r600_context_fini(struct r600_context *ctx)
struct r600_block *block;
struct r600_range *range;
- for (int i = 0; i < NUM_RANGES; i++) {
- if (!ctx->range[i].blocks)
- continue;
- for (int j = 0; j < (1 << HASH_SHIFT); j++) {
- block = ctx->range[i].blocks[j];
- if (block) {
- for (int k = 0, offset = block->start_offset; k < block->nreg; k++, offset += 4) {
- range = &ctx->range[CTX_RANGE_ID(offset)];
- range->blocks[CTX_BLOCK_ID(offset)] = NULL;
- }
- for (int k = 1; k <= block->nbo; k++) {
- pipe_resource_reference((struct pipe_resource**)&block->reloc[k].bo, NULL);
+ if (ctx->range) {
+ for (int i = 0; i < NUM_RANGES; i++) {
+ if (!ctx->range[i].blocks)
+ continue;
+ for (int j = 0; j < (1 << HASH_SHIFT); j++) {
+ block = ctx->range[i].blocks[j];
+ if (block) {
+ for (int k = 0, offset = block->start_offset; k < block->nreg; k++, offset += 4) {
+ range = &ctx->range[CTX_RANGE_ID(offset)];
+ range->blocks[CTX_BLOCK_ID(offset)] = NULL;
+ }
+ for (int k = 1; k <= block->nbo; k++) {
+ pipe_resource_reference((struct pipe_resource**)&block->reloc[k].bo, NULL);
+ }
+ free(block);
}
- free(block);
}
+ free(ctx->range[i].blocks);
}
- free(ctx->range[i].blocks);
}
r600_free_resource_range(ctx, &ctx->ps_resources, ctx->num_ps_resources);
r600_free_resource_range(ctx, &ctx->vs_resources, ctx->num_vs_resources);
diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c
index e7ba97110ef..b2b79cd8e6e 100644
--- a/src/gallium/drivers/r600/r600_pipe.c
+++ b/src/gallium/drivers/r600/r600_pipe.c
@@ -191,25 +191,32 @@ static void r600_destroy_context(struct pipe_context *context)
{
struct r600_context *rctx = (struct r600_context *)context;
- rctx->context.delete_depth_stencil_alpha_state(&rctx->context, rctx->custom_dsa_flush);
+ if (rctx->custom_dsa_flush) {
+ rctx->context.delete_depth_stencil_alpha_state(&rctx->context, rctx->custom_dsa_flush);
+ }
util_unreference_framebuffer_state(&rctx->framebuffer);
r600_context_fini(rctx);
- util_blitter_destroy(rctx->blitter);
-
+ if (rctx->blitter) {
+ util_blitter_destroy(rctx->blitter);
+ }
for (int i = 0; i < R600_PIPE_NSTATES; i++) {
free(rctx->states[i]);
}
- u_vbuf_destroy(rctx->vbuf_mgr);
+ if (rctx->vbuf_mgr) {
+ u_vbuf_destroy(rctx->vbuf_mgr);
+ }
util_slab_destroy(&rctx->pool_transfers);
r600_update_num_contexts(rctx->screen, -1);
r600_release_command_buffer(&rctx->atom_start_cs);
- rctx->ws->cs_destroy(rctx->cs);
+ if (rctx->cs) {
+ rctx->ws->cs_destroy(rctx->cs);
+ }
FREE(rctx->range);
FREE(rctx);
@@ -223,6 +230,10 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
if (rctx == NULL)
return NULL;
+ util_slab_create(&rctx->pool_transfers,
+ sizeof(struct pipe_transfer), 64,
+ UTIL_SLAB_SINGLETHREADED);
+
r600_update_num_contexts(rscreen, 1);
rctx->context.screen = screen;
@@ -244,7 +255,7 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
rctx->range = CALLOC(NUM_RANGES, sizeof(struct r600_range));
if (!rctx->range) {
- FREE(rctx);
+ r600_destroy_context(&rctx->context);
return NULL;
}
@@ -290,10 +301,6 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
rctx->ws->cs_set_flush_callback(rctx->cs, r600_flush_from_winsys, rctx);
r600_emit_atom(rctx, &rctx->atom_start_cs.atom);
- util_slab_create(&rctx->pool_transfers,
- sizeof(struct pipe_transfer), 64,
- UTIL_SLAB_SINGLETHREADED);
-
rctx->vbuf_mgr = u_vbuf_create(&rctx->context, 1024 * 1024, 256,
PIPE_BIND_VERTEX_BUFFER |
PIPE_BIND_INDEX_BUFFER |