2 #include "pipe/p_context.h"
3 #include "util/u_inlines.h"
4 #include "util/u_format.h"
5 #include "util/u_math.h"
7 #include "nv50_context.h"
8 #include "nv50_transfer.h"
9 #include "nv50_resource.h"
11 struct nv50_transfer
{
12 struct pipe_transfer base
;
13 struct nouveau_bo
*bo
;
15 unsigned level_offset
;
16 unsigned level_tiling
;
29 nv50_transfer_rect_m2mf(struct pipe_screen
*pscreen
,
30 struct nouveau_bo
*src_bo
, unsigned src_offset
,
31 int src_pitch
, unsigned src_tile_mode
,
32 int sx
, int sy
, int sz
, int sw
, int sh
, int sd
,
33 struct nouveau_bo
*dst_bo
, unsigned dst_offset
,
34 int dst_pitch
, unsigned dst_tile_mode
,
35 int dx
, int dy
, int dz
, int dw
, int dh
, int dd
,
36 int cpp
, int width
, int height
,
37 unsigned src_reloc
, unsigned dst_reloc
)
39 struct nv50_screen
*screen
= nv50_screen(pscreen
);
40 struct nouveau_channel
*chan
= screen
->m2mf
->channel
;
41 struct nouveau_grobj
*m2mf
= screen
->m2mf
;
43 src_reloc
|= NOUVEAU_BO_RD
;
44 dst_reloc
|= NOUVEAU_BO_WR
;
48 if (!nouveau_bo_tile_layout(src_bo
)) {
49 BEGIN_RING(chan
, m2mf
,
50 NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_IN
, 1);
52 BEGIN_RING(chan
, m2mf
,
53 NV04_MEMORY_TO_MEMORY_FORMAT_PITCH_IN
, 1);
54 OUT_RING (chan
, src_pitch
);
55 src_offset
+= (sy
* src_pitch
) + (sx
* cpp
);
57 BEGIN_RING(chan
, m2mf
,
58 NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_IN
, 6);
60 OUT_RING (chan
, src_tile_mode
<< 4);
61 OUT_RING (chan
, sw
* cpp
);
64 OUT_RING (chan
, sz
); /* copying only 1 zslice per call */
67 if (!nouveau_bo_tile_layout(dst_bo
)) {
68 BEGIN_RING(chan
, m2mf
,
69 NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_OUT
, 1);
71 BEGIN_RING(chan
, m2mf
,
72 NV04_MEMORY_TO_MEMORY_FORMAT_PITCH_OUT
, 1);
73 OUT_RING (chan
, dst_pitch
);
74 dst_offset
+= (dy
* dst_pitch
) + (dx
* cpp
);
76 BEGIN_RING(chan
, m2mf
,
77 NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_OUT
, 6);
79 OUT_RING (chan
, dst_tile_mode
<< 4);
80 OUT_RING (chan
, dw
* cpp
);
83 OUT_RING (chan
, dz
); /* copying only 1 zslice per call */
87 int line_count
= height
> 2047 ? 2047 : height
;
89 MARK_RING (chan
, 15, 4); /* flush on lack of space or relocs */
90 BEGIN_RING(chan
, m2mf
,
91 NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN_HIGH
, 2);
92 OUT_RELOCh(chan
, src_bo
, src_offset
, src_reloc
);
93 OUT_RELOCh(chan
, dst_bo
, dst_offset
, dst_reloc
);
94 BEGIN_RING(chan
, m2mf
,
95 NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN
, 2);
96 OUT_RELOCl(chan
, src_bo
, src_offset
, src_reloc
);
97 OUT_RELOCl(chan
, dst_bo
, dst_offset
, dst_reloc
);
98 if (nouveau_bo_tile_layout(src_bo
)) {
99 BEGIN_RING(chan
, m2mf
,
100 NV50_MEMORY_TO_MEMORY_FORMAT_TILING_POSITION_IN
, 1);
101 OUT_RING (chan
, (sy
<< 16) | (sx
* cpp
));
103 src_offset
+= (line_count
* src_pitch
);
105 if (nouveau_bo_tile_layout(dst_bo
)) {
106 BEGIN_RING(chan
, m2mf
,
107 NV50_MEMORY_TO_MEMORY_FORMAT_TILING_POSITION_OUT
, 1);
108 OUT_RING (chan
, (dy
<< 16) | (dx
* cpp
));
110 dst_offset
+= (line_count
* dst_pitch
);
112 BEGIN_RING(chan
, m2mf
,
113 NV04_MEMORY_TO_MEMORY_FORMAT_LINE_LENGTH_IN
, 4);
114 OUT_RING (chan
, width
* cpp
);
115 OUT_RING (chan
, line_count
);
116 OUT_RING (chan
, 0x00000101);
120 height
-= line_count
;
126 struct pipe_transfer
*
127 nv50_miptree_transfer_new(struct pipe_context
*pcontext
,
128 struct pipe_resource
*pt
,
131 const struct pipe_box
*box
)
133 struct pipe_screen
*pscreen
= pcontext
->screen
;
134 struct nouveau_device
*dev
= nouveau_screen(pscreen
)->device
;
135 struct nv50_miptree
*mt
= nv50_miptree(pt
);
136 struct nv50_miptree_level
*lvl
= &mt
->level
[level
];
137 struct nv50_transfer
*tx
;
138 unsigned nx
, ny
, image
= 0, boxz
= 0;
141 /* XXX can't unify these here? */
142 if (pt
->target
== PIPE_TEXTURE_CUBE
)
144 else if (pt
->target
== PIPE_TEXTURE_3D
)
147 tx
= CALLOC_STRUCT(nv50_transfer
);
151 /* Don't handle 3D transfers yet.
153 assert(box
->depth
== 1);
156 pipe_resource_reference(&tx
->base
.resource
, pt
);
157 tx
->base
.level
= level
;
158 tx
->base
.usage
= usage
;
160 tx
->nblocksx
= util_format_get_nblocksx(pt
->format
, u_minify(pt
->width0
, level
));
161 tx
->nblocksy
= util_format_get_nblocksy(pt
->format
, u_minify(pt
->height0
, level
));
162 tx
->base
.stride
= tx
->nblocksx
* util_format_get_blocksize(pt
->format
);
163 tx
->base
.usage
= usage
;
165 tx
->level_pitch
= lvl
->pitch
;
166 tx
->level_width
= u_minify(mt
->base
.base
.width0
, level
);
167 tx
->level_height
= u_minify(mt
->base
.base
.height0
, level
);
168 tx
->level_depth
= u_minify(mt
->base
.base
.depth0
, level
);
169 tx
->level_offset
= lvl
->image_offset
[image
];
170 tx
->level_tiling
= lvl
->tile_mode
;
172 tx
->level_x
= util_format_get_nblocksx(pt
->format
, box
->x
);
173 tx
->level_y
= util_format_get_nblocksy(pt
->format
, box
->y
);
174 ret
= nouveau_bo_new(dev
, NOUVEAU_BO_GART
| NOUVEAU_BO_MAP
, 0,
175 tx
->nblocksy
* tx
->base
.stride
, &tx
->bo
);
181 if (usage
& PIPE_TRANSFER_READ
) {
182 nx
= util_format_get_nblocksx(pt
->format
, box
->width
);
183 ny
= util_format_get_nblocksy(pt
->format
, box
->height
);
185 nv50_transfer_rect_m2mf(pscreen
, mt
->base
.bo
, tx
->level_offset
,
186 tx
->level_pitch
, tx
->level_tiling
,
187 box
->x
, box
->y
, boxz
,
188 tx
->nblocksx
, tx
->nblocksy
,
191 tx
->base
.stride
, tx
->bo
->tile_mode
,
193 tx
->nblocksx
, tx
->nblocksy
, 1,
194 util_format_get_blocksize(pt
->format
), nx
, ny
,
195 NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
,
203 nv50_miptree_transfer_del(struct pipe_context
*pcontext
,
204 struct pipe_transfer
*ptx
)
206 struct nv50_transfer
*tx
= (struct nv50_transfer
*)ptx
;
207 struct nv50_miptree
*mt
= nv50_miptree(ptx
->resource
);
208 struct pipe_resource
*pt
= ptx
->resource
;
210 unsigned nx
= util_format_get_nblocksx(pt
->format
, tx
->base
.box
.width
);
211 unsigned ny
= util_format_get_nblocksy(pt
->format
, tx
->base
.box
.height
);
213 if (ptx
->usage
& PIPE_TRANSFER_WRITE
) {
214 struct pipe_screen
*pscreen
= pcontext
->screen
;
216 nv50_transfer_rect_m2mf(pscreen
, tx
->bo
, 0,
217 tx
->base
.stride
, tx
->bo
->tile_mode
,
219 tx
->nblocksx
, tx
->nblocksy
, 1,
220 mt
->base
.bo
, tx
->level_offset
,
221 tx
->level_pitch
, tx
->level_tiling
,
222 tx
->level_x
, tx
->level_y
, tx
->level_z
,
223 tx
->nblocksx
, tx
->nblocksy
,
225 util_format_get_blocksize(pt
->format
), nx
, ny
,
226 NOUVEAU_BO_GART
, NOUVEAU_BO_VRAM
|
230 nouveau_bo_ref(NULL
, &tx
->bo
);
231 pipe_resource_reference(&ptx
->resource
, NULL
);
236 nv50_miptree_transfer_map(struct pipe_context
*pcontext
,
237 struct pipe_transfer
*ptx
)
239 struct nv50_transfer
*tx
= (struct nv50_transfer
*)ptx
;
243 if (tx
->map_refcnt
++)
246 if (ptx
->usage
& PIPE_TRANSFER_WRITE
)
247 flags
|= NOUVEAU_BO_WR
;
248 if (ptx
->usage
& PIPE_TRANSFER_READ
)
249 flags
|= NOUVEAU_BO_RD
;
251 ret
= nouveau_bo_map(tx
->bo
, flags
);
260 nv50_miptree_transfer_unmap(struct pipe_context
*pcontext
,
261 struct pipe_transfer
*ptx
)
263 struct nv50_transfer
*tx
= (struct nv50_transfer
*)ptx
;
265 if (--tx
->map_refcnt
)
267 nouveau_bo_unmap(tx
->bo
);
272 nv50_upload_sifc(struct nv50_context
*nv50
,
273 struct nouveau_bo
*bo
, unsigned dst_offset
, unsigned reloc
,
274 unsigned dst_format
, int dst_w
, int dst_h
, int dst_pitch
,
275 void *src
, unsigned src_format
, int src_pitch
,
276 int x
, int y
, int w
, int h
, int cpp
)
278 struct nouveau_channel
*chan
= nv50
->screen
->base
.channel
;
279 struct nouveau_grobj
*eng2d
= nv50
->screen
->eng2d
;
280 unsigned line_dwords
= (w
* cpp
+ 3) / 4;
282 reloc
|= NOUVEAU_BO_WR
;
284 MARK_RING (chan
, 32, 2); /* flush on lack of space or relocs */
286 if (nouveau_bo_tile_layout(bo
)) {
287 BEGIN_RING(chan
, eng2d
, NV50_2D_DST_FORMAT
, 5);
288 OUT_RING (chan
, dst_format
);
290 OUT_RING (chan
, bo
->tile_mode
<< 4);
294 BEGIN_RING(chan
, eng2d
, NV50_2D_DST_FORMAT
, 2);
295 OUT_RING (chan
, dst_format
);
297 BEGIN_RING(chan
, eng2d
, NV50_2D_DST_PITCH
, 1);
298 OUT_RING (chan
, dst_pitch
);
301 BEGIN_RING(chan
, eng2d
, NV50_2D_DST_WIDTH
, 4);
302 OUT_RING (chan
, dst_w
);
303 OUT_RING (chan
, dst_h
);
304 OUT_RELOCh(chan
, bo
, dst_offset
, reloc
);
305 OUT_RELOCl(chan
, bo
, dst_offset
, reloc
);
307 /* NV50_2D_OPERATION_SRCCOPY assumed already set */
309 BEGIN_RING(chan
, eng2d
, NV50_2D_SIFC_BITMAP_ENABLE
, 2);
311 OUT_RING (chan
, src_format
);
312 BEGIN_RING(chan
, eng2d
, NV50_2D_SIFC_WIDTH
, 10);
325 const uint32_t *p
= src
;
326 unsigned count
= line_dwords
;
329 unsigned nr
= MIN2(count
, 1792);
331 if (AVAIL_RING(chan
) <= nr
) {
334 BEGIN_RING(chan
, eng2d
,
335 NV50_2D_DST_ADDRESS_HIGH
, 2);
336 OUT_RELOCh(chan
, bo
, dst_offset
, reloc
);
337 OUT_RELOCl(chan
, bo
, dst_offset
, reloc
);
339 assert(AVAIL_RING(chan
) > nr
);
341 BEGIN_RING(chan
, eng2d
,
342 NV50_2D_SIFC_DATA
| (2 << 29), nr
);
343 OUT_RINGp (chan
, p
, nr
);
349 src
= (uint8_t *) src
+ src_pitch
;