ilo: rename ilo_cp_flush()
[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_builder_mi.h"
33 #include "ilo_builder_blt.h"
34 #include "ilo_context.h"
35 #include "ilo_cp.h"
36 #include "ilo_blit.h"
37 #include "ilo_resource.h"
38 #include "ilo_blitter.h"
39
40 static uint32_t
41 ilo_blitter_blt_begin(struct ilo_blitter *blitter, int max_cmd_size,
42 struct intel_bo *dst, enum intel_tiling_mode dst_tiling,
43 struct intel_bo *src, enum intel_tiling_mode src_tiling)
44 {
45 struct ilo_context *ilo = blitter->ilo;
46 struct intel_bo *aper_check[2];
47 int count;
48 uint32_t swctrl;
49
50 /* change owner */
51 ilo_cp_set_owner(ilo->cp, INTEL_RING_BLT, NULL);
52
53 /* check aperture space */
54 aper_check[0] = dst;
55 count = 1;
56
57 if (src) {
58 aper_check[1] = src;
59 count++;
60 }
61
62 if (!ilo_builder_validate(&ilo->cp->builder, count, aper_check))
63 ilo_cp_submit(ilo->cp, "out of aperture");
64
65 /* set BCS_SWCTRL */
66 swctrl = 0x0;
67
68 if (dst_tiling == INTEL_TILING_Y) {
69 swctrl |= GEN6_REG_BCS_SWCTRL_DST_TILING_Y << 16 |
70 GEN6_REG_BCS_SWCTRL_DST_TILING_Y;
71 }
72
73 if (src && src_tiling == INTEL_TILING_Y) {
74 swctrl |= GEN6_REG_BCS_SWCTRL_SRC_TILING_Y << 16 |
75 GEN6_REG_BCS_SWCTRL_SRC_TILING_Y;
76 }
77
78 /*
79 * Most clients expect BLT engine to be stateless. If we have to set
80 * BCS_SWCTRL to a non-default value, we have to set it back in the same
81 * batch buffer.
82 */
83 if (swctrl)
84 max_cmd_size += (4 + 3) * 2;
85
86 if (ilo_cp_space(ilo->cp) < max_cmd_size) {
87 ilo_cp_submit(ilo->cp, "out of space");
88 assert(ilo_cp_space(ilo->cp) >= max_cmd_size);
89 }
90
91 if (swctrl) {
92 /*
93 * From the Ivy Bridge PRM, volume 1 part 4, page 133:
94 *
95 * "SW is required to flush the HW before changing the polarity of
96 * this bit (Tile Y Destination/Source)."
97 */
98 gen6_MI_FLUSH_DW(&ilo->cp->builder);
99 gen6_MI_LOAD_REGISTER_IMM(&ilo->cp->builder,
100 GEN6_REG_BCS_SWCTRL, swctrl);
101
102 swctrl &= ~(GEN6_REG_BCS_SWCTRL_DST_TILING_Y |
103 GEN6_REG_BCS_SWCTRL_SRC_TILING_Y);
104 }
105
106 return swctrl;
107 }
108
109 static void
110 ilo_blitter_blt_end(struct ilo_blitter *blitter, uint32_t swctrl)
111 {
112 struct ilo_context *ilo = blitter->ilo;
113
114 /* set BCS_SWCTRL back */
115 if (swctrl) {
116 gen6_MI_FLUSH_DW(&ilo->cp->builder);
117 gen6_MI_LOAD_REGISTER_IMM(&ilo->cp->builder, GEN6_REG_BCS_SWCTRL, swctrl);
118 }
119 }
120
121 static bool
122 buf_clear_region(struct ilo_blitter *blitter,
123 struct ilo_buffer *buf, unsigned offset,
124 uint32_t val, unsigned size,
125 enum gen6_blt_mask value_mask,
126 enum gen6_blt_mask write_mask)
127 {
128 const uint8_t rop = 0xf0; /* PATCOPY */
129 const int cpp = gen6_blt_translate_value_cpp(value_mask);
130 struct ilo_context *ilo = blitter->ilo;
131 struct gen6_blt_bo dst;
132
133 if (offset % cpp || size % cpp)
134 return false;
135
136 dst.bo = buf->bo;
137 dst.offset = offset;
138
139 ilo_blitter_blt_begin(blitter, GEN6_COLOR_BLT__SIZE *
140 (1 + size / 32764 / gen6_blt_max_scanlines),
141 dst.bo, INTEL_TILING_NONE, NULL, INTEL_TILING_NONE);
142
143 while (size) {
144 unsigned width, height;
145
146 width = size;
147 height = 1;
148
149 if (width > gen6_blt_max_bytes_per_scanline) {
150 /* less than INT16_MAX and dword-aligned */
151 width = 32764;
152 height = size / width;
153 if (height > gen6_blt_max_scanlines)
154 height = gen6_blt_max_scanlines;
155
156 dst.pitch = width;
157 } else {
158 dst.pitch = 0;
159 }
160
161 gen6_COLOR_BLT(&ilo->cp->builder, &dst, val,
162 width, height, rop, value_mask, write_mask);
163
164 dst.offset += dst.pitch * height;
165 size -= width * height;
166 }
167
168 ilo_blitter_blt_end(blitter, 0);
169
170 return true;
171 }
172
173 static bool
174 buf_copy_region(struct ilo_blitter *blitter,
175 struct ilo_buffer *dst_buf, unsigned dst_offset,
176 struct ilo_buffer *src_buf, unsigned src_offset,
177 unsigned size)
178 {
179 const uint8_t rop = 0xcc; /* SRCCOPY */
180 struct ilo_context *ilo = blitter->ilo;
181 struct gen6_blt_bo dst, src;
182
183 dst.bo = dst_buf->bo;
184 dst.offset = dst_offset;
185 dst.pitch = 0;
186
187 src.bo = src_buf->bo;
188 src.offset = src_offset;
189 src.pitch = 0;
190
191 ilo_blitter_blt_begin(blitter, GEN6_SRC_COPY_BLT__SIZE *
192 (1 + size / 32764 / gen6_blt_max_scanlines),
193 dst_buf->bo, INTEL_TILING_NONE, src_buf->bo, INTEL_TILING_NONE);
194
195 while (size) {
196 unsigned width, height;
197
198 width = size;
199 height = 1;
200
201 if (width > gen6_blt_max_bytes_per_scanline) {
202 /* less than INT16_MAX and dword-aligned */
203 width = 32764;
204 height = size / width;
205 if (height > gen6_blt_max_scanlines)
206 height = gen6_blt_max_scanlines;
207
208 dst.pitch = width;
209 src.pitch = width;
210 } else {
211 dst.pitch = 0;
212 src.pitch = 0;
213 }
214
215 gen6_SRC_COPY_BLT(&ilo->cp->builder, &dst, &src,
216 width, height, rop, GEN6_BLT_MASK_8, GEN6_BLT_MASK_8);
217
218 dst.offset += dst.pitch * height;
219 src.offset += src.pitch * height;
220 size -= width * height;
221 }
222
223 ilo_blitter_blt_end(blitter, 0);
224
225 return true;
226 }
227
228 static bool
229 tex_clear_region(struct ilo_blitter *blitter,
230 struct ilo_texture *dst_tex, unsigned dst_level,
231 const struct pipe_box *dst_box,
232 uint32_t val,
233 enum gen6_blt_mask value_mask,
234 enum gen6_blt_mask write_mask)
235 {
236 const int cpp = gen6_blt_translate_value_cpp(value_mask);
237 const unsigned max_extent = 32767; /* INT16_MAX */
238 const uint8_t rop = 0xf0; /* PATCOPY */
239 struct ilo_context *ilo = blitter->ilo;
240 struct gen6_blt_xy_bo dst;
241 uint32_t swctrl;
242 int slice;
243
244 /* no W-tiling support */
245 if (dst_tex->separate_s8)
246 return false;
247
248 if (dst_tex->layout.bo_stride > max_extent)
249 return false;
250
251 if (dst_box->width * cpp > gen6_blt_max_bytes_per_scanline)
252 return false;
253
254 dst.bo = dst_tex->bo;
255 dst.offset = 0;
256 dst.pitch = dst_tex->layout.bo_stride;
257 dst.tiling = dst_tex->layout.tiling;
258
259 swctrl = ilo_blitter_blt_begin(blitter,
260 GEN6_XY_COLOR_BLT__SIZE * dst_box->depth,
261 dst_tex->bo, dst_tex->layout.tiling, NULL, INTEL_TILING_NONE);
262
263 for (slice = 0; slice < dst_box->depth; slice++) {
264 unsigned x, y;
265
266 ilo_layout_get_slice_pos(&dst_tex->layout,
267 dst_level, dst_box->z + slice, &x, &y);
268
269 dst.x = x + dst_box->x;
270 dst.y = y + dst_box->y;
271
272 if (dst.x + dst_box->width > max_extent ||
273 dst.y + dst_box->height > max_extent)
274 break;
275
276 gen6_XY_COLOR_BLT(&ilo->cp->builder, &dst, val,
277 dst_box->width, dst_box->height, rop, value_mask, write_mask);
278 }
279
280 ilo_blitter_blt_end(blitter, swctrl);
281
282 return (slice == dst_box->depth);
283 }
284
285 static bool
286 tex_copy_region(struct ilo_blitter *blitter,
287 struct ilo_texture *dst_tex,
288 unsigned dst_level,
289 unsigned dst_x, unsigned dst_y, unsigned dst_z,
290 struct ilo_texture *src_tex,
291 unsigned src_level,
292 const struct pipe_box *src_box)
293 {
294 const struct util_format_description *desc =
295 util_format_description(dst_tex->layout.format);
296 const unsigned max_extent = 32767; /* INT16_MAX */
297 const uint8_t rop = 0xcc; /* SRCCOPY */
298 struct ilo_context *ilo = blitter->ilo;
299 enum gen6_blt_mask mask;
300 struct gen6_blt_xy_bo dst, src;
301 uint32_t swctrl;
302 int cpp, xscale, slice;
303
304 /* no W-tiling support */
305 if (dst_tex->separate_s8 || src_tex->separate_s8)
306 return false;
307
308 if (dst_tex->layout.bo_stride > max_extent ||
309 src_tex->layout.bo_stride > max_extent)
310 return false;
311
312 cpp = desc->block.bits / 8;
313 xscale = 1;
314
315 /* accommodate for larger cpp */
316 if (cpp > 4) {
317 if (cpp % 2 == 1)
318 return false;
319
320 cpp = (cpp % 4 == 0) ? 4 : 2;
321 xscale = (desc->block.bits / 8) / cpp;
322 }
323
324 if (src_box->width * cpp * xscale > gen6_blt_max_bytes_per_scanline)
325 return false;
326
327 switch (cpp) {
328 case 1:
329 mask = GEN6_BLT_MASK_8;
330 break;
331 case 2:
332 mask = GEN6_BLT_MASK_16;
333 break;
334 case 4:
335 mask = GEN6_BLT_MASK_32;
336 break;
337 default:
338 return false;
339 break;
340 }
341
342 dst.bo = dst_tex->bo;
343 dst.offset = 0;
344 dst.pitch = dst_tex->layout.bo_stride;
345 dst.tiling = dst_tex->layout.tiling;
346
347 src.bo = src_tex->bo;
348 src.offset = 0;
349 src.pitch = src_tex->layout.bo_stride;
350 src.tiling = src_tex->layout.tiling;
351
352 swctrl = ilo_blitter_blt_begin(blitter,
353 GEN6_XY_SRC_COPY_BLT__SIZE * src_box->depth,
354 dst.bo, dst.tiling, src.bo, src.tiling);
355
356 for (slice = 0; slice < src_box->depth; slice++) {
357 unsigned dx, dy, sx, sy, width, height;
358
359 ilo_layout_get_slice_pos(&dst_tex->layout,
360 dst_level, dst_z + slice, &dx, &dy);
361 ilo_layout_get_slice_pos(&src_tex->layout,
362 src_level, src_box->z + slice, &sx, &sy);
363
364 dst.x = (dx + dst_x) * xscale;
365 dst.y = dy + dst_y;
366 src.x = (sx + src_box->x) * xscale;
367 src.y = sy + src_box->y;
368 width = src_box->width * xscale;
369 height = src_box->height;
370
371 /* in blocks */
372 dst.x /= desc->block.width;
373 dst.y /= desc->block.height;
374 src.x /= desc->block.width;
375 src.y /= desc->block.height;
376 width /= desc->block.width;
377 height /= desc->block.height;
378
379 if (src.x + width > max_extent || src.y + height > max_extent ||
380 dst.x + width > max_extent || dst.y + height > max_extent)
381 break;
382
383 gen6_XY_SRC_COPY_BLT(&ilo->cp->builder, &dst, &src,
384 width, height, rop, mask, mask);
385 }
386
387 ilo_blitter_blt_end(blitter, swctrl);
388
389 return (slice == src_box->depth);
390 }
391
392 bool
393 ilo_blitter_blt_copy_resource(struct ilo_blitter *blitter,
394 struct pipe_resource *dst, unsigned dst_level,
395 unsigned dst_x, unsigned dst_y, unsigned dst_z,
396 struct pipe_resource *src, unsigned src_level,
397 const struct pipe_box *src_box)
398 {
399 bool success;
400
401 ilo_blit_resolve_slices(blitter->ilo, src, src_level,
402 src_box->z, src_box->depth, ILO_TEXTURE_BLT_READ);
403 ilo_blit_resolve_slices(blitter->ilo, dst, dst_level,
404 dst_z, src_box->depth, ILO_TEXTURE_BLT_WRITE);
405
406 if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
407 const unsigned dst_offset = dst_x;
408 const unsigned src_offset = src_box->x;
409 const unsigned size = src_box->width;
410
411 assert(dst_level == 0 && dst_y == 0 && dst_z == 0);
412 assert(src_level == 0 &&
413 src_box->y == 0 &&
414 src_box->z == 0 &&
415 src_box->height == 1 &&
416 src_box->depth == 1);
417
418 success = buf_copy_region(blitter,
419 ilo_buffer(dst), dst_offset, ilo_buffer(src), src_offset, size);
420 }
421 else if (dst->target != PIPE_BUFFER && src->target != PIPE_BUFFER) {
422 success = tex_copy_region(blitter,
423 ilo_texture(dst), dst_level, dst_x, dst_y, dst_z,
424 ilo_texture(src), src_level, src_box);
425 }
426 else {
427 success = false;
428 }
429
430 return success;
431 }
432
433 bool
434 ilo_blitter_blt_clear_rt(struct ilo_blitter *blitter,
435 struct pipe_surface *rt,
436 const union pipe_color_union *color,
437 unsigned x, unsigned y,
438 unsigned width, unsigned height)
439 {
440 const int cpp = util_format_get_blocksize(rt->format);
441 enum gen6_blt_mask mask;
442 union util_color packed;
443 bool success;
444
445 if (!ilo_3d_pass_render_condition(blitter->ilo))
446 return true;
447
448 switch (cpp) {
449 case 1:
450 mask = GEN6_BLT_MASK_8;
451 break;
452 case 2:
453 mask = GEN6_BLT_MASK_16;
454 break;
455 case 4:
456 mask = GEN6_BLT_MASK_32;
457 break;
458 default:
459 return false;
460 break;
461 }
462
463 if (util_format_is_pure_integer(rt->format) ||
464 util_format_is_compressed(rt->format))
465 return false;
466
467 ilo_blit_resolve_surface(blitter->ilo, rt, ILO_TEXTURE_BLT_WRITE);
468
469 util_pack_color(color->f, rt->format, &packed);
470
471 if (rt->texture->target == PIPE_BUFFER) {
472 unsigned offset, end, size;
473
474 assert(y == 0 && height == 1);
475
476 offset = (rt->u.buf.first_element + x) * cpp;
477 end = (rt->u.buf.last_element + 1) * cpp;
478
479 size = width * cpp;
480 if (offset + size > end)
481 size = end - offset;
482
483 success = buf_clear_region(blitter, ilo_buffer(rt->texture),
484 offset, packed.ui[0], size, mask, mask);
485 }
486 else {
487 struct pipe_box box;
488
489 u_box_3d(x, y, rt->u.tex.first_layer, width, height,
490 rt->u.tex.last_layer - rt->u.tex.first_layer + 1, &box);
491
492 success = tex_clear_region(blitter, ilo_texture(rt->texture),
493 rt->u.tex.level, &box, packed.ui[0], mask, mask);
494 }
495
496 return success;
497 }
498
499 bool
500 ilo_blitter_blt_clear_zs(struct ilo_blitter *blitter,
501 struct pipe_surface *zs,
502 unsigned clear_flags,
503 double depth, unsigned stencil,
504 unsigned x, unsigned y,
505 unsigned width, unsigned height)
506 {
507 enum gen6_blt_mask value_mask, write_mask;
508 struct pipe_box box;
509 uint32_t val;
510
511 if (!ilo_3d_pass_render_condition(blitter->ilo))
512 return true;
513
514 switch (zs->format) {
515 case PIPE_FORMAT_Z16_UNORM:
516 if (!(clear_flags & PIPE_CLEAR_DEPTH))
517 return true;
518
519 value_mask = GEN6_BLT_MASK_16;
520 write_mask = GEN6_BLT_MASK_16;
521 break;
522 case PIPE_FORMAT_Z32_FLOAT:
523 if (!(clear_flags & PIPE_CLEAR_DEPTH))
524 return true;
525
526 value_mask = GEN6_BLT_MASK_32;
527 write_mask = GEN6_BLT_MASK_32;
528 break;
529 case PIPE_FORMAT_Z24X8_UNORM:
530 if (!(clear_flags & PIPE_CLEAR_DEPTH))
531 return true;
532
533 value_mask = GEN6_BLT_MASK_32;
534 write_mask = GEN6_BLT_MASK_32_LO;
535 break;
536 case PIPE_FORMAT_Z24_UNORM_S8_UINT:
537 if (!(clear_flags & PIPE_CLEAR_DEPTHSTENCIL))
538 return true;
539
540 value_mask = GEN6_BLT_MASK_32;
541
542 if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL)
543 write_mask = GEN6_BLT_MASK_32;
544 else if (clear_flags & PIPE_CLEAR_DEPTH)
545 write_mask = GEN6_BLT_MASK_32_LO;
546 else
547 write_mask = GEN6_BLT_MASK_32_HI;
548 break;
549 default:
550 return false;
551 break;
552 }
553
554 ilo_blit_resolve_surface(blitter->ilo, zs, ILO_TEXTURE_BLT_WRITE);
555
556 val = util_pack_z_stencil(zs->format, depth, stencil);
557
558 u_box_3d(x, y, zs->u.tex.first_layer, width, height,
559 zs->u.tex.last_layer - zs->u.tex.first_layer + 1, &box);
560
561 assert(zs->texture->target != PIPE_BUFFER);
562
563 return tex_clear_region(blitter, ilo_texture(zs->texture),
564 zs->u.tex.level, &box, val, value_mask, write_mask);
565 }