ilo: remove intel_bo_get_virtual()
[mesa.git] / src / gallium / drivers / ilo / ilo_transfer.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2012-2013 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
26 */
27
28 #include "util/u_surface.h"
29 #include "util/u_transfer.h"
30 #include "util/u_format_etc.h"
31
32 #include "ilo_blit.h"
33 #include "ilo_cp.h"
34 #include "ilo_context.h"
35 #include "ilo_resource.h"
36 #include "ilo_state.h"
37 #include "ilo_transfer.h"
38
39 static bool
40 is_bo_busy(struct ilo_context *ilo, struct intel_bo *bo, bool *need_flush)
41 {
42 const bool referenced = intel_bo_has_reloc(ilo->cp->bo, bo);
43
44 if (need_flush)
45 *need_flush = referenced;
46
47 if (referenced)
48 return true;
49
50 return intel_bo_is_busy(bo);
51 }
52
53 static void *
54 map_bo_for_transfer(struct ilo_context *ilo, struct intel_bo *bo,
55 const struct ilo_transfer *xfer)
56 {
57 void *ptr;
58
59 switch (xfer->method) {
60 case ILO_TRANSFER_MAP_CPU:
61 ptr = intel_bo_map(bo, (xfer->base.usage & PIPE_TRANSFER_WRITE));
62 break;
63 case ILO_TRANSFER_MAP_GTT:
64 ptr = intel_bo_map_gtt(bo);
65 break;
66 case ILO_TRANSFER_MAP_UNSYNC:
67 ptr = intel_bo_map_unsynchronized(bo);
68 break;
69 default:
70 assert(!"unknown mapping method");
71 ptr = NULL;
72 break;
73 }
74
75 return ptr;
76 }
77
78 /**
79 * Choose the best mapping method, depending on the transfer usage and whether
80 * the bo is busy.
81 */
82 static bool
83 choose_transfer_method(struct ilo_context *ilo, struct ilo_transfer *xfer)
84 {
85 struct pipe_resource *res = xfer->base.resource;
86 const unsigned usage = xfer->base.usage;
87 /* prefer map() when there is the last-level cache */
88 const bool prefer_cpu =
89 (ilo->dev->has_llc || (usage & PIPE_TRANSFER_READ));
90 struct ilo_texture *tex;
91 struct ilo_buffer *buf;
92 struct intel_bo *bo;
93 bool tiled, need_flush;
94
95 if (res->target == PIPE_BUFFER) {
96 tex = NULL;
97
98 buf = ilo_buffer(res);
99 bo = buf->bo;
100 tiled = false;
101 }
102 else {
103 buf = NULL;
104
105 tex = ilo_texture(res);
106 bo = tex->bo;
107 tiled = (tex->tiling != INTEL_TILING_NONE);
108 }
109
110 /* choose between mapping through CPU or GTT */
111 if (usage & PIPE_TRANSFER_MAP_DIRECTLY) {
112 /* we do not want fencing */
113 if (tiled || prefer_cpu)
114 xfer->method = ILO_TRANSFER_MAP_CPU;
115 else
116 xfer->method = ILO_TRANSFER_MAP_GTT;
117 }
118 else {
119 if (!tiled && prefer_cpu)
120 xfer->method = ILO_TRANSFER_MAP_CPU;
121 else
122 xfer->method = ILO_TRANSFER_MAP_GTT;
123 }
124
125 /* see if we can avoid stalling */
126 if (is_bo_busy(ilo, bo, &need_flush)) {
127 bool will_stall = true;
128
129 if (usage & PIPE_TRANSFER_MAP_DIRECTLY) {
130 /* nothing we can do */
131 }
132 else if (usage & PIPE_TRANSFER_UNSYNCHRONIZED) {
133 /* unsynchronized gtt mapping does not stall */
134 xfer->method = ILO_TRANSFER_MAP_UNSYNC;
135 will_stall = false;
136 }
137 else if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) {
138 /* discard old bo and allocate a new one for mapping */
139 if ((tex && ilo_texture_alloc_bo(tex)) ||
140 (buf && ilo_buffer_alloc_bo(buf))) {
141 ilo_mark_states_with_resource_dirty(ilo, res);
142 will_stall = false;
143 }
144 }
145 else if (usage & PIPE_TRANSFER_FLUSH_EXPLICIT) {
146 /*
147 * We could allocate and return a system buffer here. When a region of
148 * the buffer is explicitly flushed, we pwrite() the region to a
149 * temporary bo and emit pipelined copy blit.
150 *
151 * For now, do nothing.
152 */
153 }
154 else if (usage & PIPE_TRANSFER_DISCARD_RANGE) {
155 /*
156 * We could allocate a temporary bo for mapping, and emit pipelined copy
157 * blit upon unmapping.
158 *
159 * For now, do nothing.
160 */
161 }
162
163 if (will_stall) {
164 if (usage & PIPE_TRANSFER_DONTBLOCK)
165 return false;
166
167 /* flush to make bo busy (so that map() stalls as it should be) */
168 if (need_flush)
169 ilo_cp_flush(ilo->cp, "syncing for transfers");
170 }
171 }
172
173 if (tex && !(usage & PIPE_TRANSFER_MAP_DIRECTLY)) {
174 if (tex->separate_s8 || tex->bo_format == PIPE_FORMAT_S8_UINT)
175 xfer->method = ILO_TRANSFER_MAP_SW_ZS;
176 /* need to convert on-the-fly */
177 else if (tex->bo_format != tex->base.format)
178 xfer->method = ILO_TRANSFER_MAP_SW_CONVERT;
179 }
180
181 return true;
182 }
183
184 static void
185 tex_get_box_origin(const struct ilo_texture *tex,
186 unsigned level, unsigned slice,
187 const struct pipe_box *box,
188 unsigned *mem_x, unsigned *mem_y)
189 {
190 const struct ilo_texture_slice *s =
191 ilo_texture_get_slice(tex, level, slice + box->z);
192 unsigned x, y;
193
194 x = s->x + box->x;
195 y = s->y + box->y;
196
197 assert(x % tex->block_width == 0 && y % tex->block_height == 0);
198
199 *mem_x = x / tex->block_width * tex->bo_cpp;
200 *mem_y = y / tex->block_height;
201 }
202
203 static unsigned
204 tex_get_box_offset(const struct ilo_texture *tex, unsigned level,
205 const struct pipe_box *box)
206 {
207 unsigned mem_x, mem_y;
208
209 tex_get_box_origin(tex, level, 0, box, &mem_x, &mem_y);
210
211 return mem_y * tex->bo_stride + mem_x;
212 }
213
214 static unsigned
215 tex_get_slice_stride(const struct ilo_texture *tex, unsigned level)
216 {
217 const struct ilo_texture_slice *s0, *s1;
218 unsigned qpitch;
219
220 /* there is no 3D array texture */
221 assert(tex->base.array_size == 1 || tex->base.depth0 == 1);
222
223 if (tex->base.array_size == 1) {
224 /* non-array, non-3D */
225 if (tex->base.depth0 == 1)
226 return 0;
227
228 /* only the first level has a fixed slice stride */
229 if (level > 0) {
230 assert(!"no slice stride for 3D texture with level > 0");
231 return 0;
232 }
233 }
234
235 s0 = ilo_texture_get_slice(tex, level, 0);
236 s1 = ilo_texture_get_slice(tex, level, 1);
237 qpitch = s1->y - s0->y;
238 assert(qpitch % tex->block_height == 0);
239
240 return (qpitch / tex->block_height) * tex->bo_stride;
241 }
242
243 static unsigned
244 tex_tile_x_swizzle(unsigned addr)
245 {
246 /*
247 * From the Ivy Bridge PRM, volume 1 part 2, page 24:
248 *
249 * "As shown in the tiling algorithm, the new address bit[6] should be:
250 *
251 * Address bit[6] <= TiledAddr bit[6] XOR
252 * TiledAddr bit[9] XOR
253 * TiledAddr bit[10]"
254 */
255 return addr ^ (((addr >> 3) ^ (addr >> 4)) & 0x40);
256 }
257
258 static unsigned
259 tex_tile_y_swizzle(unsigned addr)
260 {
261 /*
262 * From the Ivy Bridge PRM, volume 1 part 2, page 24:
263 *
264 * "As shown in the tiling algorithm, The new address bit[6] becomes:
265 *
266 * Address bit[6] <= TiledAddr bit[6] XOR
267 * TiledAddr bit[9]"
268 */
269 return addr ^ ((addr >> 3) & 0x40);
270 }
271
272 static unsigned
273 tex_tile_x_offset(unsigned mem_x, unsigned mem_y,
274 unsigned tiles_per_row, bool swizzle)
275 {
276 /*
277 * From the Sandy Bridge PRM, volume 1 part 2, page 21, we know that a
278 * X-major tile has 8 rows and 32 OWord columns (512 bytes). Tiles in the
279 * tiled region are numbered in row-major order, starting from zero. The
280 * tile number can thus be calculated as follows:
281 *
282 * tile = (mem_y / 8) * tiles_per_row + (mem_x / 512)
283 *
284 * OWords in that tile are also numbered in row-major order, starting from
285 * zero. The OWord number can thus be calculated as follows:
286 *
287 * oword = (mem_y % 8) * 32 + ((mem_x % 512) / 16)
288 *
289 * and the tiled offset is
290 *
291 * offset = tile * 4096 + oword * 16 + (mem_x % 16)
292 * = tile * 4096 + (mem_y % 8) * 512 + (mem_x % 512)
293 */
294 unsigned tile, offset;
295
296 tile = (mem_y >> 3) * tiles_per_row + (mem_x >> 9);
297 offset = tile << 12 | (mem_y & 0x7) << 9 | (mem_x & 0x1ff);
298
299 return (swizzle) ? tex_tile_x_swizzle(offset) : offset;
300 }
301
302 static unsigned
303 tex_tile_y_offset(unsigned mem_x, unsigned mem_y,
304 unsigned tiles_per_row, bool swizzle)
305 {
306 /*
307 * From the Sandy Bridge PRM, volume 1 part 2, page 22, we know that a
308 * Y-major tile has 32 rows and 8 OWord columns (128 bytes). Tiles in the
309 * tiled region are numbered in row-major order, starting from zero. The
310 * tile number can thus be calculated as follows:
311 *
312 * tile = (mem_y / 32) * tiles_per_row + (mem_x / 128)
313 *
314 * OWords in that tile are numbered in column-major order, starting from
315 * zero. The OWord number can thus be calculated as follows:
316 *
317 * oword = ((mem_x % 128) / 16) * 32 + (mem_y % 32)
318 *
319 * and the tiled offset is
320 *
321 * offset = tile * 4096 + oword * 16 + (mem_x % 16)
322 */
323 unsigned tile, oword, offset;
324
325 tile = (mem_y >> 5) * tiles_per_row + (mem_x >> 7);
326 oword = (mem_x & 0x70) << 1 | (mem_y & 0x1f);
327 offset = tile << 12 | oword << 4 | (mem_x & 0xf);
328
329 return (swizzle) ? tex_tile_y_swizzle(offset) : offset;
330 }
331
332 static unsigned
333 tex_tile_w_offset(unsigned mem_x, unsigned mem_y,
334 unsigned tiles_per_row, bool swizzle)
335 {
336 /*
337 * From the Sandy Bridge PRM, volume 1 part 2, page 23, we know that a
338 * W-major tile has 8 8x8-block rows and 8 8x8-block columns. Tiles in the
339 * tiled region are numbered in row-major order, starting from zero. The
340 * tile number can thus be calculated as follows:
341 *
342 * tile = (mem_y / 64) * tiles_per_row + (mem_x / 64)
343 *
344 * 8x8-blocks in that tile are numbered in column-major order, starting
345 * from zero. The 8x8-block number can thus be calculated as follows:
346 *
347 * blk8 = ((mem_x % 64) / 8) * 8 + ((mem_y % 64) / 8)
348 *
349 * Each 8x8-block is divided into 4 4x4-blocks, in row-major order. Each
350 * 4x4-block is further divided into 4 2x2-blocks, also in row-major order.
351 * We have
352 *
353 * blk4 = (((mem_y % 64) / 4) & 1) * 2 + (((mem_x % 64) / 4) & 1)
354 * blk2 = (((mem_y % 64) / 2) & 1) * 2 + (((mem_x % 64) / 2) & 1)
355 * blk1 = (((mem_y % 64) ) & 1) * 2 + (((mem_x % 64) ) & 1)
356 *
357 * and the tiled offset is
358 *
359 * offset = tile * 4096 + blk8 * 64 + blk4 * 16 + blk2 * 4 + blk1
360 */
361 unsigned tile, blk8, blk4, blk2, blk1, offset;
362
363 tile = (mem_y >> 6) * tiles_per_row + (mem_x >> 6);
364 blk8 = ((mem_x >> 3) & 0x7) << 3 | ((mem_y >> 3) & 0x7);
365 blk4 = ((mem_y >> 2) & 0x1) << 1 | ((mem_x >> 2) & 0x1);
366 blk2 = ((mem_y >> 1) & 0x1) << 1 | ((mem_x >> 1) & 0x1);
367 blk1 = ((mem_y ) & 0x1) << 1 | ((mem_x ) & 0x1);
368 offset = tile << 12 | blk8 << 6 | blk4 << 4 | blk2 << 2 | blk1;
369
370 return (swizzle) ? tex_tile_y_swizzle(offset) : offset;
371 }
372
373 static unsigned
374 tex_tile_none_offset(unsigned mem_x, unsigned mem_y,
375 unsigned tiles_per_row, bool swizzle)
376 {
377 return mem_y * tiles_per_row + mem_x;
378 }
379
380 typedef unsigned (*tex_tile_offset_func)(unsigned mem_x, unsigned mem_y,
381 unsigned tiles_per_row,
382 bool swizzle);
383
384 static tex_tile_offset_func
385 tex_tile_choose_offset_func(const struct ilo_texture *tex,
386 unsigned *tiles_per_row)
387 {
388 switch (tex->tiling) {
389 case INTEL_TILING_X:
390 *tiles_per_row = tex->bo_stride / 512;
391 return tex_tile_x_offset;
392 case INTEL_TILING_Y:
393 *tiles_per_row = tex->bo_stride / 128;
394 return tex_tile_y_offset;
395 case INTEL_TILING_NONE:
396 default:
397 /* W-tiling */
398 if (tex->bo_format == PIPE_FORMAT_S8_UINT) {
399 *tiles_per_row = tex->bo_stride / 64;
400 return tex_tile_w_offset;
401 }
402 else {
403 *tiles_per_row = tex->bo_stride;
404 return tex_tile_none_offset;
405 }
406 }
407 }
408
409 static void *
410 tex_staging_sys_map_bo(const struct ilo_context *ilo,
411 struct ilo_texture *tex,
412 bool for_read_back, bool linear_view)
413 {
414 const bool prefer_cpu = (ilo->dev->has_llc || for_read_back);
415 void *ptr;
416
417 if (prefer_cpu && (tex->tiling == INTEL_TILING_NONE || !linear_view))
418 ptr = intel_bo_map(tex->bo, !for_read_back);
419 else
420 ptr = intel_bo_map_gtt(tex->bo);
421
422 return ptr;
423 }
424
425 static void
426 tex_staging_sys_unmap_bo(const struct ilo_context *ilo,
427 const struct ilo_texture *tex)
428 {
429 intel_bo_unmap(tex->bo);
430 }
431
432 static bool
433 tex_staging_sys_zs_read(struct ilo_context *ilo,
434 struct ilo_texture *tex,
435 const struct ilo_transfer *xfer)
436 {
437 const bool swizzle = ilo->dev->has_address_swizzling;
438 const struct pipe_box *box = &xfer->base.box;
439 const uint8_t *src;
440 tex_tile_offset_func tile_offset;
441 unsigned tiles_per_row;
442 int slice;
443
444 src = tex_staging_sys_map_bo(ilo, tex, true, false);
445 if (!src)
446 return false;
447
448 tile_offset = tex_tile_choose_offset_func(tex, &tiles_per_row);
449
450 assert(tex->block_width == 1 && tex->block_height == 1);
451
452 if (tex->separate_s8) {
453 struct ilo_texture *s8_tex = tex->separate_s8;
454 const uint8_t *s8_src;
455 tex_tile_offset_func s8_tile_offset;
456 unsigned s8_tiles_per_row;
457 int dst_cpp, dst_s8_pos, src_cpp_used;
458
459 s8_src = tex_staging_sys_map_bo(ilo, s8_tex, true, false);
460 if (!s8_src) {
461 tex_staging_sys_unmap_bo(ilo, tex);
462 return false;
463 }
464
465 s8_tile_offset = tex_tile_choose_offset_func(s8_tex, &s8_tiles_per_row);
466
467 if (tex->base.format == PIPE_FORMAT_Z24_UNORM_S8_UINT) {
468 assert(tex->bo_format == PIPE_FORMAT_Z24X8_UNORM);
469
470 dst_cpp = 4;
471 dst_s8_pos = 3;
472 src_cpp_used = 3;
473 }
474 else {
475 assert(tex->base.format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT);
476 assert(tex->bo_format == PIPE_FORMAT_Z32_FLOAT);
477
478 dst_cpp = 8;
479 dst_s8_pos = 4;
480 src_cpp_used = 4;
481 }
482
483 for (slice = 0; slice < box->depth; slice++) {
484 unsigned mem_x, mem_y, s8_mem_x, s8_mem_y;
485 uint8_t *dst;
486 int i, j;
487
488 tex_get_box_origin(tex, xfer->base.level, slice,
489 box, &mem_x, &mem_y);
490 tex_get_box_origin(s8_tex, xfer->base.level, slice,
491 box, &s8_mem_x, &s8_mem_y);
492
493 dst = xfer->staging_sys + xfer->base.layer_stride * slice;
494
495 for (i = 0; i < box->height; i++) {
496 unsigned x = mem_x, s8_x = s8_mem_x;
497 uint8_t *d = dst;
498
499 for (j = 0; j < box->width; j++) {
500 const unsigned offset =
501 tile_offset(x, mem_y, tiles_per_row, swizzle);
502 const unsigned s8_offset =
503 s8_tile_offset(s8_x, s8_mem_y, s8_tiles_per_row, swizzle);
504
505 memcpy(d, src + offset, src_cpp_used);
506 d[dst_s8_pos] = s8_src[s8_offset];
507
508 d += dst_cpp;
509 x += tex->bo_cpp;
510 s8_x++;
511 }
512
513 dst += xfer->base.stride;
514 mem_y++;
515 s8_mem_y++;
516 }
517 }
518
519 tex_staging_sys_unmap_bo(ilo, s8_tex);
520 }
521 else {
522 assert(tex->bo_format == PIPE_FORMAT_S8_UINT);
523
524 for (slice = 0; slice < box->depth; slice++) {
525 unsigned mem_x, mem_y;
526 uint8_t *dst;
527 int i, j;
528
529 tex_get_box_origin(tex, xfer->base.level, slice,
530 box, &mem_x, &mem_y);
531
532 dst = xfer->staging_sys + xfer->base.layer_stride * slice;
533
534 for (i = 0; i < box->height; i++) {
535 unsigned x = mem_x;
536 uint8_t *d = dst;
537
538 for (j = 0; j < box->width; j++) {
539 const unsigned offset =
540 tile_offset(x, mem_y, tiles_per_row, swizzle);
541
542 *d = src[offset];
543
544 d++;
545 x++;
546 }
547
548 dst += xfer->base.stride;
549 mem_y++;
550 }
551 }
552 }
553
554 tex_staging_sys_unmap_bo(ilo, tex);
555
556 return true;
557 }
558
559 static bool
560 tex_staging_sys_zs_write(struct ilo_context *ilo,
561 struct ilo_texture *tex,
562 const struct ilo_transfer *xfer)
563 {
564 const bool swizzle = ilo->dev->has_address_swizzling;
565 const struct pipe_box *box = &xfer->base.box;
566 uint8_t *dst;
567 tex_tile_offset_func tile_offset;
568 unsigned tiles_per_row;
569 int slice;
570
571 dst = tex_staging_sys_map_bo(ilo, tex, false, false);
572 if (!dst)
573 return false;
574
575 tile_offset = tex_tile_choose_offset_func(tex, &tiles_per_row);
576
577 assert(tex->block_width == 1 && tex->block_height == 1);
578
579 if (tex->separate_s8) {
580 struct ilo_texture *s8_tex = tex->separate_s8;
581 uint8_t *s8_dst;
582 tex_tile_offset_func s8_tile_offset;
583 unsigned s8_tiles_per_row;
584 int src_cpp, src_s8_pos, dst_cpp_used;
585
586 s8_dst = tex_staging_sys_map_bo(ilo, s8_tex, false, false);
587 if (!s8_dst) {
588 tex_staging_sys_unmap_bo(ilo, s8_tex);
589 return false;
590 }
591
592 s8_tile_offset = tex_tile_choose_offset_func(s8_tex, &s8_tiles_per_row);
593
594 if (tex->base.format == PIPE_FORMAT_Z24_UNORM_S8_UINT) {
595 assert(tex->bo_format == PIPE_FORMAT_Z24X8_UNORM);
596
597 src_cpp = 4;
598 src_s8_pos = 3;
599 dst_cpp_used = 3;
600 }
601 else {
602 assert(tex->base.format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT);
603 assert(tex->bo_format == PIPE_FORMAT_Z32_FLOAT);
604
605 src_cpp = 8;
606 src_s8_pos = 4;
607 dst_cpp_used = 4;
608 }
609
610 for (slice = 0; slice < box->depth; slice++) {
611 unsigned mem_x, mem_y, s8_mem_x, s8_mem_y;
612 const uint8_t *src;
613 int i, j;
614
615 tex_get_box_origin(tex, xfer->base.level, slice,
616 box, &mem_x, &mem_y);
617 tex_get_box_origin(s8_tex, xfer->base.level, slice,
618 box, &s8_mem_x, &s8_mem_y);
619
620 src = xfer->staging_sys + xfer->base.layer_stride * slice;
621
622 for (i = 0; i < box->height; i++) {
623 unsigned x = mem_x, s8_x = s8_mem_x;
624 const uint8_t *s = src;
625
626 for (j = 0; j < box->width; j++) {
627 const unsigned offset =
628 tile_offset(x, mem_y, tiles_per_row, swizzle);
629 const unsigned s8_offset =
630 s8_tile_offset(s8_x, s8_mem_y, s8_tiles_per_row, swizzle);
631
632 memcpy(dst + offset, s, dst_cpp_used);
633 s8_dst[s8_offset] = s[src_s8_pos];
634
635 s += src_cpp;
636 x += tex->bo_cpp;
637 s8_x++;
638 }
639
640 src += xfer->base.stride;
641 mem_y++;
642 s8_mem_y++;
643 }
644 }
645
646 tex_staging_sys_unmap_bo(ilo, s8_tex);
647 }
648 else {
649 assert(tex->bo_format == PIPE_FORMAT_S8_UINT);
650
651 for (slice = 0; slice < box->depth; slice++) {
652 unsigned mem_x, mem_y;
653 const uint8_t *src;
654 int i, j;
655
656 tex_get_box_origin(tex, xfer->base.level, slice,
657 box, &mem_x, &mem_y);
658
659 src = xfer->staging_sys + xfer->base.layer_stride * slice;
660
661 for (i = 0; i < box->height; i++) {
662 unsigned x = mem_x;
663 const uint8_t *s = src;
664
665 for (j = 0; j < box->width; j++) {
666 const unsigned offset =
667 tile_offset(x, mem_y, tiles_per_row, swizzle);
668
669 dst[offset] = *s;
670
671 s++;
672 x++;
673 }
674
675 src += xfer->base.stride;
676 mem_y++;
677 }
678 }
679 }
680
681 tex_staging_sys_unmap_bo(ilo, tex);
682
683 return true;
684 }
685
686 static bool
687 tex_staging_sys_convert_write(struct ilo_context *ilo,
688 struct ilo_texture *tex,
689 const struct ilo_transfer *xfer)
690 {
691 const struct pipe_box *box = &xfer->base.box;
692 unsigned dst_slice_stride;
693 void *dst;
694 int slice;
695
696 dst = tex_staging_sys_map_bo(ilo, tex, false, true);
697 if (!dst)
698 return false;
699
700 dst += tex_get_box_offset(tex, xfer->base.level, box);
701
702 /* slice stride is not always available */
703 if (box->depth > 1)
704 dst_slice_stride = tex_get_slice_stride(tex, xfer->base.level);
705 else
706 dst_slice_stride = 0;
707
708 if (unlikely(tex->bo_format == tex->base.format)) {
709 util_copy_box(dst, tex->bo_format, tex->bo_stride, dst_slice_stride,
710 0, 0, 0, box->width, box->height, box->depth,
711 xfer->staging_sys, xfer->base.stride, xfer->base.layer_stride,
712 0, 0, 0);
713
714 tex_staging_sys_unmap_bo(ilo, tex);
715
716 return true;
717 }
718
719 switch (tex->base.format) {
720 case PIPE_FORMAT_ETC1_RGB8:
721 assert(tex->bo_format == PIPE_FORMAT_R8G8B8X8_UNORM);
722
723 for (slice = 0; slice < box->depth; slice++) {
724 const void *src =
725 xfer->staging_sys + xfer->base.layer_stride * slice;
726
727 util_format_etc1_rgb8_unpack_rgba_8unorm(dst,
728 tex->bo_stride, src, xfer->base.stride,
729 box->width, box->height);
730
731 dst += dst_slice_stride;
732 }
733 break;
734 default:
735 assert(!"unable to convert the staging data");
736 break;
737 }
738
739 tex_staging_sys_unmap_bo(ilo, tex);
740
741 return true;
742 }
743
744 static void
745 tex_staging_sys_unmap(struct ilo_context *ilo,
746 struct ilo_texture *tex,
747 struct ilo_transfer *xfer)
748 {
749 bool success;
750
751 if (!(xfer->base.usage & PIPE_TRANSFER_WRITE)) {
752 FREE(xfer->staging_sys);
753 return;
754 }
755
756 switch (xfer->method) {
757 case ILO_TRANSFER_MAP_SW_CONVERT:
758 success = tex_staging_sys_convert_write(ilo, tex, xfer);
759 break;
760 case ILO_TRANSFER_MAP_SW_ZS:
761 success = tex_staging_sys_zs_write(ilo, tex, xfer);
762 break;
763 default:
764 assert(!"unknown mapping method");
765 success = false;
766 break;
767 }
768
769 if (!success)
770 ilo_err("failed to map resource for moving staging data\n");
771
772 FREE(xfer->staging_sys);
773 }
774
775 static bool
776 tex_staging_sys_map(struct ilo_context *ilo,
777 struct ilo_texture *tex,
778 struct ilo_transfer *xfer)
779 {
780 const struct pipe_box *box = &xfer->base.box;
781 const size_t stride = util_format_get_stride(tex->base.format, box->width);
782 const size_t size =
783 util_format_get_2d_size(tex->base.format, stride, box->height);
784 bool read_back = false, success;
785
786 xfer->staging_sys = MALLOC(size * box->depth);
787 if (!xfer->staging_sys)
788 return false;
789
790 xfer->base.stride = stride;
791 xfer->base.layer_stride = size;
792 xfer->ptr = xfer->staging_sys;
793
794 /* see if we need to read the resource back */
795 if (xfer->base.usage & PIPE_TRANSFER_READ) {
796 read_back = true;
797 }
798 else if (xfer->base.usage & PIPE_TRANSFER_WRITE) {
799 const unsigned discard_flags =
800 (PIPE_TRANSFER_DISCARD_RANGE | PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE);
801
802 if (!(xfer->base.usage & discard_flags))
803 read_back = true;
804 }
805
806 if (!read_back)
807 return true;
808
809 switch (xfer->method) {
810 case ILO_TRANSFER_MAP_SW_CONVERT:
811 assert(!"no on-the-fly format conversion for mapping");
812 success = false;
813 break;
814 case ILO_TRANSFER_MAP_SW_ZS:
815 success = tex_staging_sys_zs_read(ilo, tex, xfer);
816 break;
817 default:
818 assert(!"unknown mapping method");
819 success = false;
820 break;
821 }
822
823 return success;
824 }
825
826 static void
827 tex_direct_unmap(struct ilo_context *ilo,
828 struct ilo_texture *tex,
829 struct ilo_transfer *xfer)
830 {
831 intel_bo_unmap(tex->bo);
832 }
833
834 static bool
835 tex_direct_map(struct ilo_context *ilo,
836 struct ilo_texture *tex,
837 struct ilo_transfer *xfer)
838 {
839 xfer->ptr = map_bo_for_transfer(ilo, tex->bo, xfer);
840 if (!xfer->ptr)
841 return false;
842
843 xfer->ptr += tex_get_box_offset(tex, xfer->base.level, &xfer->base.box);
844
845 /* note that stride is for a block row, not a texel row */
846 xfer->base.stride = tex->bo_stride;
847
848 /* slice stride is not always available */
849 if (xfer->base.box.depth > 1)
850 xfer->base.layer_stride = tex_get_slice_stride(tex, xfer->base.level);
851 else
852 xfer->base.layer_stride = 0;
853
854 return true;
855 }
856
857 static bool
858 tex_map(struct ilo_context *ilo, struct ilo_transfer *xfer)
859 {
860 struct ilo_texture *tex = ilo_texture(xfer->base.resource);
861 bool success;
862
863 if (!choose_transfer_method(ilo, xfer))
864 return false;
865
866 switch (xfer->method) {
867 case ILO_TRANSFER_MAP_CPU:
868 case ILO_TRANSFER_MAP_GTT:
869 case ILO_TRANSFER_MAP_UNSYNC:
870 success = tex_direct_map(ilo, tex, xfer);
871 break;
872 case ILO_TRANSFER_MAP_SW_CONVERT:
873 case ILO_TRANSFER_MAP_SW_ZS:
874 success = tex_staging_sys_map(ilo, tex, xfer);
875 break;
876 default:
877 assert(!"unknown mapping method");
878 success = false;
879 break;
880 }
881
882 return success;
883 }
884
885 static void
886 tex_unmap(struct ilo_context *ilo, struct ilo_transfer *xfer)
887 {
888 struct ilo_texture *tex = ilo_texture(xfer->base.resource);
889
890 switch (xfer->method) {
891 case ILO_TRANSFER_MAP_CPU:
892 case ILO_TRANSFER_MAP_GTT:
893 case ILO_TRANSFER_MAP_UNSYNC:
894 tex_direct_unmap(ilo, tex, xfer);
895 break;
896 case ILO_TRANSFER_MAP_SW_CONVERT:
897 case ILO_TRANSFER_MAP_SW_ZS:
898 tex_staging_sys_unmap(ilo, tex, xfer);
899 break;
900 default:
901 assert(!"unknown mapping method");
902 break;
903 }
904 }
905
906 static bool
907 buf_map(struct ilo_context *ilo, struct ilo_transfer *xfer)
908 {
909 struct ilo_buffer *buf = ilo_buffer(xfer->base.resource);
910
911 if (!choose_transfer_method(ilo, xfer))
912 return false;
913
914 xfer->ptr = map_bo_for_transfer(ilo, buf->bo, xfer);
915 if (!xfer->ptr)
916 return false;
917
918 assert(xfer->base.level == 0);
919 assert(xfer->base.box.y == 0);
920 assert(xfer->base.box.z == 0);
921 assert(xfer->base.box.height == 1);
922 assert(xfer->base.box.depth == 1);
923
924 xfer->ptr += xfer->base.box.x;
925 xfer->base.stride = 0;
926 xfer->base.layer_stride = 0;
927
928 return true;
929 }
930
931 static void
932 buf_unmap(struct ilo_context *ilo, struct ilo_transfer *xfer)
933 {
934 struct ilo_buffer *buf = ilo_buffer(xfer->base.resource);
935
936 intel_bo_unmap(buf->bo);
937 }
938
939 static void
940 buf_pwrite(struct ilo_context *ilo, struct ilo_buffer *buf,
941 unsigned usage, int offset, int size, const void *data)
942 {
943 bool need_flush;
944
945 /* see if we can avoid stalling */
946 if (is_bo_busy(ilo, buf->bo, &need_flush)) {
947 bool will_stall = true;
948
949 if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) {
950 /* old data not needed so discard the old bo to avoid stalling */
951 if (ilo_buffer_alloc_bo(buf)) {
952 ilo_mark_states_with_resource_dirty(ilo, &buf->base);
953 will_stall = false;
954 }
955 }
956 else {
957 /*
958 * We could allocate a temporary bo to hold the data and emit
959 * pipelined copy blit to move them to buf->bo. But for now, do
960 * nothing.
961 */
962 }
963
964 /* flush to make bo busy (so that pwrite() stalls as it should be) */
965 if (will_stall && need_flush)
966 ilo_cp_flush(ilo->cp, "syncing for pwrites");
967 }
968
969 intel_bo_pwrite(buf->bo, offset, size, data);
970 }
971
972 static void
973 ilo_transfer_flush_region(struct pipe_context *pipe,
974 struct pipe_transfer *transfer,
975 const struct pipe_box *box)
976 {
977 }
978
979 static void
980 ilo_transfer_unmap(struct pipe_context *pipe,
981 struct pipe_transfer *transfer)
982 {
983 struct ilo_context *ilo = ilo_context(pipe);
984 struct ilo_transfer *xfer = ilo_transfer(transfer);
985
986 if (xfer->base.resource->target == PIPE_BUFFER)
987 buf_unmap(ilo, xfer);
988 else
989 tex_unmap(ilo, xfer);
990
991 pipe_resource_reference(&xfer->base.resource, NULL);
992
993 util_slab_free(&ilo->transfer_mempool, xfer);
994 }
995
996 static void *
997 ilo_transfer_map(struct pipe_context *pipe,
998 struct pipe_resource *res,
999 unsigned level,
1000 unsigned usage,
1001 const struct pipe_box *box,
1002 struct pipe_transfer **transfer)
1003 {
1004 struct ilo_context *ilo = ilo_context(pipe);
1005 struct ilo_transfer *xfer;
1006 bool success;
1007
1008 xfer = util_slab_alloc(&ilo->transfer_mempool);
1009 if (!xfer) {
1010 *transfer = NULL;
1011 return NULL;
1012 }
1013
1014 xfer->base.resource = NULL;
1015 pipe_resource_reference(&xfer->base.resource, res);
1016 xfer->base.level = level;
1017 xfer->base.usage = usage;
1018 xfer->base.box = *box;
1019
1020 ilo_blit_resolve_transfer(ilo, &xfer->base);
1021
1022 if (res->target == PIPE_BUFFER)
1023 success = buf_map(ilo, xfer);
1024 else
1025 success = tex_map(ilo, xfer);
1026
1027 if (!success) {
1028 pipe_resource_reference(&xfer->base.resource, NULL);
1029 FREE(xfer);
1030 *transfer = NULL;
1031 return NULL;
1032 }
1033
1034 *transfer = &xfer->base;
1035
1036 return xfer->ptr;
1037 }
1038
1039 static void
1040 ilo_transfer_inline_write(struct pipe_context *pipe,
1041 struct pipe_resource *res,
1042 unsigned level,
1043 unsigned usage,
1044 const struct pipe_box *box,
1045 const void *data,
1046 unsigned stride,
1047 unsigned layer_stride)
1048 {
1049 if (likely(res->target == PIPE_BUFFER) &&
1050 !(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
1051 /* they should specify just an offset and a size */
1052 assert(level == 0);
1053 assert(box->y == 0);
1054 assert(box->z == 0);
1055 assert(box->height == 1);
1056 assert(box->depth == 1);
1057
1058 buf_pwrite(ilo_context(pipe), ilo_buffer(res),
1059 usage, box->x, box->width, data);
1060 }
1061 else {
1062 u_default_transfer_inline_write(pipe, res,
1063 level, usage, box, data, stride, layer_stride);
1064 }
1065 }
1066
1067 /**
1068 * Initialize transfer-related functions.
1069 */
1070 void
1071 ilo_init_transfer_functions(struct ilo_context *ilo)
1072 {
1073 ilo->base.transfer_map = ilo_transfer_map;
1074 ilo->base.transfer_flush_region = ilo_transfer_flush_region;
1075 ilo->base.transfer_unmap = ilo_transfer_unmap;
1076 ilo->base.transfer_inline_write = ilo_transfer_inline_write;
1077 }