1bf215546Sopenharmony_ci 2bf215546Sopenharmony_ci#include "util/format/u_format.h" 3bf215546Sopenharmony_ci 4bf215546Sopenharmony_ci#include "nv50/nv50_context.h" 5bf215546Sopenharmony_ci 6bf215546Sopenharmony_ci#include "nv50/g80_defs.xml.h" 7bf215546Sopenharmony_ci 8bf215546Sopenharmony_cistruct nv50_transfer { 9bf215546Sopenharmony_ci struct pipe_transfer base; 10bf215546Sopenharmony_ci struct nv50_m2mf_rect rect[2]; 11bf215546Sopenharmony_ci uint32_t nblocksx; 12bf215546Sopenharmony_ci uint32_t nblocksy; 13bf215546Sopenharmony_ci}; 14bf215546Sopenharmony_ci 15bf215546Sopenharmony_civoid 16bf215546Sopenharmony_cinv50_m2mf_rect_setup(struct nv50_m2mf_rect *rect, 17bf215546Sopenharmony_ci struct pipe_resource *restrict res, unsigned l, 18bf215546Sopenharmony_ci unsigned x, unsigned y, unsigned z) 19bf215546Sopenharmony_ci{ 20bf215546Sopenharmony_ci struct nv50_miptree *mt = nv50_miptree(res); 21bf215546Sopenharmony_ci const unsigned w = u_minify(res->width0, l); 22bf215546Sopenharmony_ci const unsigned h = u_minify(res->height0, l); 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci rect->bo = mt->base.bo; 25bf215546Sopenharmony_ci rect->domain = mt->base.domain; 26bf215546Sopenharmony_ci rect->base = mt->level[l].offset; 27bf215546Sopenharmony_ci if (mt->base.bo->offset != mt->base.address) 28bf215546Sopenharmony_ci rect->base += mt->base.address - mt->base.bo->offset; 29bf215546Sopenharmony_ci rect->pitch = mt->level[l].pitch; 30bf215546Sopenharmony_ci if (util_format_is_plain(res->format)) { 31bf215546Sopenharmony_ci rect->width = w << mt->ms_x; 32bf215546Sopenharmony_ci rect->height = h << mt->ms_y; 33bf215546Sopenharmony_ci rect->x = x << mt->ms_x; 34bf215546Sopenharmony_ci rect->y = y << mt->ms_y; 35bf215546Sopenharmony_ci } else { 36bf215546Sopenharmony_ci rect->width = util_format_get_nblocksx(res->format, w); 37bf215546Sopenharmony_ci rect->height = util_format_get_nblocksy(res->format, h); 38bf215546Sopenharmony_ci rect->x = util_format_get_nblocksx(res->format, x); 39bf215546Sopenharmony_ci rect->y = util_format_get_nblocksy(res->format, y); 40bf215546Sopenharmony_ci } 41bf215546Sopenharmony_ci rect->tile_mode = mt->level[l].tile_mode; 42bf215546Sopenharmony_ci rect->cpp = util_format_get_blocksize(res->format); 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci if (mt->layout_3d) { 45bf215546Sopenharmony_ci rect->z = z; 46bf215546Sopenharmony_ci rect->depth = u_minify(res->depth0, l); 47bf215546Sopenharmony_ci } else { 48bf215546Sopenharmony_ci rect->base += z * mt->layer_stride; 49bf215546Sopenharmony_ci rect->z = 0; 50bf215546Sopenharmony_ci rect->depth = 1; 51bf215546Sopenharmony_ci } 52bf215546Sopenharmony_ci} 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci/* This is very similar to nv50_2d_texture_do_copy, but doesn't require 55bf215546Sopenharmony_ci * miptree objects. Maybe refactor? Although it's not straightforward. 56bf215546Sopenharmony_ci */ 57bf215546Sopenharmony_cistatic void 58bf215546Sopenharmony_cinv50_2d_transfer_rect(struct nv50_context *nv50, 59bf215546Sopenharmony_ci const struct nv50_m2mf_rect *dst, 60bf215546Sopenharmony_ci const struct nv50_m2mf_rect *src, 61bf215546Sopenharmony_ci uint32_t nblocksx, uint32_t nblocksy) 62bf215546Sopenharmony_ci{ 63bf215546Sopenharmony_ci struct nouveau_pushbuf *push = nv50->base.pushbuf; 64bf215546Sopenharmony_ci struct nouveau_bufctx *bctx = nv50->bufctx; 65bf215546Sopenharmony_ci const int cpp = dst->cpp; 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci nouveau_bufctx_refn(bctx, 0, src->bo, src->domain | NOUVEAU_BO_RD); 68bf215546Sopenharmony_ci nouveau_bufctx_refn(bctx, 0, dst->bo, dst->domain | NOUVEAU_BO_WR); 69bf215546Sopenharmony_ci nouveau_pushbuf_bufctx(push, bctx); 70bf215546Sopenharmony_ci nouveau_pushbuf_validate(push); 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_ci uint32_t format; 73bf215546Sopenharmony_ci switch (cpp) { 74bf215546Sopenharmony_ci case 1: 75bf215546Sopenharmony_ci format = G80_SURFACE_FORMAT_R8_UNORM; 76bf215546Sopenharmony_ci break; 77bf215546Sopenharmony_ci case 2: 78bf215546Sopenharmony_ci format = G80_SURFACE_FORMAT_R16_UNORM; 79bf215546Sopenharmony_ci break; 80bf215546Sopenharmony_ci case 4: 81bf215546Sopenharmony_ci format = G80_SURFACE_FORMAT_BGRA8_UNORM; 82bf215546Sopenharmony_ci break; 83bf215546Sopenharmony_ci case 8: 84bf215546Sopenharmony_ci format = G80_SURFACE_FORMAT_RGBA16_FLOAT; 85bf215546Sopenharmony_ci break; 86bf215546Sopenharmony_ci case 16: 87bf215546Sopenharmony_ci format = G80_SURFACE_FORMAT_RGBA32_FLOAT; 88bf215546Sopenharmony_ci break; 89bf215546Sopenharmony_ci default: 90bf215546Sopenharmony_ci assert(!"Unexpected cpp"); 91bf215546Sopenharmony_ci format = G80_SURFACE_FORMAT_R8_UNORM; 92bf215546Sopenharmony_ci } 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci if (nouveau_bo_memtype(src->bo)) { 95bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_2D(SRC_FORMAT), 5); 96bf215546Sopenharmony_ci PUSH_DATA (push, format); 97bf215546Sopenharmony_ci PUSH_DATA (push, 0); 98bf215546Sopenharmony_ci PUSH_DATA (push, src->tile_mode); 99bf215546Sopenharmony_ci PUSH_DATA (push, src->depth); 100bf215546Sopenharmony_ci PUSH_DATA (push, src->z); 101bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_2D(SRC_WIDTH), 4); 102bf215546Sopenharmony_ci PUSH_DATA (push, src->width); 103bf215546Sopenharmony_ci PUSH_DATA (push, src->height); 104bf215546Sopenharmony_ci PUSH_DATAh(push, src->bo->offset + src->base); 105bf215546Sopenharmony_ci PUSH_DATA (push, src->bo->offset + src->base); 106bf215546Sopenharmony_ci } else { 107bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_2D(SRC_FORMAT), 2); 108bf215546Sopenharmony_ci PUSH_DATA (push, format); 109bf215546Sopenharmony_ci PUSH_DATA (push, 1); 110bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_2D(SRC_PITCH), 5); 111bf215546Sopenharmony_ci PUSH_DATA (push, src->pitch); 112bf215546Sopenharmony_ci PUSH_DATA (push, src->width); 113bf215546Sopenharmony_ci PUSH_DATA (push, src->height); 114bf215546Sopenharmony_ci PUSH_DATAh(push, src->bo->offset + src->base); 115bf215546Sopenharmony_ci PUSH_DATA (push, src->bo->offset + src->base); 116bf215546Sopenharmony_ci } 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci if (nouveau_bo_memtype(dst->bo)) { 119bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_2D(DST_FORMAT), 5); 120bf215546Sopenharmony_ci PUSH_DATA (push, format); 121bf215546Sopenharmony_ci PUSH_DATA (push, 0); 122bf215546Sopenharmony_ci PUSH_DATA (push, dst->tile_mode); 123bf215546Sopenharmony_ci PUSH_DATA (push, dst->depth); 124bf215546Sopenharmony_ci PUSH_DATA (push, dst->z); 125bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_2D(DST_WIDTH), 4); 126bf215546Sopenharmony_ci PUSH_DATA (push, dst->width); 127bf215546Sopenharmony_ci PUSH_DATA (push, dst->height); 128bf215546Sopenharmony_ci PUSH_DATAh(push, dst->bo->offset + dst->base); 129bf215546Sopenharmony_ci PUSH_DATA (push, dst->bo->offset + dst->base); 130bf215546Sopenharmony_ci } else { 131bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_2D(DST_FORMAT), 2); 132bf215546Sopenharmony_ci PUSH_DATA (push, format); 133bf215546Sopenharmony_ci PUSH_DATA (push, 1); 134bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_2D(DST_PITCH), 5); 135bf215546Sopenharmony_ci PUSH_DATA (push, dst->pitch); 136bf215546Sopenharmony_ci PUSH_DATA (push, dst->width); 137bf215546Sopenharmony_ci PUSH_DATA (push, dst->height); 138bf215546Sopenharmony_ci PUSH_DATAh(push, dst->bo->offset + dst->base); 139bf215546Sopenharmony_ci PUSH_DATA (push, dst->bo->offset + dst->base); 140bf215546Sopenharmony_ci } 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_2D(BLIT_CONTROL), 1); 143bf215546Sopenharmony_ci PUSH_DATA (push, NV50_2D_BLIT_CONTROL_FILTER_POINT_SAMPLE); 144bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_2D(BLIT_DST_X), 4); 145bf215546Sopenharmony_ci PUSH_DATA (push, dst->x); 146bf215546Sopenharmony_ci PUSH_DATA (push, dst->y); 147bf215546Sopenharmony_ci PUSH_DATA (push, nblocksx); 148bf215546Sopenharmony_ci PUSH_DATA (push, nblocksy); 149bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_2D(BLIT_DU_DX_FRACT), 4); 150bf215546Sopenharmony_ci PUSH_DATA (push, 0); 151bf215546Sopenharmony_ci PUSH_DATA (push, 1); 152bf215546Sopenharmony_ci PUSH_DATA (push, 0); 153bf215546Sopenharmony_ci PUSH_DATA (push, 1); 154bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_2D(BLIT_SRC_X_FRACT), 4); 155bf215546Sopenharmony_ci PUSH_DATA (push, 0); 156bf215546Sopenharmony_ci PUSH_DATA (push, src->x); 157bf215546Sopenharmony_ci PUSH_DATA (push, 0); 158bf215546Sopenharmony_ci PUSH_DATA (push, src->y); 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_ci nouveau_bufctx_reset(bctx, 0); 161bf215546Sopenharmony_ci} 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_civoid 164bf215546Sopenharmony_cinv50_m2mf_transfer_rect(struct nv50_context *nv50, 165bf215546Sopenharmony_ci const struct nv50_m2mf_rect *dst, 166bf215546Sopenharmony_ci const struct nv50_m2mf_rect *src, 167bf215546Sopenharmony_ci uint32_t nblocksx, uint32_t nblocksy) 168bf215546Sopenharmony_ci{ 169bf215546Sopenharmony_ci struct nouveau_pushbuf *push = nv50->base.pushbuf; 170bf215546Sopenharmony_ci struct nouveau_bufctx *bctx = nv50->bufctx; 171bf215546Sopenharmony_ci const int cpp = dst->cpp; 172bf215546Sopenharmony_ci uint32_t src_ofst = src->base; 173bf215546Sopenharmony_ci uint32_t dst_ofst = dst->base; 174bf215546Sopenharmony_ci uint32_t height = nblocksy; 175bf215546Sopenharmony_ci uint32_t sy = src->y; 176bf215546Sopenharmony_ci uint32_t dy = dst->y; 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci assert(dst->cpp == src->cpp); 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci /* Workaround: M2MF appears to break at the 64k boundary for tiled 181bf215546Sopenharmony_ci * textures, which can really only happen with RGBA32 formats. 182bf215546Sopenharmony_ci */ 183bf215546Sopenharmony_ci bool eng2d = false; 184bf215546Sopenharmony_ci if (nouveau_bo_memtype(src->bo)) { 185bf215546Sopenharmony_ci if (src->width * cpp > 65536) 186bf215546Sopenharmony_ci eng2d = true; 187bf215546Sopenharmony_ci } 188bf215546Sopenharmony_ci if (nouveau_bo_memtype(dst->bo)) { 189bf215546Sopenharmony_ci if (dst->width * cpp > 65536) 190bf215546Sopenharmony_ci eng2d = true; 191bf215546Sopenharmony_ci } 192bf215546Sopenharmony_ci if (eng2d) { 193bf215546Sopenharmony_ci nv50_2d_transfer_rect(nv50, dst, src, nblocksx, nblocksy); 194bf215546Sopenharmony_ci return; 195bf215546Sopenharmony_ci } 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_ci nouveau_bufctx_refn(bctx, 0, src->bo, src->domain | NOUVEAU_BO_RD); 198bf215546Sopenharmony_ci nouveau_bufctx_refn(bctx, 0, dst->bo, dst->domain | NOUVEAU_BO_WR); 199bf215546Sopenharmony_ci nouveau_pushbuf_bufctx(push, bctx); 200bf215546Sopenharmony_ci nouveau_pushbuf_validate(push); 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci if (nouveau_bo_memtype(src->bo)) { 203bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_M2MF(LINEAR_IN), 6); 204bf215546Sopenharmony_ci PUSH_DATA (push, 0); 205bf215546Sopenharmony_ci PUSH_DATA (push, src->tile_mode); 206bf215546Sopenharmony_ci PUSH_DATA (push, src->width * cpp); 207bf215546Sopenharmony_ci PUSH_DATA (push, src->height); 208bf215546Sopenharmony_ci PUSH_DATA (push, src->depth); 209bf215546Sopenharmony_ci PUSH_DATA (push, src->z); 210bf215546Sopenharmony_ci } else { 211bf215546Sopenharmony_ci src_ofst += src->y * src->pitch + src->x * cpp; 212bf215546Sopenharmony_ci 213bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_M2MF(LINEAR_IN), 1); 214bf215546Sopenharmony_ci PUSH_DATA (push, 1); 215bf215546Sopenharmony_ci BEGIN_NV04(push, SUBC_M2MF(NV03_M2MF_PITCH_IN), 1); 216bf215546Sopenharmony_ci PUSH_DATA (push, src->pitch); 217bf215546Sopenharmony_ci } 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_ci if (nouveau_bo_memtype(dst->bo)) { 220bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_M2MF(LINEAR_OUT), 6); 221bf215546Sopenharmony_ci PUSH_DATA (push, 0); 222bf215546Sopenharmony_ci PUSH_DATA (push, dst->tile_mode); 223bf215546Sopenharmony_ci PUSH_DATA (push, dst->width * cpp); 224bf215546Sopenharmony_ci PUSH_DATA (push, dst->height); 225bf215546Sopenharmony_ci PUSH_DATA (push, dst->depth); 226bf215546Sopenharmony_ci PUSH_DATA (push, dst->z); 227bf215546Sopenharmony_ci } else { 228bf215546Sopenharmony_ci dst_ofst += dst->y * dst->pitch + dst->x * cpp; 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_M2MF(LINEAR_OUT), 1); 231bf215546Sopenharmony_ci PUSH_DATA (push, 1); 232bf215546Sopenharmony_ci BEGIN_NV04(push, SUBC_M2MF(NV03_M2MF_PITCH_OUT), 1); 233bf215546Sopenharmony_ci PUSH_DATA (push, dst->pitch); 234bf215546Sopenharmony_ci } 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_ci while (height) { 237bf215546Sopenharmony_ci int line_count = height > 2047 ? 2047 : height; 238bf215546Sopenharmony_ci 239bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_M2MF(OFFSET_IN_HIGH), 2); 240bf215546Sopenharmony_ci PUSH_DATAh(push, src->bo->offset + src_ofst); 241bf215546Sopenharmony_ci PUSH_DATAh(push, dst->bo->offset + dst_ofst); 242bf215546Sopenharmony_ci 243bf215546Sopenharmony_ci BEGIN_NV04(push, SUBC_M2MF(NV03_M2MF_OFFSET_IN), 2); 244bf215546Sopenharmony_ci PUSH_DATA (push, src->bo->offset + src_ofst); 245bf215546Sopenharmony_ci PUSH_DATA (push, dst->bo->offset + dst_ofst); 246bf215546Sopenharmony_ci 247bf215546Sopenharmony_ci if (nouveau_bo_memtype(src->bo)) { 248bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_M2MF(TILING_POSITION_IN), 1); 249bf215546Sopenharmony_ci PUSH_DATA (push, (sy << 16) | (src->x * cpp)); 250bf215546Sopenharmony_ci } else { 251bf215546Sopenharmony_ci src_ofst += line_count * src->pitch; 252bf215546Sopenharmony_ci } 253bf215546Sopenharmony_ci if (nouveau_bo_memtype(dst->bo)) { 254bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_M2MF(TILING_POSITION_OUT), 1); 255bf215546Sopenharmony_ci PUSH_DATA (push, (dy << 16) | (dst->x * cpp)); 256bf215546Sopenharmony_ci } else { 257bf215546Sopenharmony_ci dst_ofst += line_count * dst->pitch; 258bf215546Sopenharmony_ci } 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_ci BEGIN_NV04(push, SUBC_M2MF(NV03_M2MF_LINE_LENGTH_IN), 4); 261bf215546Sopenharmony_ci PUSH_DATA (push, nblocksx * cpp); 262bf215546Sopenharmony_ci PUSH_DATA (push, line_count); 263bf215546Sopenharmony_ci PUSH_DATA (push, (1 << 8) | (1 << 0)); 264bf215546Sopenharmony_ci PUSH_DATA (push, 0); 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ci height -= line_count; 267bf215546Sopenharmony_ci sy += line_count; 268bf215546Sopenharmony_ci dy += line_count; 269bf215546Sopenharmony_ci } 270bf215546Sopenharmony_ci 271bf215546Sopenharmony_ci nouveau_bufctx_reset(bctx, 0); 272bf215546Sopenharmony_ci} 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_civoid 275bf215546Sopenharmony_cinv50_sifc_linear_u8(struct nouveau_context *nv, 276bf215546Sopenharmony_ci struct nouveau_bo *dst, unsigned offset, unsigned domain, 277bf215546Sopenharmony_ci unsigned size, const void *data) 278bf215546Sopenharmony_ci{ 279bf215546Sopenharmony_ci struct nv50_context *nv50 = nv50_context(&nv->pipe); 280bf215546Sopenharmony_ci struct nouveau_pushbuf *push = nv50->base.pushbuf; 281bf215546Sopenharmony_ci uint32_t *src = (uint32_t *)data; 282bf215546Sopenharmony_ci unsigned count = (size + 3) / 4; 283bf215546Sopenharmony_ci unsigned xcoord = offset & 0xff; 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ci nouveau_bufctx_refn(nv50->bufctx, 0, dst, domain | NOUVEAU_BO_WR); 286bf215546Sopenharmony_ci nouveau_pushbuf_bufctx(push, nv50->bufctx); 287bf215546Sopenharmony_ci nouveau_pushbuf_validate(push); 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_ci offset &= ~0xff; 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_2D(DST_FORMAT), 2); 292bf215546Sopenharmony_ci PUSH_DATA (push, G80_SURFACE_FORMAT_R8_UNORM); 293bf215546Sopenharmony_ci PUSH_DATA (push, 1); 294bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_2D(DST_PITCH), 5); 295bf215546Sopenharmony_ci PUSH_DATA (push, 262144); 296bf215546Sopenharmony_ci PUSH_DATA (push, 65536); 297bf215546Sopenharmony_ci PUSH_DATA (push, 1); 298bf215546Sopenharmony_ci PUSH_DATAh(push, dst->offset + offset); 299bf215546Sopenharmony_ci PUSH_DATA (push, dst->offset + offset); 300bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_2D(SIFC_BITMAP_ENABLE), 2); 301bf215546Sopenharmony_ci PUSH_DATA (push, 0); 302bf215546Sopenharmony_ci PUSH_DATA (push, G80_SURFACE_FORMAT_R8_UNORM); 303bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_2D(SIFC_WIDTH), 10); 304bf215546Sopenharmony_ci PUSH_DATA (push, size); 305bf215546Sopenharmony_ci PUSH_DATA (push, 1); 306bf215546Sopenharmony_ci PUSH_DATA (push, 0); 307bf215546Sopenharmony_ci PUSH_DATA (push, 1); 308bf215546Sopenharmony_ci PUSH_DATA (push, 0); 309bf215546Sopenharmony_ci PUSH_DATA (push, 1); 310bf215546Sopenharmony_ci PUSH_DATA (push, 0); 311bf215546Sopenharmony_ci PUSH_DATA (push, xcoord); 312bf215546Sopenharmony_ci PUSH_DATA (push, 0); 313bf215546Sopenharmony_ci PUSH_DATA (push, 0); 314bf215546Sopenharmony_ci 315bf215546Sopenharmony_ci while (count) { 316bf215546Sopenharmony_ci unsigned nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN); 317bf215546Sopenharmony_ci 318bf215546Sopenharmony_ci BEGIN_NI04(push, NV50_2D(SIFC_DATA), nr); 319bf215546Sopenharmony_ci PUSH_DATAp(push, src, nr); 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci src += nr; 322bf215546Sopenharmony_ci count -= nr; 323bf215546Sopenharmony_ci } 324bf215546Sopenharmony_ci 325bf215546Sopenharmony_ci nouveau_bufctx_reset(nv50->bufctx, 0); 326bf215546Sopenharmony_ci} 327bf215546Sopenharmony_ci 328bf215546Sopenharmony_civoid 329bf215546Sopenharmony_cinv50_m2mf_copy_linear(struct nouveau_context *nv, 330bf215546Sopenharmony_ci struct nouveau_bo *dst, unsigned dstoff, unsigned dstdom, 331bf215546Sopenharmony_ci struct nouveau_bo *src, unsigned srcoff, unsigned srcdom, 332bf215546Sopenharmony_ci unsigned size) 333bf215546Sopenharmony_ci{ 334bf215546Sopenharmony_ci struct nouveau_pushbuf *push = nv->pushbuf; 335bf215546Sopenharmony_ci struct nouveau_bufctx *bctx = nv50_context(&nv->pipe)->bufctx; 336bf215546Sopenharmony_ci 337bf215546Sopenharmony_ci nouveau_bufctx_refn(bctx, 0, src, srcdom | NOUVEAU_BO_RD); 338bf215546Sopenharmony_ci nouveau_bufctx_refn(bctx, 0, dst, dstdom | NOUVEAU_BO_WR); 339bf215546Sopenharmony_ci nouveau_pushbuf_bufctx(push, bctx); 340bf215546Sopenharmony_ci nouveau_pushbuf_validate(push); 341bf215546Sopenharmony_ci 342bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_M2MF(LINEAR_IN), 1); 343bf215546Sopenharmony_ci PUSH_DATA (push, 1); 344bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_M2MF(LINEAR_OUT), 1); 345bf215546Sopenharmony_ci PUSH_DATA (push, 1); 346bf215546Sopenharmony_ci 347bf215546Sopenharmony_ci while (size) { 348bf215546Sopenharmony_ci unsigned bytes = MIN2(size, 1 << 17); 349bf215546Sopenharmony_ci 350bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_M2MF(OFFSET_IN_HIGH), 2); 351bf215546Sopenharmony_ci PUSH_DATAh(push, src->offset + srcoff); 352bf215546Sopenharmony_ci PUSH_DATAh(push, dst->offset + dstoff); 353bf215546Sopenharmony_ci BEGIN_NV04(push, SUBC_M2MF(NV03_M2MF_OFFSET_IN), 2); 354bf215546Sopenharmony_ci PUSH_DATA (push, src->offset + srcoff); 355bf215546Sopenharmony_ci PUSH_DATA (push, dst->offset + dstoff); 356bf215546Sopenharmony_ci BEGIN_NV04(push, SUBC_M2MF(NV03_M2MF_LINE_LENGTH_IN), 4); 357bf215546Sopenharmony_ci PUSH_DATA (push, bytes); 358bf215546Sopenharmony_ci PUSH_DATA (push, 1); 359bf215546Sopenharmony_ci PUSH_DATA (push, (1 << 8) | (1 << 0)); 360bf215546Sopenharmony_ci PUSH_DATA (push, 0); 361bf215546Sopenharmony_ci 362bf215546Sopenharmony_ci srcoff += bytes; 363bf215546Sopenharmony_ci dstoff += bytes; 364bf215546Sopenharmony_ci size -= bytes; 365bf215546Sopenharmony_ci } 366bf215546Sopenharmony_ci 367bf215546Sopenharmony_ci nouveau_bufctx_reset(bctx, 0); 368bf215546Sopenharmony_ci} 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_civoid * 371bf215546Sopenharmony_cinv50_miptree_transfer_map(struct pipe_context *pctx, 372bf215546Sopenharmony_ci struct pipe_resource *res, 373bf215546Sopenharmony_ci unsigned level, 374bf215546Sopenharmony_ci unsigned usage, 375bf215546Sopenharmony_ci const struct pipe_box *box, 376bf215546Sopenharmony_ci struct pipe_transfer **ptransfer) 377bf215546Sopenharmony_ci{ 378bf215546Sopenharmony_ci struct nv50_context *nv50 = nv50_context(pctx); 379bf215546Sopenharmony_ci struct nouveau_device *dev = nv50->screen->base.device; 380bf215546Sopenharmony_ci const struct nv50_miptree *mt = nv50_miptree(res); 381bf215546Sopenharmony_ci struct nv50_transfer *tx; 382bf215546Sopenharmony_ci uint32_t size; 383bf215546Sopenharmony_ci int ret; 384bf215546Sopenharmony_ci unsigned flags = 0; 385bf215546Sopenharmony_ci 386bf215546Sopenharmony_ci if (usage & PIPE_MAP_DIRECTLY) 387bf215546Sopenharmony_ci return NULL; 388bf215546Sopenharmony_ci 389bf215546Sopenharmony_ci tx = CALLOC_STRUCT(nv50_transfer); 390bf215546Sopenharmony_ci if (!tx) 391bf215546Sopenharmony_ci return NULL; 392bf215546Sopenharmony_ci 393bf215546Sopenharmony_ci pipe_resource_reference(&tx->base.resource, res); 394bf215546Sopenharmony_ci 395bf215546Sopenharmony_ci tx->base.level = level; 396bf215546Sopenharmony_ci tx->base.usage = usage; 397bf215546Sopenharmony_ci tx->base.box = *box; 398bf215546Sopenharmony_ci 399bf215546Sopenharmony_ci if (util_format_is_plain(res->format)) { 400bf215546Sopenharmony_ci tx->nblocksx = box->width << mt->ms_x; 401bf215546Sopenharmony_ci tx->nblocksy = box->height << mt->ms_y; 402bf215546Sopenharmony_ci } else { 403bf215546Sopenharmony_ci tx->nblocksx = util_format_get_nblocksx(res->format, box->width); 404bf215546Sopenharmony_ci tx->nblocksy = util_format_get_nblocksy(res->format, box->height); 405bf215546Sopenharmony_ci } 406bf215546Sopenharmony_ci 407bf215546Sopenharmony_ci tx->base.stride = tx->nblocksx * util_format_get_blocksize(res->format); 408bf215546Sopenharmony_ci tx->base.layer_stride = tx->nblocksy * tx->base.stride; 409bf215546Sopenharmony_ci 410bf215546Sopenharmony_ci nv50_m2mf_rect_setup(&tx->rect[0], res, level, box->x, box->y, box->z); 411bf215546Sopenharmony_ci 412bf215546Sopenharmony_ci size = tx->base.layer_stride; 413bf215546Sopenharmony_ci 414bf215546Sopenharmony_ci ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, 415bf215546Sopenharmony_ci size * tx->base.box.depth, NULL, &tx->rect[1].bo); 416bf215546Sopenharmony_ci if (ret) { 417bf215546Sopenharmony_ci FREE(tx); 418bf215546Sopenharmony_ci return NULL; 419bf215546Sopenharmony_ci } 420bf215546Sopenharmony_ci 421bf215546Sopenharmony_ci tx->rect[1].cpp = tx->rect[0].cpp; 422bf215546Sopenharmony_ci tx->rect[1].width = tx->nblocksx; 423bf215546Sopenharmony_ci tx->rect[1].height = tx->nblocksy; 424bf215546Sopenharmony_ci tx->rect[1].depth = 1; 425bf215546Sopenharmony_ci tx->rect[1].pitch = tx->base.stride; 426bf215546Sopenharmony_ci tx->rect[1].domain = NOUVEAU_BO_GART; 427bf215546Sopenharmony_ci 428bf215546Sopenharmony_ci if (usage & PIPE_MAP_READ) { 429bf215546Sopenharmony_ci unsigned base = tx->rect[0].base; 430bf215546Sopenharmony_ci unsigned z = tx->rect[0].z; 431bf215546Sopenharmony_ci unsigned i; 432bf215546Sopenharmony_ci for (i = 0; i < box->depth; ++i) { 433bf215546Sopenharmony_ci nv50_m2mf_transfer_rect(nv50, &tx->rect[1], &tx->rect[0], 434bf215546Sopenharmony_ci tx->nblocksx, tx->nblocksy); 435bf215546Sopenharmony_ci if (mt->layout_3d) 436bf215546Sopenharmony_ci tx->rect[0].z++; 437bf215546Sopenharmony_ci else 438bf215546Sopenharmony_ci tx->rect[0].base += mt->layer_stride; 439bf215546Sopenharmony_ci tx->rect[1].base += size; 440bf215546Sopenharmony_ci } 441bf215546Sopenharmony_ci tx->rect[0].z = z; 442bf215546Sopenharmony_ci tx->rect[0].base = base; 443bf215546Sopenharmony_ci tx->rect[1].base = 0; 444bf215546Sopenharmony_ci } 445bf215546Sopenharmony_ci 446bf215546Sopenharmony_ci if (tx->rect[1].bo->map) { 447bf215546Sopenharmony_ci *ptransfer = &tx->base; 448bf215546Sopenharmony_ci return tx->rect[1].bo->map; 449bf215546Sopenharmony_ci } 450bf215546Sopenharmony_ci 451bf215546Sopenharmony_ci if (usage & PIPE_MAP_READ) 452bf215546Sopenharmony_ci flags = NOUVEAU_BO_RD; 453bf215546Sopenharmony_ci if (usage & PIPE_MAP_WRITE) 454bf215546Sopenharmony_ci flags |= NOUVEAU_BO_WR; 455bf215546Sopenharmony_ci 456bf215546Sopenharmony_ci ret = nouveau_bo_map(tx->rect[1].bo, flags, nv50->base.client); 457bf215546Sopenharmony_ci if (ret) { 458bf215546Sopenharmony_ci nouveau_bo_ref(NULL, &tx->rect[1].bo); 459bf215546Sopenharmony_ci FREE(tx); 460bf215546Sopenharmony_ci return NULL; 461bf215546Sopenharmony_ci } 462bf215546Sopenharmony_ci 463bf215546Sopenharmony_ci *ptransfer = &tx->base; 464bf215546Sopenharmony_ci return tx->rect[1].bo->map; 465bf215546Sopenharmony_ci} 466bf215546Sopenharmony_ci 467bf215546Sopenharmony_civoid 468bf215546Sopenharmony_cinv50_miptree_transfer_unmap(struct pipe_context *pctx, 469bf215546Sopenharmony_ci struct pipe_transfer *transfer) 470bf215546Sopenharmony_ci{ 471bf215546Sopenharmony_ci struct nv50_context *nv50 = nv50_context(pctx); 472bf215546Sopenharmony_ci struct nv50_transfer *tx = (struct nv50_transfer *)transfer; 473bf215546Sopenharmony_ci struct nv50_miptree *mt = nv50_miptree(tx->base.resource); 474bf215546Sopenharmony_ci unsigned i; 475bf215546Sopenharmony_ci 476bf215546Sopenharmony_ci if (tx->base.usage & PIPE_MAP_WRITE) { 477bf215546Sopenharmony_ci for (i = 0; i < tx->base.box.depth; ++i) { 478bf215546Sopenharmony_ci nv50_m2mf_transfer_rect(nv50, &tx->rect[0], &tx->rect[1], 479bf215546Sopenharmony_ci tx->nblocksx, tx->nblocksy); 480bf215546Sopenharmony_ci if (mt->layout_3d) 481bf215546Sopenharmony_ci tx->rect[0].z++; 482bf215546Sopenharmony_ci else 483bf215546Sopenharmony_ci tx->rect[0].base += mt->layer_stride; 484bf215546Sopenharmony_ci tx->rect[1].base += tx->nblocksy * tx->base.stride; 485bf215546Sopenharmony_ci } 486bf215546Sopenharmony_ci 487bf215546Sopenharmony_ci /* Allow the copies above to finish executing before freeing the source */ 488bf215546Sopenharmony_ci nouveau_fence_work(nv50->screen->base.fence.current, 489bf215546Sopenharmony_ci nouveau_fence_unref_bo, tx->rect[1].bo); 490bf215546Sopenharmony_ci } else { 491bf215546Sopenharmony_ci nouveau_bo_ref(NULL, &tx->rect[1].bo); 492bf215546Sopenharmony_ci } 493bf215546Sopenharmony_ci 494bf215546Sopenharmony_ci pipe_resource_reference(&transfer->resource, NULL); 495bf215546Sopenharmony_ci 496bf215546Sopenharmony_ci FREE(tx); 497bf215546Sopenharmony_ci} 498bf215546Sopenharmony_ci 499bf215546Sopenharmony_cistatic void 500bf215546Sopenharmony_cinv50_cb_bo_push(struct nouveau_context *nv, 501bf215546Sopenharmony_ci struct nouveau_bo *bo, unsigned domain, 502bf215546Sopenharmony_ci unsigned bufid, 503bf215546Sopenharmony_ci unsigned offset, unsigned words, 504bf215546Sopenharmony_ci const uint32_t *data) 505bf215546Sopenharmony_ci{ 506bf215546Sopenharmony_ci struct nouveau_pushbuf *push = nv->pushbuf; 507bf215546Sopenharmony_ci 508bf215546Sopenharmony_ci assert(!(offset & 3)); 509bf215546Sopenharmony_ci 510bf215546Sopenharmony_ci while (words) { 511bf215546Sopenharmony_ci unsigned nr = MIN2(words, NV04_PFIFO_MAX_PACKET_LEN); 512bf215546Sopenharmony_ci 513bf215546Sopenharmony_ci PUSH_SPACE(push, nr + 3); 514bf215546Sopenharmony_ci PUSH_REFN (push, bo, NOUVEAU_BO_WR | domain); 515bf215546Sopenharmony_ci BEGIN_NV04(push, NV50_3D(CB_ADDR), 1); 516bf215546Sopenharmony_ci PUSH_DATA (push, (offset << 6) | bufid); 517bf215546Sopenharmony_ci BEGIN_NI04(push, NV50_3D(CB_DATA(0)), nr); 518bf215546Sopenharmony_ci PUSH_DATAp(push, data, nr); 519bf215546Sopenharmony_ci 520bf215546Sopenharmony_ci words -= nr; 521bf215546Sopenharmony_ci data += nr; 522bf215546Sopenharmony_ci offset += nr * 4; 523bf215546Sopenharmony_ci } 524bf215546Sopenharmony_ci} 525bf215546Sopenharmony_ci 526bf215546Sopenharmony_civoid 527bf215546Sopenharmony_cinv50_cb_push(struct nouveau_context *nv, 528bf215546Sopenharmony_ci struct nv04_resource *res, 529bf215546Sopenharmony_ci unsigned offset, unsigned words, const uint32_t *data) 530bf215546Sopenharmony_ci{ 531bf215546Sopenharmony_ci struct nv50_context *nv50 = nv50_context(&nv->pipe); 532bf215546Sopenharmony_ci struct nv50_constbuf *cb = NULL; 533bf215546Sopenharmony_ci int s, bufid; 534bf215546Sopenharmony_ci /* Go through all the constbuf binding points of this buffer and try to 535bf215546Sopenharmony_ci * find one which contains the region to be updated. 536bf215546Sopenharmony_ci */ 537bf215546Sopenharmony_ci for (s = 0; s < NV50_MAX_SHADER_STAGES && !cb; s++) { 538bf215546Sopenharmony_ci uint16_t bindings = res->cb_bindings[s]; 539bf215546Sopenharmony_ci while (bindings) { 540bf215546Sopenharmony_ci int i = ffs(bindings) - 1; 541bf215546Sopenharmony_ci uint32_t cb_offset = nv50->constbuf[s][i].offset; 542bf215546Sopenharmony_ci 543bf215546Sopenharmony_ci bindings &= ~(1 << i); 544bf215546Sopenharmony_ci if (cb_offset <= offset && 545bf215546Sopenharmony_ci cb_offset + nv50->constbuf[s][i].size >= offset + words * 4) { 546bf215546Sopenharmony_ci cb = &nv50->constbuf[s][i]; 547bf215546Sopenharmony_ci bufid = s * 16 + i; 548bf215546Sopenharmony_ci break; 549bf215546Sopenharmony_ci } 550bf215546Sopenharmony_ci } 551bf215546Sopenharmony_ci } 552bf215546Sopenharmony_ci 553bf215546Sopenharmony_ci if (cb) { 554bf215546Sopenharmony_ci nv50_cb_bo_push(nv, res->bo, res->domain, 555bf215546Sopenharmony_ci bufid, offset - cb->offset, words, data); 556bf215546Sopenharmony_ci } else { 557bf215546Sopenharmony_ci nv->push_data(nv, res->bo, res->offset + offset, res->domain, 558bf215546Sopenharmony_ci words * 4, data); 559bf215546Sopenharmony_ci } 560bf215546Sopenharmony_ci} 561