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