2 * Mesa 3-D graphics library
4 * Copyright (C) 2013 LunarG, Inc.
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:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
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.
25 * Chia-I Wu <olv@lunarg.com>
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"
33 #include "ilo_context.h"
36 #include "ilo_resource.h"
37 #include "ilo_blitter.h"
40 ilo_blitter_blt_begin(struct ilo_blitter
*blitter
, int max_cmd_size
,
42 enum gen_surface_tiling dst_tiling
,
44 enum gen_surface_tiling src_tiling
)
46 struct ilo_cp
*cp
= blitter
->ilo
->cp
;
47 struct intel_bo
*aper_check
[2];
52 ilo_cp_set_owner(cp
, INTEL_RING_BLT
, NULL
);
54 /* check aperture space */
63 if (!ilo_builder_validate(&cp
->builder
, count
, aper_check
))
64 ilo_cp_submit(cp
, "out of aperture");
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
);
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
;
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
;
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
92 max_cmd_size
+= (4 + 3) * 2;
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
);
101 * From the Ivy Bridge PRM, volume 1 part 4, page 133:
103 * "SW is required to flush the HW before changing the polarity of
104 * this bit (Tile Y Destination/Source)."
106 gen6_MI_FLUSH_DW(&cp
->builder
);
107 gen6_MI_LOAD_REGISTER_IMM(&cp
->builder
, GEN6_REG_BCS_SWCTRL
, swctrl
);
109 swctrl
&= ~(GEN6_REG_BCS_SWCTRL_DST_TILING_Y
|
110 GEN6_REG_BCS_SWCTRL_SRC_TILING_Y
);
117 ilo_blitter_blt_end(struct ilo_blitter
*blitter
, uint32_t swctrl
)
119 struct ilo_builder
*builder
= &blitter
->ilo
->cp
->builder
;
121 /* set BCS_SWCTRL back */
123 gen6_MI_FLUSH_DW(builder
);
124 gen6_MI_LOAD_REGISTER_IMM(builder
, GEN6_REG_BCS_SWCTRL
, swctrl
);
129 buf_clear_region(struct ilo_blitter
*blitter
,
130 struct ilo_buffer_resource
*buf
, unsigned offset
,
131 uint32_t val
, unsigned size
,
132 enum gen6_blt_mask value_mask
,
133 enum gen6_blt_mask write_mask
)
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
;
140 if (offset
% cpp
|| size
% cpp
)
143 dst
.bo
= buf
->vma
.bo
;
144 dst
.offset
= buf
->vma
.bo_offset
+ offset
;
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
);
151 unsigned width
, height
;
156 if (width
> gen6_blt_max_bytes_per_scanline
) {
157 /* less than INT16_MAX and dword-aligned */
159 height
= size
/ width
;
160 if (height
> gen6_blt_max_scanlines
)
161 height
= gen6_blt_max_scanlines
;
168 gen6_COLOR_BLT(builder
, &dst
, val
,
169 width
, height
, rop
, value_mask
, write_mask
);
171 dst
.offset
+= dst
.pitch
* height
;
172 size
-= width
* height
;
175 ilo_blitter_blt_end(blitter
, 0);
181 buf_copy_region(struct ilo_blitter
*blitter
,
182 struct ilo_buffer_resource
*dst_buf
, unsigned dst_offset
,
183 struct ilo_buffer_resource
*src_buf
, unsigned src_offset
,
186 const uint8_t rop
= 0xcc; /* SRCCOPY */
187 struct ilo_builder
*builder
= &blitter
->ilo
->cp
->builder
;
188 struct gen6_blt_bo dst
, src
;
190 dst
.bo
= dst_buf
->vma
.bo
;
191 dst
.offset
= dst_buf
->vma
.bo_offset
+ dst_offset
;
194 src
.bo
= src_buf
->vma
.bo
;
195 src
.offset
= src_buf
->vma
.bo_offset
+ src_offset
;
198 ilo_blitter_blt_begin(blitter
, GEN6_SRC_COPY_BLT__SIZE
*
199 (1 + size
/ 32764 / gen6_blt_max_scanlines
),
200 dst_buf
->vma
.bo
, GEN6_TILING_NONE
,
201 src_buf
->vma
.bo
, GEN6_TILING_NONE
);
204 unsigned width
, height
;
209 if (width
> gen6_blt_max_bytes_per_scanline
) {
210 /* less than INT16_MAX and dword-aligned */
212 height
= size
/ width
;
213 if (height
> gen6_blt_max_scanlines
)
214 height
= gen6_blt_max_scanlines
;
223 gen6_SRC_COPY_BLT(builder
, &dst
, &src
,
224 width
, height
, rop
, GEN6_BLT_MASK_8
, GEN6_BLT_MASK_8
);
226 dst
.offset
+= dst
.pitch
* height
;
227 src
.offset
+= src
.pitch
* height
;
228 size
-= width
* height
;
231 ilo_blitter_blt_end(blitter
, 0);
237 tex_clear_region(struct ilo_blitter
*blitter
,
238 struct ilo_texture
*dst_tex
, unsigned dst_level
,
239 const struct pipe_box
*dst_box
,
241 enum gen6_blt_mask value_mask
,
242 enum gen6_blt_mask write_mask
)
244 const int cpp
= gen6_blt_translate_value_cpp(value_mask
);
245 const unsigned max_extent
= 32767; /* INT16_MAX */
246 const uint8_t rop
= 0xf0; /* PATCOPY */
247 struct ilo_builder
*builder
= &blitter
->ilo
->cp
->builder
;
248 struct gen6_blt_xy_bo dst
;
252 /* no W-tiling nor separate stencil support */
253 if (dst_tex
->image
.tiling
== GEN8_TILING_W
|| dst_tex
->separate_s8
)
256 if (dst_tex
->image
.bo_stride
> max_extent
)
259 if (dst_box
->width
* cpp
> gen6_blt_max_bytes_per_scanline
)
262 dst
.bo
= dst_tex
->vma
.bo
;
263 dst
.offset
= dst_tex
->vma
.bo_offset
;
264 dst
.pitch
= dst_tex
->image
.bo_stride
;
265 dst
.tiling
= dst_tex
->image
.tiling
;
267 swctrl
= ilo_blitter_blt_begin(blitter
,
268 GEN6_XY_COLOR_BLT__SIZE
* dst_box
->depth
,
269 dst_tex
->vma
.bo
, dst_tex
->image
.tiling
, NULL
, GEN6_TILING_NONE
);
271 for (slice
= 0; slice
< dst_box
->depth
; slice
++) {
274 ilo_image_get_slice_pos(&dst_tex
->image
,
275 dst_level
, dst_box
->z
+ slice
, &x
, &y
);
277 dst
.x
= x
+ dst_box
->x
;
278 dst
.y
= y
+ dst_box
->y
;
280 if (dst
.x
+ dst_box
->width
> max_extent
||
281 dst
.y
+ dst_box
->height
> max_extent
)
284 gen6_XY_COLOR_BLT(builder
, &dst
, val
,
285 dst_box
->width
, dst_box
->height
, rop
, value_mask
, write_mask
);
288 ilo_blitter_blt_end(blitter
, swctrl
);
290 return (slice
== dst_box
->depth
);
294 tex_copy_region(struct ilo_blitter
*blitter
,
295 struct ilo_texture
*dst_tex
,
297 unsigned dst_x
, unsigned dst_y
, unsigned dst_z
,
298 struct ilo_texture
*src_tex
,
300 const struct pipe_box
*src_box
)
302 const struct util_format_description
*desc
=
303 util_format_description(dst_tex
->image_format
);
304 const unsigned max_extent
= 32767; /* INT16_MAX */
305 const uint8_t rop
= 0xcc; /* SRCCOPY */
306 struct ilo_builder
*builder
= &blitter
->ilo
->cp
->builder
;
307 enum gen6_blt_mask mask
;
308 struct gen6_blt_xy_bo dst
, src
;
310 int cpp
, xscale
, slice
;
312 /* no W-tiling nor separate stencil support */
313 if (dst_tex
->image
.tiling
== GEN8_TILING_W
|| dst_tex
->separate_s8
||
314 src_tex
->image
.tiling
== GEN8_TILING_W
|| src_tex
->separate_s8
)
317 if (dst_tex
->image
.bo_stride
> max_extent
||
318 src_tex
->image
.bo_stride
> max_extent
)
321 cpp
= desc
->block
.bits
/ 8;
324 /* accommodate for larger cpp */
329 cpp
= (cpp
% 4 == 0) ? 4 : 2;
330 xscale
= (desc
->block
.bits
/ 8) / cpp
;
333 if (src_box
->width
* cpp
* xscale
> gen6_blt_max_bytes_per_scanline
)
338 mask
= GEN6_BLT_MASK_8
;
341 mask
= GEN6_BLT_MASK_16
;
344 mask
= GEN6_BLT_MASK_32
;
351 dst
.bo
= dst_tex
->vma
.bo
;
352 dst
.offset
= dst_tex
->vma
.bo_offset
;
353 dst
.pitch
= dst_tex
->image
.bo_stride
;
354 dst
.tiling
= dst_tex
->image
.tiling
;
356 src
.bo
= src_tex
->vma
.bo
;
357 src
.offset
= src_tex
->vma
.bo_offset
;
358 src
.pitch
= src_tex
->image
.bo_stride
;
359 src
.tiling
= src_tex
->image
.tiling
;
361 swctrl
= ilo_blitter_blt_begin(blitter
,
362 GEN6_XY_SRC_COPY_BLT__SIZE
* src_box
->depth
,
363 dst
.bo
, dst
.tiling
, src
.bo
, src
.tiling
);
365 for (slice
= 0; slice
< src_box
->depth
; slice
++) {
366 unsigned dx
, dy
, sx
, sy
, width
, height
;
368 ilo_image_get_slice_pos(&dst_tex
->image
,
369 dst_level
, dst_z
+ slice
, &dx
, &dy
);
370 ilo_image_get_slice_pos(&src_tex
->image
,
371 src_level
, src_box
->z
+ slice
, &sx
, &sy
);
373 dst
.x
= (dx
+ dst_x
) * xscale
;
375 src
.x
= (sx
+ src_box
->x
) * xscale
;
376 src
.y
= sy
+ src_box
->y
;
377 width
= src_box
->width
* xscale
;
378 height
= src_box
->height
;
381 dst
.x
/= desc
->block
.width
;
382 dst
.y
/= desc
->block
.height
;
383 src
.x
/= desc
->block
.width
;
384 src
.y
/= desc
->block
.height
;
385 width
/= desc
->block
.width
;
386 height
/= desc
->block
.height
;
388 if (src
.x
+ width
> max_extent
|| src
.y
+ height
> max_extent
||
389 dst
.x
+ width
> max_extent
|| dst
.y
+ height
> max_extent
)
392 gen6_XY_SRC_COPY_BLT(builder
, &dst
, &src
,
393 width
, height
, rop
, mask
, mask
);
396 ilo_blitter_blt_end(blitter
, swctrl
);
398 return (slice
== src_box
->depth
);
402 ilo_blitter_blt_copy_resource(struct ilo_blitter
*blitter
,
403 struct pipe_resource
*dst
, unsigned dst_level
,
404 unsigned dst_x
, unsigned dst_y
, unsigned dst_z
,
405 struct pipe_resource
*src
, unsigned src_level
,
406 const struct pipe_box
*src_box
)
410 ilo_blit_resolve_slices(blitter
->ilo
, src
, src_level
,
411 src_box
->z
, src_box
->depth
, ILO_TEXTURE_BLT_READ
);
412 ilo_blit_resolve_slices(blitter
->ilo
, dst
, dst_level
,
413 dst_z
, src_box
->depth
, ILO_TEXTURE_BLT_WRITE
);
415 if (dst
->target
== PIPE_BUFFER
&& src
->target
== PIPE_BUFFER
) {
416 const unsigned dst_offset
= dst_x
;
417 const unsigned src_offset
= src_box
->x
;
418 const unsigned size
= src_box
->width
;
420 assert(dst_level
== 0 && dst_y
== 0 && dst_z
== 0);
421 assert(src_level
== 0 &&
424 src_box
->height
== 1 &&
425 src_box
->depth
== 1);
427 success
= buf_copy_region(blitter
, ilo_buffer_resource(dst
), dst_offset
,
428 ilo_buffer_resource(src
), src_offset
, size
);
430 else if (dst
->target
!= PIPE_BUFFER
&& src
->target
!= PIPE_BUFFER
) {
431 success
= tex_copy_region(blitter
,
432 ilo_texture(dst
), dst_level
, dst_x
, dst_y
, dst_z
,
433 ilo_texture(src
), src_level
, src_box
);
443 ilo_blitter_blt_clear_rt(struct ilo_blitter
*blitter
,
444 struct pipe_surface
*rt
,
445 const union pipe_color_union
*color
,
446 unsigned x
, unsigned y
,
447 unsigned width
, unsigned height
)
449 const int cpp
= util_format_get_blocksize(rt
->format
);
450 enum gen6_blt_mask mask
;
451 union util_color packed
;
454 if (ilo_skip_rendering(blitter
->ilo
))
459 mask
= GEN6_BLT_MASK_8
;
462 mask
= GEN6_BLT_MASK_16
;
465 mask
= GEN6_BLT_MASK_32
;
472 if (util_format_is_pure_integer(rt
->format
) ||
473 util_format_is_compressed(rt
->format
))
476 ilo_blit_resolve_surface(blitter
->ilo
, rt
, ILO_TEXTURE_BLT_WRITE
);
478 util_pack_color(color
->f
, rt
->format
, &packed
);
480 if (rt
->texture
->target
== PIPE_BUFFER
) {
481 unsigned offset
, end
, size
;
483 assert(y
== 0 && height
== 1);
485 offset
= (rt
->u
.buf
.first_element
+ x
) * cpp
;
486 end
= (rt
->u
.buf
.last_element
+ 1) * cpp
;
489 if (offset
+ size
> end
)
492 success
= buf_clear_region(blitter
, ilo_buffer_resource(rt
->texture
),
493 offset
, packed
.ui
[0], size
, mask
, mask
);
498 u_box_3d(x
, y
, rt
->u
.tex
.first_layer
, width
, height
,
499 rt
->u
.tex
.last_layer
- rt
->u
.tex
.first_layer
+ 1, &box
);
501 success
= tex_clear_region(blitter
, ilo_texture(rt
->texture
),
502 rt
->u
.tex
.level
, &box
, packed
.ui
[0], mask
, mask
);
509 ilo_blitter_blt_clear_zs(struct ilo_blitter
*blitter
,
510 struct pipe_surface
*zs
,
511 unsigned clear_flags
,
512 double depth
, unsigned stencil
,
513 unsigned x
, unsigned y
,
514 unsigned width
, unsigned height
)
516 enum gen6_blt_mask value_mask
, write_mask
;
520 if (ilo_skip_rendering(blitter
->ilo
))
523 switch (zs
->format
) {
524 case PIPE_FORMAT_Z16_UNORM
:
525 if (!(clear_flags
& PIPE_CLEAR_DEPTH
))
528 value_mask
= GEN6_BLT_MASK_16
;
529 write_mask
= GEN6_BLT_MASK_16
;
531 case PIPE_FORMAT_Z32_FLOAT
:
532 if (!(clear_flags
& PIPE_CLEAR_DEPTH
))
535 value_mask
= GEN6_BLT_MASK_32
;
536 write_mask
= GEN6_BLT_MASK_32
;
538 case PIPE_FORMAT_Z24X8_UNORM
:
539 if (!(clear_flags
& PIPE_CLEAR_DEPTH
))
542 value_mask
= GEN6_BLT_MASK_32
;
543 write_mask
= GEN6_BLT_MASK_32_LO
;
545 case PIPE_FORMAT_Z24_UNORM_S8_UINT
:
546 if (!(clear_flags
& PIPE_CLEAR_DEPTHSTENCIL
))
549 value_mask
= GEN6_BLT_MASK_32
;
551 if ((clear_flags
& PIPE_CLEAR_DEPTHSTENCIL
) == PIPE_CLEAR_DEPTHSTENCIL
)
552 write_mask
= GEN6_BLT_MASK_32
;
553 else if (clear_flags
& PIPE_CLEAR_DEPTH
)
554 write_mask
= GEN6_BLT_MASK_32_LO
;
556 write_mask
= GEN6_BLT_MASK_32_HI
;
563 ilo_blit_resolve_surface(blitter
->ilo
, zs
, ILO_TEXTURE_BLT_WRITE
);
565 val
= util_pack_z_stencil(zs
->format
, depth
, stencil
);
567 u_box_3d(x
, y
, zs
->u
.tex
.first_layer
, width
, height
,
568 zs
->u
.tex
.last_layer
- zs
->u
.tex
.first_layer
+ 1, &box
);
570 assert(zs
->texture
->target
!= PIPE_BUFFER
);
572 return tex_clear_region(blitter
, ilo_texture(zs
->texture
),
573 zs
->u
.tex
.level
, &box
, val
, value_mask
, write_mask
);