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