2 #include "util/u_format.h"
4 #include "nvc0_context.h"
6 #include "nv50/nv50_defs.xml.h"
9 struct pipe_transfer base
;
10 struct nv50_m2mf_rect rect
[2];
17 nvc0_m2mf_transfer_rect(struct nvc0_context
*nvc0
,
18 const struct nv50_m2mf_rect
*dst
,
19 const struct nv50_m2mf_rect
*src
,
20 uint32_t nblocksx
, uint32_t nblocksy
)
22 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
23 struct nouveau_bufctx
*bctx
= nvc0
->bufctx
;
24 const int cpp
= dst
->cpp
;
25 uint32_t src_ofst
= src
->base
;
26 uint32_t dst_ofst
= dst
->base
;
27 uint32_t height
= nblocksy
;
30 uint32_t exec
= (1 << 20);
32 assert(dst
->cpp
== src
->cpp
);
34 nouveau_bufctx_refn(bctx
, 0, src
->bo
, src
->domain
| NOUVEAU_BO_RD
);
35 nouveau_bufctx_refn(bctx
, 0, dst
->bo
, dst
->domain
| NOUVEAU_BO_WR
);
36 nouveau_pushbuf_bufctx(push
, bctx
);
37 nouveau_pushbuf_validate(push
);
39 if (nouveau_bo_memtype(src
->bo
)) {
40 BEGIN_NVC0(push
, NVC0_M2MF(TILING_MODE_IN
), 5);
41 PUSH_DATA (push
, src
->tile_mode
);
42 PUSH_DATA (push
, src
->width
* cpp
);
43 PUSH_DATA (push
, src
->height
);
44 PUSH_DATA (push
, src
->depth
);
45 PUSH_DATA (push
, src
->z
);
47 src_ofst
+= src
->y
* src
->pitch
+ src
->x
* cpp
;
49 BEGIN_NVC0(push
, NVC0_M2MF(PITCH_IN
), 1);
50 PUSH_DATA (push
, src
->width
* cpp
);
52 exec
|= NVC0_M2MF_EXEC_LINEAR_IN
;
55 if (nouveau_bo_memtype(dst
->bo
)) {
56 BEGIN_NVC0(push
, NVC0_M2MF(TILING_MODE_OUT
), 5);
57 PUSH_DATA (push
, dst
->tile_mode
);
58 PUSH_DATA (push
, dst
->width
* cpp
);
59 PUSH_DATA (push
, dst
->height
);
60 PUSH_DATA (push
, dst
->depth
);
61 PUSH_DATA (push
, dst
->z
);
63 dst_ofst
+= dst
->y
* dst
->pitch
+ dst
->x
* cpp
;
65 BEGIN_NVC0(push
, NVC0_M2MF(PITCH_OUT
), 1);
66 PUSH_DATA (push
, dst
->width
* cpp
);
68 exec
|= NVC0_M2MF_EXEC_LINEAR_OUT
;
72 int line_count
= height
> 2047 ? 2047 : height
;
74 BEGIN_NVC0(push
, NVC0_M2MF(OFFSET_IN_HIGH
), 2);
75 PUSH_DATAh(push
, src
->bo
->offset
+ src_ofst
);
76 PUSH_DATA (push
, src
->bo
->offset
+ src_ofst
);
78 BEGIN_NVC0(push
, NVC0_M2MF(OFFSET_OUT_HIGH
), 2);
79 PUSH_DATAh(push
, dst
->bo
->offset
+ dst_ofst
);
80 PUSH_DATA (push
, dst
->bo
->offset
+ dst_ofst
);
82 if (!(exec
& NVC0_M2MF_EXEC_LINEAR_IN
)) {
83 BEGIN_NVC0(push
, NVC0_M2MF(TILING_POSITION_IN_X
), 2);
84 PUSH_DATA (push
, src
->x
* cpp
);
87 src_ofst
+= line_count
* src
->pitch
;
89 if (!(exec
& NVC0_M2MF_EXEC_LINEAR_OUT
)) {
90 BEGIN_NVC0(push
, NVC0_M2MF(TILING_POSITION_OUT_X
), 2);
91 PUSH_DATA (push
, dst
->x
* cpp
);
94 dst_ofst
+= line_count
* dst
->pitch
;
97 BEGIN_NVC0(push
, NVC0_M2MF(LINE_LENGTH_IN
), 2);
98 PUSH_DATA (push
, nblocksx
* cpp
);
99 PUSH_DATA (push
, line_count
);
100 BEGIN_NVC0(push
, NVC0_M2MF(EXEC
), 1);
101 PUSH_DATA (push
, exec
);
103 height
-= line_count
;
108 nouveau_bufctx_reset(bctx
, 0);
112 nvc0_m2mf_push_linear(struct nouveau_context
*nv
,
113 struct nouveau_bo
*dst
, unsigned offset
, unsigned domain
,
114 unsigned size
, const void *data
)
116 struct nvc0_context
*nvc0
= nvc0_context(&nv
->pipe
);
117 struct nouveau_pushbuf
*push
= nv
->pushbuf
;
118 uint32_t *src
= (uint32_t *)data
;
119 unsigned count
= (size
+ 3) / 4;
121 nouveau_bufctx_refn(nvc0
->bufctx
, 0, dst
, domain
| NOUVEAU_BO_WR
);
122 nouveau_pushbuf_bufctx(push
, nvc0
->bufctx
);
123 nouveau_pushbuf_validate(push
);
128 if (!PUSH_SPACE(push
, 16))
130 nr
= PUSH_AVAIL(push
);
132 nr
= MIN2(count
, nr
- 9);
133 nr
= MIN2(nr
, NV04_PFIFO_MAX_PACKET_LEN
);
135 BEGIN_NVC0(push
, NVC0_M2MF(OFFSET_OUT_HIGH
), 2);
136 PUSH_DATAh(push
, dst
->offset
+ offset
);
137 PUSH_DATA (push
, dst
->offset
+ offset
);
138 BEGIN_NVC0(push
, NVC0_M2MF(LINE_LENGTH_IN
), 2);
139 PUSH_DATA (push
, nr
* 4);
141 BEGIN_NVC0(push
, NVC0_M2MF(EXEC
), 1);
142 PUSH_DATA (push
, 0x100111);
144 /* must not be interrupted (trap on QUERY fence, 0x50 works however) */
145 BEGIN_NIC0(push
, NVC0_M2MF(DATA
), nr
);
146 PUSH_DATAp(push
, src
, nr
);
153 nouveau_bufctx_reset(nvc0
->bufctx
, 0);
157 nvc0_m2mf_copy_linear(struct nouveau_context
*nv
,
158 struct nouveau_bo
*dst
, unsigned dstoff
, unsigned dstdom
,
159 struct nouveau_bo
*src
, unsigned srcoff
, unsigned srcdom
,
162 struct nouveau_pushbuf
*push
= nv
->pushbuf
;
163 struct nouveau_bufctx
*bctx
= nvc0_context(&nv
->pipe
)->bufctx
;
165 nouveau_bufctx_refn(bctx
, 0, src
, srcdom
| NOUVEAU_BO_RD
);
166 nouveau_bufctx_refn(bctx
, 0, dst
, dstdom
| NOUVEAU_BO_WR
);
167 nouveau_pushbuf_bufctx(push
, bctx
);
168 nouveau_pushbuf_validate(push
);
171 unsigned bytes
= MIN2(size
, 1 << 17);
173 BEGIN_NVC0(push
, NVC0_M2MF(OFFSET_OUT_HIGH
), 2);
174 PUSH_DATAh(push
, dst
->offset
+ dstoff
);
175 PUSH_DATA (push
, dst
->offset
+ dstoff
);
176 BEGIN_NVC0(push
, NVC0_M2MF(OFFSET_IN_HIGH
), 2);
177 PUSH_DATAh(push
, src
->offset
+ srcoff
);
178 PUSH_DATA (push
, src
->offset
+ srcoff
);
179 BEGIN_NVC0(push
, NVC0_M2MF(LINE_LENGTH_IN
), 2);
180 PUSH_DATA (push
, bytes
);
182 BEGIN_NVC0(push
, NVC0_M2MF(EXEC
), 1);
183 PUSH_DATA (push
, (1 << NVC0_M2MF_EXEC_INC__SHIFT
) |
184 NVC0_M2MF_EXEC_LINEAR_IN
| NVC0_M2MF_EXEC_LINEAR_OUT
);
191 nouveau_bufctx_reset(bctx
, 0);
194 struct pipe_transfer
*
195 nvc0_miptree_transfer_new(struct pipe_context
*pctx
,
196 struct pipe_resource
*res
,
199 const struct pipe_box
*box
)
201 struct nvc0_context
*nvc0
= nvc0_context(pctx
);
202 struct nouveau_device
*dev
= nvc0
->screen
->base
.device
;
203 struct nv50_miptree
*mt
= nv50_miptree(res
);
204 struct nvc0_transfer
*tx
;
208 if (usage
& PIPE_TRANSFER_MAP_DIRECTLY
)
211 tx
= CALLOC_STRUCT(nvc0_transfer
);
215 pipe_resource_reference(&tx
->base
.resource
, res
);
217 tx
->base
.level
= level
;
218 tx
->base
.usage
= usage
;
221 if (util_format_is_plain(res
->format
)) {
222 tx
->nblocksx
= box
->width
<< mt
->ms_x
;
223 tx
->nblocksy
= box
->height
<< mt
->ms_y
;
225 tx
->nblocksx
= util_format_get_nblocksx(res
->format
, box
->width
);
226 tx
->nblocksy
= util_format_get_nblocksy(res
->format
, box
->height
);
228 tx
->nlayers
= box
->depth
;
230 tx
->base
.stride
= tx
->nblocksx
* util_format_get_blocksize(res
->format
);
231 tx
->base
.layer_stride
= tx
->nblocksy
* tx
->base
.stride
;
233 nv50_m2mf_rect_setup(&tx
->rect
[0], res
, level
, box
->x
, box
->y
, box
->z
);
235 size
= tx
->base
.layer_stride
;
237 ret
= nouveau_bo_new(dev
, NOUVEAU_BO_GART
| NOUVEAU_BO_MAP
, 0,
238 size
* tx
->nlayers
, NULL
, &tx
->rect
[1].bo
);
244 tx
->rect
[1].cpp
= tx
->rect
[0].cpp
;
245 tx
->rect
[1].width
= tx
->nblocksx
;
246 tx
->rect
[1].height
= tx
->nblocksy
;
247 tx
->rect
[1].depth
= 1;
248 tx
->rect
[1].pitch
= tx
->base
.stride
;
249 tx
->rect
[1].domain
= NOUVEAU_BO_GART
;
251 if (usage
& PIPE_TRANSFER_READ
) {
252 unsigned base
= tx
->rect
[0].base
;
253 unsigned z
= tx
->rect
[0].z
;
255 for (i
= 0; i
< tx
->nlayers
; ++i
) {
256 nvc0_m2mf_transfer_rect(nvc0
, &tx
->rect
[1], &tx
->rect
[0],
257 tx
->nblocksx
, tx
->nblocksy
);
261 tx
->rect
[0].base
+= mt
->layer_stride
;
262 tx
->rect
[1].base
+= size
;
265 tx
->rect
[0].base
= base
;
266 tx
->rect
[1].base
= 0;
273 nvc0_miptree_transfer_del(struct pipe_context
*pctx
,
274 struct pipe_transfer
*transfer
)
276 struct nvc0_context
*nvc0
= nvc0_context(pctx
);
277 struct nvc0_transfer
*tx
= (struct nvc0_transfer
*)transfer
;
278 struct nv50_miptree
*mt
= nv50_miptree(tx
->base
.resource
);
281 if (tx
->base
.usage
& PIPE_TRANSFER_WRITE
) {
282 for (i
= 0; i
< tx
->nlayers
; ++i
) {
283 nvc0_m2mf_transfer_rect(nvc0
, &tx
->rect
[0], &tx
->rect
[1],
284 tx
->nblocksx
, tx
->nblocksy
);
288 tx
->rect
[0].base
+= mt
->layer_stride
;
289 tx
->rect
[1].base
+= tx
->nblocksy
* tx
->base
.stride
;
293 nouveau_bo_ref(NULL
, &tx
->rect
[1].bo
);
294 pipe_resource_reference(&transfer
->resource
, NULL
);
300 nvc0_miptree_transfer_map(struct pipe_context
*pctx
,
301 struct pipe_transfer
*transfer
)
303 struct nvc0_context
*nvc0
= nvc0_context(pctx
);
304 struct nvc0_transfer
*tx
= (struct nvc0_transfer
*)transfer
;
308 if (tx
->rect
[1].bo
->map
)
309 return tx
->rect
[1].bo
->map
;
311 if (transfer
->usage
& PIPE_TRANSFER_READ
)
312 flags
= NOUVEAU_BO_RD
;
313 if (transfer
->usage
& PIPE_TRANSFER_WRITE
)
314 flags
|= NOUVEAU_BO_WR
;
316 ret
= nouveau_bo_map(tx
->rect
[1].bo
, flags
, nvc0
->screen
->base
.client
);
319 return tx
->rect
[1].bo
->map
;
323 nvc0_miptree_transfer_unmap(struct pipe_context
*pctx
,
324 struct pipe_transfer
*transfer
)
329 nvc0_cb_push(struct nouveau_context
*nv
,
330 struct nouveau_bo
*bo
, unsigned domain
,
331 unsigned base
, unsigned size
,
332 unsigned offset
, unsigned words
, const uint32_t *data
)
334 struct nouveau_bufctx
*bctx
= nvc0_context(&nv
->pipe
)->bufctx
;
335 struct nouveau_pushbuf
*push
= nv
->pushbuf
;
337 assert(!(offset
& 3));
338 size
= align(size
, 0x100);
340 nouveau_bufctx_refn(bctx
, 0, bo
, NOUVEAU_BO_WR
| domain
);
341 nouveau_pushbuf_bufctx(push
, bctx
);
342 nouveau_pushbuf_validate(push
);
344 BEGIN_NVC0(push
, NVC0_3D(CB_SIZE
), 3);
345 PUSH_DATA (push
, size
);
346 PUSH_DATAh(push
, bo
->offset
+ base
);
347 PUSH_DATA (push
, bo
->offset
+ base
);
350 unsigned nr
= PUSH_AVAIL(push
);
351 nr
= MIN2(nr
, words
);
352 nr
= MIN2(nr
, NV04_PFIFO_MAX_PACKET_LEN
- 1);
354 BEGIN_1IC0(push
, NVC0_3D(CB_POS
), nr
+ 1);
355 PUSH_DATA (push
, offset
);
356 PUSH_DATAp(push
, data
, nr
);
363 nouveau_bufctx_reset(bctx
, 0);