Except for the first patch, this is mostly adding a bunch of different null checks:
1. r300g: Fix macro This fixes a potential bug if (has_hyperz) is false (it would act as if has_hyperz is true). 2. r300g: Fix leaks in failed context creation This patch is the biggest one: It refactors the create/destroy context functions; before, if r300_create_context failed to allocate something essential it was either ignored or it only partly cleaned up after itself (ex: leaking all the allocations in r300_init_atoms(), forgetting to decrement the number of existing contexts, leaking the mutexes initialized by r300_hyperz_init_mm, etc), and there's a *lot* to stuff to clean up, so this just re-uses the logic in r300_destroy_context to avoid code duplication. 3. r300g: Let hyperz init fail Adds a boolean return value to check if the calls to u_mmInit failed (they can potentially return null) 4. gallium: Check if draw_create returns null This changes all the drivers that depend on the draw module to abort if draw_create returned null (which it might if using LLVM and on a CPU without SSE2, or if it just couldn't allocate memory) 5. draw: Check if llvm returns null Always check for null and don't rely on assert(), since that won't help on non-debug builds. Might also help with http://bugs.freedesktop.org/29578 .
From 7ff36acc6da61bf1a7efe12bc84479b75adf893d Mon Sep 17 00:00:00 2001 From: nobled <nob...@dreamwidth.org> Date: Sun, 15 Aug 2010 02:50:04 +0000 Subject: [PATCH] r300g: Fix macro This fixes a potential bug if (has_hyperz) is false (it would still init the atom as if has_hyperz were true). --- src/gallium/drivers/r300/r300_context.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index e8b6c4f..23b654e 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -158,12 +158,14 @@ void r300_flush_cb(void *data) } #define R300_INIT_ATOM(atomname, atomsize) \ + do { \ r300->atomname.name = #atomname; \ r300->atomname.state = NULL; \ r300->atomname.size = atomsize; \ r300->atomname.emit = r300_emit_##atomname; \ r300->atomname.dirty = FALSE; \ - insert_at_tail(&r300->atom_list, &r300->atomname); + insert_at_tail(&r300->atom_list, &r300->atomname); \ + } while (0) static void r300_setup_atoms(struct r300_context* r300) { -- 1.5.4.3
From 3576a26e9bd284ed94e366063b197a1f2e93fb49 Mon Sep 17 00:00:00 2001 From: nobled <nob...@dreamwidth.org> Date: Sun, 15 Aug 2010 03:59:15 +0000 Subject: [PATCH] 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. --- src/gallium/drivers/r300/r300_context.c | 82 ++++++++++++++++++------------- 1 files changed, 48 insertions(+), 34 deletions(-) diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index 23b654e..25b39c5 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -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; } -- 1.5.4.3
From 7a7bbef1034cb50863139385aec71ab9067e1ec4 Mon Sep 17 00:00:00 2001 From: nobled <nob...@dreamwidth.org> Date: Sun, 15 Aug 2010 03:53:18 +0000 Subject: [PATCH] r300g: Let hyperz init fail --- src/gallium/drivers/r300/r300_context.c | 3 ++- src/gallium/drivers/r300/r300_hyperz.c | 21 +++++++++++++++++---- src/gallium/drivers/r300/r300_hyperz.h | 2 +- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index 25b39c5..d783f21 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -457,7 +457,8 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, /* setup hyper-z mm */ if (r300->rws->get_value(r300->rws, R300_CAN_HYPERZ)) - r300_hyperz_init_mm(r300); + if (!r300_hyperz_init_mm(r300)) + goto fail; r300->upload_ib = u_upload_create(&r300->context, 32 * 1024, 16, diff --git a/src/gallium/drivers/r300/r300_hyperz.c b/src/gallium/drivers/r300/r300_hyperz.c index 811b564..a471b73 100644 --- a/src/gallium/drivers/r300/r300_hyperz.c +++ b/src/gallium/drivers/r300/r300_hyperz.c @@ -373,23 +373,36 @@ void r300_zmask_alloc_block(struct r300_context *r300, struct r300_surface *surf return; } -void r300_hyperz_init_mm(struct r300_context *r300) +boolean r300_hyperz_init_mm(struct r300_context *r300) { struct r300_screen* r300screen = r300->screen; int frag_pipes = r300screen->caps.num_frag_pipes; - if (r300screen->caps.hiz_ram) + r300->zmask_mm = u_mmInit(0, r300screen->caps.zmask_ram * frag_pipes); + if (!r300->zmask_mm) + return FALSE; + + if (r300screen->caps.hiz_ram) { r300->hiz_mm = u_mmInit(0, r300screen->caps.hiz_ram * frag_pipes); + if (!r300->hiz_mm) { + u_mmDestroy(r300->zmask_mm); + r300->zmask_mm = NULL; + return FALSE; + } + } - r300->zmask_mm = u_mmInit(0, r300screen->caps.zmask_ram * frag_pipes); + return TRUE; } void r300_hyperz_destroy_mm(struct r300_context *r300) { struct r300_screen* r300screen = r300->screen; - if (r300screen->caps.hiz_ram) + if (r300screen->caps.hiz_ram) { u_mmDestroy(r300->hiz_mm); + r300->hiz_mm = NULL; + } u_mmDestroy(r300->zmask_mm); + r300->zmask_mm = NULL; } diff --git a/src/gallium/drivers/r300/r300_hyperz.h b/src/gallium/drivers/r300/r300_hyperz.h index 09e1ff6..30a23ec 100644 --- a/src/gallium/drivers/r300/r300_hyperz.h +++ b/src/gallium/drivers/r300/r300_hyperz.h @@ -30,6 +30,6 @@ void r300_update_hyperz_state(struct r300_context* r300); void r300_hiz_alloc_block(struct r300_context *r300, struct r300_surface *surf); void r300_zmask_alloc_block(struct r300_context *r300, struct r300_surface *surf, int compress); -void r300_hyperz_init_mm(struct r300_context *r300); +boolean r300_hyperz_init_mm(struct r300_context *r300); void r300_hyperz_destroy_mm(struct r300_context *r300); #endif -- 1.5.4.3
From 3aff8298420e87923098b16201db08c208205202 Mon Sep 17 00:00:00 2001 From: nobled <nob...@dreamwidth.org> Date: Sun, 15 Aug 2010 04:03:19 +0000 Subject: [PATCH] gallium: Check if draw_create returns null --- src/gallium/drivers/cell/ppu/cell_context.c | 6 ++++++ src/gallium/drivers/i915/i915_context.c | 7 ++++++- src/gallium/drivers/nv50/nv50_context.c | 6 +++++- src/gallium/drivers/nvfx/nvfx_context.c | 5 +++++ src/gallium/drivers/r300/r300_context.c | 2 ++ 5 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/gallium/drivers/cell/ppu/cell_context.c b/src/gallium/drivers/cell/ppu/cell_context.c index 143eca8..a025869 100644 --- a/src/gallium/drivers/cell/ppu/cell_context.c +++ b/src/gallium/drivers/cell/ppu/cell_context.c @@ -75,6 +75,8 @@ cell_draw_create(struct cell_context *cell) { struct draw_context *draw = draw_create(&cell->pipe); + if (!draw) + return NULL; #if 0 /* broken */ if (getenv("GALLIUM_CELL_VS")) { /* plug in SPU-based vertex transformation code */ @@ -150,6 +152,10 @@ cell_create_context(struct pipe_screen *screen, cell_init_texture_transfer_funcs(cell); cell->draw = cell_draw_create(cell); + if (!cell->draw) { + align_free(cell); + return NULL; + } /* Create cache of fragment ops generated code */ cell->fragment_ops_cache = diff --git a/src/gallium/drivers/i915/i915_context.c b/src/gallium/drivers/i915/i915_context.c index 2beb9e3..decc046 100644 --- a/src/gallium/drivers/i915/i915_context.c +++ b/src/gallium/drivers/i915/i915_context.c @@ -150,7 +150,12 @@ i915_create_context(struct pipe_screen *screen, void *priv) * Create drawing context and plug our rendering stage into it. */ i915->draw = draw_create(&i915->base); - assert(i915->draw); + + if (!i915->draw) { + i915_destroy(&i915->base); + return NULL; + } + if (!debug_get_bool_option("I915_NO_VBUF", FALSE)) { draw_set_rasterize_stage(i915->draw, i915_draw_vbuf_stage(i915)); } else { diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c index 0874cb5..ee10a1b 100644 --- a/src/gallium/drivers/nv50/nv50_context.c +++ b/src/gallium/drivers/nv50/nv50_context.c @@ -95,7 +95,11 @@ nv50_create(struct pipe_screen *pscreen, void *priv) nv50_init_resource_functions(&nv50->pipe); nv50->draw = draw_create(&nv50->pipe); - assert(nv50->draw); + if (!nv50->draw) { + nv50_destroy(&nv50->pipe); + return NULL; + } + draw_set_rasterize_stage(nv50->draw, nv50_draw_render_stage(nv50)); return &nv50->pipe; diff --git a/src/gallium/drivers/nvfx/nvfx_context.c b/src/gallium/drivers/nvfx/nvfx_context.c index 7218abf..0ce0513 100644 --- a/src/gallium/drivers/nvfx/nvfx_context.c +++ b/src/gallium/drivers/nvfx/nvfx_context.c @@ -70,6 +70,11 @@ nvfx_create(struct pipe_screen *pscreen, void *priv) /* Create, configure, and install fallback swtnl path */ nvfx->draw = draw_create(&nvfx->pipe); + if (!nvfx->draw) { + nvfx_destroy(&nvfx->pipe); + return NULL; + } + draw_wide_point_threshold(nvfx->draw, 9999999.0); draw_wide_line_threshold(nvfx->draw, 9999999.0); draw_enable_line_stipple(nvfx->draw, FALSE); diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index d783f21..759a7ad 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -429,6 +429,8 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, if (!r300screen->caps.has_tcl) { /* Create a Draw. This is used for SW TCL. */ r300->draw = draw_create(&r300->context); + if (!r300->draw) + goto fail; /* Enable our renderer. */ draw_set_rasterize_stage(r300->draw, r300_draw_stage(r300)); /* Enable Draw's clipping. */ -- 1.5.4.3
From 2b4dbbbba4b834eb0444bce1db873c17fb00101e Mon Sep 17 00:00:00 2001 From: nobled <nob...@dreamwidth.org> Date: Mon, 16 Aug 2010 00:21:47 +0000 Subject: [PATCH] draw: Check if llvm returns null Avoid potential segfault on non-debug builds if llvm doesn't initialize, and just return null. Same if draw_llvm_create() fails (either because of memory allocation or running on a CPU without SSE2). --- src/gallium/auxiliary/draw/draw_context.c | 5 +++++ src/gallium/auxiliary/draw/draw_llvm.c | 3 +++ 2 files changed, 8 insertions(+), 0 deletions(-) diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c index 995b675..c0841d6 100644 --- a/src/gallium/auxiliary/draw/draw_context.c +++ b/src/gallium/auxiliary/draw/draw_context.c @@ -52,8 +52,13 @@ struct draw_context *draw_create( struct pipe_context *pipe ) #if HAVE_LLVM lp_build_init(); assert(lp_build_engine); + if (lp_build_engine == NULL) + goto fail; + draw->engine = lp_build_engine; draw->llvm = draw_llvm_create(draw); + if (draw->llvm == NULL) + goto fail; #endif if (!draw_init(draw)) diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c index 8d53601..1a218ec 100644 --- a/src/gallium/auxiliary/draw/draw_llvm.c +++ b/src/gallium/auxiliary/draw/draw_llvm.c @@ -286,6 +286,9 @@ draw_llvm_create(struct draw_context *draw) void draw_llvm_destroy(struct draw_llvm *llvm) { + if (!llvm) + return; + LLVMDisposePassManager(llvm->pass); FREE(llvm); -- 1.5.4.3
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev