diff options
Diffstat (limited to 'src/gallium/drivers/nvc0/nvc0_transfer.c')
-rw-r--r-- | src/gallium/drivers/nvc0/nvc0_transfer.c | 159 |
1 files changed, 154 insertions, 5 deletions
diff --git a/src/gallium/drivers/nvc0/nvc0_transfer.c b/src/gallium/drivers/nvc0/nvc0_transfer.c index 774793d8d02..fb44190574e 100644 --- a/src/gallium/drivers/nvc0/nvc0_transfer.c +++ b/src/gallium/drivers/nvc0/nvc0_transfer.c | |||
@@ -13,7 +13,7 @@ struct nvc0_transfer { | |||
13 | uint16_t nlayers; | 13 | uint16_t nlayers; |
14 | }; | 14 | }; |
15 | 15 | ||
16 | void | 16 | static void |
17 | nvc0_m2mf_transfer_rect(struct nvc0_context *nvc0, | 17 | nvc0_m2mf_transfer_rect(struct nvc0_context *nvc0, |
18 | const struct nv50_m2mf_rect *dst, | 18 | const struct nv50_m2mf_rect *dst, |
19 | const struct nv50_m2mf_rect *src, | 19 | const struct nv50_m2mf_rect *src, |
@@ -108,6 +108,71 @@ nvc0_m2mf_transfer_rect(struct nvc0_context *nvc0, | |||
108 | nouveau_bufctx_reset(bctx, 0); | 108 | nouveau_bufctx_reset(bctx, 0); |
109 | } | 109 | } |
110 | 110 | ||
111 | static void | ||
112 | nve4_m2mf_transfer_rect(struct nvc0_context *nvc0, | ||
113 | const struct nv50_m2mf_rect *dst, | ||
114 | const struct nv50_m2mf_rect *src, | ||
115 | uint32_t nblocksx, uint32_t nblocksy) | ||
116 | { | ||
117 | struct nouveau_pushbuf *push = nvc0->base.pushbuf; | ||
118 | struct nouveau_bufctx *bctx = nvc0->bufctx; | ||
119 | uint32_t exec; | ||
120 | uint32_t src_base = src->base; | ||
121 | uint32_t dst_base = dst->base; | ||
122 | const int cpp = dst->cpp; | ||
123 | |||
124 | assert(dst->cpp == src->cpp); | ||
125 | |||
126 | nouveau_bufctx_refn(bctx, 0, dst->bo, dst->domain | NOUVEAU_BO_WR); | ||
127 | nouveau_bufctx_refn(bctx, 0, src->bo, src->domain | NOUVEAU_BO_RD); | ||
128 | nouveau_pushbuf_bufctx(push, bctx); | ||
129 | nouveau_pushbuf_validate(push); | ||
130 | |||
131 | exec = 0x200 /* 2D_ENABLE */ | 0x6 /* UNK */; | ||
132 | |||
133 | if (!nouveau_bo_memtype(dst->bo)) { | ||
134 | assert(!dst->z); | ||
135 | dst_base += dst->y * dst->pitch + dst->x * cpp; | ||
136 | exec |= 0x100; /* DST_MODE_2D_LINEAR */ | ||
137 | } | ||
138 | if (!nouveau_bo_memtype(src->bo)) { | ||
139 | assert(!src->z); | ||
140 | src_base += src->y * src->pitch + src->x * cpp; | ||
141 | exec |= 0x080; /* SRC_MODE_2D_LINEAR */ | ||
142 | } | ||
143 | |||
144 | BEGIN_NVC0(push, SUBC_COPY(0x070c), 6); | ||
145 | PUSH_DATA (push, 0x1000 | dst->tile_mode); | ||
146 | PUSH_DATA (push, dst->pitch); | ||
147 | PUSH_DATA (push, dst->height); | ||
148 | PUSH_DATA (push, dst->depth); | ||
149 | PUSH_DATA (push, dst->z); | ||
150 | PUSH_DATA (push, (dst->y << 16) | (dst->x * cpp)); | ||
151 | |||
152 | BEGIN_NVC0(push, SUBC_COPY(0x0728), 6); | ||
153 | PUSH_DATA (push, 0x1000 | src->tile_mode); | ||
154 | PUSH_DATA (push, src->pitch); | ||
155 | PUSH_DATA (push, src->height); | ||
156 | PUSH_DATA (push, src->depth); | ||
157 | PUSH_DATA (push, src->z); | ||
158 | PUSH_DATA (push, (src->y << 16) | (src->x * cpp)); | ||
159 | |||
160 | BEGIN_NVC0(push, SUBC_COPY(0x0400), 8); | ||
161 | PUSH_DATAh(push, src->bo->offset + src_base); | ||
162 | PUSH_DATA (push, src->bo->offset + src_base); | ||
163 | PUSH_DATAh(push, dst->bo->offset + dst_base); | ||
164 | PUSH_DATA (push, dst->bo->offset + dst_base); | ||
165 | PUSH_DATA (push, src->pitch); | ||
166 | PUSH_DATA (push, dst->pitch); | ||
167 | PUSH_DATA (push, nblocksx * cpp); | ||
168 | PUSH_DATA (push, nblocksy); | ||
169 | |||
170 | BEGIN_NVC0(push, SUBC_COPY(0x0300), 1); | ||
171 | PUSH_DATA (push, exec); | ||
172 | |||
173 | nouveau_bufctx_reset(bctx, 0); | ||
174 | } | ||
175 | |||
111 | void | 176 | void |
112 | nvc0_m2mf_push_linear(struct nouveau_context *nv, | 177 | nvc0_m2mf_push_linear(struct nouveau_context *nv, |
113 | struct nouveau_bo *dst, unsigned offset, unsigned domain, | 178 | struct nouveau_bo *dst, unsigned offset, unsigned domain, |
@@ -154,6 +219,49 @@ nvc0_m2mf_push_linear(struct nouveau_context *nv, | |||
154 | } | 219 | } |
155 | 220 | ||
156 | void | 221 | void |
222 | nve4_p2mf_push_linear(struct nouveau_context *nv, | ||
223 | struct nouveau_bo *dst, unsigned offset, unsigned domain, | ||
224 | unsigned size, const void *data) | ||
225 | { | ||
226 | struct nvc0_context *nvc0 = nvc0_context(&nv->pipe); | ||
227 | struct nouveau_pushbuf *push = nv->pushbuf; | ||
228 | uint32_t *src = (uint32_t *)data; | ||
229 | unsigned count = (size + 3) / 4; | ||
230 | |||
231 | nouveau_bufctx_refn(nvc0->bufctx, 0, dst, domain | NOUVEAU_BO_WR); | ||
232 | nouveau_pushbuf_bufctx(push, nvc0->bufctx); | ||
233 | nouveau_pushbuf_validate(push); | ||
234 | |||
235 | while (count) { | ||
236 | unsigned nr; | ||
237 | |||
238 | if (!PUSH_SPACE(push, 16)) | ||
239 | break; | ||
240 | nr = PUSH_AVAIL(push); | ||
241 | assert(nr >= 16); | ||
242 | nr = MIN2(count, nr - 8); | ||
243 | nr = MIN2(nr, (NV04_PFIFO_MAX_PACKET_LEN - 1)); | ||
244 | |||
245 | BEGIN_NVC0(push, NVE4_P2MF(DST_ADDRESS_HIGH), 2); | ||
246 | PUSH_DATAh(push, dst->offset + offset); | ||
247 | PUSH_DATA (push, dst->offset + offset); | ||
248 | BEGIN_NVC0(push, NVE4_P2MF(LINE_LENGTH_IN), 2); | ||
249 | PUSH_DATA (push, nr * 4); | ||
250 | PUSH_DATA (push, 1); | ||
251 | /* must not be interrupted (trap on QUERY fence, 0x50 works however) */ | ||
252 | BEGIN_1IC0(push, NVE4_P2MF(EXEC), nr + 1); | ||
253 | PUSH_DATA (push, 0x1001); | ||
254 | PUSH_DATAp(push, src, nr); | ||
255 | |||
256 | count -= nr; | ||
257 | src += nr; | ||
258 | offset += nr * 4; | ||
259 | } | ||
260 | |||
261 | nouveau_bufctx_reset(nvc0->bufctx, 0); | ||
262 | } | ||
263 | |||
264 | static void | ||
157 | nvc0_m2mf_copy_linear(struct nouveau_context *nv, | 265 | nvc0_m2mf_copy_linear(struct nouveau_context *nv, |
158 | struct nouveau_bo *dst, unsigned dstoff, unsigned dstdom, | 266 | struct nouveau_bo *dst, unsigned dstoff, unsigned dstdom, |
159 | struct nouveau_bo *src, unsigned srcoff, unsigned srcdom, | 267 | struct nouveau_bo *src, unsigned srcoff, unsigned srcdom, |
@@ -191,6 +299,32 @@ nvc0_m2mf_copy_linear(struct nouveau_context *nv, | |||
191 | nouveau_bufctx_reset(bctx, 0); | 299 | nouveau_bufctx_reset(bctx, 0); |
192 | } | 300 | } |
193 | 301 | ||
302 | static void | ||
303 | nve4_m2mf_copy_linear(struct nouveau_context *nv, | ||
304 | struct nouveau_bo *dst, unsigned dstoff, unsigned dstdom, | ||
305 | struct nouveau_bo *src, unsigned srcoff, unsigned srcdom, | ||
306 | unsigned size) | ||
307 | { | ||
308 | struct nouveau_pushbuf *push = nv->pushbuf; | ||
309 | struct nouveau_bufctx *bctx = nvc0_context(&nv->pipe)->bufctx; | ||
310 | |||
311 | nouveau_bufctx_refn(bctx, 0, src, srcdom | NOUVEAU_BO_RD); | ||
312 | nouveau_bufctx_refn(bctx, 0, dst, dstdom | NOUVEAU_BO_WR); | ||
313 | nouveau_pushbuf_bufctx(push, bctx); | ||
314 | nouveau_pushbuf_validate(push); | ||
315 | |||
316 | BEGIN_NVC0(push, SUBC_COPY(0x0400), 4); | ||
317 | PUSH_DATAh(push, src->offset + srcoff); | ||
318 | PUSH_DATA (push, src->offset + srcoff); | ||
319 | PUSH_DATAh(push, dst->offset + dstoff); | ||
320 | PUSH_DATA (push, dst->offset + dstoff); | ||
321 | BEGIN_NVC0(push, SUBC_COPY(0x0418), 1); | ||
322 | PUSH_DATA (push, size); | ||
323 | IMMED_NVC0(push, SUBC_COPY(0x0300), 0x6); | ||
324 | |||
325 | nouveau_bufctx_reset(bctx, 0); | ||
326 | } | ||
327 | |||
194 | struct pipe_transfer * | 328 | struct pipe_transfer * |
195 | nvc0_miptree_transfer_new(struct pipe_context *pctx, | 329 | nvc0_miptree_transfer_new(struct pipe_context *pctx, |
196 | struct pipe_resource *res, | 330 | struct pipe_resource *res, |
@@ -253,8 +387,8 @@ nvc0_miptree_transfer_new(struct pipe_context *pctx, | |||
253 | unsigned z = tx->rect[0].z; | 387 | unsigned z = tx->rect[0].z; |
254 | unsigned i; | 388 | unsigned i; |
255 | for (i = 0; i < tx->nlayers; ++i) { | 389 | for (i = 0; i < tx->nlayers; ++i) { |
256 | nvc0_m2mf_transfer_rect(nvc0, &tx->rect[1], &tx->rect[0], | 390 | nvc0->m2mf_copy_rect(nvc0, &tx->rect[1], &tx->rect[0], |
257 | tx->nblocksx, tx->nblocksy); | 391 | tx->nblocksx, tx->nblocksy); |
258 | if (mt->layout_3d) | 392 | if (mt->layout_3d) |
259 | tx->rect[0].z++; | 393 | tx->rect[0].z++; |
260 | else | 394 | else |
@@ -280,8 +414,8 @@ nvc0_miptree_transfer_del(struct pipe_context *pctx, | |||
280 | 414 | ||
281 | if (tx->base.usage & PIPE_TRANSFER_WRITE) { | 415 | if (tx->base.usage & PIPE_TRANSFER_WRITE) { |
282 | for (i = 0; i < tx->nlayers; ++i) { | 416 | for (i = 0; i < tx->nlayers; ++i) { |
283 | nvc0_m2mf_transfer_rect(nvc0, &tx->rect[0], &tx->rect[1], | 417 | nvc0->m2mf_copy_rect(nvc0, &tx->rect[0], &tx->rect[1], |
284 | tx->nblocksx, tx->nblocksy); | 418 | tx->nblocksx, tx->nblocksy); |
285 | if (mt->layout_3d) | 419 | if (mt->layout_3d) |
286 | tx->rect[0].z++; | 420 | tx->rect[0].z++; |
287 | else | 421 | else |
@@ -362,3 +496,18 @@ nvc0_cb_push(struct nouveau_context *nv, | |||
362 | 496 | ||
363 | nouveau_bufctx_reset(bctx, 0); | 497 | nouveau_bufctx_reset(bctx, 0); |
364 | } | 498 | } |
499 | |||
500 | void | ||
501 | nvc0_init_transfer_functions(struct nvc0_context *nvc0) | ||
502 | { | ||
503 | if (nvc0->screen->base.class_3d >= NVE4_3D_CLASS) { | ||
504 | nvc0->m2mf_copy_rect = nve4_m2mf_transfer_rect; | ||
505 | nvc0->base.copy_data = nve4_m2mf_copy_linear; | ||
506 | nvc0->base.push_data = nve4_p2mf_push_linear; | ||
507 | } else { | ||
508 | nvc0->m2mf_copy_rect = nvc0_m2mf_transfer_rect; | ||
509 | nvc0->base.copy_data = nvc0_m2mf_copy_linear; | ||
510 | nvc0->base.push_data = nvc0_m2mf_push_linear; | ||
511 | } | ||
512 | nvc0->base.push_cb = nvc0_cb_push; | ||
513 | } | ||