2 #include "util/u_format.h"
4 #include "nv50_context.h"
6 #include "nv50_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 rect
->pitch
= mt
->level
[l
].pitch
;
28 if (util_format_is_plain(res
->format
)) {
29 rect
->width
= w
<< mt
->ms_x
;
30 rect
->height
= h
<< mt
->ms_y
;
31 rect
->x
= x
<< mt
->ms_x
;
32 rect
->y
= y
<< mt
->ms_y
;
34 rect
->width
= util_format_get_nblocksx(res
->format
, w
);
35 rect
->height
= util_format_get_nblocksy(res
->format
, h
);
36 rect
->x
= util_format_get_nblocksx(res
->format
, x
);
37 rect
->y
= util_format_get_nblocksy(res
->format
, y
);
39 rect
->tile_mode
= mt
->level
[l
].tile_mode
;
40 rect
->cpp
= util_format_get_blocksize(res
->format
);
44 rect
->depth
= u_minify(res
->depth0
, l
);
46 rect
->base
+= z
* mt
->layer_stride
;
53 nv50_m2mf_transfer_rect(struct pipe_screen
*pscreen
,
54 const struct nv50_m2mf_rect
*dst
,
55 const struct nv50_m2mf_rect
*src
,
56 uint32_t nblocksx
, uint32_t nblocksy
)
58 struct nouveau_channel
*chan
= nouveau_screen(pscreen
)->channel
;
59 const int cpp
= dst
->cpp
;
60 uint32_t src_ofst
= src
->base
;
61 uint32_t dst_ofst
= dst
->base
;
62 uint32_t height
= nblocksy
;
66 assert(dst
->cpp
== src
->cpp
);
68 if (nouveau_bo_tile_layout(src
->bo
)) {
69 BEGIN_RING(chan
, RING_MF(LINEAR_IN
), 6);
71 OUT_RING (chan
, src
->tile_mode
<< 4);
72 OUT_RING (chan
, src
->width
* cpp
);
73 OUT_RING (chan
, src
->height
);
74 OUT_RING (chan
, src
->depth
);
75 OUT_RING (chan
, src
->z
);
77 src_ofst
+= src
->y
* src
->pitch
+ src
->x
* cpp
;
79 BEGIN_RING(chan
, RING_MF(LINEAR_IN
), 1);
81 BEGIN_RING(chan
, RING_MF_(NV04_M2MF_PITCH_IN
), 1);
82 OUT_RING (chan
, src
->pitch
);
85 if (nouveau_bo_tile_layout(dst
->bo
)) {
86 BEGIN_RING(chan
, RING_MF(LINEAR_OUT
), 6);
88 OUT_RING (chan
, dst
->tile_mode
<< 4);
89 OUT_RING (chan
, dst
->width
* cpp
);
90 OUT_RING (chan
, dst
->height
);
91 OUT_RING (chan
, dst
->depth
);
92 OUT_RING (chan
, dst
->z
);
94 dst_ofst
+= dst
->y
* dst
->pitch
+ dst
->x
* cpp
;
96 BEGIN_RING(chan
, RING_MF(LINEAR_OUT
), 1);
98 BEGIN_RING(chan
, RING_MF_(NV04_M2MF_PITCH_OUT
), 1);
99 OUT_RING (chan
, dst
->pitch
);
103 int line_count
= height
> 2047 ? 2047 : height
;
105 MARK_RING (chan
, 17, 4);
107 BEGIN_RING(chan
, RING_MF(OFFSET_IN_HIGH
), 2);
108 OUT_RELOCh(chan
, src
->bo
, src_ofst
, src
->domain
| NOUVEAU_BO_RD
);
109 OUT_RELOCh(chan
, dst
->bo
, dst_ofst
, dst
->domain
| NOUVEAU_BO_WR
);
111 BEGIN_RING(chan
, RING_MF_(NV04_M2MF_OFFSET_IN
), 2);
112 OUT_RELOCl(chan
, src
->bo
, src_ofst
, src
->domain
| NOUVEAU_BO_RD
);
113 OUT_RELOCl(chan
, dst
->bo
, dst_ofst
, dst
->domain
| NOUVEAU_BO_WR
);
115 if (nouveau_bo_tile_layout(src
->bo
)) {
116 BEGIN_RING(chan
, RING_MF(TILING_POSITION_IN
), 1);
117 OUT_RING (chan
, (sy
<< 16) | (src
->x
* cpp
));
119 src_ofst
+= line_count
* src
->pitch
;
121 if (nouveau_bo_tile_layout(dst
->bo
)) {
122 BEGIN_RING(chan
, RING_MF(TILING_POSITION_OUT
), 1);
123 OUT_RING (chan
, (dy
<< 16) | (dst
->x
* cpp
));
125 dst_ofst
+= line_count
* dst
->pitch
;
128 BEGIN_RING(chan
, RING_MF_(NV04_M2MF_LINE_LENGTH_IN
), 4);
129 OUT_RING (chan
, nblocksx
* cpp
);
130 OUT_RING (chan
, line_count
);
131 OUT_RING (chan
, (1 << 8) | (1 << 0));
134 height
-= line_count
;
141 nv50_sifc_linear_u8(struct nouveau_context
*nv
,
142 struct nouveau_bo
*dst
, unsigned offset
, unsigned domain
,
143 unsigned size
, const void *data
)
145 struct nouveau_channel
*chan
= nv
->screen
->channel
;
146 uint32_t *src
= (uint32_t *)data
;
147 unsigned count
= (size
+ 3) / 4;
148 unsigned xcoord
= offset
& 0xff;
152 MARK_RING (chan
, 23, 4);
153 BEGIN_RING(chan
, RING_2D(DST_FORMAT
), 2);
154 OUT_RING (chan
, NV50_SURFACE_FORMAT_R8_UNORM
);
156 BEGIN_RING(chan
, RING_2D(DST_PITCH
), 5);
157 OUT_RING (chan
, 262144);
158 OUT_RING (chan
, 65536);
160 OUT_RELOCh(chan
, dst
, offset
, domain
| NOUVEAU_BO_WR
);
161 OUT_RELOCl(chan
, dst
, offset
, domain
| NOUVEAU_BO_WR
);
162 BEGIN_RING(chan
, RING_2D(SIFC_BITMAP_ENABLE
), 2);
164 OUT_RING (chan
, NV50_SURFACE_FORMAT_R8_UNORM
);
165 BEGIN_RING(chan
, RING_2D(SIFC_WIDTH
), 10);
166 OUT_RING (chan
, size
);
173 OUT_RING (chan
, xcoord
);
178 unsigned nr
= AVAIL_RING(chan
);
182 nouveau_bo_validate(chan
, dst
, NOUVEAU_BO_WR
);
185 nr
= MIN2(count
, nr
- 1);
186 nr
= MIN2(nr
, NV04_PFIFO_MAX_PACKET_LEN
);
188 BEGIN_RING_NI(chan
, RING_2D(SIFC_DATA
), nr
);
189 OUT_RINGp (chan
, src
, nr
);
197 nv50_m2mf_copy_linear(struct nouveau_context
*nv
,
198 struct nouveau_bo
*dst
, unsigned dstoff
, unsigned dstdom
,
199 struct nouveau_bo
*src
, unsigned srcoff
, unsigned srcdom
,
202 struct nouveau_channel
*chan
= nv
->screen
->channel
;
204 BEGIN_RING(chan
, RING_MF(LINEAR_IN
), 1);
206 BEGIN_RING(chan
, RING_MF(LINEAR_OUT
), 1);
210 unsigned bytes
= MIN2(size
, 1 << 17);
212 MARK_RING (chan
, 11, 4);
213 BEGIN_RING(chan
, RING_MF(OFFSET_IN_HIGH
), 2);
214 OUT_RELOCh(chan
, src
, srcoff
, srcdom
| NOUVEAU_BO_RD
);
215 OUT_RELOCh(chan
, dst
, dstoff
, dstdom
| NOUVEAU_BO_WR
);
216 BEGIN_RING(chan
, RING_MF_(NV04_M2MF_OFFSET_IN
), 2);
217 OUT_RELOCl(chan
, src
, srcoff
, srcdom
| NOUVEAU_BO_RD
);
218 OUT_RELOCl(chan
, dst
, dstoff
, dstdom
| NOUVEAU_BO_WR
);
219 BEGIN_RING(chan
, RING_MF_(NV04_M2MF_LINE_LENGTH_IN
), 4);
220 OUT_RING (chan
, bytes
);
222 OUT_RING (chan
, (1 << 8) | (1 << 0));
231 struct pipe_transfer
*
232 nv50_miptree_transfer_new(struct pipe_context
*pctx
,
233 struct pipe_resource
*res
,
236 const struct pipe_box
*box
)
238 struct nv50_context
*nv50
= nv50_context(pctx
);
239 struct pipe_screen
*pscreen
= pctx
->screen
;
240 struct nouveau_device
*dev
= nv50
->screen
->base
.device
;
241 const struct nv50_miptree
*mt
= nv50_miptree(res
);
242 struct nv50_transfer
*tx
;
246 if (usage
& PIPE_TRANSFER_MAP_DIRECTLY
)
249 tx
= CALLOC_STRUCT(nv50_transfer
);
253 pipe_resource_reference(&tx
->base
.resource
, res
);
255 tx
->base
.level
= level
;
256 tx
->base
.usage
= usage
;
259 if (util_format_is_plain(res
->format
)) {
260 tx
->nblocksx
= box
->width
<< mt
->ms_x
;
261 tx
->nblocksy
= box
->height
<< mt
->ms_x
;
263 tx
->nblocksx
= util_format_get_nblocksx(res
->format
, box
->width
);
264 tx
->nblocksy
= util_format_get_nblocksy(res
->format
, box
->height
);
267 tx
->base
.stride
= tx
->nblocksx
* util_format_get_blocksize(res
->format
);
268 tx
->base
.layer_stride
= tx
->nblocksy
* tx
->base
.stride
;
270 nv50_m2mf_rect_setup(&tx
->rect
[0], res
, level
, box
->x
, box
->y
, box
->z
);
272 size
= tx
->base
.layer_stride
;
274 ret
= nouveau_bo_new(dev
, NOUVEAU_BO_GART
| NOUVEAU_BO_MAP
, 0,
275 size
* tx
->base
.box
.depth
, &tx
->rect
[1].bo
);
281 tx
->rect
[1].cpp
= tx
->rect
[0].cpp
;
282 tx
->rect
[1].width
= tx
->nblocksx
;
283 tx
->rect
[1].height
= tx
->nblocksy
;
284 tx
->rect
[1].depth
= 1;
285 tx
->rect
[1].pitch
= tx
->base
.stride
;
286 tx
->rect
[1].domain
= NOUVEAU_BO_GART
;
288 if (usage
& PIPE_TRANSFER_READ
) {
289 unsigned base
= tx
->rect
[0].base
;
290 unsigned z
= tx
->rect
[0].z
;
292 for (i
= 0; i
< box
->depth
; ++i
) {
293 nv50_m2mf_transfer_rect(pscreen
, &tx
->rect
[1], &tx
->rect
[0],
294 tx
->nblocksx
, tx
->nblocksy
);
298 tx
->rect
[0].base
+= mt
->layer_stride
;
299 tx
->rect
[1].base
+= size
;
302 tx
->rect
[0].base
= base
;
303 tx
->rect
[1].base
= 0;
310 nv50_miptree_transfer_del(struct pipe_context
*pctx
,
311 struct pipe_transfer
*transfer
)
313 struct pipe_screen
*pscreen
= pctx
->screen
;
314 struct nv50_transfer
*tx
= (struct nv50_transfer
*)transfer
;
315 struct nv50_miptree
*mt
= nv50_miptree(tx
->base
.resource
);
318 if (tx
->base
.usage
& PIPE_TRANSFER_WRITE
) {
319 for (i
= 0; i
< tx
->base
.box
.depth
; ++i
) {
320 nv50_m2mf_transfer_rect(pscreen
, &tx
->rect
[0], &tx
->rect
[1],
321 tx
->nblocksx
, tx
->nblocksy
);
325 tx
->rect
[0].base
+= mt
->layer_stride
;
326 tx
->rect
[1].base
+= tx
->nblocksy
* tx
->base
.stride
;
330 nouveau_bo_ref(NULL
, &tx
->rect
[1].bo
);
331 pipe_resource_reference(&transfer
->resource
, NULL
);
337 nv50_miptree_transfer_map(struct pipe_context
*pctx
,
338 struct pipe_transfer
*transfer
)
340 struct nv50_transfer
*tx
= (struct nv50_transfer
*)transfer
;
344 if (tx
->rect
[1].bo
->map
)
345 return tx
->rect
[1].bo
->map
;
347 if (transfer
->usage
& PIPE_TRANSFER_READ
)
348 flags
= NOUVEAU_BO_RD
;
349 if (transfer
->usage
& PIPE_TRANSFER_WRITE
)
350 flags
|= NOUVEAU_BO_WR
;
352 ret
= nouveau_bo_map(tx
->rect
[1].bo
, flags
);
355 return tx
->rect
[1].bo
->map
;
359 nv50_miptree_transfer_unmap(struct pipe_context
*pctx
,
360 struct pipe_transfer
*transfer
)
362 struct nv50_transfer
*tx
= (struct nv50_transfer
*)transfer
;
364 nouveau_bo_unmap(tx
->rect
[1].bo
);
368 nv50_cb_push(struct nouveau_context
*nv
,
369 struct nouveau_bo
*bo
, unsigned domain
,
370 unsigned base
, unsigned size
,
371 unsigned offset
, unsigned words
, const uint32_t *data
)
373 struct nouveau_channel
*chan
= nv
->screen
->channel
;
375 assert(!(offset
& 3));
376 size
= align(size
, 0x100);
381 MARK_RING(chan
, 24, 2);
382 nr
= AVAIL_RING(chan
);
383 nr
= MIN2(nr
- 7, words
);
384 nr
= MIN2(nr
, NV04_PFIFO_MAX_PACKET_LEN
- 1);
386 BEGIN_RING(chan
, RING_3D(CB_DEF_ADDRESS_HIGH
), 3);
387 OUT_RELOCh(chan
, bo
, base
, domain
| NOUVEAU_BO_WR
);
388 OUT_RELOCl(chan
, bo
, base
, domain
| NOUVEAU_BO_WR
);
389 OUT_RING (chan
, (NV50_CB_TMP
<< 16) | (size
& 0xffff));
390 BEGIN_RING(chan
, RING_3D(CB_ADDR
), 1);
391 OUT_RING (chan
, (offset
<< 6) | NV50_CB_TMP
);
392 BEGIN_RING_NI(chan
, RING_3D(CB_DATA(0)), nr
);
393 OUT_RINGp (chan
, data
, nr
);