diff options
author | Ben Skeggs <[email protected]> | 2007-12-23 16:18:00 +1100 |
---|---|---|
committer | Ben Skeggs <[email protected]> | 2007-12-23 16:18:00 +1100 |
commit | 74757eb970984b0404c17255f3639d8a40591964 (patch) | |
tree | b604c1aef50cdd61139fa695e6c2ef8ba6306dd0 /src/mesa/drivers | |
parent | fa605cf661c09c5866cd9aa316b6a5ce9eb65c24 (diff) |
nouveau: don't wait when deleting fences unless needed
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r-- | src/mesa/drivers/dri/nouveau_winsys/nouveau_fence.c | 41 |
1 files changed, 35 insertions, 6 deletions
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_fence.c b/src/mesa/drivers/dri/nouveau_winsys/nouveau_fence.c index 3b35a11bcbf..53037d16823 100644 --- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_fence.c +++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_fence.c @@ -22,6 +22,7 @@ #include <stdlib.h> #include <errno.h> +#include <assert.h> #include "nouveau_drmif.h" #include "nouveau_dma.h" @@ -59,6 +60,28 @@ nouveau_fence_ref(struct nouveau_fence *ref, struct nouveau_fence **fence) return 0; } +static void +nouveau_fence_del_unsignalled(struct nouveau_fence *fence) +{ + struct nouveau_channel_priv *nvchan = nouveau_channel(fence->channel); + struct nouveau_fence *le; + + if (nvchan->fence_head == fence) { + nvchan->fence_head = nouveau_fence(fence)->next; + if (nvchan->fence_head == NULL) + nvchan->fence_tail = NULL; + return; + } + + le = nvchan->fence_head; + while (le && nouveau_fence(le)->next != fence) + le = nouveau_fence(le)->next; + assert(le && nouveau_fence(le)->next == fence); + nouveau_fence(le)->next = nouveau_fence(fence)->next; + if (nvchan->fence_tail == fence) + nvchan->fence_tail = le; +} + void nouveau_fence_del(struct nouveau_fence **fence) { @@ -69,11 +92,19 @@ nouveau_fence_del(struct nouveau_fence **fence) nvfence = nouveau_fence(*fence); *fence = NULL; - if (--nvfence->refcount <= 0) { - if (nvfence->emitted && !nvfence->signalled) + if (--nvfence->refcount) + return; + + if (nvfence->emitted && !nvfence->signalled) { + if (nvfence->signal_cb) { + nvfence->refcount++; nouveau_fence_wait((void *)&nvfence); - free(nvfence); + return; + } + + nouveau_fence_del_unsignalled(&nvfence->base); } + free(nvfence); } int @@ -139,9 +170,7 @@ nouveau_fence_flush(struct nouveau_channel *chan) break; } - nvchan->fence_head = nvfence->next; - if (nvchan->fence_head == NULL) - nvchan->fence_tail = NULL; + nouveau_fence_del_unsignalled(&nvfence->base); nvfence->signalled = 1; while (nvfence->signal_cb) { |