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_owner(ilo
->cp
, INTEL_RING_BLT
, NULL
);
53 /* check aperture space */
62 if (!ilo_builder_validate(&ilo
->cp
->builder
, count
, aper_check
))
63 ilo_cp_submit(ilo
->cp
, "out of aperture");
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
;
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
;
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
84 max_cmd_size
+= (4 + 3) * 2;
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
);
93 * From the Ivy Bridge PRM, volume 1 part 4, page 133:
95 * "SW is required to flush the HW before changing the polarity of
96 * this bit (Tile Y Destination/Source)."
98 gen6_MI_FLUSH_DW(&ilo
->cp
->builder
);
99 gen6_MI_LOAD_REGISTER_IMM(&ilo
->cp
->builder
,
100 GEN6_REG_BCS_SWCTRL
, swctrl
);
102 swctrl
&= ~(GEN6_REG_BCS_SWCTRL_DST_TILING_Y
|
103 GEN6_REG_BCS_SWCTRL_SRC_TILING_Y
);
110 ilo_blitter_blt_end(struct ilo_blitter
*blitter
, uint32_t swctrl
)
112 struct ilo_context
*ilo
= blitter
->ilo
;
114 /* set BCS_SWCTRL back */
116 gen6_MI_FLUSH_DW(&ilo
->cp
->builder
);
117 gen6_MI_LOAD_REGISTER_IMM(&ilo
->cp
->builder
, GEN6_REG_BCS_SWCTRL
, swctrl
);
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
)
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
;
133 if (offset
% cpp
|| size
% cpp
)
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
);
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
, 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
);
196 unsigned width
, height
;
201 if (width
> gen6_blt_max_bytes_per_scanline
) {
202 /* less than INT16_MAX and dword-aligned */
204 height
= size
/ width
;
205 if (height
> gen6_blt_max_scanlines
)
206 height
= gen6_blt_max_scanlines
;
215 gen6_SRC_COPY_BLT(&ilo
->cp
->builder
, &dst
, &src
,
216 width
, height
, rop
, GEN6_BLT_MASK_8
, GEN6_BLT_MASK_8
);
218 dst
.offset
+= dst
.pitch
* height
;
219 src
.offset
+= src
.pitch
* height
;
220 size
-= width
* height
;
223 ilo_blitter_blt_end(blitter
, 0);
229 tex_clear_region(struct ilo_blitter
*blitter
,
230 struct ilo_texture
*dst_tex
, unsigned dst_level
,
231 const struct pipe_box
*dst_box
,
233 enum gen6_blt_mask value_mask
,
234 enum gen6_blt_mask write_mask
)
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
;
244 /* no W-tiling support */
245 if (dst_tex
->separate_s8
)
248 if (dst_tex
->layout
.bo_stride
> max_extent
)
251 if (dst_box
->width
* cpp
> gen6_blt_max_bytes_per_scanline
)
254 dst
.bo
= dst_tex
->bo
;
256 dst
.pitch
= dst_tex
->layout
.bo_stride
;
257 dst
.tiling
= dst_tex
->layout
.tiling
;
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
);
263 for (slice
= 0; slice
< dst_box
->depth
; slice
++) {
266 ilo_layout_get_slice_pos(&dst_tex
->layout
,
267 dst_level
, dst_box
->z
+ slice
, &x
, &y
);
269 dst
.x
= x
+ dst_box
->x
;
270 dst
.y
= y
+ dst_box
->y
;
272 if (dst
.x
+ dst_box
->width
> max_extent
||
273 dst
.y
+ dst_box
->height
> max_extent
)
276 gen6_XY_COLOR_BLT(&ilo
->cp
->builder
, &dst
, val
,
277 dst_box
->width
, dst_box
->height
, rop
, value_mask
, write_mask
);
280 ilo_blitter_blt_end(blitter
, swctrl
);
282 return (slice
== dst_box
->depth
);
286 tex_copy_region(struct ilo_blitter
*blitter
,
287 struct ilo_texture
*dst_tex
,
289 unsigned dst_x
, unsigned dst_y
, unsigned dst_z
,
290 struct ilo_texture
*src_tex
,
292 const struct pipe_box
*src_box
)
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
;
302 int cpp
, xscale
, slice
;
304 /* no W-tiling support */
305 if (dst_tex
->separate_s8
|| src_tex
->separate_s8
)
308 if (dst_tex
->layout
.bo_stride
> max_extent
||
309 src_tex
->layout
.bo_stride
> max_extent
)
312 cpp
= desc
->block
.bits
/ 8;
315 /* accommodate for larger cpp */
320 cpp
= (cpp
% 4 == 0) ? 4 : 2;
321 xscale
= (desc
->block
.bits
/ 8) / cpp
;
324 if (src_box
->width
* cpp
* xscale
> gen6_blt_max_bytes_per_scanline
)
329 mask
= GEN6_BLT_MASK_8
;
332 mask
= GEN6_BLT_MASK_16
;
335 mask
= GEN6_BLT_MASK_32
;
342 dst
.bo
= dst_tex
->bo
;
344 dst
.pitch
= dst_tex
->layout
.bo_stride
;
345 dst
.tiling
= dst_tex
->layout
.tiling
;
347 src
.bo
= src_tex
->bo
;
349 src
.pitch
= src_tex
->layout
.bo_stride
;
350 src
.tiling
= src_tex
->layout
.tiling
;
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
);
356 for (slice
= 0; slice
< src_box
->depth
; slice
++) {
357 unsigned dx
, dy
, sx
, sy
, width
, height
;
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
);
364 dst
.x
= (dx
+ dst_x
) * xscale
;
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
;
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
;
379 if (src
.x
+ width
> max_extent
|| src
.y
+ height
> max_extent
||
380 dst
.x
+ width
> max_extent
|| dst
.y
+ height
> max_extent
)
383 gen6_XY_SRC_COPY_BLT(&ilo
->cp
->builder
, &dst
, &src
,
384 width
, height
, rop
, mask
, mask
);
387 ilo_blitter_blt_end(blitter
, swctrl
);
389 return (slice
== src_box
->depth
);
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
)
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
);
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
;
411 assert(dst_level
== 0 && dst_y
== 0 && dst_z
== 0);
412 assert(src_level
== 0 &&
415 src_box
->height
== 1 &&
416 src_box
->depth
== 1);
418 success
= buf_copy_region(blitter
,
419 ilo_buffer(dst
), dst_offset
, ilo_buffer(src
), src_offset
, size
);
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
);
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
)
440 const int cpp
= util_format_get_blocksize(rt
->format
);
441 enum gen6_blt_mask mask
;
442 union util_color packed
;
445 if (!ilo_3d_pass_render_condition(blitter
->ilo
))
450 mask
= GEN6_BLT_MASK_8
;
453 mask
= GEN6_BLT_MASK_16
;
456 mask
= GEN6_BLT_MASK_32
;
463 if (util_format_is_pure_integer(rt
->format
) ||
464 util_format_is_compressed(rt
->format
))
467 ilo_blit_resolve_surface(blitter
->ilo
, rt
, ILO_TEXTURE_BLT_WRITE
);
469 util_pack_color(color
->f
, rt
->format
, &packed
);
471 if (rt
->texture
->target
== PIPE_BUFFER
) {
472 unsigned offset
, end
, size
;
474 assert(y
== 0 && height
== 1);
476 offset
= (rt
->u
.buf
.first_element
+ x
) * cpp
;
477 end
= (rt
->u
.buf
.last_element
+ 1) * cpp
;
480 if (offset
+ size
> end
)
483 success
= buf_clear_region(blitter
, ilo_buffer(rt
->texture
),
484 offset
, packed
.ui
[0], size
, mask
, mask
);
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
);
492 success
= tex_clear_region(blitter
, ilo_texture(rt
->texture
),
493 rt
->u
.tex
.level
, &box
, packed
.ui
[0], mask
, mask
);
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
)
507 enum gen6_blt_mask value_mask
, write_mask
;
511 if (!ilo_3d_pass_render_condition(blitter
->ilo
))
514 switch (zs
->format
) {
515 case PIPE_FORMAT_Z16_UNORM
:
516 if (!(clear_flags
& PIPE_CLEAR_DEPTH
))
519 value_mask
= GEN6_BLT_MASK_16
;
520 write_mask
= GEN6_BLT_MASK_16
;
522 case PIPE_FORMAT_Z32_FLOAT
:
523 if (!(clear_flags
& PIPE_CLEAR_DEPTH
))
526 value_mask
= GEN6_BLT_MASK_32
;
527 write_mask
= GEN6_BLT_MASK_32
;
529 case PIPE_FORMAT_Z24X8_UNORM
:
530 if (!(clear_flags
& PIPE_CLEAR_DEPTH
))
533 value_mask
= GEN6_BLT_MASK_32
;
534 write_mask
= GEN6_BLT_MASK_32_LO
;
536 case PIPE_FORMAT_Z24_UNORM_S8_UINT
:
537 if (!(clear_flags
& PIPE_CLEAR_DEPTHSTENCIL
))
540 value_mask
= GEN6_BLT_MASK_32
;
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
;
547 write_mask
= GEN6_BLT_MASK_32_HI
;
554 ilo_blit_resolve_surface(blitter
->ilo
, zs
, ILO_TEXTURE_BLT_WRITE
);
556 val
= util_pack_z_stencil(zs
->format
, depth
, stencil
);
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
);
561 assert(zs
->texture
->target
!= PIPE_BUFFER
);
563 return tex_clear_region(blitter
, ilo_texture(zs
->texture
),
564 zs
->u
.tex
.level
, &box
, val
, value_mask
, write_mask
);