summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/nouveau/nouveau_fence.c17
-rw-r--r--src/gallium/drivers/nouveau/nouveau_fence.h7
-rw-r--r--src/gallium/drivers/nouveau/nouveau_screen.h2
-rw-r--r--src/gallium/drivers/nv50/nv50_screen.c8
-rw-r--r--src/gallium/drivers/nvc0/nvc0_screen.c8
5 files changed, 28 insertions, 14 deletions
diff --git a/src/gallium/drivers/nouveau/nouveau_fence.c b/src/gallium/drivers/nouveau/nouveau_fence.c
index 26e4775b12d..a2fcafef4a7 100644
--- a/src/gallium/drivers/nouveau/nouveau_fence.c
+++ b/src/gallium/drivers/nouveau/nouveau_fence.c
@@ -86,12 +86,10 @@ nouveau_fence_emit(struct nouveau_fence *fence)
{
struct nouveau_screen *screen = fence->screen;
- fence->sequence = ++screen->fence.sequence;
-
assert(fence->state == NOUVEAU_FENCE_STATE_AVAILABLE);
/* set this now, so that if fence.emit triggers a flush we don't recurse */
- fence->state = NOUVEAU_FENCE_STATE_EMITTED;
+ fence->state = NOUVEAU_FENCE_STATE_EMITTING;
++fence->ref;
@@ -102,7 +100,10 @@ nouveau_fence_emit(struct nouveau_fence *fence)
screen->fence.tail = fence;
- screen->fence.emit(&screen->base, fence->sequence);
+ screen->fence.emit(&screen->base, &fence->sequence);
+
+ assert(fence->state == NOUVEAU_FENCE_STATE_EMITTING);
+ fence->state = NOUVEAU_FENCE_STATE_EMITTED;
}
void
@@ -162,7 +163,8 @@ nouveau_fence_update(struct nouveau_screen *screen, boolean flushed)
if (flushed) {
for (fence = next; fence; fence = fence->next)
- fence->state = NOUVEAU_FENCE_STATE_FLUSHED;
+ if (fence->state == NOUVEAU_FENCE_STATE_EMITTED)
+ fence->state = NOUVEAU_FENCE_STATE_FLUSHED;
}
}
@@ -185,6 +187,9 @@ nouveau_fence_wait(struct nouveau_fence *fence)
struct nouveau_screen *screen = fence->screen;
uint32_t spins = 0;
+ /* wtf, someone is waiting on a fence in flush_notify handler? */
+ assert(fence->state != NOUVEAU_FENCE_STATE_EMITTING);
+
if (fence->state < NOUVEAU_FENCE_STATE_EMITTED) {
nouveau_fence_emit(fence);
@@ -216,7 +221,7 @@ nouveau_fence_wait(struct nouveau_fence *fence)
void
nouveau_fence_next(struct nouveau_screen *screen)
{
- if (screen->fence.current->state < NOUVEAU_FENCE_STATE_EMITTED)
+ if (screen->fence.current->state < NOUVEAU_FENCE_STATE_EMITTING)
nouveau_fence_emit(screen->fence.current);
nouveau_fence_ref(NULL, &screen->fence.current);
diff --git a/src/gallium/drivers/nouveau/nouveau_fence.h b/src/gallium/drivers/nouveau/nouveau_fence.h
index 680c75e99f9..3984a9a942d 100644
--- a/src/gallium/drivers/nouveau/nouveau_fence.h
+++ b/src/gallium/drivers/nouveau/nouveau_fence.h
@@ -6,9 +6,10 @@
#include "util/u_double_list.h"
#define NOUVEAU_FENCE_STATE_AVAILABLE 0
-#define NOUVEAU_FENCE_STATE_EMITTED 1
-#define NOUVEAU_FENCE_STATE_FLUSHED 2
-#define NOUVEAU_FENCE_STATE_SIGNALLED 3
+#define NOUVEAU_FENCE_STATE_EMITTING 1
+#define NOUVEAU_FENCE_STATE_EMITTED 2
+#define NOUVEAU_FENCE_STATE_FLUSHED 3
+#define NOUVEAU_FENCE_STATE_SIGNALLED 4
struct nouveau_fence_work {
struct list_head list;
diff --git a/src/gallium/drivers/nouveau/nouveau_screen.h b/src/gallium/drivers/nouveau/nouveau_screen.h
index cf291c6c595..808500f3002 100644
--- a/src/gallium/drivers/nouveau/nouveau_screen.h
+++ b/src/gallium/drivers/nouveau/nouveau_screen.h
@@ -24,7 +24,7 @@ struct nouveau_screen {
struct nouveau_fence *current;
u32 sequence;
u32 sequence_ack;
- void (*emit)(struct pipe_screen *, u32 sequence);
+ void (*emit)(struct pipe_screen *, u32 *sequence);
u32 (*update)(struct pipe_screen *);
} fence;
diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c
index c36f3cd4a04..7ff11ea4b0b 100644
--- a/src/gallium/drivers/nv50/nv50_screen.c
+++ b/src/gallium/drivers/nv50/nv50_screen.c
@@ -261,16 +261,20 @@ nv50_screen_destroy(struct pipe_screen *pscreen)
}
static void
-nv50_screen_fence_emit(struct pipe_screen *pscreen, u32 sequence)
+nv50_screen_fence_emit(struct pipe_screen *pscreen, u32 *sequence)
{
struct nv50_screen *screen = nv50_screen(pscreen);
struct nouveau_channel *chan = screen->base.channel;
MARK_RING (chan, 5, 2);
+
+ /* we need to do it after possible flush in MARK_RING */
+ *sequence = ++screen->base.fence.sequence;
+
BEGIN_RING(chan, RING_3D(QUERY_ADDRESS_HIGH), 4);
OUT_RELOCh(chan, screen->fence.bo, 0, NOUVEAU_BO_WR);
OUT_RELOCl(chan, screen->fence.bo, 0, NOUVEAU_BO_WR);
- OUT_RING (chan, sequence);
+ OUT_RING (chan, *sequence);
OUT_RING (chan, NV50_3D_QUERY_GET_MODE_WRITE_UNK0 |
NV50_3D_QUERY_GET_UNK4 |
NV50_3D_QUERY_GET_UNIT_CROP |
diff --git a/src/gallium/drivers/nvc0/nvc0_screen.c b/src/gallium/drivers/nvc0/nvc0_screen.c
index cc6e6830af2..292cbddcc0c 100644
--- a/src/gallium/drivers/nvc0/nvc0_screen.c
+++ b/src/gallium/drivers/nvc0/nvc0_screen.c
@@ -334,16 +334,20 @@ nvc0_magic_3d_init(struct nouveau_channel *chan)
}
static void
-nvc0_screen_fence_emit(struct pipe_screen *pscreen, u32 sequence)
+nvc0_screen_fence_emit(struct pipe_screen *pscreen, u32 *sequence)
{
struct nvc0_screen *screen = nvc0_screen(pscreen);
struct nouveau_channel *chan = screen->base.channel;
MARK_RING (chan, 5, 2);
+
+ /* we need to do it after possible flush in MARK_RING */
+ *sequence = ++screen->base.fence.sequence;
+
BEGIN_RING(chan, RING_3D(QUERY_ADDRESS_HIGH), 4);
OUT_RELOCh(chan, screen->fence.bo, 0, NOUVEAU_BO_WR);
OUT_RELOCl(chan, screen->fence.bo, 0, NOUVEAU_BO_WR);
- OUT_RING (chan, sequence);
+ OUT_RING (chan, *sequence);
OUT_RING (chan, NVC0_3D_QUERY_GET_FENCE | NVC0_3D_QUERY_GET_SHORT |
(0xf << NVC0_3D_QUERY_GET_UNIT__SHIFT));
}