Cope with memory pool fragmentation by allowing a second attempt at
authorKeith Whitwell <keith@tungstengraphics.com>
Thu, 7 Sep 2006 19:05:40 +0000 (19:05 +0000)
committerKeith Whitwell <keith@tungstengraphics.com>
Thu, 7 Sep 2006 19:05:40 +0000 (19:05 +0000)
rendering operations to take place after evicting all resident
buffers.

Cope better with memory allocation failures throughout the driver and
improve tracking of failures.

13 files changed:
src/mesa/drivers/dri/i965/brw_draw.c
src/mesa/drivers/dri/i965/brw_state_pool.c
src/mesa/drivers/dri/i965/brw_vs_tnl.c
src/mesa/drivers/dri/i965/bufmgr.h
src/mesa/drivers/dri/i965/bufmgr_fake.c
src/mesa/drivers/dri/i965/intel_batchbuffer.c
src/mesa/drivers/dri/i965/intel_batchbuffer.h
src/mesa/drivers/dri/i965/intel_context.c
src/mesa/drivers/dri/i965/intel_mipmap_tree.c
src/mesa/drivers/dri/i965/intel_mipmap_tree.h
src/mesa/drivers/dri/i965/intel_regions.c
src/mesa/drivers/dri/i965/intel_regions.h
src/mesa/drivers/dri/i965/intel_tex_validate.c

index 104404b3019b65ce80dd7d09ce52821b85e3580a..02c24574232e686e20af6dcb855840381003ab90 100644 (file)
@@ -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 */
index d905da8000206bc388e68c9be5424239f68b023d..b9926f2a5d7e13eab06773c55db74a720265c14b 100644 (file)
@@ -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);
    }
index 107473eda5275cb216a19c35b8ff80957de365d0..c1099d4c67685464daa5b03c9e5e7da031fde62c 100644 (file)
@@ -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)
index 63e1011a76836fa414e01c289401d9d604f66364..ab5d56a231a97cd162f6af45af502ca000b98359 100644 (file)
@@ -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.
index c6bdf8ecb8996549d711eebf07929f830989b49c..34b62cd12c789b9c94b12da9620be226260368e0 100644 (file)
@@ -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;
+}
index 7510ac5b92048e1d80ed3ab794e8aff4ce130b46..636f36309509171d5a5876cef745609721bb9b4f 100644 (file)
@@ -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;
 }
 
 
index d576e97291ffc2c64a42fcf05378a37b95f65d7e..7a9ead3e3739635d9aeadc02ff1e13e4c696b131 100644 (file)
@@ -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.
index e21c7d89b9d7a51e3b9daa68764bdf221f1e0723..59fc8073eee44bf3e36f905bc9596793df625eea 100644 (file)
@@ -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);
+      }
+   }
 }
  
   
index ed19f70f4309fc972cf560c2de909d5c99f12957..8486086b274d5cdb5ff7a4279ece19a78963e49a 100644 (file)
@@ -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;
 }
 
index 483b87521f5d907c3bc04433c82a89df9d9e72a4..dbd7167b7783a59caa789429c9298c20a04a8267 100644 (file)
@@ -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:
  */
index 51495448ca9b01560d824a0b8aa15b5d8b006138..53f056123778a020808a1da1ca8ce2bd318964f0 100644 (file)
@@ -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;
    }
 }
                          
index 9f5483150c0852320f0589f9f931b359cf3eb7b1..2413f0de33c16e8a2988ae185f0bbdcf064ab6b3 100644 (file)
@@ -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
  */
index 5023aae1b8c182ef75e849590ea1890d356c6795..5f65242458aa95b13224d8d18a3ae6390d44ae25 100644 (file)
@@ -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;
    }