if (--bo->refcount)
return;
+ if (bo->fence)
+ nouveau_fence_wait(&bo->fence);
+
nouveau_bo_realloc_gpu(bo, 0, 0);
if (bo->sysmem && !bo->user)
free(bo->sysmem);
static int
nouveau_bo_upload(struct nouveau_bo_priv *bo)
{
+ if (bo->fence)
+ nouveau_fence_wait(&bo->fence);
memcpy(bo->map, bo->sysmem, bo->drm.size);
return 0;
}
int
nouveau_bo_validate(struct nouveau_channel *chan, struct nouveau_bo *bo,
- uint32_t flags)
+ struct nouveau_fence *fence, uint32_t flags)
{
struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
nouveau_bo_realloc_gpu(nvbo, flags, nvbo->base.size);
nouveau_bo_upload(nvbo);
} else
- if (nvbo->user || nvbo->base.map)
+ if (nvbo->user) {
+ nouveau_bo_upload(nvbo);
+ } else
+ if (nvbo->base.map) {
nouveau_bo_upload(nvbo);
+ nvbo->sync_hack = 1;
+ }
if (!nvbo->user && !nvbo->base.map) {
free(nvbo->sysmem);
nvbo->sysmem = NULL;
}
+ if (nvbo->fence)
+ nouveau_fence_del(&nvbo->fence);
+ nouveau_fence_ref(fence, &nvbo->fence);
+
nvbo->base.offset = nvbo->drm.offset;
if (nvbo->drm.flags & NOUVEAU_MEM_AGP)
nvbo->base.flags = NOUVEAU_BO_GART;
if ((chan->pushbuf[i] & 0xf0000000) == 0x20000000) {
int n = (((chan->pushbuf[i] & 0x0fffffff) -
chan->dma.base) / 4);
-
do {
NOUVEAU_MSG("\t0x%08x 0x%08x\n",
(n<<2)+chan->dma.base,
int user;
int refcount;
+ int sync_hack;
};
#define nouveau_bo(n) ((struct nouveau_bo_priv *)(n))
extern int
nouveau_bo_validate(struct nouveau_channel *, struct nouveau_bo *,
- uint32_t flags);
+ struct nouveau_fence *fence, uint32_t flags);
extern int
nouveau_resource_init(struct nouveau_resource **heap, int size);
struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(nvchan->pb_tail);
struct nouveau_pushbuf_bo *pbbo;
+ struct nouveau_fence *fence = NULL;
+ int sync_hack = 0;
int ret;
if (!nvpb)
if (nvpb->base.remaining == nvpb->res->size / 4)
return 0;
- ret = nouveau_fence_new(chan, &nvpb->fence);
+ ret = nouveau_fence_new(chan, &fence);
if (ret)
return ret;
struct nouveau_pushbuf_reloc *r;
struct nouveau_bo *bo = &ptr_to_bo(pbbo->handle)->base;
- ret = nouveau_bo_validate(chan, bo, pbbo->flags);
+ ret = nouveau_bo_validate(chan, bo, fence, pbbo->flags);
assert (ret == 0);
+ sync_hack |= nouveau_bo(bo)->sync_hack;
+ nouveau_bo(bo)->sync_hack = 0;
+
while ((r = ptr_to_pbrel(pbbo->relocs))) {
uint32_t push;
if (nvchan->dma.free < 1)
WAIT_RING_CH(chan, 1);
nvchan->dma.free -= 1;
+#ifdef NOUVEAU_DMA_DEBUG
+ nvchan->dma.push_free = 1;
+#endif
OUT_RING_CH(chan, 0x20000000 | (nvpb->res->start + 4096));
/* Add JMP back to master pushbuf from indirect pushbuf */
0x20000000 | ((nvchan->dma.cur << 2) + nvchan->dma.base);
/* Fence */
+ nvpb->fence = fence;
nouveau_fence_emit(nvpb->fence);
/* Kickoff */
nvpb->base.cur = &nvchan->pushbuf[(nvpb->res->start + 4096)/4];
if (nvchan->pb_tail) {
- nouveau_pushbuf(nvchan->pb_tail)->next = & nvpb->base;
+ nouveau_pushbuf(nvchan->pb_tail)->next = &nvpb->base;
} else {
nvchan->pb_head = &nvpb->base;
}
nvchan->pb_tail = &nvpb->base;
+ if (sync_hack) {
+ struct nouveau_fence *f = NULL;
+ nouveau_fence_ref(nvpb->fence, &f);
+ nouveau_fence_wait(&f);
+ }
+
return 0;
}
static void
nv04_surface_copy_done(struct nouveau_context *nv)
{
- nouveau_notifier_reset(nv->sync_notifier, 0);
- BEGIN_RING(NvGdiRect, 0x104, 1);
- OUT_RING (0);
- BEGIN_RING(NvGdiRect, 0x100, 1);
- OUT_RING (0);
FIRE_RING();
- nouveau_notifier_wait_status(nv->sync_notifier, 0, 0, 2000);
}
static int
OUT_RING ((dx << 16) | dy);
OUT_RING (( w << 16) | h);
- nouveau_notifier_reset(nv->sync_notifier, 0);
- BEGIN_RING(NvGdiRect, 0x104, 1);
- OUT_RING (0);
- BEGIN_RING(NvGdiRect, 0x100, 1);
- OUT_RING (0);
FIRE_RING();
- nouveau_notifier_wait_status(nv->sync_notifier, 0, 0, 2000);
-
return 0;
}
static void
nv50_surface_copy_done(struct nouveau_context *nv)
{
- nouveau_notifier_reset(nv->sync_notifier, 0);
- BEGIN_RING(Nv2D, 0x104, 1);
- OUT_RING (0);
- BEGIN_RING(Nv2D, 0x100, 1);
- OUT_RING (0);
FIRE_RING();
- nouveau_notifier_wait_status(nv->sync_notifier, 0, 0, 2000);
}
static int
OUT_RING (dx + w);
OUT_RING (dy + h);
- nouveau_notifier_reset(nv->sync_notifier, 0);
- BEGIN_RING(Nv2D, 0x104, 1);
- OUT_RING (0);
- BEGIN_RING(Nv2D, 0x100, 1);
- OUT_RING (0);
FIRE_RING();
- nouveau_notifier_wait_status(nv->sync_notifier, 0, 0, 2000);
return 0;
}
BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
OUT_RING (0);
- pipe->flush(pipe, PIPE_FLUSH_WAIT);
+ pipe->flush(pipe, 0);
return TRUE;
}
OUT_RING (0);
pipe->winsys->buffer_unmap(pipe->winsys, ib);
- pipe->flush(pipe, PIPE_FLUSH_WAIT);
+ pipe->flush(pipe, 0);
return TRUE;
}