4e501f14bf13e54c9305faa5e78d68254ac271a3
[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 "util/u_pack_color.h"
29 #include "intel_reg.h"
30
31 #include "ilo_3d.h"
32 #include "ilo_context.h"
33 #include "ilo_cp.h"
34 #include "ilo_resource.h"
35 #include "ilo_blitter.h"
36
37 #ifndef COLOR_BLT_CMD
38 #define COLOR_BLT_CMD (CMD_2D | (0x40 << 22))
39 #endif
40
41 #ifndef SRC_COPY_BLT_CMD
42 #define SRC_COPY_BLT_CMD (CMD_2D | (0x43 << 22))
43 #endif
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 BR13_8;
98 case GEN6_BLT_MASK_16: return BR13_565;
99 default: return BR13_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 XY_BLT_WRITE_RGB |
108 XY_BLT_WRITE_ALPHA;
109 case GEN6_BLT_MASK_32_LO: return XY_BLT_WRITE_RGB;
110 case GEN6_BLT_MASK_32_HI: return XY_BLT_WRITE_ALPHA;
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_CMD |
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 << 16 |
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_DOMAIN_RENDER,
157 INTEL_DOMAIN_RENDER);
158 ilo_cp_write(cp, pattern);
159 ilo_cp_end(cp);
160 }
161
162 static void
163 gen6_emit_XY_COLOR_BLT(struct ilo_dev_info *dev,
164 struct intel_bo *dst_bo,
165 enum intel_tiling_mode dst_tiling,
166 int16_t dst_pitch, uint32_t dst_offset,
167 int16_t x1, int16_t y1, int16_t x2, int16_t y2,
168 uint32_t pattern, uint8_t rop,
169 enum gen6_blt_mask value_mask,
170 enum gen6_blt_mask write_mask,
171 struct ilo_cp *cp)
172 {
173 const uint8_t cmd_len = 6;
174 const int cpp = gen6_translate_blt_cpp(value_mask);
175 int dst_align, dst_pitch_shift;
176 uint32_t dw0, dw1;
177
178 dw0 = XY_COLOR_BLT_CMD |
179 gen6_translate_blt_write_mask(write_mask) |
180 (cmd_len - 2);
181
182 if (dst_tiling == INTEL_TILING_NONE) {
183 dst_align = 4;
184 dst_pitch_shift = 0;
185 }
186 else {
187 dw0 |= XY_DST_TILED;
188
189 dst_align = (dst_tiling == INTEL_TILING_Y) ? 128 : 512;
190 /* in dwords when tiled */
191 dst_pitch_shift = 2;
192 }
193
194 assert((x2 - x1) * cpp < gen6_max_bytes_per_scanline);
195 assert(y2 - y1 < gen6_max_scanlines);
196 assert(dst_offset % dst_align == 0 && dst_pitch % dst_align == 0);
197
198 dw1 = rop << 16 |
199 gen6_translate_blt_value_mask(value_mask) |
200 dst_pitch >> dst_pitch_shift;
201
202 ilo_cp_begin(cp, cmd_len);
203 ilo_cp_write(cp, dw0);
204 ilo_cp_write(cp, dw1);
205 ilo_cp_write(cp, y1 << 16 | x1);
206 ilo_cp_write(cp, y2 << 16 | x2);
207 ilo_cp_write_bo(cp, dst_offset, dst_bo,
208 INTEL_DOMAIN_RENDER, INTEL_DOMAIN_RENDER);
209 ilo_cp_write(cp, pattern);
210 ilo_cp_end(cp);
211 }
212
213 static void
214 gen6_emit_SRC_COPY_BLT(struct ilo_dev_info *dev,
215 struct intel_bo *dst_bo,
216 int16_t dst_pitch, uint32_t dst_offset,
217 uint16_t width, uint16_t height,
218 struct intel_bo *src_bo,
219 int16_t src_pitch, uint32_t src_offset,
220 bool dir_rtl, uint8_t rop,
221 enum gen6_blt_mask value_mask,
222 enum gen6_blt_mask write_mask,
223 struct ilo_cp *cp)
224 {
225 const uint8_t cmd_len = 6;
226 const int cpp = gen6_translate_blt_cpp(value_mask);
227 uint32_t dw0, dw1;
228
229 dw0 = SRC_COPY_BLT_CMD |
230 gen6_translate_blt_write_mask(write_mask) |
231 (cmd_len - 2);
232
233 assert(width < gen6_max_bytes_per_scanline);
234 assert(height < gen6_max_scanlines);
235 /* offsets are naturally aligned and pitches are dword-aligned */
236 assert(dst_offset % cpp == 0 && dst_pitch % 4 == 0);
237 assert(src_offset % cpp == 0 && src_pitch % 4 == 0);
238
239 dw1 = rop << 16 |
240 gen6_translate_blt_value_mask(value_mask) |
241 dst_pitch;
242
243 if (dir_rtl)
244 dw1 |= 1 << 30;
245
246 ilo_cp_begin(cp, cmd_len);
247 ilo_cp_write(cp, dw0);
248 ilo_cp_write(cp, dw1);
249 ilo_cp_write(cp, height << 16 | width);
250 ilo_cp_write_bo(cp, dst_offset, dst_bo, INTEL_DOMAIN_RENDER,
251 INTEL_DOMAIN_RENDER);
252 ilo_cp_write(cp, src_pitch);
253 ilo_cp_write_bo(cp, src_offset, src_bo, INTEL_DOMAIN_RENDER, 0);
254 ilo_cp_end(cp);
255 }
256
257 static void
258 gen6_emit_XY_SRC_COPY_BLT(struct ilo_dev_info *dev,
259 struct intel_bo *dst_bo,
260 enum intel_tiling_mode dst_tiling,
261 int16_t dst_pitch, uint32_t dst_offset,
262 int16_t x1, int16_t y1, int16_t x2, int16_t y2,
263 struct intel_bo *src_bo,
264 enum intel_tiling_mode src_tiling,
265 int16_t src_pitch, uint32_t src_offset,
266 int16_t src_x, int16_t src_y, uint8_t rop,
267 enum gen6_blt_mask value_mask,
268 enum gen6_blt_mask write_mask,
269 struct ilo_cp *cp)
270 {
271 const uint8_t cmd_len = 8;
272 const int cpp = gen6_translate_blt_cpp(value_mask);
273 int dst_align, dst_pitch_shift;
274 int src_align, src_pitch_shift;
275 uint32_t dw0, dw1;
276
277 dw0 = XY_SRC_COPY_BLT_CMD |
278 gen6_translate_blt_write_mask(write_mask) |
279 (cmd_len - 2);
280
281 if (dst_tiling == INTEL_TILING_NONE) {
282 dst_align = 4;
283 dst_pitch_shift = 0;
284 }
285 else {
286 dw0 |= XY_DST_TILED;
287
288 dst_align = (dst_tiling == INTEL_TILING_Y) ? 128 : 512;
289 /* in dwords when tiled */
290 dst_pitch_shift = 2;
291 }
292
293 if (src_tiling == INTEL_TILING_NONE) {
294 src_align = 4;
295 src_pitch_shift = 0;
296 }
297 else {
298 dw0 |= XY_SRC_TILED;
299
300 src_align = (src_tiling == INTEL_TILING_Y) ? 128 : 512;
301 /* in dwords when tiled */
302 src_pitch_shift = 2;
303 }
304
305 assert((x2 - x1) * cpp < gen6_max_bytes_per_scanline);
306 assert(y2 - y1 < gen6_max_scanlines);
307 assert(dst_offset % dst_align == 0 && dst_pitch % dst_align == 0);
308 assert(src_offset % src_align == 0 && src_pitch % src_align == 0);
309
310 dw1 = rop << 16 |
311 gen6_translate_blt_value_mask(value_mask) |
312 dst_pitch >> dst_pitch_shift;
313
314 ilo_cp_begin(cp, cmd_len);
315 ilo_cp_write(cp, dw0);
316 ilo_cp_write(cp, dw1);
317 ilo_cp_write(cp, y1 << 16 | x1);
318 ilo_cp_write(cp, y2 << 16 | x2);
319 ilo_cp_write_bo(cp, dst_offset, dst_bo, INTEL_DOMAIN_RENDER,
320 INTEL_DOMAIN_RENDER);
321 ilo_cp_write(cp, src_y << 16 | src_x);
322 ilo_cp_write(cp, src_pitch >> src_pitch_shift);
323 ilo_cp_write_bo(cp, src_offset, src_bo, INTEL_DOMAIN_RENDER, 0);
324 ilo_cp_end(cp);
325 }
326
327 static uint32_t
328 ilo_blitter_blt_begin(struct ilo_blitter *blitter, int max_cmd_size,
329 struct intel_bo *dst, enum intel_tiling_mode dst_tiling,
330 struct intel_bo *src, enum intel_tiling_mode src_tiling)
331 {
332 struct ilo_context *ilo = blitter->ilo;
333 struct intel_bo *aper_check[3];
334 int count;
335 uint32_t swctrl;
336
337 /* change ring */
338 ilo_cp_set_ring(ilo->cp, ILO_CP_RING_BLT);
339 ilo_cp_set_owner(ilo->cp, NULL, 0);
340
341 /* check aperture space */
342 aper_check[0] = ilo->cp->bo;
343 aper_check[1] = dst;
344 count = 2;
345
346 if (src) {
347 aper_check[2] = src;
348 count++;
349 }
350
351 if (intel_winsys_check_aperture_space(ilo->winsys, aper_check, count))
352 ilo_cp_flush(ilo->cp, "out of aperture");
353
354 /* set BCS_SWCTRL */
355 swctrl = 0x0;
356
357 if (dst_tiling == INTEL_TILING_Y) {
358 swctrl |= BCS_SWCTRL_DST_Y << 16 |
359 BCS_SWCTRL_DST_Y;
360 }
361
362 if (src && src_tiling == INTEL_TILING_Y) {
363 swctrl |= BCS_SWCTRL_SRC_Y << 16 |
364 BCS_SWCTRL_SRC_Y;
365 }
366
367 if (swctrl) {
368 /*
369 * Most clients expect BLT engine to be stateless. If we have to set
370 * BCS_SWCTRL to a non-default value, we have to set it back in the same
371 * batch buffer.
372 */
373 if (ilo_cp_space(ilo->cp) < (4 + 3) * 2 + max_cmd_size)
374 ilo_cp_flush(ilo->cp, "out of space");
375
376 ilo_cp_assert_no_implicit_flush(ilo->cp, true);
377
378 /*
379 * From the Ivy Bridge PRM, volume 1 part 4, page 133:
380 *
381 * "SW is required to flush the HW before changing the polarity of
382 * this bit (Tile Y Destination/Source)."
383 */
384 gen6_emit_MI_FLUSH_DW(ilo->dev, ilo->cp);
385 gen6_emit_MI_LOAD_REGISTER_IMM(ilo->dev, BCS_SWCTRL, swctrl, ilo->cp);
386
387 swctrl &= ~(BCS_SWCTRL_DST_Y | BCS_SWCTRL_SRC_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_emit_MI_FLUSH_DW(ilo->dev, ilo->cp);
401 gen6_emit_MI_LOAD_REGISTER_IMM(ilo->dev, BCS_SWCTRL, swctrl, ilo->cp);
402
403 ilo_cp_assert_no_implicit_flush(ilo->cp, false);
404 }
405 }
406
407 static bool
408 buf_clear_region(struct ilo_blitter *blitter,
409 struct ilo_buffer *dst,
410 unsigned dst_offset, unsigned dst_size,
411 uint32_t val,
412 enum gen6_blt_mask value_mask,
413 enum gen6_blt_mask write_mask)
414 {
415 const uint8_t rop = 0xf0; /* PATCOPY */
416 const int cpp = gen6_translate_blt_cpp(value_mask);
417 struct ilo_context *ilo = blitter->ilo;
418 unsigned offset = 0;
419
420 if (dst_offset % cpp || dst_size % cpp)
421 return false;
422
423 ilo_blitter_blt_begin(blitter, 0,
424 dst->bo, INTEL_TILING_NONE, NULL, INTEL_TILING_NONE);
425
426 while (dst_size) {
427 unsigned width, height;
428 int16_t pitch;
429
430 width = dst_size;
431 height = 1;
432 pitch = 0;
433
434 if (width > gen6_max_bytes_per_scanline) {
435 /* less than INT16_MAX and dword-aligned */
436 pitch = 32764;
437
438 width = pitch;
439 height = dst_size / width;
440 if (height > gen6_max_scanlines)
441 height = gen6_max_scanlines;
442 }
443
444 gen6_emit_COLOR_BLT(ilo->dev, dst->bo, pitch, dst_offset + offset,
445 width, height, val, rop, value_mask, write_mask, ilo->cp);
446
447 offset += pitch * height;
448 dst_size -= width * height;
449 }
450
451 ilo_blitter_blt_end(blitter, 0);
452
453 return true;
454 }
455
456 static bool
457 buf_copy_region(struct ilo_blitter *blitter,
458 struct ilo_buffer *dst, unsigned dst_offset,
459 struct ilo_buffer *src, unsigned src_offset,
460 unsigned size)
461 {
462 const uint8_t rop = 0xcc; /* SRCCOPY */
463 struct ilo_context *ilo = blitter->ilo;
464 unsigned offset = 0;
465
466 ilo_blitter_blt_begin(blitter, 0,
467 dst->bo, INTEL_TILING_NONE, src->bo, INTEL_TILING_NONE);
468
469 while (size) {
470 unsigned width, height;
471 int16_t pitch;
472
473 width = size;
474 height = 1;
475 pitch = 0;
476
477 if (width > gen6_max_bytes_per_scanline) {
478 /* less than INT16_MAX and dword-aligned */
479 pitch = 32764;
480
481 width = pitch;
482 height = size / width;
483 if (height > gen6_max_scanlines)
484 height = gen6_max_scanlines;
485 }
486
487 gen6_emit_SRC_COPY_BLT(ilo->dev,
488 dst->bo, pitch, dst_offset + offset,
489 width, height,
490 src->bo, pitch, src_offset + offset,
491 false, rop, GEN6_BLT_MASK_8, GEN6_BLT_MASK_8,
492 ilo->cp);
493
494 offset += pitch * height;
495 size -= width * height;
496 }
497
498 ilo_blitter_blt_end(blitter, 0);
499
500 return true;
501 }
502
503 static bool
504 tex_clear_region(struct ilo_blitter *blitter,
505 struct ilo_texture *dst, unsigned dst_level,
506 const struct pipe_box *dst_box,
507 uint32_t val,
508 enum gen6_blt_mask value_mask,
509 enum gen6_blt_mask write_mask)
510 {
511 const int cpp = gen6_translate_blt_cpp(value_mask);
512 const unsigned max_extent = 32767; /* INT16_MAX */
513 const uint8_t rop = 0xf0; /* PATCOPY */
514 struct ilo_context *ilo = blitter->ilo;
515 uint32_t swctrl;
516 int slice;
517
518 /* no W-tiling support */
519 if (dst->separate_s8)
520 return false;
521
522 if (dst->bo_stride > max_extent)
523 return false;
524
525 swctrl = ilo_blitter_blt_begin(blitter, dst_box->depth * 6,
526 dst->bo, dst->tiling, NULL, INTEL_TILING_NONE);
527
528 for (slice = 0; slice < dst_box->depth; slice++) {
529 const struct ilo_texture_slice *dst_slice =
530 &dst->slice_offsets[dst_level][dst_box->z + slice];
531 unsigned x1, y1, x2, y2;
532
533 x1 = dst_slice->x + dst_box->x;
534 y1 = dst_slice->y + dst_box->y;
535 x2 = x1 + dst_box->width;
536 y2 = y1 + dst_box->height;
537
538 if (x2 > max_extent || y2 > max_extent ||
539 (x2 - x1) * cpp > gen6_max_bytes_per_scanline)
540 break;
541
542 gen6_emit_XY_COLOR_BLT(ilo->dev,
543 dst->bo, dst->tiling, dst->bo_stride, 0,
544 x1, y1, x2, y2, val, rop, value_mask, write_mask,
545 ilo->cp);
546 }
547
548 ilo_blitter_blt_end(blitter, swctrl);
549
550 return (slice == dst_box->depth);
551 }
552
553 static bool
554 tex_copy_region(struct ilo_blitter *blitter,
555 struct ilo_texture *dst,
556 unsigned dst_level,
557 unsigned dst_x, unsigned dst_y, unsigned dst_z,
558 struct ilo_texture *src,
559 unsigned src_level,
560 const struct pipe_box *src_box)
561 {
562 const struct util_format_description *desc =
563 util_format_description(dst->bo_format);
564 const unsigned max_extent = 32767; /* INT16_MAX */
565 const uint8_t rop = 0xcc; /* SRCCOPY */
566 struct ilo_context *ilo = blitter->ilo;
567 enum gen6_blt_mask mask;
568 uint32_t swctrl;
569 int cpp, xscale, slice;
570
571 /* no W-tiling support */
572 if (dst->separate_s8 || src->separate_s8)
573 return false;
574
575 if (dst->bo_stride > max_extent || src->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->tiling, src->bo, src->tiling);
607
608 for (slice = 0; slice < src_box->depth; slice++) {
609 const struct ilo_texture_slice *dst_slice =
610 &dst->slice_offsets[dst_level][dst_z + slice];
611 const struct ilo_texture_slice *src_slice =
612 &src->slice_offsets[src_level][src_box->z + slice];
613 unsigned x1, y1, x2, y2, src_x, src_y;
614
615 x1 = (dst_slice->x + dst_x) * xscale;
616 y1 = dst_slice->y + dst_y;
617 x2 = (x1 + src_box->width) * xscale;
618 y2 = y1 + src_box->height;
619 src_x = (src_slice->x + src_box->x) * xscale;
620 src_y = src_slice->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_emit_XY_SRC_COPY_BLT(ilo->dev,
636 dst->bo, dst->tiling, dst->bo_stride, 0,
637 x1, y1, x2, y2,
638 src->bo, src->tiling, src->bo_stride, 0,
639 src_x, src_y, rop, mask, mask,
640 ilo->cp);
641 }
642
643 ilo_blitter_blt_end(blitter, swctrl);
644
645 return (slice == src_box->depth);
646 }
647
648 bool
649 ilo_blitter_blt_copy_resource(struct ilo_blitter *blitter,
650 struct pipe_resource *dst, unsigned dst_level,
651 unsigned dst_x, unsigned dst_y, unsigned dst_z,
652 struct pipe_resource *src, unsigned src_level,
653 const struct pipe_box *src_box)
654 {
655 bool success;
656
657 if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
658 const unsigned dst_offset = dst_x;
659 const unsigned src_offset = src_box->x;
660 const unsigned size = src_box->width;
661
662 assert(dst_level == 0 && dst_y == 0 && dst_z == 0);
663 assert(src_level == 0 &&
664 src_box->y == 0 &&
665 src_box->z == 0 &&
666 src_box->height == 1 &&
667 src_box->depth == 1);
668
669 success = buf_copy_region(blitter,
670 ilo_buffer(dst), dst_offset, ilo_buffer(src), src_offset, size);
671 }
672 else if (dst->target != PIPE_BUFFER && src->target != PIPE_BUFFER) {
673 success = tex_copy_region(blitter,
674 ilo_texture(dst), dst_level, dst_x, dst_y, dst_z,
675 ilo_texture(src), src_level, src_box);
676 }
677 else {
678 success = false;
679 }
680
681 return success;
682 }
683
684 bool
685 ilo_blitter_blt_clear_rt(struct ilo_blitter *blitter,
686 struct pipe_surface *rt,
687 const union pipe_color_union *color,
688 unsigned x, unsigned y,
689 unsigned width, unsigned height)
690 {
691 const int cpp = util_format_get_blocksize(rt->format);
692 enum gen6_blt_mask mask;
693 union util_color packed;
694 bool success;
695
696 if (!ilo_3d_pass_render_condition(blitter->ilo))
697 return true;
698
699 switch (cpp) {
700 case 1:
701 mask = GEN6_BLT_MASK_8;
702 break;
703 case 2:
704 mask = GEN6_BLT_MASK_16;
705 break;
706 case 4:
707 mask = GEN6_BLT_MASK_32;
708 break;
709 default:
710 return false;
711 break;
712 }
713
714 if (util_format_is_pure_integer(rt->format) ||
715 util_format_is_compressed(rt->format))
716 return false;
717
718 util_pack_color(color->f, rt->format, &packed);
719
720 if (rt->texture->target == PIPE_BUFFER) {
721 unsigned offset, end, size;
722
723 assert(y == 0 && height == 1);
724
725 offset = (rt->u.buf.first_element + x) * cpp;
726 end = (rt->u.buf.last_element + 1) * cpp;
727
728 size = width * cpp;
729 if (offset + size > end)
730 size = end - offset;
731
732 success = buf_clear_region(blitter, ilo_buffer(rt->texture),
733 offset, size, packed.ui, mask, mask);
734 }
735 else {
736 struct pipe_box box;
737
738 u_box_3d(x, y, rt->u.tex.first_layer, width, height,
739 rt->u.tex.last_layer - rt->u.tex.first_layer + 1, &box);
740
741 success = tex_clear_region(blitter, ilo_texture(rt->texture),
742 rt->u.tex.level, &box, packed.ui, mask, mask);
743 }
744
745 return success;
746 }
747
748 bool
749 ilo_blitter_blt_clear_zs(struct ilo_blitter *blitter,
750 struct pipe_surface *zs,
751 unsigned clear_flags,
752 double depth, unsigned stencil,
753 unsigned x, unsigned y,
754 unsigned width, unsigned height)
755 {
756 enum gen6_blt_mask value_mask, write_mask;
757 struct pipe_box box;
758 uint32_t val;
759
760 if (!ilo_3d_pass_render_condition(blitter->ilo))
761 return true;
762
763 switch (zs->format) {
764 case PIPE_FORMAT_Z16_UNORM:
765 if (!(clear_flags & PIPE_CLEAR_DEPTH))
766 return true;
767
768 value_mask = GEN6_BLT_MASK_16;
769 write_mask = GEN6_BLT_MASK_16;
770 break;
771 case PIPE_FORMAT_Z32_FLOAT:
772 if (!(clear_flags & PIPE_CLEAR_DEPTH))
773 return true;
774
775 value_mask = GEN6_BLT_MASK_32;
776 write_mask = GEN6_BLT_MASK_32;
777 break;
778 case PIPE_FORMAT_Z24X8_UNORM:
779 if (!(clear_flags & PIPE_CLEAR_DEPTH))
780 return true;
781
782 value_mask = GEN6_BLT_MASK_32;
783 write_mask = GEN6_BLT_MASK_32_LO;
784 break;
785 case PIPE_FORMAT_Z24_UNORM_S8_UINT:
786 if (!(clear_flags & PIPE_CLEAR_DEPTHSTENCIL))
787 return true;
788
789 value_mask = GEN6_BLT_MASK_32;
790
791 if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL)
792 write_mask = GEN6_BLT_MASK_32;
793 else if (clear_flags & PIPE_CLEAR_DEPTH)
794 write_mask = GEN6_BLT_MASK_32_LO;
795 else
796 write_mask = GEN6_BLT_MASK_32_HI;
797 break;
798 default:
799 return false;
800 break;
801 }
802
803 val = util_pack_z_stencil(zs->format, depth, stencil);
804
805 u_box_3d(x, y, zs->u.tex.first_layer, width, height,
806 zs->u.tex.last_layer - zs->u.tex.first_layer + 1, &box);
807
808 assert(zs->texture->target != PIPE_BUFFER);
809
810 return tex_clear_region(blitter, ilo_texture(zs->texture),
811 zs->u.tex.level, &box, val, value_mask, write_mask);
812 }