summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeith Whitwell <[email protected]>2006-09-07 19:05:40 +0000
committerKeith Whitwell <[email protected]>2006-09-07 19:05:40 +0000
commit493b2ddecb47fdacc4b73d9c9a3ba2e46489105f (patch)
tree011c2f4570d336020c0db6562d294d638a981531
parentc26f36c830cc6df1093a145eb43645f535004eb7 (diff)
Cope with memory pool fragmentation by allowing a second attempt at
rendering operations to take place after evicting all resident buffers. Cope better with memory allocation failures throughout the driver and improve tracking of failures.
-rw-r--r--src/mesa/drivers/dri/i965/brw_draw.c62
-rw-r--r--src/mesa/drivers/dri/i965/brw_state_pool.c1
-rw-r--r--src/mesa/drivers/dri/i965/brw_vs_tnl.c2
-rw-r--r--src/mesa/drivers/dri/i965/bufmgr.h11
-rw-r--r--src/mesa/drivers/dri/i965/bufmgr_fake.c156
-rw-r--r--src/mesa/drivers/dri/i965/intel_batchbuffer.c23
-rw-r--r--src/mesa/drivers/dri/i965/intel_batchbuffer.h4
-rw-r--r--src/mesa/drivers/dri/i965/intel_context.c42
-rw-r--r--src/mesa/drivers/dri/i965/intel_mipmap_tree.c36
-rw-r--r--src/mesa/drivers/dri/i965/intel_mipmap_tree.h14
-rw-r--r--src/mesa/drivers/dri/i965/intel_regions.c63
-rw-r--r--src/mesa/drivers/dri/i965/intel_regions.h14
-rw-r--r--src/mesa/drivers/dri/i965/intel_tex_validate.c47
13 files changed, 321 insertions, 154 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c
index 104404b3019..02c24574232 100644
--- a/src/mesa/drivers/dri/i965/brw_draw.c
+++ b/src/mesa/drivers/dri/i965/brw_draw.c
@@ -265,14 +265,14 @@ static GLboolean check_fallbacks( struct brw_context *brw,
}
-GLboolean brw_draw_prims( GLcontext *ctx,
- const struct gl_client_array *arrays[],
- const struct brw_draw_prim *prim,
- GLuint nr_prims,
- const struct brw_draw_index_buffer *ib,
- GLuint min_index,
- GLuint max_index,
- GLuint flags )
+static GLboolean brw_try_draw_prims( GLcontext *ctx,
+ const struct gl_client_array *arrays[],
+ const struct brw_draw_prim *prim,
+ GLuint nr_prims,
+ const struct brw_draw_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index,
+ GLuint flags )
{
struct intel_context *intel = intel_context(ctx);
struct brw_context *brw = brw_context(ctx);
@@ -338,9 +338,12 @@ GLboolean brw_draw_prims( GLcontext *ctx,
* way around this, as not every flush is due to a buffer filling
* up.
*/
- intel_batchbuffer_flush( brw->intel.batch );
+ if (!intel_batchbuffer_flush( brw->intel.batch )) {
+ DBG("%s intel_batchbuffer_flush failed\n", __FUNCTION__);
+ retval = GL_FALSE;
+ }
- if (intel->thrashing) {
+ if (retval && intel->thrashing) {
bmSetFence(intel);
}
@@ -359,9 +362,48 @@ GLboolean brw_draw_prims( GLcontext *ctx,
}
UNLOCK_HARDWARE(intel);
+
+ if (!retval)
+ _mesa_printf("%s failed\n", __FUNCTION__);
+
return retval;
}
+
+GLboolean brw_draw_prims( GLcontext *ctx,
+ const struct gl_client_array *arrays[],
+ const struct brw_draw_prim *prim,
+ GLuint nr_prims,
+ const struct brw_draw_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index,
+ GLuint flags )
+{
+ struct intel_context *intel = intel_context(ctx);
+ GLboolean retval;
+
+ retval = brw_try_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index, flags);
+
+
+ if (!retval && bmError(intel)) {
+
+ DBG("retrying\n");
+ /* This looks like out-of-memory but potentially we have
+ * situation where there is enough memory but it has become
+ * fragmented. Clear out all heaps and start from scratch by
+ * faking a contended lock event: (done elsewhere)
+ */
+
+ /* Then try a second time only to upload textures and draw the
+ * primitives:
+ */
+ retval = brw_try_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index, flags);
+ }
+
+ return retval;
+}
+
+
static void brw_invalidate_vbo_cb( struct intel_context *intel, void *ptr )
{
/* nothing to do, we don't rely on the contents being preserved */
diff --git a/src/mesa/drivers/dri/i965/brw_state_pool.c b/src/mesa/drivers/dri/i965/brw_state_pool.c
index d905da80002..b9926f2a5d7 100644
--- a/src/mesa/drivers/dri/i965/brw_state_pool.c
+++ b/src/mesa/drivers/dri/i965/brw_state_pool.c
@@ -47,6 +47,7 @@ GLboolean brw_pool_alloc( struct brw_mem_pool *pool,
size = (size + 3) & ~3;
if (pool->offset + fixup + size >= pool->size) {
+ _mesa_printf("%s failed\n", __FUNCTION__);
assert(0);
exit(0);
}
diff --git a/src/mesa/drivers/dri/i965/brw_vs_tnl.c b/src/mesa/drivers/dri/i965/brw_vs_tnl.c
index 107473eda52..c1099d4c676 100644
--- a/src/mesa/drivers/dri/i965/brw_vs_tnl.c
+++ b/src/mesa/drivers/dri/i965/brw_vs_tnl.c
@@ -340,7 +340,7 @@ static struct ureg get_temp( struct tnl_program *p )
int bit = ffs( ~p->temp_in_use );
if (!bit) {
fprintf(stderr, "%s: out of temporaries\n", __FILE__);
- abort();
+ assert(0);
}
if (bit > p->program->Base.NumTemporaries)
diff --git a/src/mesa/drivers/dri/i965/bufmgr.h b/src/mesa/drivers/dri/i965/bufmgr.h
index 63e1011a768..ab5d56a231a 100644
--- a/src/mesa/drivers/dri/i965/bufmgr.h
+++ b/src/mesa/drivers/dri/i965/bufmgr.h
@@ -118,20 +118,20 @@ void bmBufferSetInvalidateCB(struct intel_context *,
* client would, so flags here is more proscriptive than the usage
* values in the ARB_vbo interface:
*/
-void bmBufferData(struct intel_context *,
+int bmBufferData(struct intel_context *,
struct buffer *buf,
unsigned size,
const void *data,
unsigned flags );
-void bmBufferSubData(struct intel_context *,
+int bmBufferSubData(struct intel_context *,
struct buffer *buf,
unsigned offset,
unsigned size,
const void *data );
-void bmBufferDataAUB(struct intel_context *,
+int bmBufferDataAUB(struct intel_context *,
struct buffer *buf,
unsigned size,
const void *data,
@@ -139,7 +139,7 @@ void bmBufferDataAUB(struct intel_context *,
unsigned aubtype,
unsigned aubsubtype );
-void bmBufferSubDataAUB(struct intel_context *,
+int bmBufferSubDataAUB(struct intel_context *,
struct buffer *buf,
unsigned offset,
unsigned size,
@@ -183,6 +183,9 @@ int bmValidateBuffers( struct intel_context * );
void bmReleaseBuffers( struct intel_context * );
+GLboolean bmError( struct intel_context * );
+void bmEvictAll( struct intel_context * );
+
/* This functionality is used by the buffer manager, not really sure
* if we need to be exposing it in this way, probably libdrm will
* offer equivalent calls.
diff --git a/src/mesa/drivers/dri/i965/bufmgr_fake.c b/src/mesa/drivers/dri/i965/bufmgr_fake.c
index c6bdf8ecb89..34b62cd12c7 100644
--- a/src/mesa/drivers/dri/i965/bufmgr_fake.c
+++ b/src/mesa/drivers/dri/i965/bufmgr_fake.c
@@ -268,7 +268,7 @@ static void set_dirty( struct intel_context *intel,
}
-static int evict_lru( struct intel_context *intel, GLuint max_fence )
+static int evict_lru( struct intel_context *intel, GLuint max_fence, GLuint *pool )
{
struct bufmgr *bm = intel->bm;
struct block *block, *tmp;
@@ -292,6 +292,7 @@ static int evict_lru( struct intel_context *intel, GLuint max_fence )
block->buf->block = NULL;
free_block(intel, block);
+ *pool = i;
return 1;
}
}
@@ -305,7 +306,7 @@ static int evict_lru( struct intel_context *intel, GLuint max_fence )
#define foreach_s_rev(ptr, t, list) \
for(ptr=(list)->prev,t=(ptr)->prev; list != ptr; ptr=t, t=(t)->prev)
-static int evict_mru( struct intel_context *intel)
+static int evict_mru( struct intel_context *intel, GLuint *pool )
{
struct bufmgr *bm = intel->bm;
struct block *block, *tmp;
@@ -325,6 +326,7 @@ static int evict_mru( struct intel_context *intel)
block->buf->block = NULL;
free_block(intel, block);
+ *pool = i;
return 1;
}
}
@@ -432,6 +434,8 @@ static GLboolean alloc_block( struct intel_context *intel,
struct bufmgr *bm = intel->bm;
int i;
+ assert(intel->locked);
+
DBG("%s 0x%x bytes (%s)\n", __FUNCTION__, buf->size, buf->name);
for (i = 0; i < bm->nr_pools; i++) {
@@ -453,6 +457,7 @@ static GLboolean alloc_block( struct intel_context *intel,
static GLboolean evict_and_alloc_block( struct intel_context *intel,
struct buffer *buf )
{
+ GLuint pool;
struct bufmgr *bm = intel->bm;
assert(buf->block == NULL);
@@ -478,16 +483,16 @@ static GLboolean evict_and_alloc_block( struct intel_context *intel,
/* Look for memory blocks not used for >1 frame:
*/
- while (evict_lru(intel, intel->second_last_swap_fence))
- if (alloc_block(intel, buf))
+ while (evict_lru(intel, intel->second_last_swap_fence, &pool))
+ if (alloc_from_pool(intel, pool, buf))
return GL_TRUE;
/* If we're not thrashing, allow lru eviction to dig deeper into
* recently used textures. We'll probably be thrashing soon:
*/
if (!intel->thrashing) {
- while (evict_lru(intel, 0))
- if (alloc_block(intel, buf))
+ while (evict_lru(intel, 0, &pool))
+ if (alloc_from_pool(intel, pool, buf))
return GL_TRUE;
}
@@ -514,7 +519,7 @@ static GLboolean evict_and_alloc_block( struct intel_context *intel,
if (!is_empty_list(&bm->on_hardware)) {
bmSetFence(intel);
- if (!is_empty_list(&bm->fenced)) {
+ while (!is_empty_list(&bm->fenced)) {
GLuint fence = bm->fenced.next->fence;
bmFinishFence(intel, fence);
}
@@ -528,10 +533,15 @@ static GLboolean evict_and_alloc_block( struct intel_context *intel,
return GL_TRUE;
}
- while (evict_mru(intel))
- if (alloc_block(intel, buf))
+ while (evict_mru(intel, &pool))
+ if (alloc_from_pool(intel, pool, buf))
return GL_TRUE;
+ DBG("%s 0x%x bytes failed\n", __FUNCTION__, buf->size);
+
+ assert(is_empty_list(&bm->on_hardware));
+ assert(is_empty_list(&bm->fenced));
+
return GL_FALSE;
}
@@ -742,13 +752,14 @@ static void wait_quiescent(struct intel_context *intel,
/* If buffer size changes, free and reallocate. Otherwise update in
* place.
*/
-void bmBufferData(struct intel_context *intel,
- struct buffer *buf,
- unsigned size,
- const void *data,
- unsigned flags )
+int bmBufferData(struct intel_context *intel,
+ struct buffer *buf,
+ unsigned size,
+ const void *data,
+ unsigned flags )
{
struct bufmgr *bm = intel->bm;
+ int retval = 0;
LOCK(bm);
{
@@ -780,13 +791,19 @@ void bmBufferData(struct intel_context *intel,
buf->size = size;
if (buf->block) {
- assert (buf->block->mem->size == size);
+ assert (buf->block->mem->size >= size);
}
if (buf->flags & (BM_NO_BACKING_STORE|BM_NO_EVICT)) {
- if (data != NULL) {
- if (!buf->block && !evict_and_alloc_block(intel, buf))
- assert(0);
+
+ assert(intel->locked || data == NULL);
+
+ if (data != NULL) {
+ if (!buf->block && !evict_and_alloc_block(intel, buf)) {
+ bm->fail = 1;
+ retval = -1;
+ goto out;
+ }
wait_quiescent(intel, buf->block);
@@ -810,22 +827,25 @@ void bmBufferData(struct intel_context *intel,
}
}
}
+ out:
UNLOCK(bm);
+ return retval;
}
/* Update the buffer in place, in whatever space it is currently resident:
*/
-void bmBufferSubData(struct intel_context *intel,
+int bmBufferSubData(struct intel_context *intel,
struct buffer *buf,
unsigned offset,
unsigned size,
const void *data )
{
struct bufmgr *bm = intel->bm;
+ int retval;
if (size == 0)
- return;
+ return 0;
LOCK(bm);
{
@@ -834,8 +854,14 @@ void bmBufferSubData(struct intel_context *intel,
assert(offset+size <= buf->size);
if (buf->flags & (BM_NO_EVICT|BM_NO_BACKING_STORE)) {
- if (!buf->block && !evict_and_alloc_block(intel, buf))
- assert(0);
+
+ assert(intel->locked);
+
+ if (!buf->block && !evict_and_alloc_block(intel, buf)) {
+ bm->fail = 1;
+ retval = -1;
+ goto out;
+ }
if (!(buf->flags & BM_NO_FENCE_SUBDATA))
wait_quiescent(intel, buf->block);
@@ -854,12 +880,14 @@ void bmBufferSubData(struct intel_context *intel,
do_memcpy(buf->backing_store + offset, data, size);
}
}
+ out:
UNLOCK(bm);
+ return retval;
}
-void bmBufferDataAUB(struct intel_context *intel,
+int bmBufferDataAUB(struct intel_context *intel,
struct buffer *buf,
unsigned size,
const void *data,
@@ -867,14 +895,14 @@ void bmBufferDataAUB(struct intel_context *intel,
unsigned aubtype,
unsigned aubsubtype )
{
- bmBufferData(intel, buf, size, data, flags);
+ int retval = bmBufferData(intel, buf, size, data, flags);
/* This only works because in this version of the buffer manager we
* allocate all buffers statically in agp space and so can emit the
* uploads to the aub file with the correct offsets as they happen.
*/
- if (data && intel->aub_file) {
+ if (retval == 0 && data && intel->aub_file) {
if (buf->block && !buf->dirty) {
intel->vtbl.aub_gtt_data(intel,
@@ -886,10 +914,12 @@ void bmBufferDataAUB(struct intel_context *intel,
buf->aub_dirty = 0;
}
}
+
+ return retval;
}
-void bmBufferSubDataAUB(struct intel_context *intel,
+int bmBufferSubDataAUB(struct intel_context *intel,
struct buffer *buf,
unsigned offset,
unsigned size,
@@ -897,7 +927,7 @@ void bmBufferSubDataAUB(struct intel_context *intel,
unsigned aubtype,
unsigned aubsubtype )
{
- bmBufferSubData(intel, buf, offset, size, data);
+ int retval = bmBufferSubData(intel, buf, offset, size, data);
/* This only works because in this version of the buffer manager we
@@ -905,7 +935,7 @@ void bmBufferSubDataAUB(struct intel_context *intel,
* uploads to the aub file with the correct offsets as they happen.
*/
if (intel->aub_file) {
- if (buf->block && !buf->dirty)
+ if (retval == 0 && buf->block && !buf->dirty)
intel->vtbl.aub_gtt_data(intel,
buf->block->mem->ofs + offset,
((const char *)buf->block->virtual) + offset,
@@ -913,6 +943,8 @@ void bmBufferSubDataAUB(struct intel_context *intel,
aubtype,
aubsubtype);
}
+
+ return retval;
}
void bmUnmapBufferAUB( struct intel_context *intel,
@@ -1016,8 +1048,12 @@ void *bmMapBuffer( struct intel_context *intel,
retval = NULL;
}
else if (buf->flags & (BM_NO_BACKING_STORE|BM_NO_EVICT)) {
+
+ assert(intel->locked);
+
if (!buf->block && !evict_and_alloc_block(intel, buf)) {
_mesa_printf("%s: alloc failed\n", __FUNCTION__);
+ bm->fail = 1;
retval = NULL;
}
else {
@@ -1116,6 +1152,7 @@ int bmValidateBuffers( struct intel_context *intel )
LOCK(bm);
{
DBG("%s fail %d\n", __FUNCTION__, bm->fail);
+ assert(intel->locked);
if (!bm->fail) {
struct block *block, *tmp;
@@ -1170,11 +1207,13 @@ int bmValidateBuffers( struct intel_context *intel )
}
retval = !bm->fail;
- bm->fail = 0;
- assert(is_empty_list(&bm->referenced));
}
UNLOCK(bm);
+
+ if (!retval)
+ _mesa_printf("%s failed\n", __FUNCTION__);
+
return retval;
}
@@ -1188,6 +1227,7 @@ void bmReleaseBuffers( struct intel_context *intel )
LOCK(bm);
{
struct block *block, *tmp;
+ assert(intel->locked);
foreach_s (block, tmp, &bm->referenced) {
@@ -1220,8 +1260,6 @@ void bmReleaseBuffers( struct intel_context *intel )
block->referenced = 0;
}
-
- bm->fail = 0;
}
UNLOCK(bm);
}
@@ -1310,13 +1348,54 @@ void bm_fake_NotifyContendedLockTake( struct intel_context *intel )
assert(is_empty_list(&bm->referenced));
bm->need_fence = 1;
+ bm->fail = 0;
+ bmFinishFence(intel, bmSetFence(intel));
+
+ assert(is_empty_list(&bm->fenced));
+ assert(is_empty_list(&bm->on_hardware));
+
+ for (i = 0; i < bm->nr_pools; i++) {
+ if (!(bm->pool[i].flags & BM_NO_EVICT)) {
+ foreach_s(block, tmp, &bm->pool[i].lru) {
+ assert(bmTestFence(intel, block->fence));
+ set_dirty(intel, block->buf);
+ }
+ }
+ }
+ }
+ UNLOCK(bm);
+}
+
+
+
+void bmEvictAll( struct intel_context *intel )
+{
+ struct bufmgr *bm = intel->bm;
+
+ LOCK(bm);
+ {
+ struct block *block, *tmp;
+ GLuint i;
+
+ DBG("%s\n", __FUNCTION__);
+
+ assert(is_empty_list(&bm->referenced));
+
+ bm->need_fence = 1;
+ bm->fail = 0;
bmFinishFence(intel, bmSetFence(intel));
+ assert(is_empty_list(&bm->fenced));
+ assert(is_empty_list(&bm->on_hardware));
+
for (i = 0; i < bm->nr_pools; i++) {
if (!(bm->pool[i].flags & BM_NO_EVICT)) {
foreach_s(block, tmp, &bm->pool[i].lru) {
assert(bmTestFence(intel, block->fence));
set_dirty(intel, block->buf);
+ block->buf->block = NULL;
+
+ free_block(intel, block);
}
}
}
@@ -1325,3 +1404,16 @@ void bm_fake_NotifyContendedLockTake( struct intel_context *intel )
}
+GLboolean bmError( struct intel_context *intel )
+{
+ struct bufmgr *bm = intel->bm;
+ GLboolean retval;
+
+ LOCK(bm);
+ {
+ retval = bm->fail;
+ }
+ UNLOCK(bm);
+
+ return retval;
+}
diff --git a/src/mesa/drivers/dri/i965/intel_batchbuffer.c b/src/mesa/drivers/dri/i965/intel_batchbuffer.c
index 7510ac5b920..636f3630950 100644
--- a/src/mesa/drivers/dri/i965/intel_batchbuffer.c
+++ b/src/mesa/drivers/dri/i965/intel_batchbuffer.c
@@ -62,14 +62,15 @@ static void intel_batchbuffer_reset_cb( struct intel_context *intel,
batch->ptr = NULL;
}
-void intel_batchbuffer_map( struct intel_batchbuffer *batch )
+GLubyte *intel_batchbuffer_map( struct intel_batchbuffer *batch )
{
if (!batch->map) {
batch->map = bmMapBuffer(batch->intel, batch->buffer,
BM_MEM_AGP|BM_MEM_LOCAL|BM_CLIENT|BM_WRITE);
batch->ptr += (unsigned long)batch->map;
}
- assert(batch->map);
+
+ return batch->map;
}
void intel_batchbuffer_unmap( struct intel_batchbuffer *batch )
@@ -122,18 +123,19 @@ void intel_batchbuffer_free( struct intel_batchbuffer *batch )
#define MI_BATCH_BUFFER_END (0xA<<23)
-void intel_batchbuffer_flush( struct intel_batchbuffer *batch )
+GLboolean intel_batchbuffer_flush( struct intel_batchbuffer *batch )
{
struct intel_context *intel = batch->intel;
GLuint used = batch->ptr - (batch->map + batch->offset);
GLuint offset;
GLboolean ignore_cliprects = (batch->flags & INTEL_BATCH_CLIPRECTS) ? GL_FALSE : GL_TRUE;
+ GLint retval = GL_TRUE;
assert(intel->locked);
if (used == 0) {
bmReleaseBuffers( batch->intel );
- return;
+ return GL_TRUE;
}
/* Throw away non-effective packets.
@@ -148,7 +150,7 @@ void intel_batchbuffer_flush( struct intel_batchbuffer *batch )
sched_yield();
LOCK_HARDWARE(intel);
- return;
+ return GL_TRUE;
}
@@ -177,7 +179,10 @@ void intel_batchbuffer_flush( struct intel_batchbuffer *batch )
offset = bmBufferOffset(batch->intel, batch->buffer);
if (!bmValidateBuffers( batch->intel )) {
- assert(0);
+ assert(intel->locked);
+ bmReleaseBuffers( batch->intel );
+ retval = GL_FALSE;
+ goto out;
}
@@ -208,8 +213,14 @@ void intel_batchbuffer_flush( struct intel_batchbuffer *batch )
/* Reset the buffer:
*/
+ out:
intel_batchbuffer_reset( batch );
intel_batchbuffer_map( batch );
+
+ if (!retval)
+ DBG("%s failed\n", __FUNCTION__);
+
+ return retval;
}
diff --git a/src/mesa/drivers/dri/i965/intel_batchbuffer.h b/src/mesa/drivers/dri/i965/intel_batchbuffer.h
index d576e97291f..7a9ead3e373 100644
--- a/src/mesa/drivers/dri/i965/intel_batchbuffer.h
+++ b/src/mesa/drivers/dri/i965/intel_batchbuffer.h
@@ -57,10 +57,10 @@ struct intel_batchbuffer *intel_batchbuffer_alloc( struct intel_context *intel )
void intel_batchbuffer_free( struct intel_batchbuffer *batch );
-void intel_batchbuffer_flush( struct intel_batchbuffer *batch );
+GLboolean intel_batchbuffer_flush( struct intel_batchbuffer *batch );
void intel_batchbuffer_unmap( struct intel_batchbuffer *batch );
-void intel_batchbuffer_map( struct intel_batchbuffer *batch );
+GLubyte *intel_batchbuffer_map( struct intel_batchbuffer *batch );
/* Unlike bmBufferData, this currently requires the buffer be mapped.
diff --git a/src/mesa/drivers/dri/i965/intel_context.c b/src/mesa/drivers/dri/i965/intel_context.c
index e21c7d89b9d..59fc8073eee 100644
--- a/src/mesa/drivers/dri/i965/intel_context.c
+++ b/src/mesa/drivers/dri/i965/intel_context.c
@@ -536,6 +536,13 @@ GLboolean intelMakeCurrent(__DRIcontextPrivate *driContextPriv,
return GL_TRUE;
}
+
+static void lost_hardware( struct intel_context *intel )
+{
+ bm_fake_NotifyContendedLockTake( intel );
+ intel->vtbl.lost_hardware( intel );
+}
+
static void intelContendedLock( struct intel_context *intel, GLuint flags )
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
@@ -560,16 +567,7 @@ static void intelContendedLock( struct intel_context *intel, GLuint flags )
*/
if (sarea->ctxOwner != me) {
sarea->ctxOwner = me;
-
- /* Should also fence the frontbuffer even if ctxOwner doesn't
- * change:
- */
- bm_fake_NotifyContendedLockTake( intel );
-
-
- /*
- */
- intel->vtbl.lost_hardware( intel );
+ lost_hardware(intel);
}
/* Drawable changed?
@@ -606,19 +604,16 @@ void LOCK_HARDWARE( struct intel_context *intel )
intel->locked = 1;
if (intel->aub_wrap) {
- /* Should also fence the frontbuffer even if ctxOwner doesn't
- * change:
- */
bm_fake_NotifyContendedLockTake( intel );
-
- /*
- */
intel->vtbl.lost_hardware( intel );
intel->vtbl.aub_wrap(intel);
-
intel->aub_wrap = 0;
}
+ if (bmError(intel)) {
+ bmEvictAll(intel);
+ intel->vtbl.lost_hardware( intel );
+ }
/* Make sure nothing has been emitted prior to getting the lock:
*/
@@ -626,7 +621,18 @@ void LOCK_HARDWARE( struct intel_context *intel )
/* XXX: postpone, may not be needed:
*/
- intel_batchbuffer_map(intel->batch);
+ if (!intel_batchbuffer_map(intel->batch)) {
+ bmEvictAll(intel);
+ intel->vtbl.lost_hardware( intel );
+
+ /* This could only fail if the batchbuffer was greater in size
+ * than the available texture memory:
+ */
+ if (!intel_batchbuffer_map(intel->batch)) {
+ _mesa_printf("double failure to map batchbuffer\n");
+ assert(0);
+ }
+ }
}
diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
index ed19f70f430..8486086b274 100644
--- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
@@ -214,13 +214,13 @@ GLuint intel_miptree_image_offset(struct intel_mipmap_tree *mt,
/* Upload data for a particular image.
*/
-void intel_miptree_image_data(struct intel_context *intel,
- struct intel_mipmap_tree *dst,
- GLuint face,
- GLuint level,
- const void *src,
- GLuint src_row_pitch,
- GLuint src_image_pitch)
+GLboolean intel_miptree_image_data(struct intel_context *intel,
+ struct intel_mipmap_tree *dst,
+ GLuint face,
+ GLuint level,
+ const void *src,
+ GLuint src_row_pitch,
+ GLuint src_image_pitch)
{
GLuint depth = dst->level[level].depth;
GLuint dst_offset = intel_miptree_image_offset(dst, face, level);
@@ -229,17 +229,19 @@ void intel_miptree_image_data(struct intel_context *intel,
DBG("%s\n", __FUNCTION__);
for (i = 0; i < depth; i++) {
- intel_region_data(intel,
- dst->region,
- dst_offset + dst_depth_offset[i],
- 0,
- 0,
- src,
- src_row_pitch,
- 0, 0, /* source x,y */
- dst->level[level].width,
- dst->level[level].height);
+ if (!intel_region_data(intel,
+ dst->region,
+ dst_offset + dst_depth_offset[i],
+ 0,
+ 0,
+ src,
+ src_row_pitch,
+ 0, 0, /* source x,y */
+ dst->level[level].width,
+ dst->level[level].height))
+ return GL_FALSE;
src += src_image_pitch;
}
+ return GL_TRUE;
}
diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
index 483b87521f5..dbd7167b778 100644
--- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
+++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
@@ -147,13 +147,13 @@ void intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
/* Upload an image into a tree
*/
-void intel_miptree_image_data(struct intel_context *intel,
- struct intel_mipmap_tree *dst,
- GLuint face,
- GLuint level,
- const void *src,
- GLuint src_row_pitch,
- GLuint src_image_pitch);
+GLboolean intel_miptree_image_data(struct intel_context *intel,
+ struct intel_mipmap_tree *dst,
+ GLuint face,
+ GLuint level,
+ const void *src,
+ GLuint src_row_pitch,
+ GLuint src_image_pitch);
/* i915_mipmap_tree.c:
*/
diff --git a/src/mesa/drivers/dri/i965/intel_regions.c b/src/mesa/drivers/dri/i965/intel_regions.c
index 51495448ca9..53f05612377 100644
--- a/src/mesa/drivers/dri/i965/intel_regions.c
+++ b/src/mesa/drivers/dri/i965/intel_regions.c
@@ -52,6 +52,8 @@ GLubyte *intel_region_map(struct intel_context *intel, struct intel_region *regi
DBG("%s\n", __FUNCTION__);
if (!region->map_refcount++) {
region->map = bmMapBuffer(intel, region->buffer, 0);
+ if (!region->map)
+ region->map_refcount--;
}
return region->map;
@@ -198,15 +200,14 @@ void _mesa_copy_rect( GLubyte *dst,
*
* Currently always memcpy.
*/
-void intel_region_data(struct intel_context *intel,
- struct intel_region *dst,
- GLuint dst_offset,
- GLuint dstx, GLuint dsty,
- const void *src, GLuint src_pitch,
- GLuint srcx, GLuint srcy,
- GLuint width, GLuint height)
+GLboolean intel_region_data(struct intel_context *intel,
+ struct intel_region *dst,
+ GLuint dst_offset,
+ GLuint dstx, GLuint dsty,
+ const void *src, GLuint src_pitch,
+ GLuint srcx, GLuint srcy,
+ GLuint width, GLuint height)
{
-
DBG("%s\n", __FUNCTION__);
if (width == dst->pitch &&
@@ -216,29 +217,33 @@ void intel_region_data(struct intel_context *intel,
srcx == 0 &&
srcy == 0)
{
- bmBufferDataAUB(intel,
- dst->buffer,
- dst->cpp * width * dst->height,
- src,
- 0,
- 0, /* DW_NOTYPE */
- 0);
+ return (bmBufferDataAUB(intel,
+ dst->buffer,
+ dst->cpp * width * dst->height,
+ src, 0, 0, 0) == 0);
}
else {
- assert (dst_offset + dstx + width +
- (dsty + height - 1) * dst->pitch * dst->cpp <=
- dst->pitch * dst->cpp * dst->height);
-
- _mesa_copy_rect(intel_region_map(intel, dst) + dst_offset,
- dst->cpp,
- dst->pitch,
- dstx, dsty,
- width, height,
- src,
- src_pitch,
- srcx, srcy);
-
- intel_region_unmap(intel, dst);
+ GLubyte *map = intel_region_map(intel, dst);
+
+ if (map) {
+ assert (dst_offset + dstx + width +
+ (dsty + height - 1) * dst->pitch * dst->cpp <=
+ dst->pitch * dst->cpp * dst->height);
+
+ _mesa_copy_rect(map + dst_offset,
+ dst->cpp,
+ dst->pitch,
+ dstx, dsty,
+ width, height,
+ src,
+ src_pitch,
+ srcx, srcy);
+
+ intel_region_unmap(intel, dst);
+ return GL_TRUE;
+ }
+ else
+ return GL_FALSE;
}
}
diff --git a/src/mesa/drivers/dri/i965/intel_regions.h b/src/mesa/drivers/dri/i965/intel_regions.h
index 9f5483150c0..2413f0de33c 100644
--- a/src/mesa/drivers/dri/i965/intel_regions.h
+++ b/src/mesa/drivers/dri/i965/intel_regions.h
@@ -91,13 +91,13 @@ void intel_region_unmap(struct intel_context *intel,
/* Upload data to a rectangular sub-region
*/
-void intel_region_data(struct intel_context *intel,
- struct intel_region *dest,
- GLuint dest_offset,
- GLuint destx, GLuint desty,
- const void *src, GLuint src_stride,
- GLuint srcx, GLuint srcy,
- GLuint width, GLuint height);
+GLboolean intel_region_data(struct intel_context *intel,
+ struct intel_region *dest,
+ GLuint dest_offset,
+ GLuint destx, GLuint desty,
+ const void *src, GLuint src_stride,
+ GLuint srcx, GLuint srcy,
+ GLuint width, GLuint height);
/* Copy rectangular sub-regions
*/
diff --git a/src/mesa/drivers/dri/i965/intel_tex_validate.c b/src/mesa/drivers/dri/i965/intel_tex_validate.c
index 5023aae1b8c..5f65242458a 100644
--- a/src/mesa/drivers/dri/i965/intel_tex_validate.c
+++ b/src/mesa/drivers/dri/i965/intel_tex_validate.c
@@ -89,21 +89,21 @@ static void intel_calculate_first_last_level( struct intel_texture_object *intel
intelObj->lastLevel = lastLevel;
}
-static void copy_image_data_to_tree( struct intel_context *intel,
- struct intel_texture_object *intelObj,
- struct gl_texture_image *texImage,
- GLuint face,
- GLuint level)
+static GLboolean copy_image_data_to_tree( struct intel_context *intel,
+ struct intel_texture_object *intelObj,
+ struct gl_texture_image *texImage,
+ GLuint face,
+ GLuint level)
{
- intel_miptree_image_data(intel,
- intelObj->mt,
- face,
- level,
- texImage->Data,
- texImage->RowStride,
- (texImage->RowStride *
- texImage->Height *
- texImage->TexFormat->TexelBytes));
+ return intel_miptree_image_data(intel,
+ intelObj->mt,
+ face,
+ level,
+ texImage->Data,
+ texImage->RowStride,
+ (texImage->RowStride *
+ texImage->Height *
+ texImage->TexFormat->TexelBytes));
}
static void intel_texture_invalidate( struct intel_texture_object *intelObj )
@@ -129,7 +129,6 @@ GLuint intel_finalize_mipmap_tree( struct intel_context *intel,
struct gl_texture_object *tObj )
{
struct intel_texture_object *intelObj = intel_texture_object(tObj);
-
GLuint face, i;
GLuint nr_faces = 0;
struct gl_texture_image *firstImage;
@@ -226,18 +225,24 @@ GLuint intel_finalize_mipmap_tree( struct intel_context *intel,
i,
texImage->Data);
- copy_image_data_to_tree(intel,
- intelObj,
- texImage,
- face,
- i);
+ if (!copy_image_data_to_tree(intel,
+ intelObj,
+ texImage,
+ face,
+ i))
+ return GL_FALSE;
}
}
- intelObj->dirty_images[face] = 0;
}
}
+ /* Only clear the dirty flags if everything went ok:
+ */
+ for (face = 0; face < nr_faces; face++) {
+ intelObj->dirty_images[face] = 0;
+ }
+
intelObj->dirty = 0;
}