diff options
author | Ben Skeggs <[email protected]> | 2008-03-24 13:01:35 +1100 |
---|---|---|
committer | Ben Skeggs <[email protected]> | 2008-03-24 13:06:29 +1100 |
commit | 46a7f297a1477b9b59a5a11bf090db0ecbdf1ed7 (patch) | |
tree | 8429ce6afc61281cde5c63139229fa1de01f6d7b /src | |
parent | 17491ea27ffa6b48e31c0ad6ad6f795dd000c476 (diff) |
nouveau: fix infinite wait on space for userbuf.
A recent commit removed a bug which essentially caused a sync after each
use of a user buffer. In fixing it, the scratch area can now become
fragmented under some circumstances leading to nouveau_bo_tmp() waiting
forever for a large enough block of free space.
This fixes ppracer, gl-117 and probably a heap of other apps.
Diffstat (limited to 'src')
-rw-r--r-- | src/gallium/winsys/dri/nouveau/nouveau_bo.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_bo.c b/src/gallium/winsys/dri/nouveau/nouveau_bo.c index 46c0759dbb4..792eaaa79e5 100644 --- a/src/gallium/winsys/dri/nouveau/nouveau_bo.c +++ b/src/gallium/winsys/dri/nouveau/nouveau_bo.c @@ -88,6 +88,26 @@ nouveau_bo_tmp_del(void *priv) nouveau_resource_free(&r); } +static unsigned +nouveau_bo_tmp_max(struct nouveau_device_priv *nvdev) +{ + struct nouveau_resource *r = nvdev->sa_heap; + unsigned max = 0; + + while (r) { + if (r->in_use && !nouveau_fence(r->priv)->emitted) { + r = r->next; + continue; + } + + if (max < r->size) + max = r->size; + r = r->next; + } + + return max; +} + static struct nouveau_resource * nouveau_bo_tmp(struct nouveau_channel *chan, unsigned size, struct nouveau_fence *fence) @@ -103,6 +123,11 @@ nouveau_bo_tmp(struct nouveau_channel *chan, unsigned size, assert(ref); while (nouveau_resource_alloc(nvdev->sa_heap, size, ref, &r)) { + if (nouveau_bo_tmp_max(nvdev) < size) { + nouveau_fence_ref(NULL, &ref); + return NULL; + } + nouveau_fence_flush(chan); } nouveau_fence_signal_cb(ref, nouveau_bo_tmp_del, r); |