2 #include "util/u_format.h"
4 #include "nv50/nv50_context.h"
6 #include "nv50/g80_defs.xml.h"
9 struct pipe_transfer base
;
10 struct nv50_m2mf_rect rect
[2];
16 nv50_m2mf_rect_setup(struct nv50_m2mf_rect
*rect
,
17 struct pipe_resource
*restrict res
, unsigned l
,
18 unsigned x
, unsigned y
, unsigned z
)
20 struct nv50_miptree
*mt
= nv50_miptree(res
);
21 const unsigned w
= u_minify(res
->width0
, l
);
22 const unsigned h
= u_minify(res
->height0
, l
);
24 rect
->bo
= mt
->base
.bo
;
25 rect
->domain
= mt
->base
.domain
;
26 rect
->base
= mt
->level
[l
].offset
;
27 if (mt
->base
.bo
->offset
!= mt
->base
.address
)
28 rect
->base
+= mt
->base
.address
- mt
->base
.bo
->offset
;
29 rect
->pitch
= mt
->level
[l
].pitch
;
30 if (util_format_is_plain(res
->format
)) {
31 rect
->width
= w
<< mt
->ms_x
;
32 rect
->height
= h
<< mt
->ms_y
;
33 rect
->x
= x
<< mt
->ms_x
;
34 rect
->y
= y
<< mt
->ms_y
;
36 rect
->width
= util_format_get_nblocksx(res
->format
, w
);
37 rect
->height
= util_format_get_nblocksy(res
->format
, h
);
38 rect
->x
= util_format_get_nblocksx(res
->format
, x
);
39 rect
->y
= util_format_get_nblocksy(res
->format
, y
);
41 rect
->tile_mode
= mt
->level
[l
].tile_mode
;
42 rect
->cpp
= util_format_get_blocksize(res
->format
);
46 rect
->depth
= u_minify(res
->depth0
, l
);
48 rect
->base
+= z
* mt
->layer_stride
;
55 nv50_m2mf_transfer_rect(struct nv50_context
*nv50
,
56 const struct nv50_m2mf_rect
*dst
,
57 const struct nv50_m2mf_rect
*src
,
58 uint32_t nblocksx
, uint32_t nblocksy
)
60 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
61 struct nouveau_bufctx
*bctx
= nv50
->bufctx
;
62 const int cpp
= dst
->cpp
;
63 uint32_t src_ofst
= src
->base
;
64 uint32_t dst_ofst
= dst
->base
;
65 uint32_t height
= nblocksy
;
69 assert(dst
->cpp
== src
->cpp
);
71 nouveau_bufctx_refn(bctx
, 0, src
->bo
, src
->domain
| NOUVEAU_BO_RD
);
72 nouveau_bufctx_refn(bctx
, 0, dst
->bo
, dst
->domain
| NOUVEAU_BO_WR
);
73 nouveau_pushbuf_bufctx(push
, bctx
);
74 nouveau_pushbuf_validate(push
);
76 if (nouveau_bo_memtype(src
->bo
)) {
77 BEGIN_NV04(push
, NV50_M2MF(LINEAR_IN
), 6);
79 PUSH_DATA (push
, src
->tile_mode
);
80 PUSH_DATA (push
, src
->width
* cpp
);
81 PUSH_DATA (push
, src
->height
);
82 PUSH_DATA (push
, src
->depth
);
83 PUSH_DATA (push
, src
->z
);
85 src_ofst
+= src
->y
* src
->pitch
+ src
->x
* cpp
;
87 BEGIN_NV04(push
, NV50_M2MF(LINEAR_IN
), 1);
89 BEGIN_NV04(push
, SUBC_M2MF(NV03_M2MF_PITCH_IN
), 1);
90 PUSH_DATA (push
, src
->pitch
);
93 if (nouveau_bo_memtype(dst
->bo
)) {
94 BEGIN_NV04(push
, NV50_M2MF(LINEAR_OUT
), 6);
96 PUSH_DATA (push
, dst
->tile_mode
);
97 PUSH_DATA (push
, dst
->width
* cpp
);
98 PUSH_DATA (push
, dst
->height
);
99 PUSH_DATA (push
, dst
->depth
);
100 PUSH_DATA (push
, dst
->z
);
102 dst_ofst
+= dst
->y
* dst
->pitch
+ dst
->x
* cpp
;
104 BEGIN_NV04(push
, NV50_M2MF(LINEAR_OUT
), 1);
106 BEGIN_NV04(push
, SUBC_M2MF(NV03_M2MF_PITCH_OUT
), 1);
107 PUSH_DATA (push
, dst
->pitch
);
111 int line_count
= height
> 2047 ? 2047 : height
;
113 BEGIN_NV04(push
, NV50_M2MF(OFFSET_IN_HIGH
), 2);
114 PUSH_DATAh(push
, src
->bo
->offset
+ src_ofst
);
115 PUSH_DATAh(push
, dst
->bo
->offset
+ dst_ofst
);
117 BEGIN_NV04(push
, SUBC_M2MF(NV03_M2MF_OFFSET_IN
), 2);
118 PUSH_DATA (push
, src
->bo
->offset
+ src_ofst
);
119 PUSH_DATA (push
, dst
->bo
->offset
+ dst_ofst
);
121 if (nouveau_bo_memtype(src
->bo
)) {
122 BEGIN_NV04(push
, NV50_M2MF(TILING_POSITION_IN
), 1);
123 PUSH_DATA (push
, (sy
<< 16) | (src
->x
* cpp
));
125 src_ofst
+= line_count
* src
->pitch
;
127 if (nouveau_bo_memtype(dst
->bo
)) {
128 BEGIN_NV04(push
, NV50_M2MF(TILING_POSITION_OUT
), 1);
129 PUSH_DATA (push
, (dy
<< 16) | (dst
->x
* cpp
));
131 dst_ofst
+= line_count
* dst
->pitch
;
134 BEGIN_NV04(push
, SUBC_M2MF(NV03_M2MF_LINE_LENGTH_IN
), 4);
135 PUSH_DATA (push
, nblocksx
* cpp
);
136 PUSH_DATA (push
, line_count
);
137 PUSH_DATA (push
, (1 << 8) | (1 << 0));
140 height
-= line_count
;
145 nouveau_bufctx_reset(bctx
, 0);
149 nv50_sifc_linear_u8(struct nouveau_context
*nv
,
150 struct nouveau_bo
*dst
, unsigned offset
, unsigned domain
,
151 unsigned size
, const void *data
)
153 struct nv50_context
*nv50
= nv50_context(&nv
->pipe
);
154 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
155 uint32_t *src
= (uint32_t *)data
;
156 unsigned count
= (size
+ 3) / 4;
157 unsigned xcoord
= offset
& 0xff;
159 nouveau_bufctx_refn(nv50
->bufctx
, 0, dst
, domain
| NOUVEAU_BO_WR
);
160 nouveau_pushbuf_bufctx(push
, nv50
->bufctx
);
161 nouveau_pushbuf_validate(push
);
165 BEGIN_NV04(push
, NV50_2D(DST_FORMAT
), 2);
166 PUSH_DATA (push
, G80_SURFACE_FORMAT_R8_UNORM
);
168 BEGIN_NV04(push
, NV50_2D(DST_PITCH
), 5);
169 PUSH_DATA (push
, 262144);
170 PUSH_DATA (push
, 65536);
172 PUSH_DATAh(push
, dst
->offset
+ offset
);
173 PUSH_DATA (push
, dst
->offset
+ offset
);
174 BEGIN_NV04(push
, NV50_2D(SIFC_BITMAP_ENABLE
), 2);
176 PUSH_DATA (push
, G80_SURFACE_FORMAT_R8_UNORM
);
177 BEGIN_NV04(push
, NV50_2D(SIFC_WIDTH
), 10);
178 PUSH_DATA (push
, size
);
185 PUSH_DATA (push
, xcoord
);
190 unsigned nr
= MIN2(count
, NV04_PFIFO_MAX_PACKET_LEN
);
192 BEGIN_NI04(push
, NV50_2D(SIFC_DATA
), nr
);
193 PUSH_DATAp(push
, src
, nr
);
199 nouveau_bufctx_reset(nv50
->bufctx
, 0);
203 nv50_m2mf_copy_linear(struct nouveau_context
*nv
,
204 struct nouveau_bo
*dst
, unsigned dstoff
, unsigned dstdom
,
205 struct nouveau_bo
*src
, unsigned srcoff
, unsigned srcdom
,
208 struct nouveau_pushbuf
*push
= nv
->pushbuf
;
209 struct nouveau_bufctx
*bctx
= nv50_context(&nv
->pipe
)->bufctx
;
211 nouveau_bufctx_refn(bctx
, 0, src
, srcdom
| NOUVEAU_BO_RD
);
212 nouveau_bufctx_refn(bctx
, 0, dst
, dstdom
| NOUVEAU_BO_WR
);
213 nouveau_pushbuf_bufctx(push
, bctx
);
214 nouveau_pushbuf_validate(push
);
216 BEGIN_NV04(push
, NV50_M2MF(LINEAR_IN
), 1);
218 BEGIN_NV04(push
, NV50_M2MF(LINEAR_OUT
), 1);
222 unsigned bytes
= MIN2(size
, 1 << 17);
224 BEGIN_NV04(push
, NV50_M2MF(OFFSET_IN_HIGH
), 2);
225 PUSH_DATAh(push
, src
->offset
+ srcoff
);
226 PUSH_DATAh(push
, dst
->offset
+ dstoff
);
227 BEGIN_NV04(push
, SUBC_M2MF(NV03_M2MF_OFFSET_IN
), 2);
228 PUSH_DATA (push
, src
->offset
+ srcoff
);
229 PUSH_DATA (push
, dst
->offset
+ dstoff
);
230 BEGIN_NV04(push
, SUBC_M2MF(NV03_M2MF_LINE_LENGTH_IN
), 4);
231 PUSH_DATA (push
, bytes
);
233 PUSH_DATA (push
, (1 << 8) | (1 << 0));
241 nouveau_bufctx_reset(bctx
, 0);
245 nv50_miptree_transfer_map(struct pipe_context
*pctx
,
246 struct pipe_resource
*res
,
249 const struct pipe_box
*box
,
250 struct pipe_transfer
**ptransfer
)
252 struct nv50_screen
*screen
= nv50_screen(pctx
->screen
);
253 struct nv50_context
*nv50
= nv50_context(pctx
);
254 struct nouveau_device
*dev
= nv50
->screen
->base
.device
;
255 const struct nv50_miptree
*mt
= nv50_miptree(res
);
256 struct nv50_transfer
*tx
;
261 if (usage
& PIPE_TRANSFER_MAP_DIRECTLY
)
264 tx
= CALLOC_STRUCT(nv50_transfer
);
268 pipe_resource_reference(&tx
->base
.resource
, res
);
270 tx
->base
.level
= level
;
271 tx
->base
.usage
= usage
;
274 if (util_format_is_plain(res
->format
)) {
275 tx
->nblocksx
= box
->width
<< mt
->ms_x
;
276 tx
->nblocksy
= box
->height
<< mt
->ms_y
;
278 tx
->nblocksx
= util_format_get_nblocksx(res
->format
, box
->width
);
279 tx
->nblocksy
= util_format_get_nblocksy(res
->format
, box
->height
);
282 tx
->base
.stride
= tx
->nblocksx
* util_format_get_blocksize(res
->format
);
283 tx
->base
.layer_stride
= tx
->nblocksy
* tx
->base
.stride
;
285 nv50_m2mf_rect_setup(&tx
->rect
[0], res
, level
, box
->x
, box
->y
, box
->z
);
287 size
= tx
->base
.layer_stride
;
289 ret
= nouveau_bo_new(dev
, NOUVEAU_BO_GART
| NOUVEAU_BO_MAP
, 0,
290 size
* tx
->base
.box
.depth
, NULL
, &tx
->rect
[1].bo
);
296 tx
->rect
[1].cpp
= tx
->rect
[0].cpp
;
297 tx
->rect
[1].width
= tx
->nblocksx
;
298 tx
->rect
[1].height
= tx
->nblocksy
;
299 tx
->rect
[1].depth
= 1;
300 tx
->rect
[1].pitch
= tx
->base
.stride
;
301 tx
->rect
[1].domain
= NOUVEAU_BO_GART
;
303 if (usage
& PIPE_TRANSFER_READ
) {
304 unsigned base
= tx
->rect
[0].base
;
305 unsigned z
= tx
->rect
[0].z
;
307 for (i
= 0; i
< box
->depth
; ++i
) {
308 nv50_m2mf_transfer_rect(nv50
, &tx
->rect
[1], &tx
->rect
[0],
309 tx
->nblocksx
, tx
->nblocksy
);
313 tx
->rect
[0].base
+= mt
->layer_stride
;
314 tx
->rect
[1].base
+= size
;
317 tx
->rect
[0].base
= base
;
318 tx
->rect
[1].base
= 0;
321 if (tx
->rect
[1].bo
->map
) {
322 *ptransfer
= &tx
->base
;
323 return tx
->rect
[1].bo
->map
;
326 if (usage
& PIPE_TRANSFER_READ
)
327 flags
= NOUVEAU_BO_RD
;
328 if (usage
& PIPE_TRANSFER_WRITE
)
329 flags
|= NOUVEAU_BO_WR
;
331 ret
= nouveau_bo_map(tx
->rect
[1].bo
, flags
, screen
->base
.client
);
333 nouveau_bo_ref(NULL
, &tx
->rect
[1].bo
);
338 *ptransfer
= &tx
->base
;
339 return tx
->rect
[1].bo
->map
;
343 nv50_miptree_transfer_unmap(struct pipe_context
*pctx
,
344 struct pipe_transfer
*transfer
)
346 struct nv50_context
*nv50
= nv50_context(pctx
);
347 struct nv50_transfer
*tx
= (struct nv50_transfer
*)transfer
;
348 struct nv50_miptree
*mt
= nv50_miptree(tx
->base
.resource
);
351 if (tx
->base
.usage
& PIPE_TRANSFER_WRITE
) {
352 for (i
= 0; i
< tx
->base
.box
.depth
; ++i
) {
353 nv50_m2mf_transfer_rect(nv50
, &tx
->rect
[0], &tx
->rect
[1],
354 tx
->nblocksx
, tx
->nblocksy
);
358 tx
->rect
[0].base
+= mt
->layer_stride
;
359 tx
->rect
[1].base
+= tx
->nblocksy
* tx
->base
.stride
;
362 /* Allow the copies above to finish executing before freeing the source */
363 nouveau_fence_work(nv50
->screen
->base
.fence
.current
,
364 nouveau_fence_unref_bo
, tx
->rect
[1].bo
);
366 nouveau_bo_ref(NULL
, &tx
->rect
[1].bo
);
369 pipe_resource_reference(&transfer
->resource
, NULL
);
375 nv50_cb_bo_push(struct nouveau_context
*nv
,
376 struct nouveau_bo
*bo
, unsigned domain
,
378 unsigned offset
, unsigned words
,
379 const uint32_t *data
)
381 struct nouveau_pushbuf
*push
= nv
->pushbuf
;
383 assert(!(offset
& 3));
386 unsigned nr
= MIN2(words
, NV04_PFIFO_MAX_PACKET_LEN
);
388 PUSH_SPACE(push
, nr
+ 3);
389 PUSH_REFN (push
, bo
, NOUVEAU_BO_WR
| domain
);
390 BEGIN_NV04(push
, NV50_3D(CB_ADDR
), 1);
391 PUSH_DATA (push
, (offset
<< 6) | bufid
);
392 BEGIN_NI04(push
, NV50_3D(CB_DATA(0)), nr
);
393 PUSH_DATAp(push
, data
, nr
);
402 nv50_cb_push(struct nouveau_context
*nv
,
403 struct nv04_resource
*res
,
404 unsigned offset
, unsigned words
, const uint32_t *data
)
406 struct nv50_context
*nv50
= nv50_context(&nv
->pipe
);
407 struct nv50_constbuf
*cb
= NULL
;
409 /* Go through all the constbuf binding points of this buffer and try to
410 * find one which contains the region to be updated.
413 for (s
= 0; s
< 3 && !cb
; s
++) {
414 uint16_t bindings
= res
->cb_bindings
[s
];
416 int i
= ffs(bindings
) - 1;
417 uint32_t cb_offset
= nv50
->constbuf
[s
][i
].offset
;
419 bindings
&= ~(1 << i
);
420 if (cb_offset
<= offset
&&
421 cb_offset
+ nv50
->constbuf
[s
][i
].size
>= offset
+ words
* 4) {
422 cb
= &nv50
->constbuf
[s
][i
];
430 nv50_cb_bo_push(nv
, res
->bo
, res
->domain
,
431 bufid
, offset
- cb
->offset
, words
, data
);
433 nv
->push_data(nv
, res
->bo
, res
->offset
+ offset
, res
->domain
,