ilo: convert BLT to use ilo_builder
[mesa.git] / src / gallium / drivers / ilo / ilo_blitter_blt.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 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 "genhw/genhw.h"
29 #include "util/u_pack_color.h"
30
31 #include "ilo_3d.h"
32 #include "ilo_context.h"
33 #include "ilo_cp.h"
34 #include "ilo_blit.h"
35 #include "ilo_resource.h"
36 #include "ilo_blitter.h"
37
38 enum gen6_blt_mask {
39 GEN6_BLT_MASK_8,
40 GEN6_BLT_MASK_16,
41 GEN6_BLT_MASK_32,
42 GEN6_BLT_MASK_32_LO,
43 GEN6_BLT_MASK_32_HI,
44 };
45
46 /*
47 * From the Sandy Bridge PRM, volume 1 part 5, page 7:
48 *
49 * "The BLT engine is capable of transferring very large quantities of
50 * graphics data. Any graphics data read from and written to the
51 * destination is permitted to represent a number of pixels that occupies
52 * up to 65,536 scan lines and up to 32,768 bytes per scan line at the
53 * destination. The maximum number of pixels that may be represented per
54 * scan line's worth of graphics data depends on the color depth."
55 */
56 static const int gen6_max_bytes_per_scanline = 32768;
57 static const int gen6_max_scanlines = 65536;
58
59 static void
60 gen6_MI_FLUSH_DW(struct ilo_builder *builder)
61 {
62 const uint8_t cmd_len = 4;
63 const uint32_t dw0 = GEN6_MI_CMD(MI_FLUSH_DW) | (cmd_len - 2);
64 uint32_t *dw;
65
66 ilo_builder_batch_pointer(builder, cmd_len, &dw);
67 dw[0] = dw0;
68 dw[1] = 0;
69 dw[2] = 0;
70 dw[3] = 0;
71 }
72
73 static void
74 gen6_MI_LOAD_REGISTER_IMM(struct ilo_builder *builder,
75 uint32_t reg, uint32_t val)
76 {
77 const uint8_t cmd_len = 3;
78 const uint32_t dw0 = GEN6_MI_CMD(MI_LOAD_REGISTER_IMM) | (cmd_len - 2);
79 uint32_t *dw;
80
81 ilo_builder_batch_pointer(builder, cmd_len, &dw);
82 dw[0] = dw0;
83 dw[1] = reg;
84 dw[2] = val;
85 }
86
87 static uint32_t
88 gen6_translate_blt_value_mask(enum gen6_blt_mask value_mask)
89 {
90 switch (value_mask) {
91 case GEN6_BLT_MASK_8: return GEN6_BLITTER_BR13_FORMAT_8;
92 case GEN6_BLT_MASK_16: return GEN6_BLITTER_BR13_FORMAT_565;
93 default: return GEN6_BLITTER_BR13_FORMAT_8888;
94 }
95 }
96
97 static uint32_t
98 gen6_translate_blt_write_mask(enum gen6_blt_mask write_mask)
99 {
100 switch (write_mask) {
101 case GEN6_BLT_MASK_32: return GEN6_BLITTER_BR00_WRITE_RGB |
102 GEN6_BLITTER_BR00_WRITE_A;
103 case GEN6_BLT_MASK_32_LO: return GEN6_BLITTER_BR00_WRITE_RGB;
104 case GEN6_BLT_MASK_32_HI: return GEN6_BLITTER_BR00_WRITE_A;
105 default: return 0;
106 }
107 }
108
109 static uint32_t
110 gen6_translate_blt_cpp(enum gen6_blt_mask mask)
111 {
112 switch (mask) {
113 case GEN6_BLT_MASK_8: return 1;
114 case GEN6_BLT_MASK_16: return 2;
115 default: return 4;
116 }
117 }
118
119 static void
120 gen6_COLOR_BLT(struct ilo_builder *builder,
121 struct intel_bo *dst_bo,
122 int16_t dst_pitch, uint32_t dst_offset,
123 uint16_t width, uint16_t height,
124 uint32_t pattern, uint8_t rop,
125 enum gen6_blt_mask value_mask,
126 enum gen6_blt_mask write_mask)
127 {
128 const uint8_t cmd_len = 5;
129 const int cpp = gen6_translate_blt_cpp(value_mask);
130 uint32_t dw0, dw1, *dw;
131 unsigned pos;
132
133 dw0 = GEN6_BLITTER_CMD(COLOR_BLT) |
134 gen6_translate_blt_write_mask(write_mask) |
135 (cmd_len - 2);
136
137 assert(width < gen6_max_bytes_per_scanline);
138 assert(height < gen6_max_scanlines);
139 /* offsets are naturally aligned and pitches are dword-aligned */
140 assert(dst_offset % cpp == 0 && dst_pitch % 4 == 0);
141
142 dw1 = rop << GEN6_BLITTER_BR13_ROP__SHIFT |
143 gen6_translate_blt_value_mask(value_mask) |
144 dst_pitch;
145
146 pos = ilo_builder_batch_pointer(builder, cmd_len, &dw);
147 dw[0] = dw0;
148 dw[1] = dw1;
149 dw[2] = height << 16 | width;
150 dw[4] = pattern;
151
152 ilo_builder_batch_reloc(builder, pos + 3,
153 dst_bo, dst_offset, INTEL_RELOC_WRITE);
154 }
155
156 static void
157 gen6_XY_COLOR_BLT(struct ilo_builder *builder,
158 struct intel_bo *dst_bo,
159 enum intel_tiling_mode dst_tiling,
160 int16_t dst_pitch, uint32_t dst_offset,
161 int16_t x1, int16_t y1, int16_t x2, int16_t y2,
162 uint32_t pattern, uint8_t rop,
163 enum gen6_blt_mask value_mask,
164 enum gen6_blt_mask write_mask)
165 {
166 const uint8_t cmd_len = 6;
167 const int cpp = gen6_translate_blt_cpp(value_mask);
168 int dst_align, dst_pitch_shift;
169 uint32_t dw0, dw1, *dw;
170 unsigned pos;
171
172 dw0 = GEN6_BLITTER_CMD(XY_COLOR_BLT) |
173 gen6_translate_blt_write_mask(write_mask) |
174 (cmd_len - 2);
175
176 if (dst_tiling == INTEL_TILING_NONE) {
177 dst_align = 4;
178 dst_pitch_shift = 0;
179 }
180 else {
181 dw0 |= GEN6_BLITTER_BR00_DST_TILED;
182
183 dst_align = (dst_tiling == INTEL_TILING_Y) ? 128 : 512;
184 /* in dwords when tiled */
185 dst_pitch_shift = 2;
186 }
187
188 assert((x2 - x1) * cpp < gen6_max_bytes_per_scanline);
189 assert(y2 - y1 < gen6_max_scanlines);
190 assert(dst_offset % dst_align == 0 && dst_pitch % dst_align == 0);
191
192 dw1 = rop << GEN6_BLITTER_BR13_ROP__SHIFT |
193 gen6_translate_blt_value_mask(value_mask) |
194 dst_pitch >> dst_pitch_shift;
195
196 pos = ilo_builder_batch_pointer(builder, cmd_len, &dw);
197 dw[0] = dw0;
198 dw[1] = dw1;
199 dw[2] = y1 << 16 | x1;
200 dw[3] = y2 << 16 | x2;
201 dw[5] = pattern;
202
203 ilo_builder_batch_reloc(builder, pos + 4,
204 dst_bo, dst_offset, INTEL_RELOC_WRITE);
205 }
206
207 static void
208 gen6_SRC_COPY_BLT(struct ilo_builder *builder,
209 struct intel_bo *dst_bo,
210 int16_t dst_pitch, uint32_t dst_offset,
211 uint16_t width, uint16_t height,
212 struct intel_bo *src_bo,
213 int16_t src_pitch, uint32_t src_offset,
214 bool dir_rtl, uint8_t rop,
215 enum gen6_blt_mask value_mask,
216 enum gen6_blt_mask write_mask)
217 {
218 const uint8_t cmd_len = 6;
219 const int cpp = gen6_translate_blt_cpp(value_mask);
220 uint32_t dw0, dw1, *dw;
221 unsigned pos;
222
223 dw0 = GEN6_BLITTER_CMD(SRC_COPY_BLT) |
224 gen6_translate_blt_write_mask(write_mask) |
225 (cmd_len - 2);
226
227 assert(width < gen6_max_bytes_per_scanline);
228 assert(height < gen6_max_scanlines);
229 /* offsets are naturally aligned and pitches are dword-aligned */
230 assert(dst_offset % cpp == 0 && dst_pitch % 4 == 0);
231 assert(src_offset % cpp == 0 && src_pitch % 4 == 0);
232
233 dw1 = rop << GEN6_BLITTER_BR13_ROP__SHIFT |
234 gen6_translate_blt_value_mask(value_mask) |
235 dst_pitch;
236
237 if (dir_rtl)
238 dw1 |= GEN6_BLITTER_BR13_DIR_RTL;
239
240 pos = ilo_builder_batch_pointer(builder, cmd_len, &dw);
241 dw[0] = dw0;
242 dw[1] = dw1;
243 dw[2] = height << 16 | width;
244 dw[4] = src_pitch;
245
246 ilo_builder_batch_reloc(builder, pos + 3,
247 dst_bo, dst_offset, INTEL_RELOC_WRITE);
248 ilo_builder_batch_reloc(builder, pos + 5,
249 src_bo, src_offset, 0);
250 }
251
252 static void
253 gen6_XY_SRC_COPY_BLT(struct ilo_builder *builder,
254 struct intel_bo *dst_bo,
255 enum intel_tiling_mode dst_tiling,
256 int16_t dst_pitch, uint32_t dst_offset,
257 int16_t x1, int16_t y1, int16_t x2, int16_t y2,
258 struct intel_bo *src_bo,
259 enum intel_tiling_mode src_tiling,
260 int16_t src_pitch, uint32_t src_offset,
261 int16_t src_x, int16_t src_y, uint8_t rop,
262 enum gen6_blt_mask value_mask,
263 enum gen6_blt_mask write_mask)
264 {
265 const uint8_t cmd_len = 8;
266 const int cpp = gen6_translate_blt_cpp(value_mask);
267 int dst_align, dst_pitch_shift;
268 int src_align, src_pitch_shift;
269 uint32_t dw0, dw1, *dw;
270 unsigned pos;
271
272 dw0 = GEN6_BLITTER_CMD(XY_SRC_COPY_BLT) |
273 gen6_translate_blt_write_mask(write_mask) |
274 (cmd_len - 2);
275
276 if (dst_tiling == INTEL_TILING_NONE) {
277 dst_align = 4;
278 dst_pitch_shift = 0;
279 }
280 else {
281 dw0 |= GEN6_BLITTER_BR00_DST_TILED;
282
283 dst_align = (dst_tiling == INTEL_TILING_Y) ? 128 : 512;
284 /* in dwords when tiled */
285 dst_pitch_shift = 2;
286 }
287
288 if (src_tiling == INTEL_TILING_NONE) {
289 src_align = 4;
290 src_pitch_shift = 0;
291 }
292 else {
293 dw0 |= GEN6_BLITTER_BR00_SRC_TILED;
294
295 src_align = (src_tiling == INTEL_TILING_Y) ? 128 : 512;
296 /* in dwords when tiled */
297 src_pitch_shift = 2;
298 }
299
300 assert((x2 - x1) * cpp < gen6_max_bytes_per_scanline);
301 assert(y2 - y1 < gen6_max_scanlines);
302 assert(dst_offset % dst_align == 0 && dst_pitch % dst_align == 0);
303 assert(src_offset % src_align == 0 && src_pitch % src_align == 0);
304
305 dw1 = rop << GEN6_BLITTER_BR13_ROP__SHIFT |
306 gen6_translate_blt_value_mask(value_mask) |
307 dst_pitch >> dst_pitch_shift;
308
309 pos = ilo_builder_batch_pointer(builder, cmd_len, &dw);
310 dw[0] = dw0;
311 dw[1] = dw1;
312 dw[2] = y1 << 16 | x1;
313 dw[3] = y2 << 16 | x2;
314 dw[5] = src_y << 16 | src_x;
315 dw[6] = src_pitch >> src_pitch_shift;
316
317 ilo_builder_batch_reloc(builder, pos + 4,
318 dst_bo, dst_offset, INTEL_RELOC_WRITE);
319 ilo_builder_batch_reloc(builder, pos + 7,
320 src_bo, src_offset, 0);
321 }
322
323 static uint32_t
324 ilo_blitter_blt_begin(struct ilo_blitter *blitter, int max_cmd_size,
325 struct intel_bo *dst, enum intel_tiling_mode dst_tiling,
326 struct intel_bo *src, enum intel_tiling_mode src_tiling)
327 {
328 struct ilo_context *ilo = blitter->ilo;
329 struct intel_bo *aper_check[2];
330 int count;
331 uint32_t swctrl;
332
333 /* change ring */
334 ilo_cp_set_ring(ilo->cp, INTEL_RING_BLT);
335 ilo_cp_set_owner(ilo->cp, NULL, 0);
336
337 /* check aperture space */
338 aper_check[0] = dst;
339 count = 1;
340
341 if (src) {
342 aper_check[1] = src;
343 count++;
344 }
345
346 if (!ilo_builder_validate(&ilo->cp->builder, count, aper_check))
347 ilo_cp_flush(ilo->cp, "out of aperture");
348
349 /* set BCS_SWCTRL */
350 swctrl = 0x0;
351
352 if (dst_tiling == INTEL_TILING_Y) {
353 swctrl |= GEN6_REG_BCS_SWCTRL_DST_TILING_Y << 16 |
354 GEN6_REG_BCS_SWCTRL_DST_TILING_Y;
355 }
356
357 if (src && src_tiling == INTEL_TILING_Y) {
358 swctrl |= GEN6_REG_BCS_SWCTRL_SRC_TILING_Y << 16 |
359 GEN6_REG_BCS_SWCTRL_SRC_TILING_Y;
360 }
361
362 /*
363 * Most clients expect BLT engine to be stateless. If we have to set
364 * BCS_SWCTRL to a non-default value, we have to set it back in the same
365 * batch buffer.
366 */
367 if (swctrl)
368 max_cmd_size += (4 + 3) * 2;
369
370 if (ilo_cp_space(ilo->cp) < max_cmd_size) {
371 ilo_cp_flush(ilo->cp, "out of space");
372 assert(ilo_cp_space(ilo->cp) >= max_cmd_size);
373 }
374
375 if (swctrl) {
376 /*
377 * From the Ivy Bridge PRM, volume 1 part 4, page 133:
378 *
379 * "SW is required to flush the HW before changing the polarity of
380 * this bit (Tile Y Destination/Source)."
381 */
382 gen6_MI_FLUSH_DW(&ilo->cp->builder);
383 gen6_MI_LOAD_REGISTER_IMM(&ilo->cp->builder,
384 GEN6_REG_BCS_SWCTRL, swctrl);
385
386 swctrl &= ~(GEN6_REG_BCS_SWCTRL_DST_TILING_Y |
387 GEN6_REG_BCS_SWCTRL_SRC_TILING_Y);
388 }
389
390 return swctrl;
391 }
392
393 static void
394 ilo_blitter_blt_end(struct ilo_blitter *blitter, uint32_t swctrl)
395 {
396 struct ilo_context *ilo = blitter->ilo;
397
398 /* set BCS_SWCTRL back */
399 if (swctrl) {
400 gen6_MI_FLUSH_DW(&ilo->cp->builder);
401 gen6_MI_LOAD_REGISTER_IMM(&ilo->cp->builder, GEN6_REG_BCS_SWCTRL, swctrl);
402 }
403 }
404
405 static bool
406 buf_clear_region(struct ilo_blitter *blitter,
407 struct ilo_buffer *dst,
408 unsigned dst_offset, unsigned dst_size,
409 uint32_t val,
410 enum gen6_blt_mask value_mask,
411 enum gen6_blt_mask write_mask)
412 {
413 const uint8_t rop = 0xf0; /* PATCOPY */
414 const int cpp = gen6_translate_blt_cpp(value_mask);
415 struct ilo_context *ilo = blitter->ilo;
416 unsigned offset = 0;
417
418 if (dst_offset % cpp || dst_size % cpp)
419 return false;
420
421 ilo_blitter_blt_begin(blitter, 0,
422 dst->bo, INTEL_TILING_NONE, NULL, INTEL_TILING_NONE);
423
424 while (dst_size) {
425 unsigned width, height;
426 int16_t pitch;
427
428 width = dst_size;
429 height = 1;
430 pitch = 0;
431
432 if (width > gen6_max_bytes_per_scanline) {
433 /* less than INT16_MAX and dword-aligned */
434 pitch = 32764;
435
436 width = pitch;
437 height = dst_size / width;
438 if (height > gen6_max_scanlines)
439 height = gen6_max_scanlines;
440 }
441
442 gen6_COLOR_BLT(&ilo->cp->builder, dst->bo, pitch, dst_offset + offset,
443 width, height, val, rop, value_mask, write_mask);
444
445 offset += pitch * height;
446 dst_size -= width * height;
447 }
448
449 ilo_blitter_blt_end(blitter, 0);
450
451 return true;
452 }
453
454 static bool
455 buf_copy_region(struct ilo_blitter *blitter,
456 struct ilo_buffer *dst, unsigned dst_offset,
457 struct ilo_buffer *src, unsigned src_offset,
458 unsigned size)
459 {
460 const uint8_t rop = 0xcc; /* SRCCOPY */
461 struct ilo_context *ilo = blitter->ilo;
462 unsigned offset = 0;
463
464 ilo_blitter_blt_begin(blitter, 0,
465 dst->bo, INTEL_TILING_NONE, src->bo, INTEL_TILING_NONE);
466
467 while (size) {
468 unsigned width, height;
469 int16_t pitch;
470
471 width = size;
472 height = 1;
473 pitch = 0;
474
475 if (width > gen6_max_bytes_per_scanline) {
476 /* less than INT16_MAX and dword-aligned */
477 pitch = 32764;
478
479 width = pitch;
480 height = size / width;
481 if (height > gen6_max_scanlines)
482 height = gen6_max_scanlines;
483 }
484
485 gen6_SRC_COPY_BLT(&ilo->cp->builder,
486 dst->bo, pitch, dst_offset + offset,
487 width, height,
488 src->bo, pitch, src_offset + offset,
489 false, rop, GEN6_BLT_MASK_8, GEN6_BLT_MASK_8);
490
491 offset += pitch * height;
492 size -= width * height;
493 }
494
495 ilo_blitter_blt_end(blitter, 0);
496
497 return true;
498 }
499
500 static bool
501 tex_clear_region(struct ilo_blitter *blitter,
502 struct ilo_texture *dst, unsigned dst_level,
503 const struct pipe_box *dst_box,
504 uint32_t val,
505 enum gen6_blt_mask value_mask,
506 enum gen6_blt_mask write_mask)
507 {
508 const int cpp = gen6_translate_blt_cpp(value_mask);
509 const unsigned max_extent = 32767; /* INT16_MAX */
510 const uint8_t rop = 0xf0; /* PATCOPY */
511 struct ilo_context *ilo = blitter->ilo;
512 uint32_t swctrl;
513 int slice;
514
515 /* no W-tiling support */
516 if (dst->separate_s8)
517 return false;
518
519 if (dst->layout.bo_stride > max_extent)
520 return false;
521
522 swctrl = ilo_blitter_blt_begin(blitter, dst_box->depth * 6,
523 dst->bo, dst->layout.tiling, NULL, INTEL_TILING_NONE);
524
525 for (slice = 0; slice < dst_box->depth; slice++) {
526 unsigned x1, y1, x2, y2;
527
528 ilo_layout_get_slice_pos(&dst->layout,
529 dst_level, dst_box->z + slice, &x1, &y1);
530
531 x1 += dst_box->x;
532 y1 += dst_box->y;
533 x2 = x1 + dst_box->width;
534 y2 = y1 + dst_box->height;
535
536 if (x2 > max_extent || y2 > max_extent ||
537 (x2 - x1) * cpp > gen6_max_bytes_per_scanline)
538 break;
539
540 gen6_XY_COLOR_BLT(&ilo->cp->builder,
541 dst->bo, dst->layout.tiling, dst->layout.bo_stride, 0,
542 x1, y1, x2, y2, val, rop, value_mask, write_mask);
543 }
544
545 ilo_blitter_blt_end(blitter, swctrl);
546
547 return (slice == dst_box->depth);
548 }
549
550 static bool
551 tex_copy_region(struct ilo_blitter *blitter,
552 struct ilo_texture *dst,
553 unsigned dst_level,
554 unsigned dst_x, unsigned dst_y, unsigned dst_z,
555 struct ilo_texture *src,
556 unsigned src_level,
557 const struct pipe_box *src_box)
558 {
559 const struct util_format_description *desc =
560 util_format_description(dst->layout.format);
561 const unsigned max_extent = 32767; /* INT16_MAX */
562 const uint8_t rop = 0xcc; /* SRCCOPY */
563 struct ilo_context *ilo = blitter->ilo;
564 enum gen6_blt_mask mask;
565 uint32_t swctrl;
566 int cpp, xscale, slice;
567
568 /* no W-tiling support */
569 if (dst->separate_s8 || src->separate_s8)
570 return false;
571
572 if (dst->layout.bo_stride > max_extent ||
573 src->layout.bo_stride > max_extent)
574 return false;
575
576 cpp = desc->block.bits / 8;
577 xscale = 1;
578
579 /* accommodate for larger cpp */
580 if (cpp > 4) {
581 if (cpp % 2 == 1)
582 return false;
583
584 cpp = (cpp % 4 == 0) ? 4 : 2;
585 xscale = (desc->block.bits / 8) / cpp;
586 }
587
588 switch (cpp) {
589 case 1:
590 mask = GEN6_BLT_MASK_8;
591 break;
592 case 2:
593 mask = GEN6_BLT_MASK_16;
594 break;
595 case 4:
596 mask = GEN6_BLT_MASK_32;
597 break;
598 default:
599 return false;
600 break;
601 }
602
603 swctrl = ilo_blitter_blt_begin(blitter, src_box->depth * 8,
604 dst->bo, dst->layout.tiling, src->bo, src->layout.tiling);
605
606 for (slice = 0; slice < src_box->depth; slice++) {
607 unsigned x1, y1, x2, y2, src_x, src_y;
608
609 ilo_layout_get_slice_pos(&dst->layout,
610 dst_level, dst_z + slice, &x1, &y1);
611 x1 = (x1 + dst_x) * xscale;
612 y1 = y1 + dst_y;
613 x2 = (x1 + src_box->width) * xscale;
614 y2 = y1 + src_box->height;
615
616 ilo_layout_get_slice_pos(&src->layout,
617 src_level, src_box->z + slice, &src_x, &src_y);
618
619 src_x = (src_x + src_box->x) * xscale;
620 src_y += src_box->y;
621
622 /* in blocks */
623 x1 /= desc->block.width;
624 y1 /= desc->block.height;
625 x2 = (x2 + desc->block.width - 1) / desc->block.width;
626 y2 = (y2 + desc->block.height - 1) / desc->block.height;
627 src_x /= desc->block.width;
628 src_y /= desc->block.height;
629
630 if (x2 > max_extent || y2 > max_extent ||
631 src_x > max_extent || src_y > max_extent ||
632 (x2 - x1) * cpp > gen6_max_bytes_per_scanline)
633 break;
634
635 gen6_XY_SRC_COPY_BLT(&ilo->cp->builder,
636 dst->bo, dst->layout.tiling, dst->layout.bo_stride, 0,
637 x1, y1, x2, y2,
638 src->bo, src->layout.tiling, src->layout.bo_stride, 0,
639 src_x, src_y, rop, mask, mask);
640 }
641
642 ilo_blitter_blt_end(blitter, swctrl);
643
644 return (slice == src_box->depth);
645 }
646
647 bool
648 ilo_blitter_blt_copy_resource(struct ilo_blitter *blitter,
649 struct pipe_resource *dst, unsigned dst_level,
650 unsigned dst_x, unsigned dst_y, unsigned dst_z,
651 struct pipe_resource *src, unsigned src_level,
652 const struct pipe_box *src_box)
653 {
654 bool success;
655
656 ilo_blit_resolve_slices(blitter->ilo, src, src_level,
657 src_box->z, src_box->depth, ILO_TEXTURE_BLT_READ);
658 ilo_blit_resolve_slices(blitter->ilo, dst, dst_level,
659 dst_z, src_box->depth, ILO_TEXTURE_BLT_WRITE);
660
661 if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
662 const unsigned dst_offset = dst_x;
663 const unsigned src_offset = src_box->x;
664 const unsigned size = src_box->width;
665
666 assert(dst_level == 0 && dst_y == 0 && dst_z == 0);
667 assert(src_level == 0 &&
668 src_box->y == 0 &&
669 src_box->z == 0 &&
670 src_box->height == 1 &&
671 src_box->depth == 1);
672
673 success = buf_copy_region(blitter,
674 ilo_buffer(dst), dst_offset, ilo_buffer(src), src_offset, size);
675 }
676 else if (dst->target != PIPE_BUFFER && src->target != PIPE_BUFFER) {
677 success = tex_copy_region(blitter,
678 ilo_texture(dst), dst_level, dst_x, dst_y, dst_z,
679 ilo_texture(src), src_level, src_box);
680 }
681 else {
682 success = false;
683 }
684
685 return success;
686 }
687
688 bool
689 ilo_blitter_blt_clear_rt(struct ilo_blitter *blitter,
690 struct pipe_surface *rt,
691 const union pipe_color_union *color,
692 unsigned x, unsigned y,
693 unsigned width, unsigned height)
694 {
695 const int cpp = util_format_get_blocksize(rt->format);
696 enum gen6_blt_mask mask;
697 union util_color packed;
698 bool success;
699
700 if (!ilo_3d_pass_render_condition(blitter->ilo))
701 return true;
702
703 switch (cpp) {
704 case 1:
705 mask = GEN6_BLT_MASK_8;
706 break;
707 case 2:
708 mask = GEN6_BLT_MASK_16;
709 break;
710 case 4:
711 mask = GEN6_BLT_MASK_32;
712 break;
713 default:
714 return false;
715 break;
716 }
717
718 if (util_format_is_pure_integer(rt->format) ||
719 util_format_is_compressed(rt->format))
720 return false;
721
722 ilo_blit_resolve_surface(blitter->ilo, rt, ILO_TEXTURE_BLT_WRITE);
723
724 util_pack_color(color->f, rt->format, &packed);
725
726 if (rt->texture->target == PIPE_BUFFER) {
727 unsigned offset, end, size;
728
729 assert(y == 0 && height == 1);
730
731 offset = (rt->u.buf.first_element + x) * cpp;
732 end = (rt->u.buf.last_element + 1) * cpp;
733
734 size = width * cpp;
735 if (offset + size > end)
736 size = end - offset;
737
738 success = buf_clear_region(blitter, ilo_buffer(rt->texture),
739 offset, size, packed.ui[0], mask, mask);
740 }
741 else {
742 struct pipe_box box;
743
744 u_box_3d(x, y, rt->u.tex.first_layer, width, height,
745 rt->u.tex.last_layer - rt->u.tex.first_layer + 1, &box);
746
747 success = tex_clear_region(blitter, ilo_texture(rt->texture),
748 rt->u.tex.level, &box, packed.ui[0], mask, mask);
749 }
750
751 return success;
752 }
753
754 bool
755 ilo_blitter_blt_clear_zs(struct ilo_blitter *blitter,
756 struct pipe_surface *zs,
757 unsigned clear_flags,
758 double depth, unsigned stencil,
759 unsigned x, unsigned y,
760 unsigned width, unsigned height)
761 {
762 enum gen6_blt_mask value_mask, write_mask;
763 struct pipe_box box;
764 uint32_t val;
765
766 if (!ilo_3d_pass_render_condition(blitter->ilo))
767 return true;
768
769 switch (zs->format) {
770 case PIPE_FORMAT_Z16_UNORM:
771 if (!(clear_flags & PIPE_CLEAR_DEPTH))
772 return true;
773
774 value_mask = GEN6_BLT_MASK_16;
775 write_mask = GEN6_BLT_MASK_16;
776 break;
777 case PIPE_FORMAT_Z32_FLOAT:
778 if (!(clear_flags & PIPE_CLEAR_DEPTH))
779 return true;
780
781 value_mask = GEN6_BLT_MASK_32;
782 write_mask = GEN6_BLT_MASK_32;
783 break;
784 case PIPE_FORMAT_Z24X8_UNORM:
785 if (!(clear_flags & PIPE_CLEAR_DEPTH))
786 return true;
787
788 value_mask = GEN6_BLT_MASK_32;
789 write_mask = GEN6_BLT_MASK_32_LO;
790 break;
791 case PIPE_FORMAT_Z24_UNORM_S8_UINT:
792 if (!(clear_flags & PIPE_CLEAR_DEPTHSTENCIL))
793 return true;
794
795 value_mask = GEN6_BLT_MASK_32;
796
797 if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL)
798 write_mask = GEN6_BLT_MASK_32;
799 else if (clear_flags & PIPE_CLEAR_DEPTH)
800 write_mask = GEN6_BLT_MASK_32_LO;
801 else
802 write_mask = GEN6_BLT_MASK_32_HI;
803 break;
804 default:
805 return false;
806 break;
807 }
808
809 ilo_blit_resolve_surface(blitter->ilo, zs, ILO_TEXTURE_BLT_WRITE);
810
811 val = util_pack_z_stencil(zs->format, depth, stencil);
812
813 u_box_3d(x, y, zs->u.tex.first_layer, width, height,
814 zs->u.tex.last_layer - zs->u.tex.first_layer + 1, &box);
815
816 assert(zs->texture->target != PIPE_BUFFER);
817
818 return tex_clear_region(blitter, ilo_texture(zs->texture),
819 zs->u.tex.level, &box, val, value_mask, write_mask);
820 }