diff options
author | Keith Whitwell <[email protected]> | 2007-11-15 09:59:33 +0000 |
---|---|---|
committer | Michel Dänzer <[email protected]> | 2007-11-26 17:10:26 +0100 |
commit | 718d2dfbbddbca3bcaebbd2b57f9e72ca594991d (patch) | |
tree | 9711055b0007374e9a1ab9cce69838de44ff31bc /src | |
parent | 0967e1270d3b3bc0917fb841314ebb8d04766746 (diff) |
i915tex: Catch cases where not all state is emitted for a new batchbuffer.
This could lead to incorrect rendering or even lockups.
Diffstat (limited to 'src')
-rw-r--r-- | src/mesa/drivers/dri/i915tex/i915_vtbl.c | 49 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i915tex/intel_batchbuffer.c | 2 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i915tex/intel_batchbuffer.h | 3 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i915tex/intel_context.h | 1 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i915tex/intel_screen.h | 1 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i915tex/intel_tris.c | 3 |
6 files changed, 57 insertions, 2 deletions
diff --git a/src/mesa/drivers/dri/i915tex/i915_vtbl.c b/src/mesa/drivers/dri/i915tex/i915_vtbl.c index e911fc40084..dfa22794c0b 100644 --- a/src/mesa/drivers/dri/i915tex/i915_vtbl.c +++ b/src/mesa/drivers/dri/i915tex/i915_vtbl.c @@ -281,7 +281,7 @@ get_state_size(struct i915_hw_state *state) /* Push the state into the sarea and/or texture memory. */ static void -i915_emit_state(struct intel_context *intel) +i915_do_emit_state(struct intel_context *intel) { struct i915_context *i915 = i915_context(&intel->ctx); struct i915_hw_state *state = i915->current; @@ -298,10 +298,33 @@ i915_emit_state(struct intel_context *intel) */ intel_batchbuffer_require_space(intel->batch, get_state_size(state), 0); + + /* Workaround. There are cases I haven't been able to track down + * where we aren't emitting a full state at the start of a new + * batchbuffer. This code spots that we are on a new batchbuffer + * and forces a full state emit no matter what. + * + * In the normal case state->emitted is already zero, this code is + * another set of checks to make sure it really is. + */ + if (intel->batch->id != intel->last_state_batch_id || + intel->batch->map == intel->batch->ptr) + { + state->emitted = 0; + intel_batchbuffer_require_space(intel->batch, get_state_size(state), 0); + } + /* Do this here as we may have flushed the batchbuffer above, * causing more state to be dirty! */ dirty = get_dirty(state); + state->emitted |= dirty; + assert(get_dirty(state) == 0); + + if (intel->batch->id != intel->last_state_batch_id) { + assert(dirty & I915_UPLOAD_CTX); + intel->last_state_batch_id = intel->batch->id; + } if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "%s dirty: %x\n", __FUNCTION__, dirty); @@ -424,7 +447,29 @@ i915_emit_state(struct intel_context *intel) i915_disassemble_program(state->Program, state->ProgramSize); } - state->emitted |= dirty; + intel->batch->dirty_state &= ~dirty; +} + +static void +i915_emit_state(struct intel_context *intel) +{ + struct i915_context *i915 = i915_context(&intel->ctx); + + i915_do_emit_state( intel ); + + /* Second chance - catch batchbuffer wrap in the middle of state + * emit. This shouldn't happen but it has been observed in + * testing. + */ + if (get_dirty( i915->current )) { + /* Force a full re-emit if this happens. + */ + i915->current->emitted = 0; + i915_do_emit_state( intel ); + } + + assert(get_dirty(i915->current) == 0); + assert((intel->batch->dirty_state & (1<<1)) == 0); } static void diff --git a/src/mesa/drivers/dri/i915tex/intel_batchbuffer.c b/src/mesa/drivers/dri/i915tex/intel_batchbuffer.c index c92b83bcb3a..d7079a2851c 100644 --- a/src/mesa/drivers/dri/i915tex/intel_batchbuffer.c +++ b/src/mesa/drivers/dri/i915tex/intel_batchbuffer.c @@ -118,6 +118,8 @@ intel_batchbuffer_reset(struct intel_batchbuffer *batch) batch->map = driBOMap(batch->buffer, DRM_BO_FLAG_WRITE, 0); batch->ptr = batch->map; + batch->dirty_state = ~0; + batch->id = batch->intel->intelScreen->batch_id++; } /*====================================================================== diff --git a/src/mesa/drivers/dri/i915tex/intel_batchbuffer.h b/src/mesa/drivers/dri/i915tex/intel_batchbuffer.h index 59261f72741..76e5b3043cf 100644 --- a/src/mesa/drivers/dri/i915tex/intel_batchbuffer.h +++ b/src/mesa/drivers/dri/i915tex/intel_batchbuffer.h @@ -38,6 +38,9 @@ struct intel_batchbuffer struct buffer_reloc reloc[MAX_RELOCS]; GLuint nr_relocs; GLuint size; + + GLuint dirty_state; + GLuint id; }; struct intel_batchbuffer *intel_batchbuffer_alloc(struct intel_context diff --git a/src/mesa/drivers/dri/i915tex/intel_context.h b/src/mesa/drivers/dri/i915tex/intel_context.h index 5fc8eb3e382..6f893bd70b2 100644 --- a/src/mesa/drivers/dri/i915tex/intel_context.h +++ b/src/mesa/drivers/dri/i915tex/intel_context.h @@ -189,6 +189,7 @@ struct intel_context struct _DriFenceObject *first_swap_fence; struct intel_batchbuffer *batch; + GLuint last_state_batch_id; struct { diff --git a/src/mesa/drivers/dri/i915tex/intel_screen.h b/src/mesa/drivers/dri/i915tex/intel_screen.h index bac43aadddf..760a1eb7f33 100644 --- a/src/mesa/drivers/dri/i915tex/intel_screen.h +++ b/src/mesa/drivers/dri/i915tex/intel_screen.h @@ -95,6 +95,7 @@ typedef struct struct _DriBufferPool *regionPool; struct _DriBufferPool *staticPool; unsigned int maxBatchSize; + unsigned batch_id; GLboolean havePools; } intelScreenPrivate; diff --git a/src/mesa/drivers/dri/i915tex/intel_tris.c b/src/mesa/drivers/dri/i915tex/intel_tris.c index 5fe3d4561fc..06dd505e93e 100644 --- a/src/mesa/drivers/dri/i915tex/intel_tris.c +++ b/src/mesa/drivers/dri/i915tex/intel_tris.c @@ -111,6 +111,9 @@ intelStartInlinePrimitive(struct intel_context *intel, BEGIN_BATCH(2, batch_flags); OUT_BATCH(0); + assert(intel->batch->id == intel->last_state_batch_id); + assert((intel->batch->dirty_state & (1<<1)) == 0); + intel->prim.start_ptr = intel->batch->ptr; intel->prim.primitive = prim; intel->prim.flush = intel_flush_inline_primitive; |