nouveau_fence_new(screen, &screen->fence.current, false);
}
+
+void
+nouveau_fence_unref_bo(void *data)
+{
+ struct nouveau_bo *bo = data;
+
+ nouveau_bo_ref(NULL, &bo);
+}
bool nouveau_fence_wait(struct nouveau_fence *);
bool nouveau_fence_signalled(struct nouveau_fence *);
+void nouveau_fence_unref_bo(void *data); /* generic unref bo callback */
+
+
static inline void
nouveau_fence_ref(struct nouveau_fence *fence, struct nouveau_fence **ref)
{
struct nv30_context *nv30 = nv30_context(pipe);
struct nv30_transfer *tx = nv30_transfer(ptx);
- if (ptx->usage & PIPE_TRANSFER_WRITE)
+ if (ptx->usage & PIPE_TRANSFER_WRITE) {
nv30_transfer_rect(nv30, NEAREST, &tx->tmp, &tx->img);
- nouveau_bo_ref(NULL, &tx->tmp.bo);
+ /* Allow the copies above to finish executing before freeing the source */
+ nouveau_fence_work(nv30->screen->base.fence.current,
+ nouveau_fence_unref_bo, tx->tmp.bo);
+ } else {
+ nouveau_bo_ref(NULL, &tx->tmp.bo);
+ }
pipe_resource_reference(&ptx->resource, NULL);
FREE(tx);
}
tx->rect[0].base += mt->layer_stride;
tx->rect[1].base += tx->nblocksy * tx->base.stride;
}
+
+ /* Allow the copies above to finish executing before freeing the source */
+ nouveau_fence_work(nv50->screen->base.fence.current,
+ nouveau_fence_unref_bo, tx->rect[1].bo);
+ } else {
+ nouveau_bo_ref(NULL, &tx->rect[1].bo);
}
- nouveau_bo_ref(NULL, &tx->rect[1].bo);
pipe_resource_reference(&transfer->resource, NULL);
FREE(tx);
tx->rect[1].base += tx->nblocksy * tx->base.stride;
}
NOUVEAU_DRV_STAT(&nvc0->screen->base, tex_transfers_wr, 1);
+
+ /* Allow the copies above to finish executing before freeing the source */
+ nouveau_fence_work(nvc0->screen->base.fence.current,
+ nouveau_fence_unref_bo, tx->rect[1].bo);
+ } else {
+ nouveau_bo_ref(NULL, &tx->rect[1].bo);
}
if (tx->base.usage & PIPE_TRANSFER_READ)
NOUVEAU_DRV_STAT(&nvc0->screen->base, tex_transfers_rd, 1);
- nouveau_bo_ref(NULL, &tx->rect[1].bo);
pipe_resource_reference(&transfer->resource, NULL);
FREE(tx);