diff options
author | Marek Olšák <[email protected]> | 2012-02-21 18:30:18 +0100 |
---|---|---|
committer | Marek Olšák <[email protected]> | 2012-02-23 20:29:55 +0100 |
commit | 6a94c9dde0d62b5ccfcbe3dbafdadeab37fd48a6 (patch) | |
tree | 7de74977c02177f66a39108b3af58f06226f84a4 | |
parent | 9670e72f6ef85f0e6f6c9afe136dc67c017e3fae (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.c | 36 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_pipe.c | 27 |
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 | |