summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <skeggsb@gmail.com>2007-12-23 16:18:00 +1100
committerBen Skeggs <skeggsb@gmail.com>2007-12-23 16:18:00 +1100
commit74757eb970984b0404c17255f3639d8a40591964 (patch)
treeb604c1aef50cdd61139fa695e6c2ef8ba6306dd0
parentfa605cf661c09c5866cd9aa316b6a5ce9eb65c24 (diff)
nouveau: don't wait when deleting fences unless needed
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_fence.c41
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 3b35a11bcb..53037d1682 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) {