static void nve4_m2mf_copy_linear(struct nouveau_context *nv, struct nouveau_bo *dst, unsigned dstoff, unsigned dstdom, struct nouveau_bo *src, unsigned srcoff, unsigned srcdom, unsigned size) { struct nouveau_pushbuf *push = nv->pushbuf; struct nouveau_bufctx *bctx = nvc0_context(&nv->pipe)->bufctx; nouveau_bufctx_refn(bctx, 0, src, srcdom | NOUVEAU_BO_RD); nouveau_bufctx_refn(bctx, 0, dst, dstdom | NOUVEAU_BO_WR); nouveau_pushbuf_bufctx(push, bctx); nouveau_pushbuf_validate(push); BEGIN_NVC0(push, SUBC_COPY(0x0400), 4); PUSH_DATAh(push, src->offset + srcoff); PUSH_DATA (push, src->offset + srcoff); PUSH_DATAh(push, dst->offset + dstoff); PUSH_DATA (push, dst->offset + dstoff); BEGIN_NVC0(push, SUBC_COPY(0x0418), 1); PUSH_DATA (push, size); BEGIN_NVC0(push, SUBC_COPY(0x0300), 1); PUSH_DATA (push, 0x186); nouveau_bufctx_reset(bctx, 0); }
static void nv50_compute_upload_input(struct nv50_context *nv50, const uint32_t *input) { struct nv50_screen *screen = nv50->screen; struct nouveau_pushbuf *push = screen->base.pushbuf; unsigned size = align(nv50->compprog->parm_size, 0x4); BEGIN_NV04(push, NV50_COMPUTE(USER_PARAM_COUNT), 1); PUSH_DATA (push, (size / 4) << 8); if (size) { struct nouveau_mm_allocation *mm; struct nouveau_bo *bo = NULL; unsigned offset; mm = nouveau_mm_allocate(screen->base.mm_GART, size, &bo, &offset); assert(mm); nouveau_bo_map(bo, 0, screen->base.client); memcpy(bo->map + offset, input, size); nouveau_bufctx_refn(nv50->bufctx, 0, bo, NOUVEAU_BO_GART | NOUVEAU_BO_RD); nouveau_pushbuf_bufctx(push, nv50->bufctx); nouveau_pushbuf_validate(push); BEGIN_NV04(push, NV50_COMPUTE(USER_PARAM(0)), size / 4); nouveau_pushbuf_data(push, bo, offset, size); nouveau_fence_work(screen->base.fence.current, nouveau_mm_free_work, mm); nouveau_bo_ref(NULL, &bo); nouveau_bufctx_reset(nv50->bufctx, 0); } }
static void nvc0_m2mf_copy_linear(struct nouveau_context *nv, struct nouveau_bo *dst, unsigned dstoff, unsigned dstdom, struct nouveau_bo *src, unsigned srcoff, unsigned srcdom, unsigned size) { struct nouveau_pushbuf *push = nv->pushbuf; struct nouveau_bufctx *bctx = nvc0_context(&nv->pipe)->bufctx; nouveau_bufctx_refn(bctx, 0, src, srcdom | NOUVEAU_BO_RD); nouveau_bufctx_refn(bctx, 0, dst, dstdom | NOUVEAU_BO_WR); nouveau_pushbuf_bufctx(push, bctx); nouveau_pushbuf_validate(push); while (size) { unsigned bytes = MIN2(size, 1 << 17); BEGIN_NVC0(push, NVC0_M2MF(OFFSET_OUT_HIGH), 2); PUSH_DATAh(push, dst->offset + dstoff); PUSH_DATA (push, dst->offset + dstoff); BEGIN_NVC0(push, NVC0_M2MF(OFFSET_IN_HIGH), 2); PUSH_DATAh(push, src->offset + srcoff); PUSH_DATA (push, src->offset + srcoff); BEGIN_NVC0(push, NVC0_M2MF(LINE_LENGTH_IN), 2); PUSH_DATA (push, bytes); PUSH_DATA (push, 1); BEGIN_NVC0(push, NVC0_M2MF(EXEC), 1); PUSH_DATA (push, (1 << NVC0_M2MF_EXEC_INC__SHIFT) | NVC0_M2MF_EXEC_LINEAR_IN | NVC0_M2MF_EXEC_LINEAR_OUT); srcoff += bytes; dstoff += bytes; size -= bytes; } nouveau_bufctx_reset(bctx, 0); }
void nvc0_m2mf_push_linear(struct nouveau_context *nv, struct nouveau_bo *dst, unsigned offset, unsigned domain, unsigned size, const void *data) { struct nvc0_context *nvc0 = nvc0_context(&nv->pipe); struct nouveau_pushbuf *push = nv->pushbuf; uint32_t *src = (uint32_t *)data; unsigned count = (size + 3) / 4; nouveau_bufctx_refn(nvc0->bufctx, 0, dst, domain | NOUVEAU_BO_WR); nouveau_pushbuf_bufctx(push, nvc0->bufctx); nouveau_pushbuf_validate(push); while (count) { unsigned nr; if (!PUSH_SPACE(push, 16)) 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); PUSH_DATA (push, dst->offset + offset); BEGIN_NVC0(push, NVC0_M2MF(LINE_LENGTH_IN), 2); PUSH_DATA (push, MIN2(size, nr * 4)); PUSH_DATA (push, 1); BEGIN_NVC0(push, NVC0_M2MF(EXEC), 1); PUSH_DATA (push, 0x100111); /* must not be interrupted (trap on QUERY fence, 0x50 works however) */ BEGIN_NIC0(push, NVC0_M2MF(DATA), nr); PUSH_DATAp(push, src, nr); count -= nr; src += nr; offset += nr * 4; size -= nr * 4; } nouveau_bufctx_reset(nvc0->bufctx, 0); }
struct nouveau_bufref * nouveau_bufctx_mthd(struct nouveau_bufctx *bctx, int bin, uint32_t packet, struct nouveau_bo *bo, uint64_t data, uint32_t flags, uint32_t vor, uint32_t tor) { struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx); struct nouveau_bufbin_priv *pbin = &pctx->bins[bin]; struct nouveau_bufref *bref = nouveau_bufctx_refn(bctx, bin, bo, flags); if (bref) { bref->packet = packet; bref->data = data; bref->vor = vor; bref->tor = tor; pbin->relocs++; bctx->relocs++; } return bref; }
void nvc0_cb_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_bufctx *bctx = nvc0_context(&nv->pipe)->bufctx; struct nouveau_pushbuf *push = nv->pushbuf; NOUVEAU_DRV_STAT(nv->screen, constbuf_upload_count, 1); NOUVEAU_DRV_STAT(nv->screen, constbuf_upload_bytes, words * 4); assert(!(offset & 3)); size = align(size, 0x100); nouveau_bufctx_refn(bctx, 0, bo, NOUVEAU_BO_WR | domain); nouveau_pushbuf_bufctx(push, bctx); nouveau_pushbuf_validate(push); 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); BEGIN_1IC0(push, NVC0_3D(CB_POS), nr + 1); PUSH_DATA (push, offset); PUSH_DATAp(push, data, nr); words -= nr; data += nr; offset += nr * 4; } nouveau_bufctx_reset(bctx, 0); }
void nve4_p2mf_push_linear(struct nouveau_context *nv, struct nouveau_bo *dst, unsigned offset, unsigned domain, unsigned size, const void *data) { struct nvc0_context *nvc0 = nvc0_context(&nv->pipe); struct nouveau_pushbuf *push = nv->pushbuf; uint32_t *src = (uint32_t *)data; unsigned count = (size + 3) / 4; nouveau_bufctx_refn(nvc0->bufctx, 0, dst, domain | NOUVEAU_BO_WR); nouveau_pushbuf_bufctx(push, nvc0->bufctx); nouveau_pushbuf_validate(push); while (count) { unsigned nr = MIN2(count, (NV04_PFIFO_MAX_PACKET_LEN - 1)); if (!PUSH_SPACE(push, nr + 10)) break; BEGIN_NVC0(push, NVE4_P2MF(UPLOAD_DST_ADDRESS_HIGH), 2); PUSH_DATAh(push, dst->offset + offset); PUSH_DATA (push, dst->offset + offset); BEGIN_NVC0(push, NVE4_P2MF(UPLOAD_LINE_LENGTH_IN), 2); PUSH_DATA (push, MIN2(size, nr * 4)); PUSH_DATA (push, 1); /* must not be interrupted (trap on QUERY fence, 0x50 works however) */ BEGIN_1IC0(push, NVE4_P2MF(UPLOAD_EXEC), nr + 1); PUSH_DATA (push, 0x1001); PUSH_DATAp(push, src, nr); count -= nr; src += nr; offset += nr * 4; size -= nr * 4; } nouveau_bufctx_reset(nvc0->bufctx, 0); }
static void nvc0_m2mf_transfer_rect(struct nvc0_context *nvc0, const struct nv50_m2mf_rect *dst, const struct nv50_m2mf_rect *src, uint32_t nblocksx, uint32_t nblocksy) { struct nouveau_pushbuf *push = nvc0->base.pushbuf; struct nouveau_bufctx *bctx = nvc0->bufctx; const int cpp = dst->cpp; uint32_t src_ofst = src->base; uint32_t dst_ofst = dst->base; uint32_t height = nblocksy; uint32_t sy = src->y; uint32_t dy = dst->y; uint32_t exec = (1 << 20); assert(dst->cpp == src->cpp); nouveau_bufctx_refn(bctx, 0, src->bo, src->domain | NOUVEAU_BO_RD); nouveau_bufctx_refn(bctx, 0, dst->bo, dst->domain | NOUVEAU_BO_WR); nouveau_pushbuf_bufctx(push, bctx); nouveau_pushbuf_validate(push); if (nouveau_bo_memtype(src->bo)) { BEGIN_NVC0(push, NVC0_M2MF(TILING_MODE_IN), 5); PUSH_DATA (push, src->tile_mode); PUSH_DATA (push, src->width * cpp); PUSH_DATA (push, src->height); PUSH_DATA (push, src->depth); PUSH_DATA (push, src->z); } else { src_ofst += src->y * src->pitch + src->x * cpp; BEGIN_NVC0(push, NVC0_M2MF(PITCH_IN), 1); PUSH_DATA (push, src->width * cpp); exec |= NVC0_M2MF_EXEC_LINEAR_IN; } if (nouveau_bo_memtype(dst->bo)) { BEGIN_NVC0(push, NVC0_M2MF(TILING_MODE_OUT), 5); PUSH_DATA (push, dst->tile_mode); PUSH_DATA (push, dst->width * cpp); PUSH_DATA (push, dst->height); PUSH_DATA (push, dst->depth); PUSH_DATA (push, dst->z); } else { dst_ofst += dst->y * dst->pitch + dst->x * cpp; BEGIN_NVC0(push, NVC0_M2MF(PITCH_OUT), 1); PUSH_DATA (push, dst->width * cpp); exec |= NVC0_M2MF_EXEC_LINEAR_OUT; } while (height) { int line_count = height > 2047 ? 2047 : height; BEGIN_NVC0(push, NVC0_M2MF(OFFSET_IN_HIGH), 2); PUSH_DATAh(push, src->bo->offset + src_ofst); PUSH_DATA (push, src->bo->offset + src_ofst); BEGIN_NVC0(push, NVC0_M2MF(OFFSET_OUT_HIGH), 2); PUSH_DATAh(push, dst->bo->offset + dst_ofst); PUSH_DATA (push, dst->bo->offset + dst_ofst); if (!(exec & NVC0_M2MF_EXEC_LINEAR_IN)) { BEGIN_NVC0(push, NVC0_M2MF(TILING_POSITION_IN_X), 2); PUSH_DATA (push, src->x * cpp); PUSH_DATA (push, sy); } else { src_ofst += line_count * src->pitch; } if (!(exec & NVC0_M2MF_EXEC_LINEAR_OUT)) { BEGIN_NVC0(push, NVC0_M2MF(TILING_POSITION_OUT_X), 2); PUSH_DATA (push, dst->x * cpp); PUSH_DATA (push, dy); } else { dst_ofst += line_count * dst->pitch; } BEGIN_NVC0(push, NVC0_M2MF(LINE_LENGTH_IN), 2); PUSH_DATA (push, nblocksx * cpp); PUSH_DATA (push, line_count); BEGIN_NVC0(push, NVC0_M2MF(EXEC), 1); PUSH_DATA (push, exec); height -= line_count; sy += line_count; dy += line_count; } nouveau_bufctx_reset(bctx, 0); }
static void nve4_m2mf_transfer_rect(struct nvc0_context *nvc0, const struct nv50_m2mf_rect *dst, const struct nv50_m2mf_rect *src, uint32_t nblocksx, uint32_t nblocksy) { struct nouveau_pushbuf *push = nvc0->base.pushbuf; struct nouveau_bufctx *bctx = nvc0->bufctx; uint32_t exec; uint32_t src_base = src->base; uint32_t dst_base = dst->base; const int cpp = dst->cpp; assert(dst->cpp == src->cpp); nouveau_bufctx_refn(bctx, 0, dst->bo, dst->domain | NOUVEAU_BO_WR); nouveau_bufctx_refn(bctx, 0, src->bo, src->domain | NOUVEAU_BO_RD); nouveau_pushbuf_bufctx(push, bctx); nouveau_pushbuf_validate(push); exec = 0x200 /* 2D_ENABLE */ | 0x6 /* UNK */; if (!nouveau_bo_memtype(dst->bo)) { assert(!dst->z); dst_base += dst->y * dst->pitch + dst->x * cpp; exec |= 0x100; /* DST_MODE_2D_LINEAR */ } if (!nouveau_bo_memtype(src->bo)) { assert(!src->z); src_base += src->y * src->pitch + src->x * cpp; exec |= 0x080; /* SRC_MODE_2D_LINEAR */ } BEGIN_NVC0(push, SUBC_COPY(0x070c), 6); PUSH_DATA (push, 0x1000 | dst->tile_mode); PUSH_DATA (push, dst->pitch); PUSH_DATA (push, dst->height); PUSH_DATA (push, dst->depth); PUSH_DATA (push, dst->z); PUSH_DATA (push, (dst->y << 16) | (dst->x * cpp)); BEGIN_NVC0(push, SUBC_COPY(0x0728), 6); PUSH_DATA (push, 0x1000 | src->tile_mode); PUSH_DATA (push, src->pitch); PUSH_DATA (push, src->height); PUSH_DATA (push, src->depth); PUSH_DATA (push, src->z); PUSH_DATA (push, (src->y << 16) | (src->x * cpp)); BEGIN_NVC0(push, SUBC_COPY(0x0400), 8); PUSH_DATAh(push, src->bo->offset + src_base); PUSH_DATA (push, src->bo->offset + src_base); PUSH_DATAh(push, dst->bo->offset + dst_base); PUSH_DATA (push, dst->bo->offset + dst_base); PUSH_DATA (push, src->pitch); PUSH_DATA (push, dst->pitch); PUSH_DATA (push, nblocksx * cpp); PUSH_DATA (push, nblocksy); BEGIN_NVC0(push, SUBC_COPY(0x0300), 1); PUSH_DATA (push, exec); nouveau_bufctx_reset(bctx, 0); }