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"
32 #include "ilo_builder_mi.h"
33 #include "ilo_builder_blt.h"
34 #include "ilo_context.h"
37 #include "ilo_resource.h"
38 #include "ilo_blitter.h"
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
)
45 struct ilo_context
*ilo
= blitter
->ilo
;
46 struct intel_bo
*aper_check
[2];
51 ilo_cp_set_ring(ilo
->cp
, INTEL_RING_BLT
);
52 ilo_cp_set_owner(ilo
->cp
, NULL
, 0);
54 /* check aperture space */
63 if (!ilo_builder_validate(&ilo
->cp
->builder
, count
, aper_check
))
64 ilo_cp_flush(ilo
->cp
, "out of aperture");
69 if (dst_tiling
== INTEL_TILING_Y
) {
70 swctrl
|= GEN6_REG_BCS_SWCTRL_DST_TILING_Y
<< 16 |
71 GEN6_REG_BCS_SWCTRL_DST_TILING_Y
;
74 if (src
&& src_tiling
== INTEL_TILING_Y
) {
75 swctrl
|= GEN6_REG_BCS_SWCTRL_SRC_TILING_Y
<< 16 |
76 GEN6_REG_BCS_SWCTRL_SRC_TILING_Y
;
80 * Most clients expect BLT engine to be stateless. If we have to set
81 * BCS_SWCTRL to a non-default value, we have to set it back in the same
85 max_cmd_size
+= (4 + 3) * 2;
87 if (ilo_cp_space(ilo
->cp
) < max_cmd_size
) {
88 ilo_cp_flush(ilo
->cp
, "out of space");
89 assert(ilo_cp_space(ilo
->cp
) >= max_cmd_size
);
94 * From the Ivy Bridge PRM, volume 1 part 4, page 133:
96 * "SW is required to flush the HW before changing the polarity of
97 * this bit (Tile Y Destination/Source)."
99 gen6_MI_FLUSH_DW(&ilo
->cp
->builder
);
100 gen6_MI_LOAD_REGISTER_IMM(&ilo
->cp
->builder
,
101 GEN6_REG_BCS_SWCTRL
, swctrl
);
103 swctrl
&= ~(GEN6_REG_BCS_SWCTRL_DST_TILING_Y
|
104 GEN6_REG_BCS_SWCTRL_SRC_TILING_Y
);
111 ilo_blitter_blt_end(struct ilo_blitter
*blitter
, uint32_t swctrl
)
113 struct ilo_context
*ilo
= blitter
->ilo
;
115 /* set BCS_SWCTRL back */
117 gen6_MI_FLUSH_DW(&ilo
->cp
->builder
);
118 gen6_MI_LOAD_REGISTER_IMM(&ilo
->cp
->builder
, GEN6_REG_BCS_SWCTRL
, swctrl
);
123 buf_clear_region(struct ilo_blitter
*blitter
,
124 struct ilo_buffer
*buf
, unsigned offset
,
125 uint32_t val
, unsigned size
,
126 enum gen6_blt_mask value_mask
,
127 enum gen6_blt_mask write_mask
)
129 const uint8_t rop
= 0xf0; /* PATCOPY */
130 const int cpp
= gen6_blt_translate_value_cpp(value_mask
);
131 struct ilo_context
*ilo
= blitter
->ilo
;
132 struct gen6_blt_bo dst
;
134 if (offset
% cpp
|| size
% cpp
)
140 ilo_blitter_blt_begin(blitter
, 0,
141 dst
.bo
, INTEL_TILING_NONE
, NULL
, INTEL_TILING_NONE
);
144 unsigned width
, height
;
149 if (width
> gen6_blt_max_bytes_per_scanline
) {
150 /* less than INT16_MAX and dword-aligned */
152 height
= size
/ width
;
153 if (height
> gen6_blt_max_scanlines
)
154 height
= gen6_blt_max_scanlines
;
161 gen6_COLOR_BLT(&ilo
->cp
->builder
, &dst
, val
,
162 width
, height
, rop
, value_mask
, write_mask
);
164 dst
.offset
+= dst
.pitch
* height
;
165 size
-= width
* height
;
168 ilo_blitter_blt_end(blitter
, 0);
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
,
179 const uint8_t rop
= 0xcc; /* SRCCOPY */
180 struct ilo_context
*ilo
= blitter
->ilo
;
181 struct gen6_blt_bo dst
, src
;
183 dst
.bo
= dst_buf
->bo
;
184 dst
.offset
= dst_offset
;
187 src
.bo
= src_buf
->bo
;
188 src
.offset
= src_offset
;
191 ilo_blitter_blt_begin(blitter
, 0,
192 dst_buf
->bo
, INTEL_TILING_NONE
, src_buf
->bo
, INTEL_TILING_NONE
);
195 unsigned width
, height
;
200 if (width
> gen6_blt_max_bytes_per_scanline
) {
201 /* less than INT16_MAX and dword-aligned */
203 height
= size
/ width
;
204 if (height
> gen6_blt_max_scanlines
)
205 height
= gen6_blt_max_scanlines
;
214 gen6_SRC_COPY_BLT(&ilo
->cp
->builder
, &dst
, &src
,
215 width
, height
, rop
, GEN6_BLT_MASK_8
, GEN6_BLT_MASK_8
);
217 dst
.offset
+= dst
.pitch
* height
;
218 src
.offset
+= src
.pitch
* height
;
219 size
-= width
* height
;
222 ilo_blitter_blt_end(blitter
, 0);
228 tex_clear_region(struct ilo_blitter
*blitter
,
229 struct ilo_texture
*dst_tex
, unsigned dst_level
,
230 const struct pipe_box
*dst_box
,
232 enum gen6_blt_mask value_mask
,
233 enum gen6_blt_mask write_mask
)
235 const int cpp
= gen6_blt_translate_value_cpp(value_mask
);
236 const unsigned max_extent
= 32767; /* INT16_MAX */
237 const uint8_t rop
= 0xf0; /* PATCOPY */
238 struct ilo_context
*ilo
= blitter
->ilo
;
239 struct gen6_blt_xy_bo dst
;
243 /* no W-tiling support */
244 if (dst_tex
->separate_s8
)
247 if (dst_tex
->layout
.bo_stride
> max_extent
)
250 if (dst_box
->width
* cpp
> gen6_blt_max_bytes_per_scanline
)
253 dst
.bo
= dst_tex
->bo
;
255 dst
.pitch
= dst_tex
->layout
.bo_stride
;
256 dst
.tiling
= dst_tex
->layout
.tiling
;
258 swctrl
= ilo_blitter_blt_begin(blitter
, dst_box
->depth
* 6,
259 dst_tex
->bo
, dst_tex
->layout
.tiling
, NULL
, INTEL_TILING_NONE
);
261 for (slice
= 0; slice
< dst_box
->depth
; slice
++) {
264 ilo_layout_get_slice_pos(&dst_tex
->layout
,
265 dst_level
, dst_box
->z
+ slice
, &x
, &y
);
267 dst
.x
= x
+ dst_box
->x
;
268 dst
.y
= y
+ dst_box
->y
;
270 if (dst
.x
+ dst_box
->width
> max_extent
||
271 dst
.y
+ dst_box
->height
> max_extent
)
274 gen6_XY_COLOR_BLT(&ilo
->cp
->builder
, &dst
, val
,
275 dst_box
->width
, dst_box
->height
, rop
, value_mask
, write_mask
);
278 ilo_blitter_blt_end(blitter
, swctrl
);
280 return (slice
== dst_box
->depth
);
284 tex_copy_region(struct ilo_blitter
*blitter
,
285 struct ilo_texture
*dst_tex
,
287 unsigned dst_x
, unsigned dst_y
, unsigned dst_z
,
288 struct ilo_texture
*src_tex
,
290 const struct pipe_box
*src_box
)
292 const struct util_format_description
*desc
=
293 util_format_description(dst_tex
->layout
.format
);
294 const unsigned max_extent
= 32767; /* INT16_MAX */
295 const uint8_t rop
= 0xcc; /* SRCCOPY */
296 struct ilo_context
*ilo
= blitter
->ilo
;
297 enum gen6_blt_mask mask
;
298 struct gen6_blt_xy_bo dst
, src
;
300 int cpp
, xscale
, slice
;
302 /* no W-tiling support */
303 if (dst_tex
->separate_s8
|| src_tex
->separate_s8
)
306 if (dst_tex
->layout
.bo_stride
> max_extent
||
307 src_tex
->layout
.bo_stride
> max_extent
)
310 cpp
= desc
->block
.bits
/ 8;
313 /* accommodate for larger cpp */
318 cpp
= (cpp
% 4 == 0) ? 4 : 2;
319 xscale
= (desc
->block
.bits
/ 8) / cpp
;
322 if (src_box
->width
* cpp
* xscale
> gen6_blt_max_bytes_per_scanline
)
327 mask
= GEN6_BLT_MASK_8
;
330 mask
= GEN6_BLT_MASK_16
;
333 mask
= GEN6_BLT_MASK_32
;
340 dst
.bo
= dst_tex
->bo
;
342 dst
.pitch
= dst_tex
->layout
.bo_stride
;
343 dst
.tiling
= dst_tex
->layout
.tiling
;
345 src
.bo
= src_tex
->bo
;
347 src
.pitch
= src_tex
->layout
.bo_stride
;
348 src
.tiling
= src_tex
->layout
.tiling
;
350 swctrl
= ilo_blitter_blt_begin(blitter
, src_box
->depth
* 8,
351 dst
.bo
, dst
.tiling
, src
.bo
, src
.tiling
);
353 for (slice
= 0; slice
< src_box
->depth
; slice
++) {
354 unsigned dx
, dy
, sx
, sy
, width
, height
;
356 ilo_layout_get_slice_pos(&dst_tex
->layout
,
357 dst_level
, dst_z
+ slice
, &dx
, &dy
);
358 ilo_layout_get_slice_pos(&src_tex
->layout
,
359 src_level
, src_box
->z
+ slice
, &sx
, &sy
);
361 dst
.x
= (dx
+ dst_x
) * xscale
;
363 src
.x
= (sx
+ src_box
->x
) * xscale
;
364 src
.y
= sy
+ src_box
->y
;
365 width
= src_box
->width
* xscale
;
366 height
= src_box
->height
;
369 dst
.x
/= desc
->block
.width
;
370 dst
.y
/= desc
->block
.height
;
371 src
.x
/= desc
->block
.width
;
372 src
.y
/= desc
->block
.height
;
373 width
/= desc
->block
.width
;
374 height
/= desc
->block
.height
;
376 if (src
.x
+ width
> max_extent
|| src
.y
+ height
> max_extent
||
377 dst
.x
+ width
> max_extent
|| dst
.y
+ height
> max_extent
)
380 gen6_XY_SRC_COPY_BLT(&ilo
->cp
->builder
, &dst
, &src
,
381 width
, height
, rop
, mask
, mask
);
384 ilo_blitter_blt_end(blitter
, swctrl
);
386 return (slice
== src_box
->depth
);
390 ilo_blitter_blt_copy_resource(struct ilo_blitter
*blitter
,
391 struct pipe_resource
*dst
, unsigned dst_level
,
392 unsigned dst_x
, unsigned dst_y
, unsigned dst_z
,
393 struct pipe_resource
*src
, unsigned src_level
,
394 const struct pipe_box
*src_box
)
398 ilo_blit_resolve_slices(blitter
->ilo
, src
, src_level
,
399 src_box
->z
, src_box
->depth
, ILO_TEXTURE_BLT_READ
);
400 ilo_blit_resolve_slices(blitter
->ilo
, dst
, dst_level
,
401 dst_z
, src_box
->depth
, ILO_TEXTURE_BLT_WRITE
);
403 if (dst
->target
== PIPE_BUFFER
&& src
->target
== PIPE_BUFFER
) {
404 const unsigned dst_offset
= dst_x
;
405 const unsigned src_offset
= src_box
->x
;
406 const unsigned size
= src_box
->width
;
408 assert(dst_level
== 0 && dst_y
== 0 && dst_z
== 0);
409 assert(src_level
== 0 &&
412 src_box
->height
== 1 &&
413 src_box
->depth
== 1);
415 success
= buf_copy_region(blitter
,
416 ilo_buffer(dst
), dst_offset
, ilo_buffer(src
), src_offset
, size
);
418 else if (dst
->target
!= PIPE_BUFFER
&& src
->target
!= PIPE_BUFFER
) {
419 success
= tex_copy_region(blitter
,
420 ilo_texture(dst
), dst_level
, dst_x
, dst_y
, dst_z
,
421 ilo_texture(src
), src_level
, src_box
);
431 ilo_blitter_blt_clear_rt(struct ilo_blitter
*blitter
,
432 struct pipe_surface
*rt
,
433 const union pipe_color_union
*color
,
434 unsigned x
, unsigned y
,
435 unsigned width
, unsigned height
)
437 const int cpp
= util_format_get_blocksize(rt
->format
);
438 enum gen6_blt_mask mask
;
439 union util_color packed
;
442 if (!ilo_3d_pass_render_condition(blitter
->ilo
))
447 mask
= GEN6_BLT_MASK_8
;
450 mask
= GEN6_BLT_MASK_16
;
453 mask
= GEN6_BLT_MASK_32
;
460 if (util_format_is_pure_integer(rt
->format
) ||
461 util_format_is_compressed(rt
->format
))
464 ilo_blit_resolve_surface(blitter
->ilo
, rt
, ILO_TEXTURE_BLT_WRITE
);
466 util_pack_color(color
->f
, rt
->format
, &packed
);
468 if (rt
->texture
->target
== PIPE_BUFFER
) {
469 unsigned offset
, end
, size
;
471 assert(y
== 0 && height
== 1);
473 offset
= (rt
->u
.buf
.first_element
+ x
) * cpp
;
474 end
= (rt
->u
.buf
.last_element
+ 1) * cpp
;
477 if (offset
+ size
> end
)
480 success
= buf_clear_region(blitter
, ilo_buffer(rt
->texture
),
481 offset
, packed
.ui
[0], size
, mask
, mask
);
486 u_box_3d(x
, y
, rt
->u
.tex
.first_layer
, width
, height
,
487 rt
->u
.tex
.last_layer
- rt
->u
.tex
.first_layer
+ 1, &box
);
489 success
= tex_clear_region(blitter
, ilo_texture(rt
->texture
),
490 rt
->u
.tex
.level
, &box
, packed
.ui
[0], mask
, mask
);
497 ilo_blitter_blt_clear_zs(struct ilo_blitter
*blitter
,
498 struct pipe_surface
*zs
,
499 unsigned clear_flags
,
500 double depth
, unsigned stencil
,
501 unsigned x
, unsigned y
,
502 unsigned width
, unsigned height
)
504 enum gen6_blt_mask value_mask
, write_mask
;
508 if (!ilo_3d_pass_render_condition(blitter
->ilo
))
511 switch (zs
->format
) {
512 case PIPE_FORMAT_Z16_UNORM
:
513 if (!(clear_flags
& PIPE_CLEAR_DEPTH
))
516 value_mask
= GEN6_BLT_MASK_16
;
517 write_mask
= GEN6_BLT_MASK_16
;
519 case PIPE_FORMAT_Z32_FLOAT
:
520 if (!(clear_flags
& PIPE_CLEAR_DEPTH
))
523 value_mask
= GEN6_BLT_MASK_32
;
524 write_mask
= GEN6_BLT_MASK_32
;
526 case PIPE_FORMAT_Z24X8_UNORM
:
527 if (!(clear_flags
& PIPE_CLEAR_DEPTH
))
530 value_mask
= GEN6_BLT_MASK_32
;
531 write_mask
= GEN6_BLT_MASK_32_LO
;
533 case PIPE_FORMAT_Z24_UNORM_S8_UINT
:
534 if (!(clear_flags
& PIPE_CLEAR_DEPTHSTENCIL
))
537 value_mask
= GEN6_BLT_MASK_32
;
539 if ((clear_flags
& PIPE_CLEAR_DEPTHSTENCIL
) == PIPE_CLEAR_DEPTHSTENCIL
)
540 write_mask
= GEN6_BLT_MASK_32
;
541 else if (clear_flags
& PIPE_CLEAR_DEPTH
)
542 write_mask
= GEN6_BLT_MASK_32_LO
;
544 write_mask
= GEN6_BLT_MASK_32_HI
;
551 ilo_blit_resolve_surface(blitter
->ilo
, zs
, ILO_TEXTURE_BLT_WRITE
);
553 val
= util_pack_z_stencil(zs
->format
, depth
, stencil
);
555 u_box_3d(x
, y
, zs
->u
.tex
.first_layer
, width
, height
,
556 zs
->u
.tex
.last_layer
- zs
->u
.tex
.first_layer
+ 1, &box
);
558 assert(zs
->texture
->target
!= PIPE_BUFFER
);
560 return tex_clear_region(blitter
, ilo_texture(zs
->texture
),
561 zs
->u
.tex
.level
, &box
, val
, value_mask
, write_mask
);