#include "nvc0/nvc0_context.h"
-#include "nv50/nv50_defs.xml.h"
-
struct nvc0_transfer {
struct pipe_transfer base;
struct nv50_m2mf_rect rect[2];
nouveau_pushbuf_validate(push);
while (count) {
- unsigned nr;
+ unsigned nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN);
- if (!PUSH_SPACE(push, 16))
+ if (!PUSH_SPACE(push, nr + 9))
break;
- nr = PUSH_AVAIL(push);
- assert(nr >= 16);
- nr = MIN2(count, nr - 9);
- nr = MIN2(nr, NV04_PFIFO_MAX_PACKET_LEN);
BEGIN_NVC0(push, NVC0_M2MF(OFFSET_OUT_HIGH), 2);
PUSH_DATAh(push, dst->offset + offset);
nouveau_pushbuf_validate(push);
while (count) {
- unsigned nr;
+ unsigned nr = MIN2(count, (NV04_PFIFO_MAX_PACKET_LEN - 1));
- if (!PUSH_SPACE(push, 16))
+ if (!PUSH_SPACE(push, nr + 10))
break;
- nr = PUSH_AVAIL(push);
- assert(nr >= 16);
- nr = MIN2(count, nr - 8);
- nr = MIN2(nr, (NV04_PFIFO_MAX_PACKET_LEN - 1));
BEGIN_NVC0(push, NVE4_P2MF(UPLOAD_DST_ADDRESS_HIGH), 2);
PUSH_DATAh(push, dst->offset + offset);
}
-static INLINE boolean
+static inline bool
nvc0_mt_transfer_can_map_directly(struct nv50_miptree *mt)
{
if (mt->base.domain == NOUVEAU_BO_VRAM)
- return FALSE;
+ return false;
if (mt->base.base.usage != PIPE_USAGE_STAGING)
- return FALSE;
+ return false;
return !nouveau_bo_memtype(mt->base.bo);
}
-static INLINE boolean
+static inline bool
nvc0_mt_sync(struct nvc0_context *nvc0, struct nv50_miptree *mt, unsigned usage)
{
if (!mt->base.mm) {
return !nouveau_bo_wait(mt->base.bo, access, nvc0->base.client);
}
if (usage & PIPE_TRANSFER_WRITE)
- return !mt->base.fence || nouveau_fence_wait(mt->base.fence);
- return !mt->base.fence_wr || nouveau_fence_wait(mt->base.fence_wr);
+ return !mt->base.fence || nouveau_fence_wait(mt->base.fence, &nvc0->base.debug);
+ return !mt->base.fence_wr || nouveau_fence_wait(mt->base.fence_wr, &nvc0->base.debug);
}
void *
}
tx->nlayers = box->depth;
- tx->base.stride = tx->nblocksx * util_format_get_blocksize(res->format);
- tx->base.layer_stride = tx->nblocksy * tx->base.stride;
-
if (usage & PIPE_TRANSFER_MAP_DIRECTLY) {
- tx->base.stride = align(tx->base.stride, 128);
+ tx->base.stride = mt->level[level].pitch;
+ tx->base.layer_stride = mt->layer_stride;
+ uint32_t offset = box->y * tx->base.stride +
+ util_format_get_stride(res->format, box->x);
+ if (!mt->layout_3d)
+ offset += mt->layer_stride * box->z;
+ else
+ offset += nvc0_mt_zslice_offset(mt, level, box->z);
*ptransfer = &tx->base;
- return mt->base.bo->map + mt->base.offset;
+ return mt->base.bo->map + mt->base.offset + offset;
}
+ tx->base.stride = tx->nblocksx * util_format_get_blocksize(res->format);
+ tx->base.layer_stride = tx->nblocksy * tx->base.stride;
+
nv50_m2mf_rect_setup(&tx->rect[0], res, level, box->x, box->y, box->z);
size = tx->base.layer_stride;
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);
}
/* This happens rather often with DTD9/st. */
-void
+static void
nvc0_cb_push(struct nouveau_context *nv,
- struct nouveau_bo *bo, unsigned domain,
- unsigned base, unsigned size,
+ struct nv04_resource *res,
unsigned offset, unsigned words, const uint32_t *data)
+{
+ struct nvc0_context *nvc0 = nvc0_context(&nv->pipe);
+ struct nvc0_constbuf *cb = NULL;
+ int s;
+
+ /* Go through all the constbuf binding points of this buffer and try to
+ * find one which contains the region to be updated.
+ */
+ for (s = 0; s < 6 && !cb; s++) {
+ uint16_t bindings = res->cb_bindings[s];
+ while (bindings) {
+ int i = ffs(bindings) - 1;
+ uint32_t cb_offset = nvc0->constbuf[s][i].offset;
+
+ bindings &= ~(1 << i);
+ if (cb_offset <= offset &&
+ cb_offset + nvc0->constbuf[s][i].size >= offset + words * 4) {
+ cb = &nvc0->constbuf[s][i];
+ break;
+ }
+ }
+ }
+
+ if (cb) {
+ nvc0_cb_bo_push(nv, res->bo, res->domain,
+ res->offset + cb->offset, cb->size,
+ offset - cb->offset, words, data);
+ } else {
+ nv->push_data(nv, res->bo, res->offset + offset, res->domain,
+ words * 4, data);
+ }
+}
+
+void
+nvc0_cb_bo_push(struct nouveau_context *nv,
+ struct nouveau_bo *bo, unsigned domain,
+ unsigned base, unsigned size,
+ unsigned offset, unsigned words, const uint32_t *data)
{
struct nouveau_pushbuf *push = nv->pushbuf;
assert(!(offset & 3));
size = align(size, 0x100);
+ assert(offset < size);
+ assert(offset + words * 4 <= size);
+
BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
PUSH_DATA (push, size);
PUSH_DATAh(push, bo->offset + base);
PUSH_DATA (push, bo->offset + base);
while (words) {
- unsigned nr = PUSH_AVAIL(push);
- nr = MIN2(nr, words);
- nr = MIN2(nr, NV04_PFIFO_MAX_PACKET_LEN - 1);
+ unsigned nr = MIN2(words, NV04_PFIFO_MAX_PACKET_LEN - 1);
PUSH_SPACE(push, nr + 2);
PUSH_REFN (push, bo, NOUVEAU_BO_WR | domain);