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 "util/u_pack_color.h"
31 #include "ilo_builder_mi.h"
32 #include "ilo_builder_blt.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
*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
)
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
*dst_buf
, unsigned dst_offset
,
183 struct ilo_buffer
*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
->bo
;
191 dst
.offset
= dst_offset
;
194 src
.bo
= src_buf
->bo
;
195 src
.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
->bo
, GEN6_TILING_NONE
, src_buf
->bo
, GEN6_TILING_NONE
);
203 unsigned width
, height
;
208 if (width
> gen6_blt_max_bytes_per_scanline
) {
209 /* less than INT16_MAX and dword-aligned */
211 height
= size
/ width
;
212 if (height
> gen6_blt_max_scanlines
)
213 height
= gen6_blt_max_scanlines
;
222 gen6_SRC_COPY_BLT(builder
, &dst
, &src
,
223 width
, height
, rop
, GEN6_BLT_MASK_8
, GEN6_BLT_MASK_8
);
225 dst
.offset
+= dst
.pitch
* height
;
226 src
.offset
+= src
.pitch
* height
;
227 size
-= width
* height
;
230 ilo_blitter_blt_end(blitter
, 0);
236 tex_clear_region(struct ilo_blitter
*blitter
,
237 struct ilo_texture
*dst_tex
, unsigned dst_level
,
238 const struct pipe_box
*dst_box
,
240 enum gen6_blt_mask value_mask
,
241 enum gen6_blt_mask write_mask
)
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
;
251 /* no W-tiling nor separate stencil support */
252 if (dst_tex
->image
.tiling
== GEN8_TILING_W
|| dst_tex
->separate_s8
)
255 if (dst_tex
->image
.bo_stride
> max_extent
)
258 if (dst_box
->width
* cpp
> gen6_blt_max_bytes_per_scanline
)
261 dst
.bo
= dst_tex
->image
.bo
;
263 dst
.pitch
= dst_tex
->image
.bo_stride
;
264 dst
.tiling
= dst_tex
->image
.tiling
;
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
);
270 for (slice
= 0; slice
< dst_box
->depth
; slice
++) {
273 ilo_image_get_slice_pos(&dst_tex
->image
,
274 dst_level
, dst_box
->z
+ slice
, &x
, &y
);
276 dst
.x
= x
+ dst_box
->x
;
277 dst
.y
= y
+ dst_box
->y
;
279 if (dst
.x
+ dst_box
->width
> max_extent
||
280 dst
.y
+ dst_box
->height
> max_extent
)
283 gen6_XY_COLOR_BLT(builder
, &dst
, val
,
284 dst_box
->width
, dst_box
->height
, rop
, value_mask
, write_mask
);
287 ilo_blitter_blt_end(blitter
, swctrl
);
289 return (slice
== dst_box
->depth
);
293 tex_copy_region(struct ilo_blitter
*blitter
,
294 struct ilo_texture
*dst_tex
,
296 unsigned dst_x
, unsigned dst_y
, unsigned dst_z
,
297 struct ilo_texture
*src_tex
,
299 const struct pipe_box
*src_box
)
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
;
309 int cpp
, xscale
, slice
;
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
)
316 if (dst_tex
->image
.bo_stride
> max_extent
||
317 src_tex
->image
.bo_stride
> max_extent
)
320 cpp
= desc
->block
.bits
/ 8;
323 /* accommodate for larger cpp */
328 cpp
= (cpp
% 4 == 0) ? 4 : 2;
329 xscale
= (desc
->block
.bits
/ 8) / cpp
;
332 if (src_box
->width
* cpp
* xscale
> gen6_blt_max_bytes_per_scanline
)
337 mask
= GEN6_BLT_MASK_8
;
340 mask
= GEN6_BLT_MASK_16
;
343 mask
= GEN6_BLT_MASK_32
;
350 dst
.bo
= dst_tex
->image
.bo
;
352 dst
.pitch
= dst_tex
->image
.bo_stride
;
353 dst
.tiling
= dst_tex
->image
.tiling
;
355 src
.bo
= src_tex
->image
.bo
;
357 src
.pitch
= src_tex
->image
.bo_stride
;
358 src
.tiling
= src_tex
->image
.tiling
;
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
);
364 for (slice
= 0; slice
< src_box
->depth
; slice
++) {
365 unsigned dx
, dy
, sx
, sy
, width
, height
;
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
);
372 dst
.x
= (dx
+ dst_x
) * xscale
;
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
;
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
;
387 if (src
.x
+ width
> max_extent
|| src
.y
+ height
> max_extent
||
388 dst
.x
+ width
> max_extent
|| dst
.y
+ height
> max_extent
)
391 gen6_XY_SRC_COPY_BLT(builder
, &dst
, &src
,
392 width
, height
, rop
, mask
, mask
);
395 ilo_blitter_blt_end(blitter
, swctrl
);
397 return (slice
== src_box
->depth
);
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
)
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
);
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
;
419 assert(dst_level
== 0 && dst_y
== 0 && dst_z
== 0);
420 assert(src_level
== 0 &&
423 src_box
->height
== 1 &&
424 src_box
->depth
== 1);
426 success
= buf_copy_region(blitter
,
427 ilo_buffer(dst
), dst_offset
, ilo_buffer(src
), src_offset
, size
);
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
);
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
)
448 const int cpp
= util_format_get_blocksize(rt
->format
);
449 enum gen6_blt_mask mask
;
450 union util_color packed
;
453 if (ilo_skip_rendering(blitter
->ilo
))
458 mask
= GEN6_BLT_MASK_8
;
461 mask
= GEN6_BLT_MASK_16
;
464 mask
= GEN6_BLT_MASK_32
;
471 if (util_format_is_pure_integer(rt
->format
) ||
472 util_format_is_compressed(rt
->format
))
475 ilo_blit_resolve_surface(blitter
->ilo
, rt
, ILO_TEXTURE_BLT_WRITE
);
477 util_pack_color(color
->f
, rt
->format
, &packed
);
479 if (rt
->texture
->target
== PIPE_BUFFER
) {
480 unsigned offset
, end
, size
;
482 assert(y
== 0 && height
== 1);
484 offset
= (rt
->u
.buf
.first_element
+ x
) * cpp
;
485 end
= (rt
->u
.buf
.last_element
+ 1) * cpp
;
488 if (offset
+ size
> end
)
491 success
= buf_clear_region(blitter
, ilo_buffer(rt
->texture
),
492 offset
, packed
.ui
[0], size
, mask
, mask
);
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
);
500 success
= tex_clear_region(blitter
, ilo_texture(rt
->texture
),
501 rt
->u
.tex
.level
, &box
, packed
.ui
[0], mask
, mask
);
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
)
515 enum gen6_blt_mask value_mask
, write_mask
;
519 if (ilo_skip_rendering(blitter
->ilo
))
522 switch (zs
->format
) {
523 case PIPE_FORMAT_Z16_UNORM
:
524 if (!(clear_flags
& PIPE_CLEAR_DEPTH
))
527 value_mask
= GEN6_BLT_MASK_16
;
528 write_mask
= GEN6_BLT_MASK_16
;
530 case PIPE_FORMAT_Z32_FLOAT
:
531 if (!(clear_flags
& PIPE_CLEAR_DEPTH
))
534 value_mask
= GEN6_BLT_MASK_32
;
535 write_mask
= GEN6_BLT_MASK_32
;
537 case PIPE_FORMAT_Z24X8_UNORM
:
538 if (!(clear_flags
& PIPE_CLEAR_DEPTH
))
541 value_mask
= GEN6_BLT_MASK_32
;
542 write_mask
= GEN6_BLT_MASK_32_LO
;
544 case PIPE_FORMAT_Z24_UNORM_S8_UINT
:
545 if (!(clear_flags
& PIPE_CLEAR_DEPTHSTENCIL
))
548 value_mask
= GEN6_BLT_MASK_32
;
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
;
555 write_mask
= GEN6_BLT_MASK_32_HI
;
562 ilo_blit_resolve_surface(blitter
->ilo
, zs
, ILO_TEXTURE_BLT_WRITE
);
564 val
= util_pack_z_stencil(zs
->format
, depth
, stencil
);
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
);
569 assert(zs
->texture
->target
!= PIPE_BUFFER
);
571 return tex_clear_region(blitter
, ilo_texture(zs
->texture
),
572 zs
->u
.tex
.level
, &box
, val
, value_mask
, write_mask
);