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