From c88f3e0374620f18cf38d9fc3c45d14bc53f62b2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Wed, 9 Nov 2011 19:29:37 +0000 Subject: [PATCH] llvmpipe: Make more resilient to out-of-memory situations. Most of the code was alright, but we were missing a few paths. Reviewed-by: Brian Paul --- src/gallium/drivers/llvmpipe/lp_rast.c | 13 ++++++- src/gallium/drivers/llvmpipe/lp_screen.c | 3 +- src/gallium/drivers/llvmpipe/lp_setup.c | 29 ++++++++++---- src/gallium/drivers/llvmpipe/lp_state_setup.c | 9 +++-- src/gallium/drivers/llvmpipe/lp_texture.c | 38 +++++++++++++++---- 5 files changed, 68 insertions(+), 24 deletions(-) diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c index c4560bfe6c0..873c2612e89 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.c +++ b/src/gallium/drivers/llvmpipe/lp_rast.c @@ -879,10 +879,14 @@ lp_rast_create( unsigned num_threads ) unsigned i; rast = CALLOC_STRUCT(lp_rasterizer); - if(!rast) - return NULL; + if (!rast) { + goto no_rast; + } rast->full_scenes = lp_scene_queue_create(); + if (!rast->full_scenes) { + goto no_full_scenes; + } for (i = 0; i < Elements(rast->tasks); i++) { struct lp_rasterizer_task *task = &rast->tasks[i]; @@ -902,6 +906,11 @@ lp_rast_create( unsigned num_threads ) memset(lp_dummy_tile, 0, sizeof lp_dummy_tile); return rast; + +no_full_scenes: + FREE(rast); +no_rast: + return NULL; } diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c index 942ec623cb4..fac13e7dda9 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.c +++ b/src/gallium/drivers/llvmpipe/lp_screen.c @@ -399,14 +399,13 @@ llvmpipe_create_screen(struct sw_winsys *winsys) return NULL; #endif - screen = CALLOC_STRUCT(llvmpipe_screen); - #ifdef DEBUG LP_DEBUG = debug_get_flags_option("LP_DEBUG", lp_debug_flags, 0 ); #endif LP_PERF = debug_get_flags_option("LP_PERF", lp_perf_flags, 0 ); + screen = CALLOC_STRUCT(llvmpipe_screen); if (!screen) return NULL; diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index 1479ed44f0f..4f7d116d486 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -39,6 +39,7 @@ #include "util/u_inlines.h" #include "util/u_memory.h" #include "util/u_pack_color.h" +#include "draw/draw_pipe.h" #include "lp_context.h" #include "lp_memory.h" #include "lp_scene.h" @@ -1010,11 +1011,13 @@ lp_setup_create( struct pipe_context *pipe, struct draw_context *draw ) { struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); - struct lp_setup_context *setup = CALLOC_STRUCT(lp_setup_context); + struct lp_setup_context *setup; unsigned i; - if (!setup) - return NULL; + setup = CALLOC_STRUCT(lp_setup_context); + if (!setup) { + goto no_setup; + } lp_setup_init_vbuf(setup); @@ -1025,8 +1028,9 @@ lp_setup_create( struct pipe_context *pipe, setup->num_threads = screen->num_threads; setup->vbuf = draw_vbuf_stage(draw, &setup->base); - if (!setup->vbuf) - goto fail; + if (!setup->vbuf) { + goto no_vbuf; + } draw_set_rasterize_stage(draw, setup->vbuf); draw_set_render(draw, &setup->base); @@ -1034,6 +1038,9 @@ lp_setup_create( struct pipe_context *pipe, /* create some empty scenes */ for (i = 0; i < MAX_SCENES; i++) { setup->scenes[i] = lp_scene_create( pipe ); + if (!setup->scenes[i]) { + goto no_scenes; + } } setup->triangle = first_triangle; @@ -1044,11 +1051,17 @@ lp_setup_create( struct pipe_context *pipe, return setup; -fail: - if (setup->vbuf) - ; +no_scenes: + for (i = 0; i < MAX_SCENES; i++) { + if (setup->scenes[i]) { + lp_scene_destroy(setup->scenes[i]); + } + } + setup->vbuf->destroy(setup->vbuf); +no_vbuf: FREE(setup); +no_setup: return NULL; } diff --git a/src/gallium/drivers/llvmpipe/lp_state_setup.c b/src/gallium/drivers/llvmpipe/lp_state_setup.c index a9d9f4f4665..97c9238f989 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_state_setup.c @@ -874,10 +874,11 @@ llvmpipe_update_setup(struct llvmpipe_context *lp) } variant = generate_setup_variant(lp->gallivm, key, lp); - insert_at_head(&lp->setup_variants_list, &variant->list_item_global); - lp->nr_setup_variants++; - - llvmpipe_variant_count++; + if (variant) { + insert_at_head(&lp->setup_variants_list, &variant->list_item_global); + lp->nr_setup_variants++; + llvmpipe_variant_count++; + } } lp_setup_set_setup_variant(lp->setup, diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c index fa4ce5bf2ac..ca38571b2bc 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.c +++ b/src/gallium/drivers/llvmpipe/lp_texture.c @@ -163,6 +163,9 @@ llvmpipe_texture_layout(struct llvmpipe_screen *screen, lpr->num_slices_faces[level] = num_slices; lpr->layout[level] = alloc_layout_array(num_slices, width, height); + if (!lpr->layout[level]) { + goto fail; + } } /* Compute size of next mipmap level */ @@ -172,6 +175,15 @@ llvmpipe_texture_layout(struct llvmpipe_screen *screen, } return TRUE; + +fail: + for (level = 0; level <= pt->last_level; level++) { + if (lpr->layout[level]) { + FREE(lpr->layout[level]); + } + } + + return FALSE; } @@ -196,7 +208,9 @@ llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen, lpr->img_stride[0] = 0; lpr->layout[0] = alloc_layout_array(1, width, height); - //lpr->layout[0][0] = LP_TEX_LAYOUT_LINEAR; + if (!lpr->layout[0]) { + return FALSE; + } lpr->dt = winsys->displaytarget_create(winsys, lpr->base.bind, @@ -437,13 +451,15 @@ llvmpipe_resource_from_handle(struct pipe_screen *screen, struct winsys_handle *whandle) { struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys; - struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource); + struct llvmpipe_resource *lpr; unsigned width, height, width_t, height_t; /* XXX Seems like from_handled depth textures doesn't work that well */ - if (!lpr) - return NULL; + lpr = CALLOC_STRUCT(llvmpipe_resource); + if (!lpr) { + goto no_lpr; + } lpr->base = *template; pipe_reference_init(&lpr->base.reference, 1); @@ -472,12 +488,15 @@ llvmpipe_resource_from_handle(struct pipe_screen *screen, template, whandle, &lpr->row_stride[0]); - if (!lpr->dt) - goto fail; + if (!lpr->dt) { + goto no_dt; + } lpr->layout[0] = alloc_layout_array(1, lpr->base.width0, lpr->base.height0); + if (!lpr->layout[0]) { + goto no_layout_0; + } - assert(lpr->layout[0]); assert(lpr->layout[0][0] == LP_TEX_LAYOUT_NONE); lpr->id = id_counter++; @@ -488,8 +507,11 @@ llvmpipe_resource_from_handle(struct pipe_screen *screen, return &lpr->base; - fail: +no_layout_0: + winsys->displaytarget_destroy(winsys, lpr->dt); +no_dt: FREE(lpr); +no_lpr: return NULL; } -- 2.30.2