mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-02-01 22:00:26 +01:00
llvmpipe: fail gracefully on oom in scene creation
This commit is contained in:
parent
eb605701aa
commit
ad6730fadb
6 changed files with 92 additions and 42 deletions
|
|
@ -56,7 +56,7 @@
|
|||
#include "draw/draw_vbuf.h"
|
||||
|
||||
|
||||
static void set_scene_state( struct lp_setup_context *, enum setup_state,
|
||||
static boolean set_scene_state( struct lp_setup_context *, enum setup_state,
|
||||
const char *reason);
|
||||
static boolean try_update_scene_state( struct lp_setup_context *setup );
|
||||
|
||||
|
|
@ -167,7 +167,7 @@ lp_setup_rasterize_scene( struct lp_setup_context *setup )
|
|||
|
||||
|
||||
|
||||
static void
|
||||
static boolean
|
||||
begin_binning( struct lp_setup_context *setup )
|
||||
{
|
||||
struct lp_scene *scene = setup->scene;
|
||||
|
|
@ -181,6 +181,8 @@ begin_binning( struct lp_setup_context *setup )
|
|||
/* Always create a fence:
|
||||
*/
|
||||
scene->fence = lp_fence_create(MAX2(1, setup->num_threads));
|
||||
if (!scene->fence)
|
||||
return FALSE;
|
||||
|
||||
/* Initialize the bin flags and x/y coords:
|
||||
*/
|
||||
|
|
@ -192,7 +194,8 @@ begin_binning( struct lp_setup_context *setup )
|
|||
}
|
||||
|
||||
ok = try_update_scene_state(setup);
|
||||
assert(ok);
|
||||
if (!ok)
|
||||
return FALSE;
|
||||
|
||||
if (setup->fb.zsbuf &&
|
||||
((setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) &&
|
||||
|
|
@ -208,7 +211,8 @@ begin_binning( struct lp_setup_context *setup )
|
|||
ok = lp_scene_bin_everywhere( scene,
|
||||
LP_RAST_OP_CLEAR_COLOR,
|
||||
setup->clear.color );
|
||||
assert(ok);
|
||||
if (!ok)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -216,12 +220,14 @@ begin_binning( struct lp_setup_context *setup )
|
|||
if (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) {
|
||||
if (!need_zsload)
|
||||
scene->has_depthstencil_clear = TRUE;
|
||||
|
||||
ok = lp_scene_bin_everywhere( scene,
|
||||
LP_RAST_OP_CLEAR_ZSTENCIL,
|
||||
lp_rast_arg_clearzs(
|
||||
setup->clear.zsvalue,
|
||||
setup->clear.zsmask));
|
||||
assert(ok);
|
||||
if (!ok)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -229,15 +235,16 @@ begin_binning( struct lp_setup_context *setup )
|
|||
ok = lp_scene_bin_everywhere( scene,
|
||||
LP_RAST_OP_BEGIN_QUERY,
|
||||
lp_rast_arg_query(setup->active_query) );
|
||||
assert(ok);
|
||||
if (!ok)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
setup->clear.flags = 0;
|
||||
setup->clear.zsmask = 0;
|
||||
setup->clear.zsvalue = 0;
|
||||
|
||||
LP_DBG(DEBUG_SETUP, "%s done\n", __FUNCTION__);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -246,12 +253,12 @@ begin_binning( struct lp_setup_context *setup )
|
|||
*
|
||||
* TODO: fast path for fullscreen clears and no triangles.
|
||||
*/
|
||||
static void
|
||||
static boolean
|
||||
execute_clears( struct lp_setup_context *setup )
|
||||
{
|
||||
LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
|
||||
|
||||
begin_binning( setup );
|
||||
return begin_binning( setup );
|
||||
}
|
||||
|
||||
const char *states[] = {
|
||||
|
|
@ -262,7 +269,7 @@ const char *states[] = {
|
|||
};
|
||||
|
||||
|
||||
static void
|
||||
static boolean
|
||||
set_scene_state( struct lp_setup_context *setup,
|
||||
enum setup_state new_state,
|
||||
const char *reason)
|
||||
|
|
@ -270,7 +277,7 @@ set_scene_state( struct lp_setup_context *setup,
|
|||
unsigned old_state = setup->state;
|
||||
|
||||
if (old_state == new_state)
|
||||
return;
|
||||
return TRUE;
|
||||
|
||||
if (LP_DEBUG & DEBUG_SCENE) {
|
||||
debug_printf("%s old %s new %s%s%s\n",
|
||||
|
|
@ -294,12 +301,14 @@ set_scene_state( struct lp_setup_context *setup,
|
|||
break;
|
||||
|
||||
case SETUP_ACTIVE:
|
||||
begin_binning( setup );
|
||||
if (!begin_binning( setup ))
|
||||
goto fail;
|
||||
break;
|
||||
|
||||
case SETUP_FLUSHED:
|
||||
if (old_state == SETUP_CLEARED)
|
||||
execute_clears( setup );
|
||||
if (!execute_clears( setup ))
|
||||
goto fail;
|
||||
|
||||
lp_setup_rasterize_scene( setup );
|
||||
assert(setup->scene == NULL);
|
||||
|
|
@ -307,9 +316,21 @@ set_scene_state( struct lp_setup_context *setup,
|
|||
|
||||
default:
|
||||
assert(0 && "invalid setup state mode");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
setup->state = new_state;
|
||||
return TRUE;
|
||||
|
||||
fail:
|
||||
if (setup->scene) {
|
||||
lp_scene_end_rasterization(setup->scene);
|
||||
setup->scene = NULL;
|
||||
}
|
||||
|
||||
setup->state = SETUP_FLUSHED;
|
||||
lp_setup_reset( setup );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -878,7 +899,7 @@ try_update_scene_state( struct lp_setup_context *setup )
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
boolean
|
||||
lp_setup_update_state( struct lp_setup_context *setup,
|
||||
boolean update_scene )
|
||||
{
|
||||
|
|
@ -902,20 +923,38 @@ lp_setup_update_state( struct lp_setup_context *setup,
|
|||
assert(lp->dirty == 0);
|
||||
}
|
||||
|
||||
if (update_scene)
|
||||
set_scene_state( setup, SETUP_ACTIVE, __FUNCTION__ );
|
||||
if (update_scene) {
|
||||
if (!set_scene_state( setup, SETUP_ACTIVE, __FUNCTION__ ))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Only call into update_scene_state() if we already have a
|
||||
* scene:
|
||||
*/
|
||||
if (update_scene && setup->scene) {
|
||||
assert(setup->state == SETUP_ACTIVE);
|
||||
if (!try_update_scene_state(setup)) {
|
||||
lp_setup_flush_and_restart(setup);
|
||||
if (!try_update_scene_state(setup))
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (try_update_scene_state(setup))
|
||||
return TRUE;
|
||||
|
||||
/* Update failed, try to restart the scene.
|
||||
*
|
||||
* Cannot call lp_setup_flush_and_restart() directly here
|
||||
* because of potential recursion.
|
||||
*/
|
||||
if (!set_scene_state(setup, SETUP_FLUSHED, __FUNCTION__))
|
||||
return FALSE;
|
||||
|
||||
if (!set_scene_state(setup, SETUP_ACTIVE, __FUNCTION__))
|
||||
return FALSE;
|
||||
|
||||
if (!setup->scene)
|
||||
return FALSE;
|
||||
|
||||
return try_update_scene_state(setup);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1019,12 +1058,12 @@ lp_setup_begin_query(struct lp_setup_context *setup,
|
|||
LP_RAST_OP_BEGIN_QUERY,
|
||||
lp_rast_arg_query(pq))) {
|
||||
|
||||
lp_setup_flush_and_restart(setup);
|
||||
if (!lp_setup_flush_and_restart(setup))
|
||||
return;
|
||||
|
||||
if (!lp_scene_bin_everywhere(setup->scene,
|
||||
LP_RAST_OP_BEGIN_QUERY,
|
||||
lp_rast_arg_query(pq))) {
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -1068,14 +1107,20 @@ lp_setup_end_query(struct lp_setup_context *setup, struct llvmpipe_query *pq)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
boolean
|
||||
lp_setup_flush_and_restart(struct lp_setup_context *setup)
|
||||
{
|
||||
if (0) debug_printf("%s\n", __FUNCTION__);
|
||||
|
||||
assert(setup->state == SETUP_ACTIVE);
|
||||
set_scene_state(setup, SETUP_FLUSHED, __FUNCTION__);
|
||||
lp_setup_update_state(setup, TRUE);
|
||||
|
||||
if (!set_scene_state(setup, SETUP_FLUSHED, __FUNCTION__))
|
||||
return FALSE;
|
||||
|
||||
if (!lp_setup_update_state(setup, TRUE))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -160,12 +160,12 @@ void lp_setup_choose_point( struct lp_setup_context *setup );
|
|||
|
||||
void lp_setup_init_vbuf(struct lp_setup_context *setup);
|
||||
|
||||
void lp_setup_update_state( struct lp_setup_context *setup,
|
||||
boolean lp_setup_update_state( struct lp_setup_context *setup,
|
||||
boolean update_scene);
|
||||
|
||||
void lp_setup_destroy( struct lp_setup_context *setup );
|
||||
|
||||
void lp_setup_flush_and_restart(struct lp_setup_context *setup);
|
||||
boolean lp_setup_flush_and_restart(struct lp_setup_context *setup);
|
||||
|
||||
void
|
||||
lp_setup_print_triangle(struct lp_setup_context *setup,
|
||||
|
|
@ -191,6 +191,4 @@ lp_setup_bin_triangle( struct lp_setup_context *setup,
|
|||
const struct u_rect *bbox,
|
||||
int nr_planes );
|
||||
|
||||
void lp_setup_flush_and_restart(struct lp_setup_context *setup);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -712,10 +712,11 @@ static void lp_setup_line( struct lp_setup_context *setup,
|
|||
{
|
||||
if (!try_setup_line( setup, v0, v1 ))
|
||||
{
|
||||
lp_setup_flush_and_restart(setup);
|
||||
if (!lp_setup_flush_and_restart(setup))
|
||||
return;
|
||||
|
||||
if (!try_setup_line( setup, v0, v1 ))
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -414,10 +414,11 @@ lp_setup_point(struct lp_setup_context *setup,
|
|||
{
|
||||
if (!try_setup_point( setup, v0 ))
|
||||
{
|
||||
lp_setup_flush_and_restart(setup);
|
||||
if (!lp_setup_flush_and_restart(setup))
|
||||
return;
|
||||
|
||||
if (!try_setup_point( setup, v0 ))
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -644,27 +644,30 @@ static void triangle_cw( struct lp_setup_context *setup,
|
|||
{
|
||||
if (!do_triangle_ccw( setup, v1, v0, v2, !setup->ccw_is_frontface ))
|
||||
{
|
||||
lp_setup_flush_and_restart(setup);
|
||||
if (!lp_setup_flush_and_restart(setup))
|
||||
return;
|
||||
|
||||
if (!do_triangle_ccw( setup, v1, v0, v2, !setup->ccw_is_frontface ))
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draw triangle if it's CCW, cull otherwise.
|
||||
* Draw triangle if it's CW, cull otherwise.
|
||||
*/
|
||||
static void triangle_ccw( struct lp_setup_context *setup,
|
||||
static void triangle_cw( struct lp_setup_context *setup,
|
||||
const float (*v0)[4],
|
||||
const float (*v1)[4],
|
||||
const float (*v2)[4] )
|
||||
{
|
||||
if (!do_triangle_ccw( setup, v0, v1, v2, setup->ccw_is_frontface ))
|
||||
{
|
||||
lp_setup_flush_and_restart(setup);
|
||||
if (!lp_setup_flush_and_restart(setup))
|
||||
return;
|
||||
|
||||
if (!do_triangle_ccw( setup, v0, v1, v2, setup->ccw_is_frontface ))
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -141,7 +141,8 @@ lp_setup_draw_elements(struct vbuf_render *vbr, const ushort *indices, uint nr)
|
|||
const boolean flatshade_first = setup->flatshade_first;
|
||||
unsigned i;
|
||||
|
||||
lp_setup_update_state(setup, TRUE);
|
||||
if (!lp_setup_update_state(setup, TRUE))
|
||||
return;
|
||||
|
||||
switch (setup->prim) {
|
||||
case PIPE_PRIM_POINTS:
|
||||
|
|
@ -338,7 +339,8 @@ lp_setup_draw_arrays(struct vbuf_render *vbr, uint start, uint nr)
|
|||
const boolean flatshade_first = setup->flatshade_first;
|
||||
unsigned i;
|
||||
|
||||
lp_setup_update_state(setup, TRUE);
|
||||
if (!lp_setup_update_state(setup, TRUE))
|
||||
return;
|
||||
|
||||
switch (setup->prim) {
|
||||
case PIPE_PRIM_POINTS:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue