From: Keith Whitwell Date: Thu, 5 Nov 2009 13:57:05 +0000 (+0000) Subject: i965g: add lots of error checks and early returns X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c796aed5ddad011d66e631c4cafdbf779e73f213;p=mesa.git i965g: add lots of error checks and early returns Any allocation that may fail should be checked, and propogate the error upwards. At the highest level we will flush batch and retry. This is an alternate strategy to what the original DRI driver did of attempting to flush batch from the lowest levels (eg inside BEGIN_BATCH). The trouble with that strategy was that flushes could occur at unexpected times, and additionally there was a need for a wierd notification mechanism to propogate the 'lost context' state back up to higher levels. Propogating the errors directly gives us a lot of flexibility how to deal with these states, at the expense of a lot more checking in the code. Will add some sanity checks later to make sure that out-of-memory conditions are properly escalated and not lost halfway up the stack. --- diff --git a/src/gallium/drivers/i965/brw_batchbuffer.c b/src/gallium/drivers/i965/brw_batchbuffer.c index ca612e5ed0b..e5f73bd6a31 100644 --- a/src/gallium/drivers/i965/brw_batchbuffer.c +++ b/src/gallium/drivers/i965/brw_batchbuffer.c @@ -38,17 +38,17 @@ #define USE_MALLOC_BUFFER 1 #define ALWAYS_EMIT_MI_FLUSH 1 -void +enum pipe_error brw_batchbuffer_reset(struct brw_batchbuffer *batch) { - if (batch->buf) { - batch->sws->bo_unreference(batch->buf); - batch->buf = NULL; - } + enum pipe_error ret; - batch->buf = batch->sws->bo_alloc(batch->sws, - BRW_BUFFER_TYPE_BATCH, - BRW_BATCH_SIZE, 4096); + ret = batch->sws->bo_alloc( batch->sws, + BRW_BUFFER_TYPE_BATCH, + BRW_BATCH_SIZE, 4096, + &batch->buf ); + if (ret) + return ret; if (batch->malloc_buffer) batch->map = batch->malloc_buffer; @@ -59,6 +59,7 @@ brw_batchbuffer_reset(struct brw_batchbuffer *batch) batch->size = BRW_BATCH_SIZE; batch->ptr = batch->map; + return PIPE_OK; } struct brw_batchbuffer * @@ -91,7 +92,7 @@ brw_batchbuffer_free(struct brw_batchbuffer *batch) batch->map = NULL; } - batch->sws->bo_unreference(batch->buf); + bo_reference(&batch->buf, NULL); FREE(batch); } diff --git a/src/gallium/drivers/i965/brw_batchbuffer.h b/src/gallium/drivers/i965/brw_batchbuffer.h index 1f04826aea6..288a9d27555 100644 --- a/src/gallium/drivers/i965/brw_batchbuffer.h +++ b/src/gallium/drivers/i965/brw_batchbuffer.h @@ -65,7 +65,8 @@ void _brw_batchbuffer_flush(struct brw_batchbuffer *batch, const char *file, int line); -void brw_batchbuffer_reset(struct brw_batchbuffer *batch); +enum pipe_error +brw_batchbuffer_reset(struct brw_batchbuffer *batch); /* Unlike bmBufferData, this currently requires the buffer be mapped. diff --git a/src/gallium/drivers/i965/brw_cc.c b/src/gallium/drivers/i965/brw_cc.c index 20967f01911..8e25fe85854 100644 --- a/src/gallium/drivers/i965/brw_cc.c +++ b/src/gallium/drivers/i965/brw_cc.c @@ -57,10 +57,11 @@ static void calc_sane_viewport( const struct pipe_viewport_state *vp, svp->far = 1; } -static int prepare_cc_vp( struct brw_context *brw ) +static enum pipe_error prepare_cc_vp( struct brw_context *brw ) { struct brw_cc_viewport ccv; struct sane_viewport svp; + enum pipe_error ret; memset(&ccv, 0, sizeof(ccv)); @@ -70,10 +71,12 @@ static int prepare_cc_vp( struct brw_context *brw ) ccv.min_depth = svp.near; ccv.max_depth = svp.far; - brw->sws->bo_unreference(brw->cc.vp_bo); - brw->cc.vp_bo = brw_cache_data( &brw->cache, BRW_CC_VP, &ccv, NULL, 0 ); - - return 0; + ret = brw_cache_data( &brw->cache, BRW_CC_VP, &ccv, NULL, 0, + &brw->cc.vp_bo ); + if (ret) + return ret; + + return PIPE_OK; } const struct brw_tracked_state brw_cc_vp = { @@ -123,11 +126,13 @@ cc_unit_populate_key(const struct brw_context *brw, /** * Creates the state cache entry for the given CC unit key. */ -static struct brw_winsys_buffer * -cc_unit_create_from_key(struct brw_context *brw, struct brw_cc_unit_key *key) +static enum pipe_error +cc_unit_create_from_key(struct brw_context *brw, + struct brw_cc_unit_key *key, + struct brw_winsys_buffer **bo_out) { struct brw_cc_unit_state cc; - struct brw_winsys_buffer *bo; + enum pipe_error ret; memset(&cc, 0, sizeof(cc)); @@ -143,38 +148,48 @@ cc_unit_create_from_key(struct brw_context *brw, struct brw_cc_unit_key *key) cc.cc6 = key->cc6; cc.cc7 = key->cc7; - bo = brw_upload_cache(&brw->cache, BRW_CC_UNIT, - key, sizeof(*key), - &brw->cc.vp_bo, 1, - &cc, sizeof(cc), - NULL, NULL); + ret = brw_upload_cache(&brw->cache, BRW_CC_UNIT, + key, sizeof(*key), + &brw->cc.vp_bo, 1, + &cc, sizeof(cc), + NULL, NULL, + bo_out); + if (ret) + return ret; - /* Emit CC viewport relocation */ - brw->sws->bo_emit_reloc(bo, - BRW_USAGE_STATE, - 0, - offsetof(struct brw_cc_unit_state, cc4), - brw->cc.vp_bo); - return bo; + /* Emit CC viewport relocation */ + ret = brw->sws->bo_emit_reloc(*bo_out, + BRW_USAGE_STATE, + 0, + offsetof(struct brw_cc_unit_state, cc4), + brw->cc.vp_bo); + if (ret) + return ret; + + return PIPE_OK; } static int prepare_cc_unit( struct brw_context *brw ) { struct brw_cc_unit_key key; + enum pipe_error ret; cc_unit_populate_key(brw, &key); - brw->sws->bo_unreference(brw->cc.state_bo); - brw->cc.state_bo = brw_search_cache(&brw->cache, BRW_CC_UNIT, - &key, sizeof(key), - &brw->cc.vp_bo, 1, - NULL); - - if (brw->cc.state_bo == NULL) - brw->cc.state_bo = cc_unit_create_from_key(brw, &key); + if (brw_search_cache(&brw->cache, BRW_CC_UNIT, + &key, sizeof(key), + &brw->cc.vp_bo, 1, + NULL, + &brw->cc.state_bo)) + return PIPE_OK; + + ret = cc_unit_create_from_key(brw, &key, + &brw->cc.state_bo); + if (ret) + return ret; - return 0; + return PIPE_OK; } const struct brw_tracked_state brw_cc_unit = { diff --git a/src/gallium/drivers/i965/brw_clip.c b/src/gallium/drivers/i965/brw_clip.c index 1a52fa771bf..35e1d2fdbd0 100644 --- a/src/gallium/drivers/i965/brw_clip.c +++ b/src/gallium/drivers/i965/brw_clip.c @@ -48,9 +48,12 @@ #define BACK_UNFILLED_BIT 0x2 -static void compile_clip_prog( struct brw_context *brw, - struct brw_clip_prog_key *key ) +static enum pipe_error +compile_clip_prog( struct brw_context *brw, + struct brw_clip_prog_key *key, + struct brw_winsys_buffer **bo_out ) { + enum pipe_error ret; struct brw_clip_compile c; const GLuint *program; GLuint program_size; @@ -123,31 +126,39 @@ static void compile_clip_prog( struct brw_context *brw, break; default: assert(0); - return; + return PIPE_ERROR_BAD_INPUT; } /* get the program */ - program = brw_get_program(&c.func, &program_size); + ret = brw_get_program(&c.func, &program, &program_size); + if (ret) + return ret; /* Upload */ - brw->sws->bo_unreference(brw->clip.prog_bo); - brw->clip.prog_bo = brw_upload_cache( &brw->cache, - BRW_CLIP_PROG, - &c.key, sizeof(c.key), - NULL, 0, - program, program_size, - &c.prog_data, - &brw->clip.prog_data ); + ret = brw_upload_cache( &brw->cache, + BRW_CLIP_PROG, + &c.key, sizeof(c.key), + NULL, 0, + program, program_size, + &c.prog_data, + &brw->clip.prog_data, + bo_out ); + if (ret) + return ret; + + return PIPE_OK; } /* Calculate interpolants for triangle and line rasterization. */ -static int upload_clip_prog(struct brw_context *brw) +static enum pipe_error +upload_clip_prog(struct brw_context *brw) { + enum pipe_error ret; struct brw_clip_prog_key key; /* Populate the key, starting from the almost-complete version from @@ -166,15 +177,22 @@ static int upload_clip_prog(struct brw_context *brw) /* PIPE_NEW_CLIP */ key.nr_userclip = brw->curr.ucp.nr; - brw->sws->bo_unreference(brw->clip.prog_bo); - brw->clip.prog_bo = brw_search_cache(&brw->cache, BRW_CLIP_PROG, - &key, sizeof(key), - NULL, 0, - &brw->clip.prog_data); - if (brw->clip.prog_bo == NULL) - compile_clip_prog( brw, &key ); + /* Already cached? + */ + if (brw_search_cache(&brw->cache, BRW_CLIP_PROG, + &key, sizeof(key), + NULL, 0, + &brw->clip.prog_data, + &brw->clip.prog_bo)) + return PIPE_OK; + + /* Compile new program: + */ + ret = compile_clip_prog( brw, &key, &brw->clip.prog_bo ); + if (ret) + return ret; - return 0; + return PIPE_OK; } diff --git a/src/gallium/drivers/i965/brw_clip_state.c b/src/gallium/drivers/i965/brw_clip_state.c index 6f8309fea92..d4e3c43c61a 100644 --- a/src/gallium/drivers/i965/brw_clip_state.c +++ b/src/gallium/drivers/i965/brw_clip_state.c @@ -72,12 +72,13 @@ clip_unit_populate_key(struct brw_context *brw, struct brw_clip_unit_key *key) key->depth_clamp = 0; // XXX: add this to gallium: ctx->Transform.DepthClamp; } -static struct brw_winsys_buffer * +static enum pipe_error clip_unit_create_from_key(struct brw_context *brw, - struct brw_clip_unit_key *key) + struct brw_clip_unit_key *key, + struct brw_winsys_buffer **bo_out) { struct brw_clip_unit_state clip; - struct brw_winsys_buffer *bo; + enum pipe_error ret; memset(&clip, 0, sizeof(clip)); @@ -141,39 +142,50 @@ clip_unit_create_from_key(struct brw_context *brw, clip.viewport_ymin = -1; clip.viewport_ymax = 1; - bo = brw_upload_cache(&brw->cache, BRW_CLIP_UNIT, - key, sizeof(*key), - &brw->clip.prog_bo, 1, - &clip, sizeof(clip), - NULL, NULL); + ret = brw_upload_cache(&brw->cache, BRW_CLIP_UNIT, + key, sizeof(*key), + &brw->clip.prog_bo, 1, + &clip, sizeof(clip), + NULL, NULL, + bo_out); + if (ret) + return ret; /* Emit clip program relocation */ assert(brw->clip.prog_bo); - brw->sws->bo_emit_reloc(bo, - BRW_USAGE_STATE, - clip.thread0.grf_reg_count << 1, - offsetof(struct brw_clip_unit_state, thread0), - brw->clip.prog_bo); - - return bo; + ret = brw->sws->bo_emit_reloc(*bo_out, + BRW_USAGE_STATE, + clip.thread0.grf_reg_count << 1, + offsetof(struct brw_clip_unit_state, thread0), + brw->clip.prog_bo); + if (ret) + return ret; + + return PIPE_OK; } static int upload_clip_unit( struct brw_context *brw ) { struct brw_clip_unit_key key; + enum pipe_error ret; clip_unit_populate_key(brw, &key); - brw->sws->bo_unreference(brw->clip.state_bo); - brw->clip.state_bo = brw_search_cache(&brw->cache, BRW_CLIP_UNIT, - &key, sizeof(key), - &brw->clip.prog_bo, 1, - NULL); - if (brw->clip.state_bo == NULL) { - brw->clip.state_bo = clip_unit_create_from_key(brw, &key); - } + if (brw_search_cache(&brw->cache, BRW_CLIP_UNIT, + &key, sizeof(key), + &brw->clip.prog_bo, 1, + NULL, + &brw->clip.state_bo)) + return PIPE_OK; + + /* Create new: + */ + ret = clip_unit_create_from_key(brw, &key, + &brw->clip.state_bo); + if (ret) + return ret; - return 0; + return PIPE_OK; } const struct brw_tracked_state brw_clip_unit = { diff --git a/src/gallium/drivers/i965/brw_context.c b/src/gallium/drivers/i965/brw_context.c index aaf7d1834ea..2cee7a7a3cf 100644 --- a/src/gallium/drivers/i965/brw_context.c +++ b/src/gallium/drivers/i965/brw_context.c @@ -72,29 +72,33 @@ static void brw_destroy_context( struct pipe_context *pipe ) brw->curr.fb.nr_cbufs = 0; pipe_surface_reference(&brw->curr.fb.zsbuf, NULL); - brw->sws->bo_unreference(brw->curbe.curbe_bo); - brw->sws->bo_unreference(brw->vs.prog_bo); - brw->sws->bo_unreference(brw->vs.state_bo); - brw->sws->bo_unreference(brw->vs.bind_bo); - brw->sws->bo_unreference(brw->gs.prog_bo); - brw->sws->bo_unreference(brw->gs.state_bo); - brw->sws->bo_unreference(brw->clip.prog_bo); - brw->sws->bo_unreference(brw->clip.state_bo); - brw->sws->bo_unreference(brw->clip.vp_bo); - brw->sws->bo_unreference(brw->sf.prog_bo); - brw->sws->bo_unreference(brw->sf.state_bo); - brw->sws->bo_unreference(brw->sf.vp_bo); + bo_reference(&brw->curbe.curbe_bo, NULL); + bo_reference(&brw->vs.prog_bo, NULL); + bo_reference(&brw->vs.state_bo, NULL); + bo_reference(&brw->vs.bind_bo, NULL); + bo_reference(&brw->gs.prog_bo, NULL); + bo_reference(&brw->gs.state_bo, NULL); + bo_reference(&brw->clip.prog_bo, NULL); + bo_reference(&brw->clip.state_bo, NULL); + bo_reference(&brw->clip.vp_bo, NULL); + bo_reference(&brw->sf.prog_bo, NULL); + bo_reference(&brw->sf.state_bo, NULL); + bo_reference(&brw->sf.vp_bo, NULL); + for (i = 0; i < BRW_MAX_TEX_UNIT; i++) - brw->sws->bo_unreference(brw->wm.sdc_bo[i]); - brw->sws->bo_unreference(brw->wm.bind_bo); + bo_reference(&brw->wm.sdc_bo[i], NULL); + + bo_reference(&brw->wm.bind_bo, NULL); + for (i = 0; i < BRW_WM_MAX_SURF; i++) - brw->sws->bo_unreference(brw->wm.surf_bo[i]); - brw->sws->bo_unreference(brw->wm.sampler_bo); - brw->sws->bo_unreference(brw->wm.prog_bo); - brw->sws->bo_unreference(brw->wm.state_bo); - brw->sws->bo_unreference(brw->cc.prog_bo); - brw->sws->bo_unreference(brw->cc.state_bo); - brw->sws->bo_unreference(brw->cc.vp_bo); + bo_reference(&brw->wm.surf_bo[i], NULL); + + bo_reference(&brw->wm.sampler_bo, NULL); + bo_reference(&brw->wm.prog_bo, NULL); + bo_reference(&brw->wm.state_bo, NULL); + bo_reference(&brw->cc.prog_bo, NULL); + bo_reference(&brw->cc.state_bo, NULL); + bo_reference(&brw->cc.vp_bo, NULL); } diff --git a/src/gallium/drivers/i965/brw_context.h b/src/gallium/drivers/i965/brw_context.h index 09d34615c74..580251d2f12 100644 --- a/src/gallium/drivers/i965/brw_context.h +++ b/src/gallium/drivers/i965/brw_context.h @@ -744,7 +744,7 @@ struct brw_context * brw_queryobj.c */ void brw_init_query(struct brw_context *brw); -void brw_prepare_query_begin(struct brw_context *brw); +enum pipe_error brw_prepare_query_begin(struct brw_context *brw); void brw_emit_query_begin(struct brw_context *brw); void brw_emit_query_end(struct brw_context *brw); diff --git a/src/gallium/drivers/i965/brw_curbe.c b/src/gallium/drivers/i965/brw_curbe.c index 1e2e232204e..ca7774a7cc2 100644 --- a/src/gallium/drivers/i965/brw_curbe.c +++ b/src/gallium/drivers/i965/brw_curbe.c @@ -160,10 +160,11 @@ static GLfloat fixed_plane[6][4] = { * cache mechanism, but maybe would benefit from a comparison against * the current uploaded set of constants. */ -static int prepare_curbe_buffer(struct brw_context *brw) +static enum pipe_error prepare_curbe_buffer(struct brw_context *brw) { const GLuint sz = brw->curbe.total_size; const GLuint bufsz = sz * 16 * sizeof(GLfloat); + enum pipe_error ret; GLfloat *buf; GLuint i; @@ -267,17 +268,20 @@ static int prepare_curbe_buffer(struct brw_context *brw) (brw->curbe.need_new_bo || brw->curbe.curbe_next_offset + bufsz > brw->curbe.curbe_bo->size)) { - brw->sws->bo_unreference(brw->curbe.curbe_bo); - brw->curbe.curbe_bo = NULL; + bo_reference(&brw->curbe.curbe_bo, NULL); } if (brw->curbe.curbe_bo == NULL) { /* Allocate a single page for CURBE entries for this batchbuffer. * They're generally around 64b. */ - brw->curbe.curbe_bo = brw->sws->bo_alloc(brw->sws, - BRW_BUFFER_TYPE_CURBE, - 4096, 1 << 6); + ret = brw->sws->bo_alloc(brw->sws, + BRW_BUFFER_TYPE_CURBE, + 4096, 1 << 6, + &brw->curbe.curbe_bo); + if (ret) + return ret; + brw->curbe.curbe_next_offset = 0; } @@ -313,7 +317,7 @@ static int prepare_curbe_buffer(struct brw_context *brw) return 0; } -static int emit_curbe_buffer(struct brw_context *brw) +static enum pipe_error emit_curbe_buffer(struct brw_context *brw) { GLuint sz = brw->curbe.total_size; diff --git a/src/gallium/drivers/i965/brw_draw.c b/src/gallium/drivers/i965/brw_draw.c index 6d6b1c7c5c3..88cb31ad546 100644 --- a/src/gallium/drivers/i965/brw_draw.c +++ b/src/gallium/drivers/i965/brw_draw.c @@ -280,6 +280,5 @@ void brw_draw_cleanup( struct brw_context *brw ) u_upload_destroy( brw->vb.upload_vertex ); u_upload_destroy( brw->vb.upload_index ); - brw->sws->bo_unreference(brw->ib.bo); - brw->ib.bo = NULL; + bo_reference(&brw->ib.bo, NULL); } diff --git a/src/gallium/drivers/i965/brw_draw_upload.c b/src/gallium/drivers/i965/brw_draw_upload.c index 4fa7d549ebd..188605a0c12 100644 --- a/src/gallium/drivers/i965/brw_draw_upload.c +++ b/src/gallium/drivers/i965/brw_draw_upload.c @@ -251,9 +251,8 @@ static int brw_prepare_vertices(struct brw_context *brw) brw->vb.vb[i].vertex_count = (vb->stride == 0 ? 1 : (bo->size - offset) / vb->stride); - brw->sws->bo_unreference(brw->vb.vb[i].bo); - brw->vb.vb[i].bo = bo; - brw->sws->bo_reference(brw->vb.vb[i].bo); + + bo_reference( &brw->vb.vb[i].bo, bo ); /* Don't need to retain this reference. We have a reference on * the underlying winsys buffer: @@ -417,6 +416,7 @@ const struct brw_tracked_state brw_vertices = { static int brw_prepare_indices(struct brw_context *brw) { struct pipe_buffer *index_buffer = brw->curr.index_buffer; + struct pipe_buffer *upload_buf = NULL; struct brw_winsys_buffer *bo = NULL; GLuint offset; GLuint index_size; @@ -438,7 +438,6 @@ static int brw_prepare_indices(struct brw_context *brw) /* Turn userbuffer into a proper hardware buffer? */ if (brw_buffer_is_user_buffer(index_buffer)) { - struct pipe_buffer *upload_buf; ret = u_upload_buffer( brw->vb.upload_index, 0, @@ -450,8 +449,6 @@ static int brw_prepare_indices(struct brw_context *brw) return ret; bo = brw_buffer(upload_buf)->bo; - brw->sws->bo_reference(bo); - pipe_buffer_reference( &upload_buf, NULL ); /* XXX: annotate the userbuffer with the upload information so * that successive calls don't get re-uploaded. @@ -459,8 +456,6 @@ static int brw_prepare_indices(struct brw_context *brw) } else { bo = brw_buffer(index_buffer)->bo; - brw->sws->bo_reference(bo); - ib_size = bo->size; offset = 0; } @@ -486,15 +481,12 @@ static int brw_prepare_indices(struct brw_context *brw) if (brw->ib.bo != bo || brw->ib.size != ib_size) { - brw->sws->bo_unreference(brw->ib.bo); - brw->ib.bo = bo; + bo_reference(&brw->ib.bo, bo); brw->ib.size = ib_size; brw->state.dirty.brw |= BRW_NEW_INDEX_BUFFER; } - else { - brw->sws->bo_unreference(bo); - } + pipe_buffer_reference( &upload_buf, NULL ); brw_add_validated_bo(brw, brw->ib.bo); return 0; } diff --git a/src/gallium/drivers/i965/brw_eu.c b/src/gallium/drivers/i965/brw_eu.c index de43b14512d..a8fcb5f97eb 100644 --- a/src/gallium/drivers/i965/brw_eu.c +++ b/src/gallium/drivers/i965/brw_eu.c @@ -118,16 +118,23 @@ void brw_init_compile( struct brw_context *brw, struct brw_compile *p ) } -const GLuint *brw_get_program( struct brw_compile *p, - GLuint *sz ) +enum pipe_error brw_get_program( struct brw_compile *p, + const GLuint **data, + GLuint *sz ) { GLuint i; for (i = 0; i < 8; i++) brw_NOP(p); + /* Is the generated program malformed for some reason? + */ + if (p->error) + return PIPE_ERROR_BAD_INPUT; + *sz = p->nr_insn * sizeof(struct brw_instruction); - return (const GLuint *)p->store; + *data = (const GLuint *)p->store; + return PIPE_OK; } diff --git a/src/gallium/drivers/i965/brw_eu.h b/src/gallium/drivers/i965/brw_eu.h index 7bddc3859ca..565f4ef1c59 100644 --- a/src/gallium/drivers/i965/brw_eu.h +++ b/src/gallium/drivers/i965/brw_eu.h @@ -34,6 +34,7 @@ #define BRW_EU_H #include "util/u_debug.h" +#include "pipe/p_error.h" #include "brw_structs.h" #include "brw_defines.h" @@ -132,6 +133,8 @@ struct brw_compile { struct brw_eu_label *first_label; /**< linked list of labels */ struct brw_eu_call *first_call; /**< linked list of CALs */ + + boolean error; }; @@ -772,7 +775,10 @@ void brw_set_predicate_control( struct brw_compile *p, GLuint pc ); void brw_set_conditionalmod( struct brw_compile *p, GLuint conditional ); void brw_init_compile( struct brw_context *, struct brw_compile *p ); -const GLuint *brw_get_program( struct brw_compile *p, GLuint *sz ); + +enum pipe_error brw_get_program( struct brw_compile *p, + const GLuint **program, + GLuint *sz ); /* Helpers for regular instructions: diff --git a/src/gallium/drivers/i965/brw_gs.c b/src/gallium/drivers/i965/brw_gs.c index 693d8bfdf8d..ce77be24f60 100644 --- a/src/gallium/drivers/i965/brw_gs.c +++ b/src/gallium/drivers/i965/brw_gs.c @@ -40,10 +40,12 @@ -static void compile_gs_prog( struct brw_context *brw, - struct brw_gs_prog_key *key ) +static enum pipe_error compile_gs_prog( struct brw_context *brw, + struct brw_gs_prog_key *key, + struct brw_winsys_buffer **bo_out ) { struct brw_gs_compile c; + enum pipe_error ret; const GLuint *program; GLuint program_size; @@ -57,9 +59,9 @@ static void compile_gs_prog( struct brw_context *brw, c.nr_attrs = c.key.nr_attrs; if (BRW_IS_IGDNG(brw)) - c.nr_regs = (c.nr_attrs + 1) / 2 + 3; /* are vertices packed, or reg-aligned? */ + c.nr_regs = (c.nr_attrs + 1) / 2 + 3; /* are vertices packed, or reg-aligned? */ else - c.nr_regs = (c.nr_attrs + 1) / 2 + 1; /* are vertices packed, or reg-aligned? */ + c.nr_regs = (c.nr_attrs + 1) / 2 + 1; /* are vertices packed, or reg-aligned? */ c.nr_bytes = c.nr_regs * REG_SIZE; @@ -93,40 +95,47 @@ static void compile_gs_prog( struct brw_context *brw, if (key->hint_gs_always) brw_gs_lines( &c ); else { - return; + return PIPE_OK; } break; case PIPE_PRIM_TRIANGLES: if (key->hint_gs_always) brw_gs_tris( &c ); else { - return; + return PIPE_OK; } break; case PIPE_PRIM_POINTS: if (key->hint_gs_always) brw_gs_points( &c ); else { - return; + return PIPE_OK; } - break; + break; default: - return; + assert(0); + return PIPE_ERROR_BAD_INPUT; } /* get the program */ - program = brw_get_program(&c.func, &program_size); + ret = brw_get_program(&c.func, &program, &program_size); + if (ret) + return ret; /* Upload */ - brw->sws->bo_unreference(brw->gs.prog_bo); - brw->gs.prog_bo = brw_upload_cache( &brw->cache, BRW_GS_PROG, - &c.key, sizeof(c.key), - NULL, 0, - program, program_size, - &c.prog_data, - &brw->gs.prog_data ); + ret = brw_upload_cache( &brw->cache, BRW_GS_PROG, + &c.key, sizeof(c.key), + NULL, 0, + program, program_size, + &c.prog_data, + &brw->gs.prog_data, + bo_out ); + if (ret) + return ret; + + return PIPE_OK; } static const unsigned gs_prim[PIPE_PRIM_MAX] = { @@ -166,6 +175,8 @@ static void populate_key( struct brw_context *brw, static int prepare_gs_prog(struct brw_context *brw) { struct brw_gs_prog_key key; + enum pipe_error ret; + /* Populate the key: */ populate_key(brw, &key); @@ -175,17 +186,21 @@ static int prepare_gs_prog(struct brw_context *brw) brw->gs.prog_active = key.need_gs_prog; } - if (brw->gs.prog_active) { - brw->sws->bo_unreference(brw->gs.prog_bo); - brw->gs.prog_bo = brw_search_cache(&brw->cache, BRW_GS_PROG, - &key, sizeof(key), - NULL, 0, - &brw->gs.prog_data); - if (brw->gs.prog_bo == NULL) - compile_gs_prog( brw, &key ); - } + if (!brw->gs.prog_active) + return PIPE_OK; + + if (brw_search_cache(&brw->cache, BRW_GS_PROG, + &key, sizeof(key), + NULL, 0, + &brw->gs.prog_data, + &brw->gs.prog_bo)) + return PIPE_OK; + + ret = compile_gs_prog( brw, &key, &brw->gs.prog_bo ); + if (ret) + return ret; - return 0; + return PIPE_OK; } diff --git a/src/gallium/drivers/i965/brw_gs_state.c b/src/gallium/drivers/i965/brw_gs_state.c index f27f886a651..18a66da538e 100644 --- a/src/gallium/drivers/i965/brw_gs_state.c +++ b/src/gallium/drivers/i965/brw_gs_state.c @@ -69,11 +69,13 @@ gs_unit_populate_key(struct brw_context *brw, struct brw_gs_unit_key *key) key->urb_size = brw->urb.vsize; } -static struct brw_winsys_buffer * -gs_unit_create_from_key(struct brw_context *brw, struct brw_gs_unit_key *key) +static enum pipe_error +gs_unit_create_from_key(struct brw_context *brw, + struct brw_gs_unit_key *key, + struct brw_winsys_buffer **bo_out) { struct brw_gs_unit_state gs; - struct brw_winsys_buffer *bo; + enum pipe_error ret; memset(&gs, 0, sizeof(gs)); @@ -104,40 +106,46 @@ gs_unit_create_from_key(struct brw_context *brw, struct brw_gs_unit_key *key) if (BRW_DEBUG & DEBUG_STATS) gs.thread4.stats_enable = 1; - bo = brw_upload_cache(&brw->cache, BRW_GS_UNIT, - key, sizeof(*key), - &brw->gs.prog_bo, 1, - &gs, sizeof(gs), - NULL, NULL); + ret = brw_upload_cache(&brw->cache, BRW_GS_UNIT, + key, sizeof(*key), + &brw->gs.prog_bo, 1, + &gs, sizeof(gs), + NULL, NULL, + bo_out); + if (ret) + return ret; if (key->prog_active) { /* Emit GS program relocation */ - brw->sws->bo_emit_reloc(bo, + brw->sws->bo_emit_reloc(*bo_out, BRW_USAGE_STATE, gs.thread0.grf_reg_count << 1, offsetof(struct brw_gs_unit_state, thread0), brw->gs.prog_bo); } - return bo; + return PIPE_OK; } -static int prepare_gs_unit(struct brw_context *brw) +static enum pipe_error prepare_gs_unit(struct brw_context *brw) { struct brw_gs_unit_key key; + enum pipe_error ret; gs_unit_populate_key(brw, &key); - brw->sws->bo_unreference(brw->gs.state_bo); - brw->gs.state_bo = brw_search_cache(&brw->cache, BRW_GS_UNIT, - &key, sizeof(key), - &brw->gs.prog_bo, 1, - NULL); - if (brw->gs.state_bo == NULL) { - brw->gs.state_bo = gs_unit_create_from_key(brw, &key); - } + if (brw_search_cache(&brw->cache, BRW_GS_UNIT, + &key, sizeof(key), + &brw->gs.prog_bo, 1, + NULL, + &brw->gs.state_bo)) + return PIPE_OK; + + ret = gs_unit_create_from_key(brw, &key, &brw->gs.state_bo); + if (ret) + return ret; - return 0; + return PIPE_OK; } const struct brw_tracked_state brw_gs_unit = { diff --git a/src/gallium/drivers/i965/brw_pipe_query.c b/src/gallium/drivers/i965/brw_pipe_query.c index 3370ebd2626..6a011737879 100644 --- a/src/gallium/drivers/i965/brw_pipe_query.c +++ b/src/gallium/drivers/i965/brw_pipe_query.c @@ -72,8 +72,7 @@ brw_query_get_result(struct pipe_context *pipe, } brw->sws->bo_unmap(query->bo); - brw->sws->bo_unreference(query->bo); - query->bo = NULL; + bo_reference(&query->bo, NULL); } *result = query->result; @@ -100,10 +99,9 @@ brw_query_create(struct pipe_context *pipe, unsigned type ) static void brw_query_destroy(struct pipe_context *pipe, struct pipe_query *q) { - struct brw_context *brw = brw_context(pipe); struct brw_query_object *query = (struct brw_query_object *)q; - brw->sws->bo_unreference(query->bo); + bo_reference(&query->bo, NULL); FREE(query); } @@ -114,9 +112,8 @@ brw_query_begin(struct pipe_context *pipe, struct pipe_query *q) struct brw_query_object *query = (struct brw_query_object *)q; /* Reset our driver's tracking of query state. */ - brw->sws->bo_unreference(query->bo); + bo_reference(&query->bo, NULL); query->result = 0; - query->bo = NULL; query->first_index = -1; query->last_index = -1; @@ -139,8 +136,7 @@ brw_query_end(struct pipe_context *pipe, struct pipe_query *q) brw_emit_query_end(brw); brw_context_flush( brw ); - brw->sws->bo_unreference(brw->query.bo); - brw->query.bo = NULL; + bo_reference(&brw->query.bo, NULL); } remove_from_list(query); @@ -153,24 +149,30 @@ brw_query_end(struct pipe_context *pipe, struct pipe_query *q) */ /** Called to set up the query BO and account for its aperture space */ -void +enum pipe_error brw_prepare_query_begin(struct brw_context *brw) { + enum pipe_error ret; + /* Skip if we're not doing any queries. */ if (is_empty_list(&brw->query.active_head)) - return; + return PIPE_OK; /* Get a new query BO if we're going to need it. */ if (brw->query.bo == NULL || brw->query.index * 2 + 1 >= 4096 / sizeof(uint64_t)) { - brw->sws->bo_unreference(brw->query.bo); - brw->query.bo = NULL; - brw->query.bo = brw->sws->bo_alloc(brw->sws, BRW_BUFFER_TYPE_QUERY, 4096, 1); + ret = brw->sws->bo_alloc(brw->sws, BRW_BUFFER_TYPE_QUERY, 4096, 1, + &brw->query.bo); + if (ret) + return ret; + brw->query.index = 0; } brw_add_validated_bo(brw, brw->query.bo); + + return PIPE_OK; } /** Called just before primitive drawing to get a beginning PS_DEPTH_COUNT. */ @@ -213,8 +215,7 @@ brw_emit_query_begin(struct brw_context *brw) FALSE, &tmp ); - brw->sws->bo_reference(brw->query.bo); - query->bo = brw->query.bo; + bo_reference( &query->bo, brw->query.bo ); query->first_index = brw->query.index; } query->last_index = brw->query.index; diff --git a/src/gallium/drivers/i965/brw_pipe_shader.c b/src/gallium/drivers/i965/brw_pipe_shader.c index 2833f2bce02..662c43c3e5f 100644 --- a/src/gallium/drivers/i965/brw_pipe_shader.c +++ b/src/gallium/drivers/i965/brw_pipe_shader.c @@ -146,10 +146,9 @@ fail: static void brw_delete_fs_state( struct pipe_context *pipe, void *prog ) { - struct brw_context *brw = brw_context(pipe); struct brw_fragment_shader *fs = (struct brw_fragment_shader *)prog; - brw->sws->bo_unreference(fs->const_buffer); + bo_reference(&fs->const_buffer, NULL); FREE( (void *)fs->tokens ); FREE( fs ); } diff --git a/src/gallium/drivers/i965/brw_pipe_vertex.c b/src/gallium/drivers/i965/brw_pipe_vertex.c index 97e9a236883..73bba5b0881 100644 --- a/src/gallium/drivers/i965/brw_pipe_vertex.c +++ b/src/gallium/drivers/i965/brw_pipe_vertex.c @@ -56,7 +56,7 @@ brw_pipe_vertex_cleanup( struct brw_context *brw ) */ #if 0 for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { - brw->sws->bo_unreference(brw->vb.inputs[i].bo); + bo_reference(&brw->vb.inputs[i].bo, NULL); brw->vb.inputs[i].bo = NULL; } #endif diff --git a/src/gallium/drivers/i965/brw_screen_buffers.c b/src/gallium/drivers/i965/brw_screen_buffers.c index ba54740225c..7ae386ffb34 100644 --- a/src/gallium/drivers/i965/brw_screen_buffers.c +++ b/src/gallium/drivers/i965/brw_screen_buffers.c @@ -43,15 +43,11 @@ brw_buffer_unmap( struct pipe_screen *screen, static void brw_buffer_destroy( struct pipe_buffer *buffer ) { - struct brw_screen *bscreen = brw_screen( buffer->screen ); - struct brw_winsys_screen *sws = bscreen->sws; struct brw_buffer *buf = brw_buffer( buffer ); assert(!p_atomic_read(&buffer->reference.count)); - if (buf->bo) - sws->bo_unreference(buf->bo); - + bo_reference(&buf->bo, NULL); FREE(buf); } @@ -66,6 +62,7 @@ brw_buffer_create(struct pipe_screen *screen, struct brw_winsys_screen *sws = bscreen->sws; struct brw_buffer *buf; unsigned buffer_type; + enum pipe_error ret; buf = CALLOC_STRUCT(brw_buffer); if (!buf) @@ -101,10 +98,11 @@ brw_buffer_create(struct pipe_screen *screen, break; } - buf->bo = sws->bo_alloc( sws, - buffer_type, - size, - alignment ); + ret = sws->bo_alloc( sws, buffer_type, + size, alignment, + &buf->bo ); + if (ret != PIPE_OK) + return NULL; return &buf->base; } diff --git a/src/gallium/drivers/i965/brw_screen_surface.c b/src/gallium/drivers/i965/brw_screen_surface.c index 1c408e9f2e5..21a7382873f 100644 --- a/src/gallium/drivers/i965/brw_screen_surface.c +++ b/src/gallium/drivers/i965/brw_screen_surface.c @@ -150,9 +150,7 @@ static struct brw_surface *create_in_place_view( struct brw_screen *brw_screen, surface->pitch = tex->pitch; surface->tiling = tex->tiling; - surface->bo = tex->bo; - brw_screen->sws->bo_reference(surface->bo); - + bo_reference( &surface->bo, tex->bo ); pipe_texture_reference( &surface->base.texture, &tex->base ); surface->ss.ss0.surface_format = tex->ss.ss0.surface_format; @@ -244,11 +242,10 @@ static struct pipe_surface *brw_get_tex_surface(struct pipe_screen *screen, static void brw_tex_surface_destroy( struct pipe_surface *surf ) { struct brw_surface *surface = brw_surface(surf); - struct brw_screen *screen = brw_screen(surf->texture->screen); /* Unreference texture, shared buffer: */ - screen->sws->bo_unreference(surface->bo); + bo_reference(&surface->bo, NULL); pipe_texture_reference( &surface->base.texture, NULL ); diff --git a/src/gallium/drivers/i965/brw_screen_texture.c b/src/gallium/drivers/i965/brw_screen_texture.c index ba6dc7dfdee..355abf0b898 100644 --- a/src/gallium/drivers/i965/brw_screen_texture.c +++ b/src/gallium/drivers/i965/brw_screen_texture.c @@ -187,6 +187,7 @@ static struct pipe_texture *brw_texture_create( struct pipe_screen *screen, struct brw_screen *bscreen = brw_screen(screen); struct brw_texture *tex; enum brw_buffer_type buffer_type; + enum pipe_error ret; tex = CALLOC_STRUCT(brw_texture); if (tex == NULL) @@ -235,10 +236,13 @@ static struct pipe_texture *brw_texture_create( struct pipe_screen *screen, buffer_type = BRW_BUFFER_TYPE_TEXTURE; } - tex->bo = bscreen->sws->bo_alloc( bscreen->sws, - buffer_type, - tex->pitch * tex->total_height * tex->cpp, - 64 ); + ret = bscreen->sws->bo_alloc( bscreen->sws, + buffer_type, + tex->pitch * tex->total_height * tex->cpp, + 64, + &tex->bo ); + if (ret) + goto fail; tex->ss.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW; tex->ss.ss0.surface_type = translate_tex_target(tex->base.target); @@ -289,7 +293,7 @@ static struct pipe_texture *brw_texture_create( struct pipe_screen *screen, return &tex->base; fail: - bscreen->sws->bo_unreference(tex->bo); + bo_reference(&tex->bo, NULL); FREE(tex); return NULL; } @@ -306,7 +310,8 @@ static struct pipe_texture *brw_texture_blanket(struct pipe_screen *screen, static void brw_texture_destroy(struct pipe_texture *pt) { - //bscreen->sws->bo_unreference(tex->bo); + struct brw_texture *tex = brw_texture(pt); + bo_reference(&tex->bo, NULL); FREE(pt); } diff --git a/src/gallium/drivers/i965/brw_sf.c b/src/gallium/drivers/i965/brw_sf.c index 013d839e37d..24d1015bbd5 100644 --- a/src/gallium/drivers/i965/brw_sf.c +++ b/src/gallium/drivers/i965/brw_sf.c @@ -40,9 +40,11 @@ #include "brw_sf.h" #include "brw_state.h" -static void compile_sf_prog( struct brw_context *brw, - struct brw_sf_prog_key *key ) +static enum pipe_error compile_sf_prog( struct brw_context *brw, + struct brw_sf_prog_key *key, + struct brw_winsys_buffer **bo_out ) { + enum pipe_error ret; struct brw_sf_compile c; const GLuint *program; GLuint program_size; @@ -87,28 +89,35 @@ static void compile_sf_prog( struct brw_context *brw, break; default: assert(0); - return; + return PIPE_ERROR_BAD_INPUT; } /* get the program */ - program = brw_get_program(&c.func, &program_size); + ret = brw_get_program(&c.func, &program, &program_size); + if (ret) + return ret; /* Upload */ - brw->sws->bo_unreference(brw->sf.prog_bo); - brw->sf.prog_bo = brw_upload_cache( &brw->cache, BRW_SF_PROG, - &c.key, sizeof(c.key), - NULL, 0, - program, program_size, - &c.prog_data, - &brw->sf.prog_data ); + ret = brw_upload_cache( &brw->cache, BRW_SF_PROG, + &c.key, sizeof(c.key), + NULL, 0, + program, program_size, + &c.prog_data, + &brw->sf.prog_data, + bo_out); + if (ret) + return ret; + + return PIPE_OK; } /* Calculate interpolants for triangle and line rasterization. */ -static int upload_sf_prog(struct brw_context *brw) +static enum pipe_error upload_sf_prog(struct brw_context *brw) { + enum pipe_error ret; struct brw_sf_prog_key key; memset(&key, 0, sizeof(key)); @@ -161,15 +170,18 @@ static int upload_sf_prog(struct brw_context *brw) PIPE_WINDING_CCW); } - brw->sws->bo_unreference(brw->sf.prog_bo); - brw->sf.prog_bo = brw_search_cache(&brw->cache, BRW_SF_PROG, - &key, sizeof(key), - NULL, 0, - &brw->sf.prog_data); - if (brw->sf.prog_bo == NULL) - compile_sf_prog( brw, &key ); + if (brw_search_cache(&brw->cache, BRW_SF_PROG, + &key, sizeof(key), + NULL, 0, + &brw->sf.prog_data, + &brw->sf.prog_bo)) + return PIPE_OK; - return 0; + ret = compile_sf_prog( brw, &key, &brw->sf.prog_bo ); + if (ret) + return ret; + + return PIPE_OK; } diff --git a/src/gallium/drivers/i965/brw_sf_state.c b/src/gallium/drivers/i965/brw_sf_state.c index 31343ff2459..f030f26c19f 100644 --- a/src/gallium/drivers/i965/brw_sf_state.c +++ b/src/gallium/drivers/i965/brw_sf_state.c @@ -39,11 +39,12 @@ #include "brw_debug.h" #include "brw_pipe_rast.h" -static int upload_sf_vp(struct brw_context *brw) +static enum pipe_error upload_sf_vp(struct brw_context *brw) { const struct pipe_viewport_state *vp = &brw->curr.vp; const struct pipe_scissor_state *scissor = &brw->curr.scissor; struct brw_sf_viewport sfv; + enum pipe_error ret; memset(&sfv, 0, sizeof(sfv)); @@ -61,10 +62,12 @@ static int upload_sf_vp(struct brw_context *brw) sfv.scissor.ymin = scissor->miny; sfv.scissor.ymax = scissor->maxy; /* -1 ?? */ - brw->sws->bo_unreference(brw->sf.vp_bo); - brw->sf.vp_bo = brw_cache_data( &brw->cache, BRW_SF_VP, &sfv, NULL, 0 ); + ret = brw_cache_data( &brw->cache, BRW_SF_VP, &sfv, NULL, 0, + &brw->sf.vp_bo ); + if (ret) + return ret; - return 0; + return PIPE_OK; } const struct brw_tracked_state brw_sf_vp = { @@ -128,12 +131,13 @@ sf_unit_populate_key(struct brw_context *brw, struct brw_sf_unit_key *key) rast->point_size_max); } -static struct brw_winsys_buffer * +static enum pipe_error sf_unit_create_from_key(struct brw_context *brw, struct brw_sf_unit_key *key, - struct brw_winsys_buffer **reloc_bufs) + struct brw_winsys_buffer **reloc_bufs, + struct brw_winsys_buffer **bo_out) { struct brw_sf_unit_state sf; - struct brw_winsys_buffer *bo; + enum pipe_error ret; int chipset_max_threads; memset(&sf, 0, sizeof(sf)); @@ -273,51 +277,65 @@ sf_unit_create_from_key(struct brw_context *brw, struct brw_sf_unit_key *key, sf.sf6.dest_org_hbias = 0x0; } - bo = brw_upload_cache(&brw->cache, BRW_SF_UNIT, - key, sizeof(*key), - reloc_bufs, 2, - &sf, sizeof(sf), - NULL, NULL); + ret = brw_upload_cache(&brw->cache, BRW_SF_UNIT, + key, sizeof(*key), + reloc_bufs, 2, + &sf, sizeof(sf), + NULL, NULL, + bo_out); + if (ret) + return ret; /* STATE_PREFETCH command description describes this state as being * something loaded through the GPE (L2 ISC), so it's INSTRUCTION domain. */ /* Emit SF program relocation */ - brw->sws->bo_emit_reloc(bo, - BRW_USAGE_STATE, - sf.thread0.grf_reg_count << 1, - offsetof(struct brw_sf_unit_state, thread0), - brw->sf.prog_bo); + ret = brw->sws->bo_emit_reloc(*bo_out, + BRW_USAGE_STATE, + sf.thread0.grf_reg_count << 1, + offsetof(struct brw_sf_unit_state, thread0), + brw->sf.prog_bo); + if (ret) + return ret; - /* Emit SF viewport relocation */ - brw->sws->bo_emit_reloc(bo, - BRW_USAGE_STATE, - sf.sf5.front_winding | (sf.sf5.viewport_transform << 1), - offsetof(struct brw_sf_unit_state, sf5), - brw->sf.vp_bo); - return bo; + /* Emit SF viewport relocation */ + ret = brw->sws->bo_emit_reloc(*bo_out, + BRW_USAGE_STATE, + sf.sf5.front_winding | (sf.sf5.viewport_transform << 1), + offsetof(struct brw_sf_unit_state, sf5), + brw->sf.vp_bo); + if (ret) + return ret; + + return PIPE_OK; } -static int upload_sf_unit( struct brw_context *brw ) +static enum pipe_error upload_sf_unit( struct brw_context *brw ) { struct brw_sf_unit_key key; struct brw_winsys_buffer *reloc_bufs[2]; + enum pipe_error ret; sf_unit_populate_key(brw, &key); reloc_bufs[0] = brw->sf.prog_bo; reloc_bufs[1] = brw->sf.vp_bo; - brw->sws->bo_unreference(brw->sf.state_bo); - brw->sf.state_bo = brw_search_cache(&brw->cache, BRW_SF_UNIT, - &key, sizeof(key), - reloc_bufs, 2, - NULL); - if (brw->sf.state_bo == NULL) { - brw->sf.state_bo = sf_unit_create_from_key(brw, &key, reloc_bufs); - } - return 0; + if (brw_search_cache(&brw->cache, BRW_SF_UNIT, + &key, sizeof(key), + reloc_bufs, 2, + NULL, + &brw->sf.state_bo)) + return PIPE_OK; + + + ret = sf_unit_create_from_key(brw, &key, reloc_bufs, + &brw->sf.state_bo); + if (ret) + return ret; + + return PIPE_OK; } const struct brw_tracked_state brw_sf_unit = { diff --git a/src/gallium/drivers/i965/brw_state.h b/src/gallium/drivers/i965/brw_state.h index 94d2cb6f829..e219a1d8701 100644 --- a/src/gallium/drivers/i965/brw_state.h +++ b/src/gallium/drivers/i965/brw_state.h @@ -44,8 +44,8 @@ brw_add_validated_bo(struct brw_context *brw, struct brw_winsys_buffer *bo) assert(brw->state.validated_bo_count < Elements(brw->state.validated_bos)); if (bo != NULL) { - brw->sws->bo_reference(bo); - brw->state.validated_bos[brw->state.validated_bo_count++] = bo; + bo_reference( &brw->state.validated_bos[brw->state.validated_bo_count++], + bo ); } } @@ -106,37 +106,42 @@ void brw_destroy_state(struct brw_context *brw); /*********************************************************************** * brw_state_cache.c */ -struct brw_winsys_buffer *brw_cache_data(struct brw_cache *cache, - enum brw_cache_id cache_id, - const void *data, - struct brw_winsys_buffer **reloc_bufs, - GLuint nr_reloc_bufs); - -struct brw_winsys_buffer *brw_cache_data_sz(struct brw_cache *cache, - enum brw_cache_id cache_id, - const void *data, - GLuint data_size, - struct brw_winsys_buffer **reloc_bufs, - GLuint nr_reloc_bufs); - -struct brw_winsys_buffer *brw_upload_cache( struct brw_cache *cache, - enum brw_cache_id cache_id, - const void *key, - GLuint key_sz, - struct brw_winsys_buffer **reloc_bufs, - GLuint nr_reloc_bufs, - const void *data, - GLuint data_sz, - const void *aux, - void *aux_return ); - -struct brw_winsys_buffer *brw_search_cache( struct brw_cache *cache, - enum brw_cache_id cache_id, - const void *key, - GLuint key_size, - struct brw_winsys_buffer **reloc_bufs, - GLuint nr_reloc_bufs, - void *aux_return); +enum pipe_error brw_cache_data(struct brw_cache *cache, + enum brw_cache_id cache_id, + const void *data, + struct brw_winsys_buffer **reloc_bufs, + GLuint nr_reloc_bufs, + struct brw_winsys_buffer **bo_out ); + +enum pipe_error brw_cache_data_sz(struct brw_cache *cache, + enum brw_cache_id cache_id, + const void *data, + GLuint data_size, + struct brw_winsys_buffer **reloc_bufs, + GLuint nr_reloc_bufs, + struct brw_winsys_buffer **bo_out); + +enum pipe_error brw_upload_cache( struct brw_cache *cache, + enum brw_cache_id cache_id, + const void *key, + GLuint key_sz, + struct brw_winsys_buffer **reloc_bufs, + GLuint nr_reloc_bufs, + const void *data, + GLuint data_sz, + const void *aux, + void *aux_return , + struct brw_winsys_buffer **bo_out); + +boolean brw_search_cache( struct brw_cache *cache, + enum brw_cache_id cache_id, + const void *key, + GLuint key_size, + struct brw_winsys_buffer **reloc_bufs, + GLuint nr_reloc_bufs, + void *aux_return, + struct brw_winsys_buffer **bo_out); + void brw_state_cache_check_size( struct brw_context *brw ); void brw_init_caches( struct brw_context *brw ); diff --git a/src/gallium/drivers/i965/brw_state_cache.c b/src/gallium/drivers/i965/brw_state_cache.c index cbd1f02d77d..f8369d31ec1 100644 --- a/src/gallium/drivers/i965/brw_state_cache.c +++ b/src/gallium/drivers/i965/brw_state_cache.c @@ -109,9 +109,8 @@ update_cache_last(struct brw_cache *cache, enum brw_cache_id cache_id, if (bo == cache->last_bo[cache_id]) return; /* no change */ - cache->sws->bo_unreference(cache->last_bo[cache_id]); - cache->last_bo[cache_id] = bo; - cache->sws->bo_reference(cache->last_bo[cache_id]); + bo_reference( &cache->last_bo[cache_id], bo ); + cache->brw->state.dirty.cache |= 1 << cache_id; } @@ -174,14 +173,15 @@ rehash(struct brw_cache *cache) /** * Returns the buffer object matching cache_id and key, or NULL. */ -struct brw_winsys_buffer * +boolean brw_search_cache(struct brw_cache *cache, enum brw_cache_id cache_id, const void *key, GLuint key_size, struct brw_winsys_buffer **reloc_bufs, GLuint nr_reloc_bufs, - void *aux_return) + void *aux_return, + struct brw_winsys_buffer **bo_out) { struct brw_cache_item *item; GLuint hash = hash_key(key, key_size, reloc_bufs, nr_reloc_bufs); @@ -189,20 +189,20 @@ brw_search_cache(struct brw_cache *cache, item = search_cache(cache, cache_id, hash, key, key_size, reloc_bufs, nr_reloc_bufs); - if (item == NULL) - return NULL; - - if (aux_return) - *(void **)aux_return = (void *)((char *)item->key + item->key_size); - - update_cache_last(cache, cache_id, item->bo); - - cache->sws->bo_reference(item->bo); - return item->bo; + if (item) { + if (aux_return) + *(void **)aux_return = (void *)((char *)item->key + item->key_size); + + update_cache_last(cache, cache_id, item->bo); + bo_reference(bo_out, item->bo); + return TRUE; + } + + return FALSE; } -struct brw_winsys_buffer * +enum pipe_error brw_upload_cache( struct brw_cache *cache, enum brw_cache_id cache_id, const void *key, @@ -212,14 +212,15 @@ brw_upload_cache( struct brw_cache *cache, const void *data, GLuint data_size, const void *aux, - void *aux_return ) + void *aux_return, + struct brw_winsys_buffer **bo_out) { struct brw_cache_item *item = CALLOC_STRUCT(brw_cache_item); GLuint hash = hash_key(key, key_size, reloc_bufs, nr_reloc_bufs); GLuint relocs_size = nr_reloc_bufs * sizeof(struct brw_winsys_buffer *); GLuint aux_size = cache->aux_size[cache_id]; + enum pipe_error ret; void *tmp; - struct brw_winsys_buffer *bo; int i; /* Create the buffer object to contain the data. For now, use a @@ -227,9 +228,12 @@ brw_upload_cache( struct brw_cache *cache, * may want to take advantage of hardware distinctions between * these various entities. */ - bo = cache->sws->bo_alloc(cache->sws, - cache->buffer_type, - data_size, 1 << 6); + ret = cache->sws->bo_alloc(cache->sws, + cache->buffer_type, + data_size, 1 << 6, + bo_out); + if (ret) + return ret; /* Set up the memory containing the key, aux_data, and reloc_bufs */ @@ -240,7 +244,7 @@ brw_upload_cache( struct brw_cache *cache, memcpy((char *)tmp + key_size + aux_size, reloc_bufs, relocs_size); for (i = 0; i < nr_reloc_bufs; i++) { if (reloc_bufs[i] != NULL) - cache->sws->bo_reference(reloc_bufs[i]); + p_atomic_inc(&reloc_bufs[i]->reference.count); } item->cache_id = cache_id; @@ -249,9 +253,7 @@ brw_upload_cache( struct brw_cache *cache, item->key_size = key_size; item->reloc_bufs = (struct brw_winsys_buffer **)((char *)tmp + key_size + aux_size); item->nr_reloc_bufs = nr_reloc_bufs; - - item->bo = bo; - cache->sws->bo_reference(bo); + bo_reference( &item->bo, *bo_out ); item->data_size = data_size; if (cache->n_items > cache->size * 1.5) @@ -273,28 +275,28 @@ brw_upload_cache( struct brw_cache *cache, data_size, cache_id); /* Copy data to the buffer */ - cache->sws->bo_subdata(bo, + cache->sws->bo_subdata(item->bo, cache_id, 0, data_size, data); - update_cache_last(cache, cache_id, bo); + update_cache_last(cache, cache_id, item->bo); - return bo; + return PIPE_OK; } /** * This doesn't really work with aux data. Use search/upload instead */ -struct brw_winsys_buffer * +enum pipe_error brw_cache_data_sz(struct brw_cache *cache, enum brw_cache_id cache_id, const void *data, GLuint data_size, struct brw_winsys_buffer **reloc_bufs, - GLuint nr_reloc_bufs) + GLuint nr_reloc_bufs, + struct brw_winsys_buffer **bo_out) { - struct brw_winsys_buffer *bo; struct brw_cache_item *item; GLuint hash = hash_key(data, data_size, reloc_bufs, nr_reloc_bufs); @@ -302,17 +304,17 @@ brw_cache_data_sz(struct brw_cache *cache, reloc_bufs, nr_reloc_bufs); if (item) { update_cache_last(cache, cache_id, item->bo); - cache->sws->bo_reference(item->bo); - return item->bo; - } - bo = brw_upload_cache(cache, cache_id, - data, data_size, - reloc_bufs, nr_reloc_bufs, - data, data_size, - NULL, NULL); + bo_reference(bo_out, item->bo); + return PIPE_OK; + } - return bo; + return brw_upload_cache(cache, cache_id, + data, data_size, + reloc_bufs, nr_reloc_bufs, + data, data_size, + NULL, NULL, + bo_out); } @@ -323,15 +325,16 @@ brw_cache_data_sz(struct brw_cache *cache, * better to use, as the potentially changing offsets in the data-used-as-key * will result in excessive cache misses. */ -struct brw_winsys_buffer * +enum pipe_error brw_cache_data(struct brw_cache *cache, enum brw_cache_id cache_id, const void *data, struct brw_winsys_buffer **reloc_bufs, - GLuint nr_reloc_bufs) + GLuint nr_reloc_bufs, + struct brw_winsys_buffer **bo_out) { return brw_cache_data_sz(cache, cache_id, data, cache->key_size[cache_id], - reloc_bufs, nr_reloc_bufs); + reloc_bufs, nr_reloc_bufs, bo_out); } @@ -506,11 +509,13 @@ brw_clear_cache(struct brw_context *brw, struct brw_cache *cache) int j; next = c->next; + for (j = 0; j < c->nr_reloc_bufs; j++) - brw->sws->bo_unreference(c->reloc_bufs[j]); - brw->sws->bo_unreference(c->bo); - free((void *)c->key); - free(c); + bo_reference(&c->reloc_bufs[j], NULL); + + bo_reference(&c->bo, NULL); + FREE((void *)c->key); + FREE(c); } cache->items[i] = NULL; } @@ -551,10 +556,12 @@ brw_state_cache_bo_delete(struct brw_cache *cache, struct brw_winsys_buffer *bo) *prev = c->next; for (j = 0; j < c->nr_reloc_bufs; j++) - cache->sws->bo_unreference(c->reloc_bufs[j]); - cache->sws->bo_unreference(c->bo); - free((void *)c->key); - free(c); + bo_reference(&c->reloc_bufs[j], NULL); + + bo_reference(&c->bo, NULL); + + FREE((void *)c->key); + FREE(c); cache->n_items--; } else { prev = &c->next; @@ -590,10 +597,10 @@ brw_destroy_cache(struct brw_context *brw, struct brw_cache *cache) brw_clear_cache(brw, cache); for (i = 0; i < BRW_MAX_CACHE; i++) { - brw->sws->bo_unreference(cache->last_bo[i]); - free(cache->name[i]); + bo_reference(&cache->last_bo[i], NULL); + FREE(cache->name[i]); } - free(cache->items); + FREE(cache->items); cache->items = NULL; cache->size = 0; } diff --git a/src/gallium/drivers/i965/brw_state_upload.c b/src/gallium/drivers/i965/brw_state_upload.c index a71af4d2b91..fdcdd59129f 100644 --- a/src/gallium/drivers/i965/brw_state_upload.c +++ b/src/gallium/drivers/i965/brw_state_upload.c @@ -140,8 +140,7 @@ brw_clear_validated_bos(struct brw_context *brw) /* Clear the last round of validated bos */ for (i = 0; i < brw->state.validated_bo_count; i++) { - brw->sws->bo_unreference(brw->state.validated_bos[i]); - brw->state.validated_bos[i] = NULL; + bo_reference(&brw->state.validated_bos[i], NULL); } brw->state.validated_bo_count = 0; } diff --git a/src/gallium/drivers/i965/brw_vs.c b/src/gallium/drivers/i965/brw_vs.c index 26a28114d98..966940ceacb 100644 --- a/src/gallium/drivers/i965/brw_vs.c +++ b/src/gallium/drivers/i965/brw_vs.c @@ -39,10 +39,12 @@ -static void do_vs_prog( struct brw_context *brw, - struct brw_vertex_shader *vp, - struct brw_vs_prog_key *key ) +static enum pipe_error do_vs_prog( struct brw_context *brw, + struct brw_vertex_shader *vp, + struct brw_vs_prog_key *key, + struct brw_winsys_buffer **bo_out) { + enum pipe_error ret; GLuint program_size; const GLuint *program; struct brw_vs_compile c; @@ -66,22 +68,29 @@ static void do_vs_prog( struct brw_context *brw, /* get the program */ - program = brw_get_program(&c.func, &program_size); - - brw->sws->bo_unreference(brw->vs.prog_bo); - brw->vs.prog_bo = brw_upload_cache( &brw->cache, BRW_VS_PROG, - &c.key, sizeof(c.key), - NULL, 0, - program, program_size, - &c.prog_data, - &brw->vs.prog_data ); + ret = brw_get_program(&c.func, &program, &program_size); + if (ret) + return ret; + + ret = brw_upload_cache( &brw->cache, BRW_VS_PROG, + &c.key, sizeof(c.key), + NULL, 0, + program, program_size, + &c.prog_data, + &brw->vs.prog_data, + bo_out); + if (ret) + return ret; + + return PIPE_OK; } -static int brw_upload_vs_prog(struct brw_context *brw) +static enum pipe_error brw_upload_vs_prog(struct brw_context *brw) { struct brw_vs_prog_key key; struct brw_vertex_shader *vp = brw->curr.vertex_shader; + enum pipe_error ret; memset(&key, 0, sizeof(key)); @@ -95,15 +104,18 @@ static int brw_upload_vs_prog(struct brw_context *brw) /* Make an early check for the key. */ - brw->sws->bo_unreference(brw->vs.prog_bo); - brw->vs.prog_bo = brw_search_cache(&brw->cache, BRW_VS_PROG, - &key, sizeof(key), - NULL, 0, - &brw->vs.prog_data); - if (brw->vs.prog_bo == NULL) - do_vs_prog(brw, vp, &key); - - return 0; + if (brw_search_cache(&brw->cache, BRW_VS_PROG, + &key, sizeof(key), + NULL, 0, + &brw->vs.prog_data, + &brw->vs.prog_bo)) + return PIPE_OK; + + ret = do_vs_prog(brw, vp, &key, &brw->vs.prog_bo); + if (ret) + return ret; + + return PIPE_OK; } diff --git a/src/gallium/drivers/i965/brw_vs_state.c b/src/gallium/drivers/i965/brw_vs_state.c index 26d5d005faa..22a4d7f01b9 100644 --- a/src/gallium/drivers/i965/brw_vs_state.c +++ b/src/gallium/drivers/i965/brw_vs_state.c @@ -78,11 +78,13 @@ vs_unit_populate_key(struct brw_context *brw, struct brw_vs_unit_key *key) } } -static struct brw_winsys_buffer * -vs_unit_create_from_key(struct brw_context *brw, struct brw_vs_unit_key *key) +static enum pipe_error +vs_unit_create_from_key(struct brw_context *brw, + struct brw_vs_unit_key *key, + struct brw_winsys_buffer **bo_out) { + enum pipe_error ret; struct brw_vs_unit_state vs; - struct brw_winsys_buffer *bo; int chipset_max_threads; memset(&vs, 0, sizeof(vs)); @@ -141,38 +143,46 @@ vs_unit_create_from_key(struct brw_context *brw, struct brw_vs_unit_key *key) */ vs.vs6.vs_enable = 1; - bo = brw_upload_cache(&brw->cache, BRW_VS_UNIT, - key, sizeof(*key), - &brw->vs.prog_bo, 1, - &vs, sizeof(vs), - NULL, NULL); + ret = brw_upload_cache(&brw->cache, BRW_VS_UNIT, + key, sizeof(*key), + &brw->vs.prog_bo, 1, + &vs, sizeof(vs), + NULL, NULL, + bo_out); + if (ret) + return ret; /* Emit VS program relocation */ - brw->sws->bo_emit_reloc(bo, - BRW_USAGE_STATE, - vs.thread0.grf_reg_count << 1, - offsetof(struct brw_vs_unit_state, thread0), - brw->vs.prog_bo); - - return bo; + ret = brw->sws->bo_emit_reloc(*bo_out, + BRW_USAGE_STATE, + vs.thread0.grf_reg_count << 1, + offsetof(struct brw_vs_unit_state, thread0), + brw->vs.prog_bo); + if (ret) + return ret; + + return PIPE_OK; } static int prepare_vs_unit(struct brw_context *brw) { struct brw_vs_unit_key key; + enum pipe_error ret; vs_unit_populate_key(brw, &key); - brw->sws->bo_unreference(brw->vs.state_bo); - brw->vs.state_bo = brw_search_cache(&brw->cache, BRW_VS_UNIT, - &key, sizeof(key), - &brw->vs.prog_bo, 1, - NULL); - if (brw->vs.state_bo == NULL) { - brw->vs.state_bo = vs_unit_create_from_key(brw, &key); - } + if (brw_search_cache(&brw->cache, BRW_VS_UNIT, + &key, sizeof(key), + &brw->vs.prog_bo, 1, + NULL, + &brw->vs.state_bo)) + return PIPE_OK; + + ret = vs_unit_create_from_key(brw, &key, &brw->vs.state_bo); + if (ret) + return ret; - return 0; + return PIPE_OK; } const struct brw_tracked_state brw_vs_unit = { diff --git a/src/gallium/drivers/i965/brw_vs_surface_state.c b/src/gallium/drivers/i965/brw_vs_surface_state.c index 32fb9b2a8b9..b12df0ec038 100644 --- a/src/gallium/drivers/i965/brw_vs_surface_state.c +++ b/src/gallium/drivers/i965/brw_vs_surface_state.c @@ -83,22 +83,23 @@ brw_update_vs_constant_surface( struct brw_context *brw, { struct brw_surface_key key; struct pipe_buffer *cb = brw->curr.vs_constants; + enum pipe_error ret; assert(surf == 0); /* If we're in this state update atom, we need to update VS constants, so * free the old buffer and create a new one for the new contents. */ - brw->sws->bo_unreference(vp->const_buffer); - vp->const_buffer = brw_vs_update_constant_buffer(brw); + ret = brw_vs_update_constant_buffer(brw, &vp->const_buffer); + if (ret) + return ret; /* If there's no constant buffer, then no surface BO is needed to point at * it. */ - if (vp->const_buffer == 0) { - drm_intel_bo_unreference(brw->vs.surf_bo[surf]); - brw->vs.surf_bo[surf] = NULL; - return; + if (vp->const_buffer == NULL) { + bo_reference(brw->vs.surf_bo[surf], NULL); + return PIPE_OK; } memset(&key, 0, sizeof(key)); @@ -118,15 +119,20 @@ brw_update_vs_constant_surface( struct brw_context *brw, key.width, key.height, key.depth, key.cpp, key.pitch); */ - drm_intel_bo_unreference(brw->vs.surf_bo[surf]); - brw->vs.surf_bo[surf] = brw_search_cache(&brw->surface_cache, - BRW_SS_SURFACE, - &key, sizeof(key), - &key.bo, key.bo ? 1 : 0, - NULL); - if (brw->vs.surf_bo[surf] == NULL) { - brw->vs.surf_bo[surf] = brw_create_constant_surface(brw, &key); - } + if (brw_search_cache(&brw->surface_cache, + BRW_SS_SURFACE, + &key, sizeof(key), + &key.bo, key.bo ? 1 : 0, + NULL, + &brw->vs.surf_bo[surf])) + return PIPE_OK; + + ret = brw_create_constant_surface(brw, &key + &brw->vs.surf_bo[surf]); + if (ret) + return ret; + + return PIPE_OK; } #endif @@ -134,18 +140,20 @@ brw_update_vs_constant_surface( struct brw_context *brw, /** * Constructs the binding table for the VS surface state. */ -static struct brw_winsys_buffer * -brw_vs_get_binding_table(struct brw_context *brw) +static enum pipe_error +brw_vs_get_binding_table(struct brw_context *brw, + struct brw_winsys_buffer **bo_out) { #if 0 - struct brw_winsys_buffer *bind_bo; - - bind_bo = brw_search_cache(&brw->surface_cache, BRW_SS_SURF_BIND, - NULL, 0, - brw->vs.surf_bo, BRW_VS_MAX_SURF, - NULL); - - if (bind_bo == NULL) { + if (brw_search_cache(&brw->surface_cache, BRW_SS_SURF_BIND, + NULL, 0, + brw->vs.surf_bo, BRW_VS_MAX_SURF, + NULL, + bo_out)) + { + return PIPE_OK; + } + else { GLuint data_size = BRW_VS_MAX_SURF * sizeof(GLuint); uint32_t *data = malloc(data_size); int i; @@ -156,11 +164,14 @@ brw_vs_get_binding_table(struct brw_context *brw) else data[i] = 0; - bind_bo = brw_upload_cache( &brw->surface_cache, BRW_SS_SURF_BIND, - NULL, 0, - brw->vs.surf_bo, BRW_VS_MAX_SURF, - data, data_size, - NULL, NULL); + ret = brw_upload_cache( &brw->surface_cache, BRW_SS_SURF_BIND, + NULL, 0, + brw->vs.surf_bo, BRW_VS_MAX_SURF, + data, data_size, + NULL, NULL, + bo_out); + if (ret) + return ret; /* Emit binding table relocations to surface state */ for (i = 0; i < BRW_VS_MAX_SURF; i++) { @@ -168,18 +179,19 @@ brw_vs_get_binding_table(struct brw_context *brw) /* The presumed offsets were set in the data values for * brw_upload_cache. */ - drm_intel_bo_emit_reloc(bind_bo, i * 4, - brw->vs.surf_bo[i], 0, - BRW_USAGE_STATE); + ret = sws->bo_emit_reloc(*bo_out, i * 4, + brw->vs.surf_bo[i], 0, + BRW_USAGE_STATE); + if (ret) + return ret; } } - free(data); + FREE(data); + return PIPE_OK; } - - return bind_bo; #else - return NULL; + return PIPE_OK; #endif } @@ -190,8 +202,10 @@ brw_vs_get_binding_table(struct brw_context *brw) * to be updated, and produces BRW_NEW_NR_VS_SURFACES for the VS unit and * CACHE_NEW_SURF_BIND for the binding table upload. */ -static int prepare_vs_surfaces(struct brw_context *brw ) +static enum pipe_error prepare_vs_surfaces(struct brw_context *brw ) { + enum pipe_error ret; + #if 0 int i; int nr_surfaces = 0; @@ -215,11 +229,12 @@ static int prepare_vs_surfaces(struct brw_context *brw ) * just slightly increases our working set size. */ if (brw->vs.nr_surfaces != 0) { - brw->sws->bo_unreference(brw->vs.bind_bo); - brw->vs.bind_bo = brw_vs_get_binding_table(brw); + ret = brw_vs_get_binding_table(brw, &brw->vs.bind_bo); + if (ret) + return ret; } - return 0; + return PIPE_OK; } const struct brw_tracked_state brw_vs_surfaces = { diff --git a/src/gallium/drivers/i965/brw_winsys.h b/src/gallium/drivers/i965/brw_winsys.h index d941fbcebee..f61c541ad15 100644 --- a/src/gallium/drivers/i965/brw_winsys.h +++ b/src/gallium/drivers/i965/brw_winsys.h @@ -28,6 +28,7 @@ #include "pipe/p_compiler.h" #include "pipe/p_error.h" +#include "pipe/p_refcnt.h" struct brw_winsys; struct pipe_fence_handle; @@ -36,10 +37,13 @@ struct pipe_fence_handle; */ #define BRW_BATCH_SIZE (32*1024) +struct brw_winsys_screen; /* Need a tiny bit of information inside the abstract buffer struct: */ struct brw_winsys_buffer { + struct pipe_reference reference; + struct brw_winsys_screen *sws; unsigned *offset; unsigned size; }; @@ -105,6 +109,10 @@ enum brw_buffer_data_type { BRW_DATA_MAX }; + + + + struct brw_winsys_screen { @@ -116,33 +124,33 @@ struct brw_winsys_screen { /** * Create a buffer. */ - struct brw_winsys_buffer *(*bo_alloc)( struct brw_winsys_screen *sws, - enum brw_buffer_type type, - unsigned size, - unsigned alignment ); + enum pipe_error (*bo_alloc)( struct brw_winsys_screen *sws, + enum brw_buffer_type type, + unsigned size, + unsigned alignment, + struct brw_winsys_buffer **bo_out ); - /* Reference and unreference buffers: + /* Destroy a buffer when our refcount goes to zero: */ - void (*bo_reference)( struct brw_winsys_buffer *buffer ); - void (*bo_unreference)( struct brw_winsys_buffer *buffer ); + void (*bo_destroy)( struct brw_winsys_buffer *buffer ); /* delta -- added to b2->offset, and written into buffer * offset -- location above value is written to within buffer */ - int (*bo_emit_reloc)( struct brw_winsys_buffer *buffer, - enum brw_buffer_usage usage, - unsigned delta, - unsigned offset, - struct brw_winsys_buffer *b2); + enum pipe_error (*bo_emit_reloc)( struct brw_winsys_buffer *buffer, + enum brw_buffer_usage usage, + unsigned delta, + unsigned offset, + struct brw_winsys_buffer *b2); - int (*bo_exec)( struct brw_winsys_buffer *buffer, - unsigned bytes_used ); + enum pipe_error (*bo_exec)( struct brw_winsys_buffer *buffer, + unsigned bytes_used ); - int (*bo_subdata)(struct brw_winsys_buffer *buffer, - enum brw_buffer_data_type data_type, - size_t offset, - size_t size, - const void *data); + enum pipe_error (*bo_subdata)(struct brw_winsys_buffer *buffer, + enum brw_buffer_data_type data_type, + size_t offset, + size_t size, + const void *data); boolean (*bo_is_busy)(struct brw_winsys_buffer *buffer); boolean (*bo_references)(struct brw_winsys_buffer *a, @@ -175,6 +183,16 @@ struct brw_winsys_screen { }; +static INLINE void +bo_reference(struct brw_winsys_buffer **ptr, struct brw_winsys_buffer *buf) +{ + struct brw_winsys_buffer *old_buf = *ptr; + + if (pipe_reference((struct pipe_reference **)ptr, &buf->reference)) + old_buf->sws->bo_destroy(old_buf); +} + + /** * Create brw pipe_screen. */ diff --git a/src/gallium/drivers/i965/brw_wm.c b/src/gallium/drivers/i965/brw_wm.c index 815ae8c51aa..93f90bf3298 100644 --- a/src/gallium/drivers/i965/brw_wm.c +++ b/src/gallium/drivers/i965/brw_wm.c @@ -137,30 +137,26 @@ brw_wm_linear_shader_emit(struct brw_context *brw, struct brw_wm_compile *c) * Depending on the instructions used (i.e. flow control instructions) * we'll use one of two code generators. */ -static int do_wm_prog( struct brw_context *brw, - struct brw_fragment_shader *fp, - struct brw_wm_prog_key *key) +static enum pipe_error do_wm_prog( struct brw_context *brw, + struct brw_fragment_shader *fp, + struct brw_wm_prog_key *key, + struct brw_winsys_buffer **bo_out) { + enum pipe_error ret; struct brw_wm_compile *c; const GLuint *program; GLuint program_size; - c = brw->wm.compile_data; - if (c == NULL) { - brw->wm.compile_data = calloc(1, sizeof(*brw->wm.compile_data)); - c = brw->wm.compile_data; - if (c == NULL) { - /* Ouch - big out of memory problem. Can't continue - * without triggering a segfault, no way to signal, - * so just return. - */ + if (brw->wm.compile_data == NULL) { + brw->wm.compile_data = MALLOC(sizeof(*brw->wm.compile_data)); + if (!brw->wm.compile_data) return PIPE_ERROR_OUT_OF_MEMORY; - } - } else { - memset(c, 0, sizeof(*brw->wm.compile_data)); } - memcpy(&c->key, key, sizeof(*key)); + c = brw->wm.compile_data; + memset(c, 0, sizeof *c); + + c->key = *key; c->fp = fp; c->env_param = NULL; /*brw->intel.ctx.FragmentProgram.Parameters;*/ @@ -190,17 +186,21 @@ static int do_wm_prog( struct brw_context *brw, /* get the program */ - program = brw_get_program(&c->func, &program_size); - - brw->sws->bo_unreference(brw->wm.prog_bo); - brw->wm.prog_bo = brw_upload_cache( &brw->cache, BRW_WM_PROG, - &c->key, sizeof(c->key), - NULL, 0, - program, program_size, - &c->prog_data, - &brw->wm.prog_data ); - - return 0; + ret = brw_get_program(&c->func, &program, &program_size); + if (ret) + return ret; + + ret = brw_upload_cache( &brw->cache, BRW_WM_PROG, + &c->key, sizeof(c->key), + NULL, 0, + program, program_size, + &c->prog_data, + &brw->wm.prog_data, + bo_out ); + if (ret) + return ret; + + return PIPE_OK; } @@ -267,24 +267,28 @@ static void brw_wm_populate_key( struct brw_context *brw, } -static int brw_prepare_wm_prog(struct brw_context *brw) +static enum pipe_error brw_prepare_wm_prog(struct brw_context *brw) { struct brw_wm_prog_key key; struct brw_fragment_shader *fs = brw->curr.fragment_shader; + enum pipe_error ret; brw_wm_populate_key(brw, &key); /* Make an early check for the key. */ - brw->sws->bo_unreference(brw->wm.prog_bo); - brw->wm.prog_bo = brw_search_cache(&brw->cache, BRW_WM_PROG, - &key, sizeof(key), - NULL, 0, - &brw->wm.prog_data); - if (brw->wm.prog_bo == NULL) - return do_wm_prog(brw, fs, &key); - - return 0; + if (brw_search_cache(&brw->cache, BRW_WM_PROG, + &key, sizeof(key), + NULL, 0, + &brw->wm.prog_data, + &brw->wm.prog_bo)) + return PIPE_OK; + + ret = do_wm_prog(brw, fs, &key, &brw->wm.prog_bo); + if (ret) + return ret; + + return PIPE_OK; } diff --git a/src/gallium/drivers/i965/brw_wm_constant_buffer.c b/src/gallium/drivers/i965/brw_wm_constant_buffer.c index 50ecef29a41..14568265dd0 100644 --- a/src/gallium/drivers/i965/brw_wm_constant_buffer.c +++ b/src/gallium/drivers/i965/brw_wm_constant_buffer.c @@ -6,12 +6,14 @@ * Create the constant buffer surface. Vertex/fragment shader constants will be * read from this buffer with Data Port Read instructions/messages. */ -struct brw_winsys_buffer * +enum pipe_error brw_create_constant_surface( struct brw_context *brw, - struct brw_surface_key *key ) + struct brw_surface_key *key, + struct brw_winsys_buffer **bo_out ) { const GLint w = key->width - 1; struct brw_winsys_buffer *bo; + enum pipe_error ret; memset(&surf, 0, sizeof(surf)); @@ -28,22 +30,27 @@ brw_create_constant_surface( struct brw_context *brw, surf.ss3.pitch = (key->pitch * key->cpp) - 1; /* ignored?? */ brw_set_surface_tiling(&surf, key->tiling); /* tiling now allowed */ - bo = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE, - key, sizeof(*key), - &key->bo, key->bo ? 1 : 0, - &surf, sizeof(surf), - NULL, NULL); + ret = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE, + key, sizeof(*key), + &key->bo, key->bo ? 1 : 0, + &surf, sizeof(surf), + NULL, NULL, + &bo_out); + if (ret) + return ret; if (key->bo) { /* Emit relocation to surface contents */ - brw->sws->bo_emit_reloc(bo, - BRW_USAGE_SAMPLER, - 0, - offsetof(struct brw_surface_state, ss1), - key->bo); + ret = brw->sws->bo_emit_reloc(*bo_out, + BRW_USAGE_SAMPLER, + 0, + offsetof(struct brw_surface_state, ss1), + key->bo); + if (ret) + return ret; } - return bo; + return PIPE_OK; } @@ -52,7 +59,7 @@ brw_create_constant_surface( struct brw_context *brw, * Update the surface state for a WM constant buffer. * The constant buffer will be (re)allocated here if needed. */ -static void +static enum pipe_error brw_update_wm_constant_surface( struct brw_context *brw, GLuint surf) { @@ -60,20 +67,21 @@ brw_update_wm_constant_surface( struct brw_context *brw, struct brw_fragment_shader *fp = brw->curr.fragment_shader; struct pipe_buffer *cbuf = brw->curr.fragment_constants; int pitch = cbuf->size / (4 * sizeof(float)); + enum pipe_error ret; /* If we're in this state update atom, we need to update WM constants, so * free the old buffer and create a new one for the new contents. */ - brw->sws->bo_unreference(fp->const_buffer); - fp->const_buffer = brw_wm_update_constant_buffer(brw); + ret = brw_wm_update_constant_buffer(brw, &fp->const_buffer); + if (ret) + return ret; /* If there's no constant buffer, then no surface BO is needed to point at * it. */ if (cbuf == NULL) { - drm_intel_bo_unreference(brw->wm.surf_bo[surf]); - brw->wm.surf_bo[surf] = NULL; - return; + bo_reference(&brw->wm.surf_bo[surf], NULL); + return PIPE_OK; } memset(&key, 0, sizeof(key)); @@ -97,16 +105,20 @@ brw_update_wm_constant_surface( struct brw_context *brw, key.width, key.height, key.depth, key.cpp, key.pitch); */ - brw->sws->bo_unreference(brw->wm.surf_bo[surf]); - brw->wm.surf_bo[surf] = brw_search_cache(&brw->surface_cache, - BRW_SS_SURFACE, - &key, sizeof(key), - &key.bo, 1, - NULL); - if (brw->wm.surf_bo[surf] == NULL) { - brw->wm.surf_bo[surf] = brw_create_constant_surface(brw, &key); - } + if (brw_search_cache(&brw->surface_cache, + BRW_SS_SURFACE, + &key, sizeof(key), + &key.bo, 1, + NULL, + &brw->wm.surf_bo[surf])) + return PIPE_OK; + + ret = brw_create_constant_surface(brw, &key, &brw->wm.surf_bo[surf]); + if (ret) + return ret; + brw->state.dirty.brw |= BRW_NEW_WM_SURFACES; + return PIPE_OK; } /** @@ -117,28 +129,33 @@ brw_update_wm_constant_surface( struct brw_context *brw, * BRW_NEW_WM_SURFACES to get picked up by brw_prepare_wm_surfaces for * inclusion in the binding table. */ -static void prepare_wm_constant_surface(struct brw_context *brw ) +static enum pipe_error prepare_wm_constant_surface(struct brw_context *brw ) { struct brw_fragment_program *fp = (struct brw_fragment_program *) brw->fragment_program; GLuint surf = SURF_INDEX_FRAG_CONST_BUFFER; - drm_intel_bo_unreference(fp->const_buffer); - fp->const_buffer = brw_wm_update_constant_buffer(brw); + ret = brw_wm_update_constant_buffer(brw, + &fp->const_buffer); + if (ret) + return ret; /* If there's no constant buffer, then no surface BO is needed to point at * it. */ if (fp->const_buffer == 0) { if (brw->wm.surf_bo[surf] != NULL) { - drm_intel_bo_unreference(brw->wm.surf_bo[surf]); - brw->wm.surf_bo[surf] = NULL; + bo_reference(&brw->wm.surf_bo[surf], NULL); brw->state.dirty.brw |= BRW_NEW_WM_SURFACES; } - return; + return PIPE_OK; } - brw_update_wm_constant_surface(ctx, surf); + ret = brw_update_wm_constant_surface(ctx, surf); + if (ret) + return ret; + + return PIPE_OK } const struct brw_tracked_state brw_wm_constant_surface = { diff --git a/src/gallium/drivers/i965/brw_wm_sampler_state.c b/src/gallium/drivers/i965/brw_wm_sampler_state.c index 2fddb4ad897..2861aa979fe 100644 --- a/src/gallium/drivers/i965/brw_wm_sampler_state.c +++ b/src/gallium/drivers/i965/brw_wm_sampler_state.c @@ -43,16 +43,22 @@ -static struct brw_winsys_buffer * +static enum pipe_error upload_default_color( struct brw_context *brw, - const GLfloat *color ) + const GLfloat *color, + struct brw_winsys_buffer **bo_out ) { struct brw_sampler_default_color sdc; + enum pipe_error ret; COPY_4V(sdc.color, color); - return brw_cache_data( &brw->cache, BRW_SAMPLER_DEFAULT_COLOR, &sdc, - NULL, 0 ); + ret = brw_cache_data( &brw->cache, BRW_SAMPLER_DEFAULT_COLOR, &sdc, + NULL, 0, bo_out ); + if (ret) + return ret; + + return PIPE_OK; } @@ -111,9 +117,10 @@ brw_wm_sampler_populate_key(struct brw_context *brw, } -static void +static enum pipe_error brw_wm_sampler_update_default_colors(struct brw_context *brw) { + enum pipe_error ret; int nr = MIN2(brw->curr.num_textures, brw->curr.num_samplers); int i; @@ -121,8 +128,7 @@ brw_wm_sampler_update_default_colors(struct brw_context *brw) for (i = 0; i < nr; i++) { const struct brw_texture *tex = brw_texture(brw->curr.texture[i]); const struct brw_sampler *sampler = brw->curr.sampler[i]; - - brw->sws->bo_unreference(brw->wm.sdc_bo[i]); + const float *bc; if (pf_is_depth_or_stencil(tex->base.format)) { float bordercolor[4] = { @@ -131,15 +137,25 @@ brw_wm_sampler_update_default_colors(struct brw_context *brw) sampler->border_color[0], sampler->border_color[0] }; - /* GL specs that border color for depth textures is taken from the - * R channel, while the hardware uses A. Spam R into all the - * channels for safety. - */ - brw->wm.sdc_bo[i] = upload_default_color(brw, bordercolor); - } else { - brw->wm.sdc_bo[i] = upload_default_color(brw, sampler->border_color); + + bc = bordercolor; + } + else { + bc = sampler->border_color; } + + /* GL specs that border color for depth textures is taken from the + * R channel, while the hardware uses A. Spam R into all the + * channels for safety. + */ + ret = upload_default_color(brw, + bc, + &brw->wm.sdc_bo[i]); + if (ret) + return ret; } + + return PIPE_OK; } @@ -149,6 +165,7 @@ brw_wm_sampler_update_default_colors(struct brw_context *brw) static int upload_wm_samplers( struct brw_context *brw ) { struct wm_sampler_key key; + enum pipe_error ret; int i; brw_wm_sampler_update_default_colors(brw); @@ -159,35 +176,40 @@ static int upload_wm_samplers( struct brw_context *brw ) brw->state.dirty.cache |= CACHE_NEW_SAMPLER; } - brw->sws->bo_unreference(brw->wm.sampler_bo); - brw->wm.sampler_bo = NULL; - if (brw->wm.sampler_count == 0) - return 0; + if (brw->wm.sampler_count == 0) { + bo_reference(&brw->wm.sampler_bo, NULL); + return PIPE_OK; + } - brw->wm.sampler_bo = brw_search_cache(&brw->cache, BRW_SAMPLER, - &key, sizeof(key), - brw->wm.sdc_bo, key.sampler_count, - NULL); + if (brw_search_cache(&brw->cache, BRW_SAMPLER, + &key, sizeof(key), + brw->wm.sdc_bo, key.sampler_count, + NULL, + &brw->wm.sampler_bo)) + return PIPE_OK; /* If we didnt find it in the cache, compute the state and put it in the * cache. */ - if (brw->wm.sampler_bo == NULL) { - brw->wm.sampler_bo = brw_upload_cache(&brw->cache, BRW_SAMPLER, - &key, sizeof(key), - brw->wm.sdc_bo, key.sampler_count, - &key.sampler, sizeof(key.sampler), - NULL, NULL); - - /* Emit SDC relocations */ - for (i = 0; i < key.sampler_count; i++) { - brw->sws->bo_emit_reloc(brw->wm.sampler_bo, - BRW_USAGE_SAMPLER, - 0, - i * sizeof(struct brw_sampler_state) + - offsetof(struct brw_sampler_state, ss2), - brw->wm.sdc_bo[i]); - } + ret = brw_upload_cache(&brw->cache, BRW_SAMPLER, + &key, sizeof(key), + brw->wm.sdc_bo, key.sampler_count, + &key.sampler, sizeof(key.sampler), + NULL, NULL, + &brw->wm.sampler_bo); + if (ret) + return ret; + + /* Emit SDC relocations */ + for (i = 0; i < key.sampler_count; i++) { + ret = brw->sws->bo_emit_reloc(brw->wm.sampler_bo, + BRW_USAGE_SAMPLER, + 0, + i * sizeof(struct brw_sampler_state) + + offsetof(struct brw_sampler_state, ss2), + brw->wm.sdc_bo[i]); + if (ret) + return ret; } return 0; diff --git a/src/gallium/drivers/i965/brw_wm_state.c b/src/gallium/drivers/i965/brw_wm_state.c index ccbb647bcd0..86dc10540d7 100644 --- a/src/gallium/drivers/i965/brw_wm_state.c +++ b/src/gallium/drivers/i965/brw_wm_state.c @@ -138,12 +138,13 @@ wm_unit_populate_key(struct brw_context *brw, struct brw_wm_unit_key *key) /** * Setup wm hardware state. See page 225 of Volume 2 */ -static struct brw_winsys_buffer * +static enum pipe_error wm_unit_create_from_key(struct brw_context *brw, struct brw_wm_unit_key *key, - struct brw_winsys_buffer **reloc_bufs) + struct brw_winsys_buffer **reloc_bufs, + struct brw_winsys_buffer **bo_out) { struct brw_wm_unit_state wm; - struct brw_winsys_buffer *bo; + enum pipe_error ret; memset(&wm, 0, sizeof(wm)); @@ -222,45 +223,56 @@ wm_unit_create_from_key(struct brw_context *brw, struct brw_wm_unit_key *key, if (BRW_DEBUG & DEBUG_STATS || key->stats_wm) wm.wm4.stats_enable = 1; - bo = brw_upload_cache(&brw->cache, BRW_WM_UNIT, - key, sizeof(*key), - reloc_bufs, 3, - &wm, sizeof(wm), - NULL, NULL); + ret = brw_upload_cache(&brw->cache, BRW_WM_UNIT, + key, sizeof(*key), + reloc_bufs, 3, + &wm, sizeof(wm), + NULL, NULL, + bo_out); + if (ret) + return ret; /* Emit WM program relocation */ - brw->sws->bo_emit_reloc(bo, - BRW_USAGE_STATE, - wm.thread0.grf_reg_count << 1, - offsetof(struct brw_wm_unit_state, thread0), - brw->wm.prog_bo); + ret = brw->sws->bo_emit_reloc(*bo_out, + BRW_USAGE_STATE, + wm.thread0.grf_reg_count << 1, + offsetof(struct brw_wm_unit_state, thread0), + brw->wm.prog_bo); + if (ret) + return ret; /* Emit scratch space relocation */ if (key->total_scratch != 0) { - brw->sws->bo_emit_reloc(bo, - BRW_USAGE_SCRATCH, - wm.thread2.per_thread_scratch_space, - offsetof(struct brw_wm_unit_state, thread2), - brw->wm.scratch_bo); + ret = brw->sws->bo_emit_reloc(*bo_out, + BRW_USAGE_SCRATCH, + wm.thread2.per_thread_scratch_space, + offsetof(struct brw_wm_unit_state, thread2), + brw->wm.scratch_bo); + if (ret) + return ret; } /* Emit sampler state relocation */ if (key->sampler_count != 0) { - brw->sws->bo_emit_reloc(bo, - BRW_USAGE_STATE, - wm.wm4.stats_enable | (wm.wm4.sampler_count << 2), - offsetof(struct brw_wm_unit_state, wm4), - brw->wm.sampler_bo); + ret = brw->sws->bo_emit_reloc(*bo_out, + BRW_USAGE_STATE, + wm.wm4.stats_enable | (wm.wm4.sampler_count << 2), + offsetof(struct brw_wm_unit_state, wm4), + brw->wm.sampler_bo); + if (ret) + return ret; } - return bo; + return PIPE_OK; } -static int upload_wm_unit( struct brw_context *brw ) +static enum pipe_error upload_wm_unit( struct brw_context *brw ) { struct brw_wm_unit_key key; struct brw_winsys_buffer *reloc_bufs[3]; + enum pipe_error ret; + wm_unit_populate_key(brw, &key); /* Allocate the necessary scratch space if we haven't already. Don't @@ -271,15 +283,19 @@ static int upload_wm_unit( struct brw_context *brw ) if (key.total_scratch) { GLuint total = key.total_scratch * key.max_threads; - if (brw->wm.scratch_bo && total > brw->wm.scratch_bo->size) { - brw->sws->bo_unreference(brw->wm.scratch_bo); - brw->wm.scratch_bo = NULL; - } + /* Do we need a new buffer: + */ + if (brw->wm.scratch_bo && total > brw->wm.scratch_bo->size) + bo_reference(&brw->wm.scratch_bo, NULL); + if (brw->wm.scratch_bo == NULL) { - brw->wm.scratch_bo = brw->sws->bo_alloc(brw->sws, - BRW_BUFFER_TYPE_SHADER_SCRATCH, - total, - 4096); + ret = brw->sws->bo_alloc(brw->sws, + BRW_BUFFER_TYPE_SHADER_SCRATCH, + total, + 4096, + &brw->wm.scratch_bo); + if (ret) + return ret; } } @@ -287,16 +303,19 @@ static int upload_wm_unit( struct brw_context *brw ) reloc_bufs[1] = brw->wm.scratch_bo; reloc_bufs[2] = brw->wm.sampler_bo; - brw->sws->bo_unreference(brw->wm.state_bo); - brw->wm.state_bo = brw_search_cache(&brw->cache, BRW_WM_UNIT, - &key, sizeof(key), - reloc_bufs, 3, - NULL); - if (brw->wm.state_bo == NULL) { - brw->wm.state_bo = wm_unit_create_from_key(brw, &key, reloc_bufs); - } + if (brw_search_cache(&brw->cache, BRW_WM_UNIT, + &key, sizeof(key), + reloc_bufs, 3, + NULL, + &brw->wm.state_bo)) + return PIPE_OK; + + ret = wm_unit_create_from_key(brw, &key, reloc_bufs, + &brw->wm.state_bo); + if (ret) + return ret; - return 0; + return PIPE_OK; } const struct brw_tracked_state brw_wm_unit = { diff --git a/src/gallium/drivers/i965/brw_wm_surface_state.c b/src/gallium/drivers/i965/brw_wm_surface_state.c index b055dde20cf..e5d03299677 100644 --- a/src/gallium/drivers/i965/brw_wm_surface_state.c +++ b/src/gallium/drivers/i965/brw_wm_surface_state.c @@ -40,31 +40,40 @@ -static void +static enum pipe_error brw_update_texture_surface( struct brw_context *brw, struct brw_texture *tex, - GLuint surf ) + struct brw_winsys_buffer **bo_out) { - brw->wm.surf_bo[surf] = brw_search_cache(&brw->surface_cache, - BRW_SS_SURFACE, - &tex->ss, sizeof tex->ss, - &tex->bo, 1, - NULL); - - if (brw->wm.surf_bo[surf] == NULL) { - brw->wm.surf_bo[surf] = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE, - &tex->ss, sizeof tex->ss, - &tex->bo, 1, - &tex->ss, sizeof tex->ss, - NULL, NULL); + enum pipe_error ret; + + if (brw_search_cache(&brw->surface_cache, + BRW_SS_SURFACE, + &tex->ss, sizeof tex->ss, + &tex->bo, 1, + NULL, + bo_out)) + return PIPE_OK; + + ret = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE, + &tex->ss, sizeof tex->ss, + &tex->bo, 1, + &tex->ss, sizeof tex->ss, + NULL, NULL, + bo_out); + if (ret) + return ret; - /* Emit relocation to surface contents */ - brw->sws->bo_emit_reloc(brw->wm.surf_bo[surf], - BRW_USAGE_SAMPLER, - 0, - offsetof(struct brw_surface_state, ss1), - tex->bo); - } + /* Emit relocation to surface contents */ + ret = brw->sws->bo_emit_reloc(*bo_out, + BRW_USAGE_SAMPLER, + 0, + offsetof(struct brw_surface_state, ss1), + tex->bo); + if (ret) + return ret; + + return PIPE_OK; } @@ -79,13 +88,14 @@ brw_update_texture_surface( struct brw_context *brw, * While it is only used for the front/back buffer currently, it should be * usable for further buffers when doing ARB_draw_buffer support. */ -static void -brw_update_renderbuffer_surface(struct brw_context *brw, - struct brw_surface *surface, - unsigned int unit) +static enum pipe_error +brw_update_render_surface(struct brw_context *brw, + struct brw_surface *surface, + struct brw_winsys_buffer **bo_out) { struct brw_surf_ss0 blend_ss0 = brw->curr.blend->ss0; struct brw_surface_state ss; + enum pipe_error ret; /* Surfaces are potentially shared between contexts, so can't * scribble the in-place ss0 value in the surface. @@ -98,30 +108,35 @@ brw_update_renderbuffer_surface(struct brw_context *brw, ss.ss0.writedisable_red = blend_ss0.writedisable_red; ss.ss0.writedisable_alpha = blend_ss0.writedisable_alpha; - brw->sws->bo_unreference(brw->wm.surf_bo[unit]); - brw->wm.surf_bo[unit] = brw_search_cache(&brw->surface_cache, - BRW_SS_SURFACE, - &ss, sizeof(ss), - &surface->bo, 1, - NULL); - - if (brw->wm.surf_bo[unit] == NULL) { - - brw->wm.surf_bo[unit] = brw_upload_cache(&brw->surface_cache, - BRW_SS_SURFACE, - &ss, sizeof ss, - &surface->bo, 1, - &ss, sizeof ss, - NULL, NULL); + if (brw_search_cache(&brw->surface_cache, + BRW_SS_SURFACE, + &ss, sizeof(ss), + &surface->bo, 1, + NULL, + bo_out)) + return PIPE_OK; + + ret = brw_upload_cache(&brw->surface_cache, + BRW_SS_SURFACE, + &ss, sizeof ss, + &surface->bo, 1, + &ss, sizeof ss, + NULL, NULL, + bo_out); + if (ret) + return ret; /* XXX: we will only be rendering to this surface: */ - brw->sws->bo_emit_reloc(brw->wm.surf_bo[unit], - BRW_USAGE_RENDER_TARGET, - ss.ss1.base_addr - surface->bo->offset[0], /* XXX */ - offsetof(struct brw_surface_state, ss1), - surface->bo); - } + ret = brw->sws->bo_emit_reloc(*bo_out, + BRW_USAGE_RENDER_TARGET, + ss.ss1.base_addr - surface->bo->offset[0], /* XXX */ + offsetof(struct brw_surface_state, ss1), + surface->bo); + if (ret) + return ret; + + return PIPE_OK; } @@ -129,60 +144,60 @@ brw_update_renderbuffer_surface(struct brw_context *brw, * Constructs the binding table for the WM surface state, which maps unit * numbers to surface state objects. */ -static struct brw_winsys_buffer * -brw_wm_get_binding_table(struct brw_context *brw) +static enum pipe_error +brw_wm_get_binding_table(struct brw_context *brw, + struct brw_winsys_buffer **bo_out ) { - struct brw_winsys_buffer *bind_bo; + enum pipe_error ret; + uint32_t data[BRW_WM_MAX_SURF]; + GLuint data_size = brw->wm.nr_surfaces * sizeof data[0]; + int i; assert(brw->wm.nr_surfaces <= BRW_WM_MAX_SURF); + assert(brw->wm.nr_surfaces > 0); /* Note there is no key for this search beyond the values in the * relocation array: */ - bind_bo = brw_search_cache(&brw->surface_cache, BRW_SS_SURF_BIND, - NULL, 0, - brw->wm.surf_bo, brw->wm.nr_surfaces, - NULL); - - if (bind_bo == NULL) { - uint32_t data[BRW_WM_MAX_SURF]; - GLuint data_size = brw->wm.nr_surfaces * sizeof data[0]; - int i; - - for (i = 0; i < brw->wm.nr_surfaces; i++) - data[i] = brw->wm.surf_bo[i]->offset[0]; - - bind_bo = brw_upload_cache( &brw->surface_cache, BRW_SS_SURF_BIND, - NULL, 0, - brw->wm.surf_bo, brw->wm.nr_surfaces, - data, data_size, - NULL, NULL); - - /* Emit binding table relocations to surface state */ - for (i = 0; i < brw->wm.nr_surfaces; i++) { - brw->sws->bo_emit_reloc(bind_bo, - BRW_USAGE_STATE, - 0, - i * sizeof(GLuint), - brw->wm.surf_bo[i]); - } + if (brw_search_cache(&brw->surface_cache, BRW_SS_SURF_BIND, + NULL, 0, + brw->wm.surf_bo, + brw->wm.nr_surfaces, + NULL, + bo_out)) + return PIPE_OK; + + for (i = 0; i < brw->wm.nr_surfaces; i++) + data[i] = brw->wm.surf_bo[i]->offset[0]; + + ret = brw_upload_cache( &brw->surface_cache, BRW_SS_SURF_BIND, + NULL, 0, + brw->wm.surf_bo, brw->wm.nr_surfaces, + data, data_size, + NULL, NULL, + bo_out); + if (ret) + return ret; + + /* Emit binding table relocations to surface state */ + for (i = 0; i < brw->wm.nr_surfaces; i++) { + ret = brw->sws->bo_emit_reloc(*bo_out, + BRW_USAGE_STATE, + 0, + i * sizeof(GLuint), + brw->wm.surf_bo[i]); + if (ret) + return ret; } - return bind_bo; + return PIPE_OK; } -static int prepare_wm_surfaces(struct brw_context *brw ) +static enum pipe_error prepare_wm_surfaces(struct brw_context *brw ) { - GLuint i; + enum pipe_error ret; int nr_surfaces = 0; - - /* Unreference old buffers - */ - for (i = 0; i < brw->wm.nr_surfaces; i++) { - brw->sws->bo_unreference(brw->wm.surf_bo[i]); - brw->wm.surf_bo[i] = NULL; - } - + GLuint i; /* PIPE_NEW_COLOR_BUFFERS | PIPE_NEW_BLEND * @@ -192,38 +207,51 @@ static int prepare_wm_surfaces(struct brw_context *brw ) * XXX: no color buffer case */ for (i = 0; i < brw->curr.fb.nr_cbufs; i++) { - brw_update_renderbuffer_surface(brw, - brw_surface(brw->curr.fb.cbufs[i]), - nr_surfaces++); + ret = brw_update_render_surface(brw, + brw_surface(brw->curr.fb.cbufs[i]), + &brw->wm.surf_bo[nr_surfaces++]); + if (ret) + return ret; } /* PIPE_NEW_TEXTURE */ for (i = 0; i < brw->curr.num_textures; i++) { - brw_update_texture_surface(brw, - brw_texture(brw->curr.texture[i]), - nr_surfaces++); + ret = brw_update_texture_surface(brw, + brw_texture(brw->curr.texture[i]), + &brw->wm.surf_bo[nr_surfaces++]); + if (ret) + return ret; } /* PIPE_NEW_FRAGMENT_CONSTANTS */ #if 0 if (brw->curr.fragment_constants) { - brw_update_fragment_constant_surface(brw, - brw->curr.fragment_constants, - nr_surfaces++); + ret = brw_update_fragment_constant_surface(brw, + brw->curr.fragment_constants, + &brw->wm.surf_bo[nr_surfaces++]); + if (ret) + return ret; } #endif if (brw->wm.nr_surfaces != nr_surfaces) { + + /* Unreference any left-over old buffers + */ + for (i = nr_surfaces; i < brw->wm.nr_surfaces; i++) + bo_reference(&brw->wm.surf_bo[i], NULL); + brw->wm.nr_surfaces = nr_surfaces; brw->state.dirty.brw |= BRW_NEW_NR_WM_SURFACES; } - brw->sws->bo_unreference(brw->wm.bind_bo); - brw->wm.bind_bo = brw_wm_get_binding_table(brw); + ret = brw_wm_get_binding_table(brw, &brw->wm.bind_bo); + if (ret) + return ret; - return 0; + return PIPE_OK; } const struct brw_tracked_state brw_wm_surfaces = { diff --git a/src/gallium/winsys/drm/i965/xlib/xlib_i965.c b/src/gallium/winsys/drm/i965/xlib/xlib_i965.c index b1edca818a1..fc465d7c143 100644 --- a/src/gallium/winsys/drm/i965/xlib/xlib_i965.c +++ b/src/gallium/winsys/drm/i965/xlib/xlib_i965.c @@ -134,11 +134,12 @@ const char *data_types[BRW_DATA_MAX] = }; -static struct brw_winsys_buffer * +static enum pipe_error xlib_brw_bo_alloc( struct brw_winsys_screen *sws, - enum brw_buffer_type type, - unsigned size, - unsigned alignment ) + enum brw_buffer_type type, + unsigned size, + unsigned alignment, + struct brw_winsys_buffer **bo_out ) { struct xlib_brw_winsys *xbw = xlib_brw_winsys(sws); struct xlib_brw_buffer *buf; @@ -148,12 +149,13 @@ xlib_brw_bo_alloc( struct brw_winsys_screen *sws, buf = CALLOC_STRUCT(xlib_brw_buffer); if (!buf) - return NULL; + return PIPE_ERROR_OUT_OF_MEMORY; + + pipe_reference_init(&buf->base.reference, 1); buf->offset = align(xbw->offset, alignment); buf->type = type; buf->virtual = MALLOC(size); - buf->cheesy_refcount = 1; buf->base.offset = &buf->offset; /* hmm, cheesy */ buf->base.size = size; @@ -161,36 +163,25 @@ xlib_brw_bo_alloc( struct brw_winsys_screen *sws, if (xbw->offset > MAX_VRAM) goto err; - return &buf->base; + /* XXX: possibly rentrant call to bo_destroy: + */ + bo_reference(bo_out, &buf->base); + return PIPE_OK; err: assert(0); + FREE(buf->virtual); FREE(buf); - return NULL; -} - -static void -xlib_brw_bo_reference( struct brw_winsys_buffer *buffer ) -{ - struct xlib_brw_buffer *buf = xlib_brw_buffer(buffer); - - buf->cheesy_refcount++; + return PIPE_ERROR_OUT_OF_MEMORY; } static void -xlib_brw_bo_unreference( struct brw_winsys_buffer *buffer ) +xlib_brw_bo_destroy( struct brw_winsys_buffer *buffer ) { struct xlib_brw_buffer *buf = xlib_brw_buffer(buffer); - /* As a special favor in this call only, buffer is allowed to be - * NULL: - */ - if (buffer == NULL) - return; - - if (--buf->cheesy_refcount == 0) { - FREE(buffer); - } + FREE(buf->virtual); + FREE(buf); } static int @@ -378,8 +369,7 @@ xlib_create_brw_winsys_screen( void ) ws->base.destroy = xlib_brw_winsys_destroy; ws->base.bo_alloc = xlib_brw_bo_alloc; - ws->base.bo_reference = xlib_brw_bo_reference; - ws->base.bo_unreference = xlib_brw_bo_unreference; + ws->base.bo_destroy = xlib_brw_bo_destroy; ws->base.bo_emit_reloc = xlib_brw_bo_emit_reloc; ws->base.bo_exec = xlib_brw_bo_exec; ws->base.bo_subdata = xlib_brw_bo_subdata;