summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKeith Whitwell <[email protected]>2007-11-15 09:59:33 +0000
committerMichel Dänzer <[email protected]>2007-11-26 17:10:26 +0100
commit718d2dfbbddbca3bcaebbd2b57f9e72ca594991d (patch)
tree9711055b0007374e9a1ab9cce69838de44ff31bc /src
parent0967e1270d3b3bc0917fb841314ebb8d04766746 (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.c49
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_batchbuffer.c2
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_batchbuffer.h3
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_context.h1
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_screen.h1
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_tris.c3
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;