r300g: Fix leaks in failed context creation

This changes r300_destroy_context() so it can be called
on a partially-initialized context, and uses it when
r300_create_context() hits a fatal error.

This makes sure r300_create_context() doesn't leak memory
or neglect to call r300_update_num_contexts() when it fails.

Signed-off-by: Marek Olšák <maraeo@gmail.com>
This commit is contained in:
nobled 2010-08-15 03:59:15 +00:00 committed by Marek Olšák
parent b0e1565b5f
commit 1e2cd02eae

View file

@ -99,8 +99,10 @@ static void r300_destroy_context(struct pipe_context* context)
struct r300_context* r300 = r300_context(context);
struct r300_atom *atom;
util_blitter_destroy(r300->blitter);
draw_destroy(r300->draw);
if (r300->blitter)
util_blitter_destroy(r300->blitter);
if (r300->draw)
draw_destroy(r300->draw);
/* Print stats, if enabled. */
if (SCREEN_DBG_ON(r300->screen, DBG_STATS)) {
@ -112,40 +114,48 @@ static void r300_destroy_context(struct pipe_context* context)
}
}
u_upload_destroy(r300->upload_vb);
u_upload_destroy(r300->upload_ib);
if (r300->upload_vb)
u_upload_destroy(r300->upload_vb);
if (r300->upload_ib)
u_upload_destroy(r300->upload_ib);
/* setup hyper-z mm */
if (r300->rws->get_value(r300->rws, R300_CAN_HYPERZ))
if (r300->zmask_mm)
r300_hyperz_destroy_mm(r300);
translate_cache_destroy(r300->tran.translate_cache);
if (r300->tran.translate_cache)
translate_cache_destroy(r300->tran.translate_cache);
/* XXX: This function assumes r300->query_list was initialized */
r300_release_referenced_objects(r300);
r300->rws->cs_destroy(r300->cs);
if (r300->cs)
r300->rws->cs_destroy(r300->cs);
/* XXX: No way to tell if this was initialized or not? */
util_mempool_destroy(&r300->pool_transfers);
r300_update_num_contexts(r300->screen, -1);
FREE(r300->aa_state.state);
FREE(r300->blend_color_state.state);
FREE(r300->clip_state.state);
FREE(r300->fb_state.state);
FREE(r300->gpu_flush.state);
FREE(r300->hyperz_state.state);
FREE(r300->invariant_state.state);
FREE(r300->rs_block_state.state);
FREE(r300->scissor_state.state);
FREE(r300->textures_state.state);
FREE(r300->vap_invariant_state.state);
FREE(r300->viewport_state.state);
FREE(r300->ztop_state.state);
FREE(r300->fs_constants.state);
FREE(r300->vs_constants.state);
if (!r300->screen->caps.has_tcl) {
FREE(r300->vertex_stream_state.state);
/* Free the structs allocated in r300_setup_atoms() */
if (r300->aa_state.state) {
FREE(r300->aa_state.state);
FREE(r300->blend_color_state.state);
FREE(r300->clip_state.state);
FREE(r300->fb_state.state);
FREE(r300->gpu_flush.state);
FREE(r300->hyperz_state.state);
FREE(r300->invariant_state.state);
FREE(r300->rs_block_state.state);
FREE(r300->scissor_state.state);
FREE(r300->textures_state.state);
FREE(r300->vap_invariant_state.state);
FREE(r300->viewport_state.state);
FREE(r300->ztop_state.state);
FREE(r300->fs_constants.state);
FREE(r300->vs_constants.state);
if (r300->vertex_stream_state.state) {
FREE(r300->vertex_stream_state.state);
}
}
FREE(r300);
}
@ -406,12 +416,16 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
r300->context.destroy = r300_destroy_context;
r300->cs = rws->cs_create(rws);
make_empty_list(&r300->query_list);
util_mempool_create(&r300->pool_transfers,
sizeof(struct pipe_transfer), 64,
UTIL_MEMPOOL_SINGLETHREADED);
r300->cs = rws->cs_create(rws);
if (r300->cs == NULL)
goto fail;
if (!r300screen->caps.has_tcl) {
/* Create a Draw. This is used for SW TCL. */
r300->draw = draw_create(&r300->context);
@ -426,8 +440,6 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
r300_setup_atoms(r300);
make_empty_list(&r300->query_list);
r300_init_blit_functions(r300);
r300_init_flush_functions(r300);
r300_init_query_functions(r300);
@ -435,6 +447,8 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
r300_init_resource_functions(r300);
r300->blitter = util_blitter_create(&r300->context);
if (r300->blitter == NULL)
goto fail;
/* Render functions must be initialized after blitter. */
r300_init_render_functions(r300);
@ -450,15 +464,17 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
PIPE_BIND_INDEX_BUFFER);
if (r300->upload_ib == NULL)
goto no_upload_ib;
goto fail;
r300->upload_vb = u_upload_create(&r300->context,
128 * 1024, 16,
PIPE_BIND_VERTEX_BUFFER);
if (r300->upload_vb == NULL)
goto no_upload_vb;
goto fail;
r300->tran.translate_cache = translate_cache_create();
if (r300->tran.translate_cache == NULL)
goto fail;
r300_init_states(&r300->context);
@ -488,10 +504,8 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
return &r300->context;
no_upload_ib:
u_upload_destroy(r300->upload_ib);
no_upload_vb:
FREE(r300);
fail:
r300_destroy_context(&r300->context);
return NULL;
}