Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / libs / mesa / src / gallium / drivers / nv50 / nv50_transfer.c
blobd9fb22aa673a0c9601de1ba5ddd1059997084acb
2 #include "util/u_format.h"
4 #include "nv50_context.h"
5 #include "nv50_transfer.h"
7 #include "nv50_defs.xml.h"
9 struct nv50_transfer {
10 struct pipe_transfer base;
11 struct nv50_m2mf_rect rect[2];
12 uint32_t nblocksx;
13 uint32_t nblocksy;
16 static void
17 nv50_m2mf_transfer_rect(struct pipe_screen *pscreen,
18 const struct nv50_m2mf_rect *dst,
19 const struct nv50_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;
27 uint32_t sy = src->y;
28 uint32_t dy = dst->y;
30 assert(dst->cpp == src->cpp);
32 if (nouveau_bo_tile_layout(src->bo)) {
33 BEGIN_RING(chan, RING_MF(LINEAR_IN), 6);
34 OUT_RING (chan, 0);
35 OUT_RING (chan, src->tile_mode << 4);
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);
40 } else {
41 src_ofst += src->y * src->pitch + src->x * cpp;
43 BEGIN_RING(chan, RING_MF(LINEAR_IN), 1);
44 OUT_RING (chan, 1);
45 BEGIN_RING(chan, RING_MF_(NV04_M2MF_PITCH_IN), 1);
46 OUT_RING (chan, src->pitch);
49 if (nouveau_bo_tile_layout(dst->bo)) {
50 BEGIN_RING(chan, RING_MF(LINEAR_OUT), 6);
51 OUT_RING (chan, 0);
52 OUT_RING (chan, dst->tile_mode << 4);
53 OUT_RING (chan, dst->width * cpp);
54 OUT_RING (chan, dst->height);
55 OUT_RING (chan, dst->depth);
56 OUT_RING (chan, dst->z);
57 } else {
58 dst_ofst += dst->y * dst->pitch + dst->x * cpp;
60 BEGIN_RING(chan, RING_MF(LINEAR_OUT), 1);
61 OUT_RING (chan, 1);
62 BEGIN_RING(chan, RING_MF_(NV04_M2MF_PITCH_OUT), 1);
63 OUT_RING (chan, dst->pitch);
66 while (height) {
67 int line_count = height > 2047 ? 2047 : height;
69 MARK_RING (chan, 17, 4);
71 BEGIN_RING(chan, RING_MF(OFFSET_IN_HIGH), 2);
72 OUT_RELOCh(chan, src->bo, src_ofst, src->domain | NOUVEAU_BO_RD);
73 OUT_RELOCh(chan, dst->bo, dst_ofst, dst->domain | NOUVEAU_BO_WR);
75 BEGIN_RING(chan, RING_MF_(NV04_M2MF_OFFSET_IN), 2);
76 OUT_RELOCl(chan, src->bo, src_ofst, src->domain | NOUVEAU_BO_RD);
77 OUT_RELOCl(chan, dst->bo, dst_ofst, dst->domain | NOUVEAU_BO_WR);
79 if (nouveau_bo_tile_layout(src->bo)) {
80 BEGIN_RING(chan, RING_MF(TILING_POSITION_IN), 1);
81 OUT_RING (chan, (sy << 16) | (src->x * cpp));
82 } else {
83 src_ofst += line_count * src->pitch;
85 if (nouveau_bo_tile_layout(dst->bo)) {
86 BEGIN_RING(chan, RING_MF(TILING_POSITION_OUT), 1);
87 OUT_RING (chan, (dy << 16) | (dst->x * cpp));
88 } else {
89 dst_ofst += line_count * dst->pitch;
92 BEGIN_RING(chan, RING_MF_(NV04_M2MF_LINE_LENGTH_IN), 4);
93 OUT_RING (chan, nblocksx * cpp);
94 OUT_RING (chan, line_count);
95 OUT_RING (chan, (1 << 8) | (1 << 0));
96 OUT_RING (chan, 0);
98 height -= line_count;
99 sy += line_count;
100 dy += line_count;
104 void
105 nv50_sifc_linear_u8(struct nouveau_context *nv,
106 struct nouveau_bo *dst, unsigned offset, unsigned domain,
107 unsigned size, void *data)
109 struct nouveau_channel *chan = nv->screen->channel;
110 uint32_t *src = (uint32_t *)data;
111 unsigned count = (size + 3) / 4;
112 unsigned xcoord = offset & 0xff;
114 offset &= ~0xff;
116 MARK_RING (chan, 23, 4);
117 BEGIN_RING(chan, RING_2D(DST_FORMAT), 2);
118 OUT_RING (chan, NV50_SURFACE_FORMAT_R8_UNORM);
119 OUT_RING (chan, 1);
120 BEGIN_RING(chan, RING_2D(DST_PITCH), 5);
121 OUT_RING (chan, 262144);
122 OUT_RING (chan, 65536);
123 OUT_RING (chan, 1);
124 OUT_RELOCh(chan, dst, offset, domain | NOUVEAU_BO_WR);
125 OUT_RELOCl(chan, dst, offset, domain | NOUVEAU_BO_WR);
126 BEGIN_RING(chan, RING_2D(SIFC_BITMAP_ENABLE), 2);
127 OUT_RING (chan, 0);
128 OUT_RING (chan, NV50_SURFACE_FORMAT_R8_UNORM);
129 BEGIN_RING(chan, RING_2D(SIFC_WIDTH), 10);
130 OUT_RING (chan, size);
131 OUT_RING (chan, 1);
132 OUT_RING (chan, 0);
133 OUT_RING (chan, 1);
134 OUT_RING (chan, 0);
135 OUT_RING (chan, 1);
136 OUT_RING (chan, 0);
137 OUT_RING (chan, xcoord);
138 OUT_RING (chan, 0);
139 OUT_RING (chan, 0);
141 while (count) {
142 unsigned nr = AVAIL_RING(chan);
144 if (nr < 9) {
145 FIRE_RING(chan);
146 nouveau_bo_validate(chan, dst, NOUVEAU_BO_WR);
147 continue;
149 nr = MIN2(count, nr - 1);
150 nr = MIN2(nr, NV04_PFIFO_MAX_PACKET_LEN);
152 BEGIN_RING_NI(chan, RING_2D(SIFC_DATA), nr);
153 OUT_RINGp (chan, src, nr);
155 src += nr;
156 count -= nr;
160 void
161 nv50_m2mf_copy_linear(struct nouveau_context *nv,
162 struct nouveau_bo *dst, unsigned dstoff, unsigned dstdom,
163 struct nouveau_bo *src, unsigned srcoff, unsigned srcdom,
164 unsigned size)
166 struct nouveau_channel *chan = nv->screen->channel;
168 BEGIN_RING(chan, RING_MF(LINEAR_IN), 1);
169 OUT_RING (chan, 1);
170 BEGIN_RING(chan, RING_MF(LINEAR_OUT), 1);
171 OUT_RING (chan, 1);
173 while (size) {
174 unsigned bytes = MIN2(size, 1 << 17);
176 MARK_RING (chan, 11, 4);
177 BEGIN_RING(chan, RING_MF(OFFSET_IN_HIGH), 2);
178 OUT_RELOCh(chan, src, srcoff, srcdom | NOUVEAU_BO_RD);
179 OUT_RELOCh(chan, dst, dstoff, dstdom | NOUVEAU_BO_WR);
180 BEGIN_RING(chan, RING_MF_(NV04_M2MF_OFFSET_IN), 2);
181 OUT_RELOCl(chan, src, srcoff, srcdom | NOUVEAU_BO_RD);
182 OUT_RELOCl(chan, dst, dstoff, dstdom | NOUVEAU_BO_WR);
183 BEGIN_RING(chan, RING_MF_(NV04_M2MF_LINE_LENGTH_IN), 4);
184 OUT_RING (chan, bytes);
185 OUT_RING (chan, 1);
186 OUT_RING (chan, (1 << 8) | (1 << 0));
187 OUT_RING (chan, 0);
189 srcoff += bytes;
190 dstoff += bytes;
191 size -= bytes;
195 struct pipe_transfer *
196 nv50_miptree_transfer_new(struct pipe_context *pctx,
197 struct pipe_resource *res,
198 unsigned level,
199 unsigned usage,
200 const struct pipe_box *box)
202 struct nv50_context *nv50 = nv50_context(pctx);
203 struct pipe_screen *pscreen = pctx->screen;
204 struct nouveau_device *dev = nv50->screen->base.device;
205 struct nv50_miptree *mt = nv50_miptree(res);
206 struct nv50_miptree_level *lvl = &mt->level[level];
207 struct nv50_transfer *tx;
208 uint32_t size;
209 uint32_t w, h, d, z, layer;
210 int ret;
212 if (usage & PIPE_TRANSFER_MAP_DIRECTLY)
213 return NULL;
215 if (mt->layout_3d) {
216 z = box->z;
217 d = u_minify(res->depth0, level);
218 layer = 0;
219 } else {
220 z = 0;
221 d = 1;
222 layer = box->z;
225 tx = CALLOC_STRUCT(nv50_transfer);
226 if (!tx)
227 return NULL;
229 pipe_resource_reference(&tx->base.resource, res);
231 tx->base.level = level;
232 tx->base.usage = usage;
233 tx->base.box = *box;
235 tx->nblocksx = util_format_get_nblocksx(res->format, box->width);
236 tx->nblocksy = util_format_get_nblocksy(res->format, box->height);
238 tx->base.stride = tx->nblocksx * util_format_get_blocksize(res->format);
239 tx->base.layer_stride = tx->nblocksy * tx->base.stride;
241 w = u_minify(res->width0, level);
242 h = u_minify(res->height0, level);
244 tx->rect[0].cpp = tx->rect[1].cpp = util_format_get_blocksize(res->format);
246 tx->rect[0].bo = mt->base.bo;
247 tx->rect[0].base = lvl->offset + layer * mt->layer_stride;
248 tx->rect[0].tile_mode = lvl->tile_mode;
249 tx->rect[0].x = util_format_get_nblocksx(res->format, box->x);
250 tx->rect[0].y = util_format_get_nblocksy(res->format, box->y);
251 tx->rect[0].z = z;
252 tx->rect[0].width = util_format_get_nblocksx(res->format, w);
253 tx->rect[0].height = util_format_get_nblocksy(res->format, h);
254 tx->rect[0].depth = d;
255 tx->rect[0].pitch = lvl->pitch;
256 tx->rect[0].domain = NOUVEAU_BO_VRAM;
258 size = tx->base.layer_stride;
260 ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0,
261 size * tx->base.box.depth, &tx->rect[1].bo);
262 if (ret) {
263 FREE(tx);
264 return NULL;
267 tx->rect[1].width = tx->nblocksx;
268 tx->rect[1].height = tx->nblocksy;
269 tx->rect[1].depth = 1;
270 tx->rect[1].pitch = tx->base.stride;
271 tx->rect[1].domain = NOUVEAU_BO_GART;
273 if (usage & PIPE_TRANSFER_READ) {
274 unsigned base = tx->rect[0].base;
275 unsigned i;
276 for (i = 0; i < box->depth; ++i) {
277 nv50_m2mf_transfer_rect(pscreen, &tx->rect[1], &tx->rect[0],
278 tx->nblocksx, tx->nblocksy);
279 if (mt->layout_3d)
280 tx->rect[0].z++;
281 else
282 tx->rect[0].base += mt->layer_stride;
283 tx->rect[1].base += size;
285 tx->rect[0].z = z;
286 tx->rect[0].base = base;
287 tx->rect[1].base = 0;
290 return &tx->base;
293 void
294 nv50_miptree_transfer_del(struct pipe_context *pctx,
295 struct pipe_transfer *transfer)
297 struct pipe_screen *pscreen = pctx->screen;
298 struct nv50_transfer *tx = (struct nv50_transfer *)transfer;
299 struct nv50_miptree *mt = nv50_miptree(tx->base.resource);
300 unsigned i;
302 if (tx->base.usage & PIPE_TRANSFER_WRITE) {
303 for (i = 0; i < tx->base.box.depth; ++i) {
304 nv50_m2mf_transfer_rect(pscreen, &tx->rect[0], &tx->rect[1],
305 tx->nblocksx, tx->nblocksy);
306 if (mt->layout_3d)
307 tx->rect[0].z++;
308 else
309 tx->rect[0].base += mt->layer_stride;
310 tx->rect[1].base += tx->nblocksy * tx->base.stride;
314 nouveau_bo_ref(NULL, &tx->rect[1].bo);
315 pipe_resource_reference(&transfer->resource, NULL);
317 FREE(tx);
320 void *
321 nv50_miptree_transfer_map(struct pipe_context *pctx,
322 struct pipe_transfer *transfer)
324 struct nv50_transfer *tx = (struct nv50_transfer *)transfer;
325 int ret;
326 unsigned flags = 0;
328 if (tx->rect[1].bo->map)
329 return tx->rect[1].bo->map;
331 if (transfer->usage & PIPE_TRANSFER_READ)
332 flags = NOUVEAU_BO_RD;
333 if (transfer->usage & PIPE_TRANSFER_WRITE)
334 flags |= NOUVEAU_BO_WR;
336 ret = nouveau_bo_map(tx->rect[1].bo, flags);
337 if (ret)
338 return NULL;
339 return tx->rect[1].bo->map;
342 void
343 nv50_miptree_transfer_unmap(struct pipe_context *pctx,
344 struct pipe_transfer *transfer)
346 struct nv50_transfer *tx = (struct nv50_transfer *)transfer;
348 nouveau_bo_unmap(tx->rect[1].bo);