2 #include "util/u_format.h"
4 #include "nvc0_context.h"
5 #include "nvc0_transfer.h"
7 #include "nv50_defs.xml.h"
10 struct pipe_transfer base
;
11 struct nvc0_m2mf_rect rect
[2];
17 nvc0_m2mf_transfer_rect(struct pipe_screen
*pscreen
,
18 const struct nvc0_m2mf_rect
*dst
,
19 const struct nvc0_m2mf_rect
*src
,
20 uint32_t nblocksx
, uint32_t nblocksy
)
22 struct nouveau_channel
*chan
= nouveau_screen(pscreen
)->channel
;
23 const int cpp
= dst
->cpp
;
24 uint32_t src_ofst
= src
->base
;
25 uint32_t dst_ofst
= dst
->base
;
26 uint32_t height
= nblocksy
;
29 uint32_t exec
= (1 << 20);
31 assert(dst
->cpp
== src
->cpp
);
33 if (src
->bo
->tile_flags
) {
34 BEGIN_RING(chan
, RING_MF(TILING_MODE_IN
), 5);
35 OUT_RING (chan
, src
->tile_mode
);
36 OUT_RING (chan
, src
->width
* cpp
);
37 OUT_RING (chan
, src
->height
);
38 OUT_RING (chan
, src
->depth
);
39 OUT_RING (chan
, src
->z
);
41 src_ofst
+= src
->y
* src
->pitch
+ src
->x
* cpp
;
43 BEGIN_RING(chan
, RING_MF(PITCH_IN
), 1);
44 OUT_RING (chan
, src
->width
* cpp
);
46 exec
|= NVC0_M2MF_EXEC_LINEAR_IN
;
49 if (dst
->bo
->tile_flags
) {
50 BEGIN_RING(chan
, RING_MF(TILING_MODE_OUT
), 5);
51 OUT_RING (chan
, dst
->tile_mode
);
52 OUT_RING (chan
, dst
->width
* cpp
);
53 OUT_RING (chan
, dst
->height
);
54 OUT_RING (chan
, dst
->depth
);
55 OUT_RING (chan
, dst
->z
);
57 dst_ofst
+= dst
->y
* dst
->pitch
+ dst
->x
* cpp
;
59 BEGIN_RING(chan
, RING_MF(PITCH_OUT
), 1);
60 OUT_RING (chan
, dst
->width
* cpp
);
62 exec
|= NVC0_M2MF_EXEC_LINEAR_OUT
;
66 int line_count
= height
> 2047 ? 2047 : height
;
68 MARK_RING (chan
, 17, 4);
70 BEGIN_RING(chan
, RING_MF(OFFSET_IN_HIGH
), 2);
71 OUT_RELOCh(chan
, src
->bo
, src_ofst
, src
->domain
| NOUVEAU_BO_RD
);
72 OUT_RELOCl(chan
, src
->bo
, src_ofst
, src
->domain
| NOUVEAU_BO_RD
);
74 BEGIN_RING(chan
, RING_MF(OFFSET_OUT_HIGH
), 2);
75 OUT_RELOCh(chan
, dst
->bo
, dst_ofst
, dst
->domain
| NOUVEAU_BO_WR
);
76 OUT_RELOCl(chan
, dst
->bo
, dst_ofst
, dst
->domain
| NOUVEAU_BO_WR
);
78 if (!(exec
& NVC0_M2MF_EXEC_LINEAR_IN
)) {
79 BEGIN_RING(chan
, RING_MF(TILING_POSITION_IN_X
), 2);
80 OUT_RING (chan
, src
->x
* cpp
);
83 src_ofst
+= line_count
* src
->pitch
;
85 if (!(exec
& NVC0_M2MF_EXEC_LINEAR_OUT
)) {
86 BEGIN_RING(chan
, RING_MF(TILING_POSITION_OUT_X
), 2);
87 OUT_RING (chan
, dst
->x
* cpp
);
90 dst_ofst
+= line_count
* dst
->pitch
;
93 BEGIN_RING(chan
, RING_MF(LINE_LENGTH_IN
), 2);
94 OUT_RING (chan
, nblocksx
* cpp
);
95 OUT_RING (chan
, line_count
);
96 BEGIN_RING(chan
, RING_MF(EXEC
), 1);
97 OUT_RING (chan
, exec
);
106 nvc0_m2mf_push_linear(struct nvc0_context
*nvc0
,
107 struct nouveau_bo
*dst
, unsigned domain
, int offset
,
108 unsigned size
, void *data
)
110 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
111 uint32_t *src
= (uint32_t *)data
;
112 unsigned count
= (size
+ 3) / 4;
114 BEGIN_RING(chan
, RING_MF(OFFSET_OUT_HIGH
), 2);
115 OUT_RELOCh(chan
, dst
, offset
, domain
| NOUVEAU_BO_WR
);
116 OUT_RELOCl(chan
, dst
, offset
, domain
| NOUVEAU_BO_WR
);
117 BEGIN_RING(chan
, RING_MF(LINE_LENGTH_IN
), 2);
118 OUT_RING (chan
, size
);
120 BEGIN_RING(chan
, RING_MF(EXEC
), 1);
121 OUT_RING (chan
, 0x100111);
124 unsigned nr
= AVAIL_RING(chan
);
130 nr
= MIN2(count
, nr
- 1);
131 nr
= MIN2(nr
, NV04_PFIFO_MAX_PACKET_LEN
);
133 BEGIN_RING_NI(chan
, RING_MF(DATA
), nr
);
134 OUT_RINGp (chan
, src
, nr
);
142 nvc0_sifc_push_rect(struct pipe_screen
*pscreen
,
143 const struct nvc0_m2mf_rect
*dst
, unsigned dst_format
,
144 unsigned src_format
, unsigned src_pitch
, void *src
,
145 unsigned nblocksx
, unsigned nblocksy
)
147 struct nouveau_channel
*chan
;
149 if (dst
->bo
->tile_flags
) {
150 BEGIN_RING(chan
, RING_2D(DST_FORMAT
), 5);
151 OUT_RING (chan
, dst_format
);
153 OUT_RING (chan
, dst
->tile_mode
);
157 BEGIN_RING(chan
, RING_2D(DST_FORMAT
), 2);
158 OUT_RING (chan
, NV50_SURFACE_FORMAT_A8R8G8B8_UNORM
);
160 BEGIN_RING(chan
, RING_2D(DST_PITCH
), 1);
161 OUT_RING (chan
, dst
->pitch
);
164 BEGIN_RING(chan
, RING_2D(DST_WIDTH
), 4);
165 OUT_RING (chan
, dst
->width
);
166 OUT_RING (chan
, dst
->height
);
167 OUT_RELOCh(chan
, dst
->bo
, dst
->base
, dst
->domain
| NOUVEAU_BO_WR
);
168 OUT_RELOCl(chan
, dst
->bo
, dst
->base
, dst
->domain
| NOUVEAU_BO_WR
);
170 BEGIN_RING(chan
, RING_2D(SIFC_BITMAP_ENABLE
), 2);
172 OUT_RING (chan
, src_format
);
173 BEGIN_RING(chan
, RING_2D(SIFC_WIDTH
), 10);
174 OUT_RING (chan
, nblocksx
);
175 OUT_RING (chan
, nblocksy
);
181 OUT_RING (chan
, dst
->x
);
183 OUT_RING (chan
, dst
->y
);
187 src
= (uint8_t *)src
+ src_pitch
;
191 struct pipe_transfer
*
192 nvc0_miptree_transfer_new(struct pipe_context
*pctx
,
193 struct pipe_resource
*res
,
194 struct pipe_subresource sr
,
196 const struct pipe_box
*box
)
198 struct nvc0_context
*nvc0
= nvc0_context(pctx
);
199 struct pipe_screen
*pscreen
= pctx
->screen
;
200 struct nouveau_device
*dev
= nvc0
->screen
->base
.device
;
201 struct nvc0_miptree
*mt
= nvc0_miptree(res
);
202 struct nvc0_miptree_level
*lvl
= &mt
->level
[sr
.level
];
203 struct nvc0_transfer
*tx
;
208 if (res
->target
== PIPE_TEXTURE_CUBE
)
213 tx
= CALLOC_STRUCT(nvc0_transfer
);
217 pipe_resource_reference(&tx
->base
.resource
, res
);
220 tx
->base
.usage
= usage
;
223 tx
->nblocksx
= util_format_get_nblocksx(res
->format
, box
->width
);
224 tx
->nblocksy
= util_format_get_nblocksy(res
->format
, box
->height
);
226 tx
->base
.stride
= tx
->nblocksx
* util_format_get_blocksize(res
->format
);
228 w
= u_minify(res
->width0
, sr
.level
);
229 h
= u_minify(res
->height0
, sr
.level
);
231 tx
->rect
[0].cpp
= tx
->rect
[1].cpp
= util_format_get_blocksize(res
->format
);
233 tx
->rect
[0].bo
= mt
->base
.bo
;
234 tx
->rect
[0].base
= lvl
->image_offset
[image
];
235 tx
->rect
[0].tile_mode
= lvl
->tile_mode
;
236 tx
->rect
[0].x
= util_format_get_nblocksx(res
->format
, box
->x
);
237 tx
->rect
[0].y
= util_format_get_nblocksx(res
->format
, box
->y
);
238 tx
->rect
[0].z
= box
->z
;
239 tx
->rect
[0].width
= util_format_get_nblocksx(res
->format
, w
);
240 tx
->rect
[0].height
= util_format_get_nblocksx(res
->format
, h
);
241 tx
->rect
[0].depth
= res
->depth0
;
242 tx
->rect
[0].pitch
= lvl
->pitch
;
243 tx
->rect
[0].domain
= NOUVEAU_BO_VRAM
;
245 ret
= nouveau_bo_new(dev
, NOUVEAU_BO_GART
| NOUVEAU_BO_MAP
, 0,
246 tx
->nblocksy
* tx
->base
.stride
, &tx
->rect
[1].bo
);
252 tx
->rect
[1].width
= tx
->nblocksx
;
253 tx
->rect
[1].height
= tx
->nblocksy
;
254 tx
->rect
[1].depth
= box
->depth
;
255 tx
->rect
[1].pitch
= tx
->base
.stride
;
256 tx
->rect
[1].domain
= NOUVEAU_BO_GART
;
258 if (usage
& PIPE_TRANSFER_READ
) {
259 for (z
= 0; z
< box
->depth
; ++z
) {
260 nvc0_m2mf_transfer_rect(pscreen
, &tx
->rect
[1], &tx
->rect
[0],
261 tx
->nblocksx
, tx
->nblocksy
);
265 tx
->rect
[0].z
= box
->z
;
271 nvc0_miptree_transfer_del(struct pipe_context
*pctx
,
272 struct pipe_transfer
*transfer
)
274 struct pipe_screen
*pscreen
= pctx
->screen
;
275 struct nvc0_transfer
*tx
= (struct nvc0_transfer
*)transfer
;
278 if (tx
->base
.usage
& PIPE_TRANSFER_WRITE
) {
279 for (z
= 0; z
< tx
->base
.box
.depth
; ++z
) {
280 nvc0_m2mf_transfer_rect(pscreen
, &tx
->rect
[0], &tx
->rect
[1],
281 tx
->nblocksx
, tx
->nblocksy
);
286 nouveau_bo_ref(NULL
, &tx
->rect
[1].bo
);
287 pipe_resource_reference(&transfer
->resource
, NULL
);
293 nvc0_miptree_transfer_map(struct pipe_context
*pctx
,
294 struct pipe_transfer
*transfer
)
296 struct nvc0_transfer
*tx
= (struct nvc0_transfer
*)transfer
;
300 if (tx
->rect
[1].bo
->map
)
301 return tx
->rect
[1].bo
->map
;
303 if (transfer
->usage
& PIPE_TRANSFER_READ
)
304 flags
= NOUVEAU_BO_RD
;
305 if (transfer
->usage
& PIPE_TRANSFER_WRITE
)
306 flags
|= NOUVEAU_BO_WR
;
308 ret
= nouveau_bo_map(tx
->rect
[1].bo
, flags
);
311 return tx
->rect
[1].bo
->map
;
315 nvc0_miptree_transfer_unmap(struct pipe_context
*pctx
,
316 struct pipe_transfer
*transfer
)
318 struct nvc0_transfer
*tx
= (struct nvc0_transfer
*)transfer
;
320 nouveau_bo_unmap(tx
->rect
[1].bo
);