2 * Copyright (c) 2017 Etnaviv Project
3 * Copyright (C) 2017 Zodiac Inflight Innovations
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
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 NON-INFRINGEMENT. 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 * Wladimir J. van der Laan <laanwj@gmail.com>
27 #include "etnaviv_blt.h"
29 #include "etnaviv_emit.h"
30 #include "etnaviv_clear_blit.h"
31 #include "etnaviv_context.h"
32 #include "etnaviv_emit.h"
33 #include "etnaviv_format.h"
34 #include "etnaviv_resource.h"
35 #include "etnaviv_surface.h"
36 #include "etnaviv_translate.h"
38 #include "util/u_math.h"
39 #include "pipe/p_defines.h"
40 #include "pipe/p_state.h"
41 #include "util/u_blitter.h"
42 #include "util/u_inlines.h"
43 #include "util/u_memory.h"
44 #include "util/u_surface.h"
46 #include "hw/common_3d.xml.h"
47 #include "hw/state_blt.xml.h"
48 #include "hw/common.xml.h"
53 etna_compatible_blt_format(enum pipe_format fmt
)
55 /* YUYV and UYVY are blocksize 4, but 2 bytes per pixel */
56 if (fmt
== PIPE_FORMAT_YUYV
|| fmt
== PIPE_FORMAT_UYVY
)
57 return BLT_FORMAT_R8G8
;
59 switch (util_format_get_blocksize(fmt
)) {
60 case 1: return BLT_FORMAT_R8
;
61 case 2: return BLT_FORMAT_R8G8
;
62 case 4: return BLT_FORMAT_A8R8G8B8
;
63 case 8: return BLT_FORMAT_A16R16G16B16
;
64 default: return ETNA_NO_MATCH
;
68 static inline uint32_t
69 blt_compute_stride_bits(const struct blt_imginfo
*img
)
71 return VIVS_BLT_DEST_STRIDE_TILING(img
->tiling
== ETNA_LAYOUT_LINEAR
? 0 : 3) | /* 1/3? */
72 VIVS_BLT_DEST_STRIDE_FORMAT(img
->format
) |
73 VIVS_BLT_DEST_STRIDE_STRIDE(img
->stride
);
76 static inline uint32_t
77 blt_compute_img_config_bits(const struct blt_imginfo
*img
, bool for_dest
)
79 uint32_t tiling_bits
= 0;
80 if (img
->tiling
== ETNA_LAYOUT_SUPER_TILED
) {
81 tiling_bits
|= for_dest
? BLT_IMAGE_CONFIG_TO_SUPER_TILED
: BLT_IMAGE_CONFIG_FROM_SUPER_TILED
;
84 return BLT_IMAGE_CONFIG_TS_MODE(img
->ts_mode
) |
85 COND(img
->use_ts
, BLT_IMAGE_CONFIG_TS
) |
86 COND(img
->use_ts
&& img
->ts_compress_fmt
>= 0, BLT_IMAGE_CONFIG_COMPRESSION
) |
87 BLT_IMAGE_CONFIG_COMPRESSION_FORMAT(img
->ts_compress_fmt
) |
88 COND(for_dest
, BLT_IMAGE_CONFIG_UNK22
) |
89 BLT_IMAGE_CONFIG_SWIZ_R(0) | /* not used? */
90 BLT_IMAGE_CONFIG_SWIZ_G(1) |
91 BLT_IMAGE_CONFIG_SWIZ_B(2) |
92 BLT_IMAGE_CONFIG_SWIZ_A(3) |
96 static inline uint32_t
97 blt_compute_swizzle_bits(const struct blt_imginfo
*img
, bool for_dest
)
99 uint32_t swiz
= VIVS_BLT_SWIZZLE_SRC_R(img
->swizzle
[0]) |
100 VIVS_BLT_SWIZZLE_SRC_G(img
->swizzle
[1]) |
101 VIVS_BLT_SWIZZLE_SRC_B(img
->swizzle
[2]) |
102 VIVS_BLT_SWIZZLE_SRC_A(img
->swizzle
[3]);
103 return for_dest
? (swiz
<< 12) : swiz
;
106 /* Clear (part of) an image */
108 emit_blt_clearimage(struct etna_cmd_stream
*stream
, const struct blt_clear_op
*op
)
110 etna_cmd_stream_reserve(stream
, 64*2); /* Make sure BLT op doesn't get broken up */
112 etna_set_state(stream
, VIVS_BLT_ENABLE
, 0x00000001);
113 assert(op
->dest
.bpp
);
114 etna_set_state(stream
, VIVS_BLT_CONFIG
, VIVS_BLT_CONFIG_CLEAR_BPP(op
->dest
.bpp
-1));
115 /* NB: blob sets format to 1 in dest/src config for clear, and the swizzle to RRRR.
116 * does this matter? It seems to just be ignored. But if we run into issues with BLT
117 * behaving stragely, it's something to look at.
119 etna_set_state(stream
, VIVS_BLT_DEST_STRIDE
, blt_compute_stride_bits(&op
->dest
));
120 etna_set_state(stream
, VIVS_BLT_DEST_CONFIG
, blt_compute_img_config_bits(&op
->dest
, true));
121 etna_set_state_reloc(stream
, VIVS_BLT_DEST_ADDR
, &op
->dest
.addr
);
122 etna_set_state(stream
, VIVS_BLT_SRC_STRIDE
, blt_compute_stride_bits(&op
->dest
));
123 etna_set_state(stream
, VIVS_BLT_SRC_CONFIG
, blt_compute_img_config_bits(&op
->dest
, false));
124 etna_set_state_reloc(stream
, VIVS_BLT_SRC_ADDR
, &op
->dest
.addr
);
125 etna_set_state(stream
, VIVS_BLT_DEST_POS
, VIVS_BLT_DEST_POS_X(op
->rect_x
) | VIVS_BLT_DEST_POS_Y(op
->rect_y
));
126 etna_set_state(stream
, VIVS_BLT_IMAGE_SIZE
, VIVS_BLT_IMAGE_SIZE_WIDTH(op
->rect_w
) | VIVS_BLT_IMAGE_SIZE_HEIGHT(op
->rect_h
));
127 etna_set_state(stream
, VIVS_BLT_CLEAR_COLOR0
, op
->clear_value
[0]);
128 etna_set_state(stream
, VIVS_BLT_CLEAR_COLOR1
, op
->clear_value
[1]);
129 etna_set_state(stream
, VIVS_BLT_CLEAR_BITS0
, op
->clear_bits
[0]);
130 etna_set_state(stream
, VIVS_BLT_CLEAR_BITS1
, op
->clear_bits
[1]);
131 if (op
->dest
.use_ts
) {
132 etna_set_state_reloc(stream
, VIVS_BLT_DEST_TS
, &op
->dest
.ts_addr
);
133 etna_set_state_reloc(stream
, VIVS_BLT_SRC_TS
, &op
->dest
.ts_addr
);
134 etna_set_state(stream
, VIVS_BLT_DEST_TS_CLEAR_VALUE0
, op
->dest
.ts_clear_value
[0]);
135 etna_set_state(stream
, VIVS_BLT_DEST_TS_CLEAR_VALUE1
, op
->dest
.ts_clear_value
[1]);
136 etna_set_state(stream
, VIVS_BLT_SRC_TS_CLEAR_VALUE0
, op
->dest
.ts_clear_value
[0]);
137 etna_set_state(stream
, VIVS_BLT_SRC_TS_CLEAR_VALUE1
, op
->dest
.ts_clear_value
[1]);
139 etna_set_state(stream
, VIVS_BLT_SET_COMMAND
, 0x00000003);
140 etna_set_state(stream
, VIVS_BLT_COMMAND
, VIVS_BLT_COMMAND_COMMAND_CLEAR_IMAGE
);
141 etna_set_state(stream
, VIVS_BLT_SET_COMMAND
, 0x00000003);
142 etna_set_state(stream
, VIVS_BLT_ENABLE
, 0x00000000);
145 /* Copy (a subset of) an image to another image. */
147 emit_blt_copyimage(struct etna_cmd_stream
*stream
, const struct blt_imgcopy_op
*op
)
149 etna_cmd_stream_reserve(stream
, 64*2); /* Never allow BLT sequences to be broken up */
151 etna_set_state(stream
, VIVS_BLT_ENABLE
, 0x00000001);
152 etna_set_state(stream
, VIVS_BLT_CONFIG
,
153 VIVS_BLT_CONFIG_SRC_ENDIAN(op
->src
.endian_mode
) |
154 VIVS_BLT_CONFIG_DEST_ENDIAN(op
->dest
.endian_mode
));
155 etna_set_state(stream
, VIVS_BLT_SRC_STRIDE
, blt_compute_stride_bits(&op
->src
));
156 etna_set_state(stream
, VIVS_BLT_SRC_CONFIG
, blt_compute_img_config_bits(&op
->src
, false));
157 etna_set_state(stream
, VIVS_BLT_SWIZZLE
,
158 blt_compute_swizzle_bits(&op
->src
, false) |
159 blt_compute_swizzle_bits(&op
->dest
, true));
160 etna_set_state(stream
, VIVS_BLT_UNK140A0
, 0x00040004);
161 etna_set_state(stream
, VIVS_BLT_UNK1409C
, 0x00400040);
162 if (op
->src
.use_ts
) {
163 etna_set_state_reloc(stream
, VIVS_BLT_SRC_TS
, &op
->src
.ts_addr
);
164 etna_set_state(stream
, VIVS_BLT_SRC_TS_CLEAR_VALUE0
, op
->src
.ts_clear_value
[0]);
165 etna_set_state(stream
, VIVS_BLT_SRC_TS_CLEAR_VALUE1
, op
->src
.ts_clear_value
[1]);
167 etna_set_state_reloc(stream
, VIVS_BLT_SRC_ADDR
, &op
->src
.addr
);
168 etna_set_state(stream
, VIVS_BLT_DEST_STRIDE
, blt_compute_stride_bits(&op
->dest
));
169 etna_set_state(stream
, VIVS_BLT_DEST_CONFIG
,
170 blt_compute_img_config_bits(&op
->dest
, true) |
171 COND(op
->flip_y
, BLT_IMAGE_CONFIG_FLIP_Y
));
172 assert(!op
->dest
.use_ts
); /* Dest TS path doesn't work for copies? */
173 if (op
->dest
.use_ts
) {
174 etna_set_state_reloc(stream
, VIVS_BLT_DEST_TS
, &op
->dest
.ts_addr
);
175 etna_set_state(stream
, VIVS_BLT_DEST_TS_CLEAR_VALUE0
, op
->dest
.ts_clear_value
[0]);
176 etna_set_state(stream
, VIVS_BLT_DEST_TS_CLEAR_VALUE1
, op
->dest
.ts_clear_value
[1]);
178 etna_set_state_reloc(stream
, VIVS_BLT_DEST_ADDR
, &op
->dest
.addr
);
179 etna_set_state(stream
, VIVS_BLT_SRC_POS
, VIVS_BLT_DEST_POS_X(op
->src_x
) | VIVS_BLT_DEST_POS_Y(op
->src_y
));
180 etna_set_state(stream
, VIVS_BLT_DEST_POS
, VIVS_BLT_DEST_POS_X(op
->dest_x
) | VIVS_BLT_DEST_POS_Y(op
->dest_y
));
181 etna_set_state(stream
, VIVS_BLT_IMAGE_SIZE
, VIVS_BLT_IMAGE_SIZE_WIDTH(op
->rect_w
) | VIVS_BLT_IMAGE_SIZE_HEIGHT(op
->rect_h
));
182 etna_set_state(stream
, VIVS_BLT_UNK14058
, 0xffffffff);
183 etna_set_state(stream
, VIVS_BLT_UNK1405C
, 0xffffffff);
184 etna_set_state(stream
, VIVS_BLT_SET_COMMAND
, 0x00000003);
185 etna_set_state(stream
, VIVS_BLT_COMMAND
, VIVS_BLT_COMMAND_COMMAND_COPY_IMAGE
);
186 etna_set_state(stream
, VIVS_BLT_SET_COMMAND
, 0x00000003);
187 etna_set_state(stream
, VIVS_BLT_ENABLE
, 0x00000000);
190 /* Emit in-place resolve using BLT. */
192 emit_blt_inplace(struct etna_cmd_stream
*stream
, const struct blt_inplace_op
*op
)
194 assert(op
->bpp
> 0 && util_is_power_of_two_nonzero(op
->bpp
));
195 etna_cmd_stream_reserve(stream
, 64*2); /* Never allow BLT sequences to be broken up */
196 etna_set_state(stream
, VIVS_BLT_ENABLE
, 0x00000001);
197 etna_set_state(stream
, VIVS_BLT_CONFIG
,
198 VIVS_BLT_CONFIG_INPLACE_TS_MODE(op
->ts_mode
) |
199 VIVS_BLT_CONFIG_INPLACE_BOTH
|
200 (util_logbase2(op
->bpp
) << VIVS_BLT_CONFIG_INPLACE_BPP__SHIFT
));
201 etna_set_state(stream
, VIVS_BLT_DEST_TS_CLEAR_VALUE0
, op
->ts_clear_value
[0]);
202 etna_set_state(stream
, VIVS_BLT_DEST_TS_CLEAR_VALUE1
, op
->ts_clear_value
[1]);
203 etna_set_state_reloc(stream
, VIVS_BLT_DEST_ADDR
, &op
->addr
);
204 etna_set_state_reloc(stream
, VIVS_BLT_DEST_TS
, &op
->ts_addr
);
205 etna_set_state(stream
, 0x14068, op
->num_tiles
);
206 etna_set_state(stream
, VIVS_BLT_SET_COMMAND
, 0x00000003);
207 etna_set_state(stream
, VIVS_BLT_COMMAND
, 0x00000004);
208 etna_set_state(stream
, VIVS_BLT_SET_COMMAND
, 0x00000003);
209 etna_set_state(stream
, VIVS_BLT_ENABLE
, 0x00000000);
213 etna_blit_clear_color_blt(struct pipe_context
*pctx
, struct pipe_surface
*dst
,
214 const union pipe_color_union
*color
)
216 struct etna_context
*ctx
= etna_context(pctx
);
217 struct etna_surface
*surf
= etna_surface(dst
);
218 uint32_t new_clear_value
= etna_clear_blit_pack_rgba(surf
->base
.format
, color
->f
);
220 struct etna_resource
*res
= etna_resource(surf
->base
.texture
);
221 struct blt_clear_op clr
= {};
222 clr
.dest
.addr
.bo
= res
->bo
;
223 clr
.dest
.addr
.offset
= surf
->surf
.offset
;
224 clr
.dest
.addr
.flags
= ETNA_RELOC_WRITE
;
225 clr
.dest
.bpp
= util_format_get_blocksize(surf
->base
.format
);
226 clr
.dest
.stride
= surf
->surf
.stride
;
227 clr
.dest
.tiling
= res
->layout
;
229 if (surf
->surf
.ts_size
) {
231 clr
.dest
.ts_addr
.bo
= res
->ts_bo
;
232 clr
.dest
.ts_addr
.offset
= 0;
233 clr
.dest
.ts_addr
.flags
= ETNA_RELOC_WRITE
;
234 clr
.dest
.ts_clear_value
[0] = new_clear_value
;
235 clr
.dest
.ts_clear_value
[1] = new_clear_value
;
236 clr
.dest
.ts_mode
= surf
->level
->ts_mode
;
237 clr
.dest
.ts_compress_fmt
= surf
->level
->ts_compress_fmt
;
240 clr
.clear_value
[0] = new_clear_value
;
241 clr
.clear_value
[1] = new_clear_value
;
242 clr
.clear_bits
[0] = 0xffffffff; /* TODO: Might want to clear only specific channels? */
243 clr
.clear_bits
[1] = 0xffffffff;
244 clr
.rect_x
= 0; /* What about scissors? */
246 clr
.rect_w
= surf
->surf
.width
;
247 clr
.rect_h
= surf
->surf
.height
;
249 emit_blt_clearimage(ctx
->stream
, &clr
);
251 /* This made the TS valid */
252 if (surf
->surf
.ts_size
) {
253 ctx
->framebuffer
.TS_COLOR_CLEAR_VALUE
= new_clear_value
;
254 surf
->level
->ts_valid
= true;
257 surf
->level
->clear_value
= new_clear_value
;
258 resource_written(ctx
, surf
->base
.texture
);
259 etna_resource(surf
->base
.texture
)->seqno
++;
263 etna_blit_clear_zs_blt(struct pipe_context
*pctx
, struct pipe_surface
*dst
,
264 unsigned buffers
, double depth
, unsigned stencil
)
266 struct etna_context
*ctx
= etna_context(pctx
);
267 struct etna_surface
*surf
= etna_surface(dst
);
268 uint32_t new_clear_value
= translate_clear_depth_stencil(surf
->base
.format
, depth
, stencil
);
269 uint32_t new_clear_bits
= 0, clear_bits_depth
, clear_bits_stencil
;
271 /* Get the channels to clear */
272 switch (surf
->base
.format
) {
273 case PIPE_FORMAT_Z16_UNORM
:
274 case PIPE_FORMAT_X8Z24_UNORM
:
275 clear_bits_depth
= 0xffffffff;
276 clear_bits_stencil
= 0x00000000;
278 case PIPE_FORMAT_S8_UINT_Z24_UNORM
:
279 clear_bits_depth
= 0xffffff00;
280 clear_bits_stencil
= 0x000000ff;
283 clear_bits_depth
= clear_bits_stencil
= 0xffffffff;
287 if (buffers
& PIPE_CLEAR_DEPTH
)
288 new_clear_bits
|= clear_bits_depth
;
289 if (buffers
& PIPE_CLEAR_STENCIL
)
290 new_clear_bits
|= clear_bits_stencil
;
292 /* TODO unduplicate this */
293 struct etna_resource
*res
= etna_resource(surf
->base
.texture
);
294 struct blt_clear_op clr
= {};
295 clr
.dest
.addr
.bo
= res
->bo
;
296 clr
.dest
.addr
.offset
= surf
->surf
.offset
;
297 clr
.dest
.addr
.flags
= ETNA_RELOC_WRITE
;
298 clr
.dest
.bpp
= util_format_get_blocksize(surf
->base
.format
);
299 clr
.dest
.stride
= surf
->surf
.stride
;
300 clr
.dest
.tiling
= res
->layout
;
302 if (surf
->surf
.ts_size
) {
304 clr
.dest
.ts_addr
.bo
= res
->ts_bo
;
305 clr
.dest
.ts_addr
.offset
= 0;
306 clr
.dest
.ts_addr
.flags
= ETNA_RELOC_WRITE
;
307 clr
.dest
.ts_clear_value
[0] = new_clear_value
;
308 clr
.dest
.ts_clear_value
[1] = new_clear_value
;
309 clr
.dest
.ts_mode
= surf
->level
->ts_mode
;
310 clr
.dest
.ts_compress_fmt
= surf
->level
->ts_compress_fmt
;
313 clr
.clear_value
[0] = new_clear_value
;
314 clr
.clear_value
[1] = new_clear_value
;
315 clr
.clear_bits
[0] = new_clear_bits
;
316 clr
.clear_bits
[1] = new_clear_bits
;
317 clr
.rect_x
= 0; /* What about scissors? */
319 clr
.rect_w
= surf
->surf
.width
;
320 clr
.rect_h
= surf
->surf
.height
;
322 emit_blt_clearimage(ctx
->stream
, &clr
);
324 /* This made the TS valid */
325 if (surf
->surf
.ts_size
) {
326 ctx
->framebuffer
.TS_DEPTH_CLEAR_VALUE
= new_clear_value
;
327 surf
->level
->ts_valid
= true;
330 surf
->level
->clear_value
= new_clear_value
;
331 resource_written(ctx
, surf
->base
.texture
);
332 etna_resource(surf
->base
.texture
)->seqno
++;
336 etna_clear_blt(struct pipe_context
*pctx
, unsigned buffers
,
337 const union pipe_color_union
*color
, double depth
, unsigned stencil
)
339 struct etna_context
*ctx
= etna_context(pctx
);
340 mtx_lock(&ctx
->lock
);
342 etna_set_state(ctx
->stream
, VIVS_GL_FLUSH_CACHE
, 0x00000c23);
343 etna_set_state(ctx
->stream
, VIVS_TS_FLUSH_CACHE
, VIVS_TS_FLUSH_CACHE_FLUSH
);
345 if (buffers
& PIPE_CLEAR_COLOR
) {
346 for (int idx
= 0; idx
< ctx
->framebuffer_s
.nr_cbufs
; ++idx
) {
347 etna_blit_clear_color_blt(pctx
, ctx
->framebuffer_s
.cbufs
[idx
],
352 if ((buffers
& PIPE_CLEAR_DEPTHSTENCIL
) && ctx
->framebuffer_s
.zsbuf
!= NULL
)
353 etna_blit_clear_zs_blt(pctx
, ctx
->framebuffer_s
.zsbuf
, buffers
, depth
, stencil
);
355 etna_stall(ctx
->stream
, SYNC_RECIPIENT_RA
, SYNC_RECIPIENT_BLT
);
357 if ((buffers
& PIPE_CLEAR_COLOR
) && (buffers
& PIPE_CLEAR_DEPTH
))
358 etna_set_state(ctx
->stream
, VIVS_GL_FLUSH_CACHE
, 0x00000c23);
360 etna_set_state(ctx
->stream
, VIVS_GL_FLUSH_CACHE
, 0x00000002);
361 mtx_unlock(&ctx
->lock
);
365 etna_try_blt_blit(struct pipe_context
*pctx
,
366 const struct pipe_blit_info
*blit_info
)
368 struct etna_context
*ctx
= etna_context(pctx
);
369 struct etna_resource
*src
= etna_resource(blit_info
->src
.resource
);
370 struct etna_resource
*dst
= etna_resource(blit_info
->dst
.resource
);
371 int msaa_xscale
= 1, msaa_yscale
= 1;
373 /* Ensure that the level is valid */
374 assert(blit_info
->src
.level
<= src
->base
.last_level
);
375 assert(blit_info
->dst
.level
<= dst
->base
.last_level
);
377 if (!translate_samples_to_xyscale(src
->base
.nr_samples
, &msaa_xscale
, &msaa_yscale
, NULL
))
380 /* The width/height are in pixels; they do not change as a result of
381 * multi-sampling. So, when blitting from a 4x multisampled surface
382 * to a non-multisampled surface, the width and height will be
383 * identical. As we do not support scaling, reject different sizes.
384 * TODO: could handle 2x downsample here with emit_blt_genmipmaps */
385 if (blit_info
->dst
.box
.width
!= blit_info
->src
.box
.width
||
386 blit_info
->dst
.box
.height
!= abs(blit_info
->src
.box
.height
)) { /* allow y flip for glTexImage2D */
387 DBG("scaling requested: source %dx%d destination %dx%d",
388 blit_info
->src
.box
.width
, blit_info
->src
.box
.height
,
389 blit_info
->dst
.box
.width
, blit_info
->dst
.box
.height
);
393 /* No masks - not sure if BLT can copy individual channels */
394 unsigned mask
= util_format_get_mask(blit_info
->dst
.format
);
395 if ((blit_info
->mask
& mask
) != mask
) {
396 DBG("sub-mask requested: 0x%02x vs format mask 0x%02x", blit_info
->mask
, mask
);
400 /* Only support same format (used tiling/detiling) blits for now.
401 * TODO: figure out which different-format blits are possible and test them
402 * - need to use correct swizzle
403 * - set sRGB bits correctly
404 * - avoid trying to convert between float/int formats?
406 if (blit_info
->src
.format
!= blit_info
->dst
.format
)
409 uint32_t format
= etna_compatible_blt_format(blit_info
->dst
.format
);
410 if (format
== ETNA_NO_MATCH
)
413 if (blit_info
->scissor_enable
||
414 blit_info
->dst
.box
.depth
!= blit_info
->src
.box
.depth
||
415 blit_info
->dst
.box
.depth
!= 1) {
419 struct etna_resource_level
*src_lev
= &src
->levels
[blit_info
->src
.level
];
420 struct etna_resource_level
*dst_lev
= &dst
->levels
[blit_info
->dst
.level
];
422 /* if we asked for in-place resolve, return immediately if ts isn't valid
423 * do this check separately because it applies when compression is used, but
424 * we can't use inplace resolve path with compression
427 assert(!memcmp(&blit_info
->src
, &blit_info
->dst
, sizeof(blit_info
->src
)));
428 if (!src_lev
->ts_size
|| !src_lev
->ts_valid
) /* No TS, no worries */
432 mtx_lock(&ctx
->lock
);
433 /* Kick off BLT here */
434 if (src
== dst
&& src_lev
->ts_compress_fmt
< 0) {
435 /* Resolve-in-place */
436 struct blt_inplace_op op
= {};
438 op
.addr
.bo
= src
->bo
;
439 op
.addr
.offset
= src_lev
->offset
+ blit_info
->src
.box
.z
* src_lev
->layer_stride
;
440 op
.addr
.flags
= ETNA_RELOC_READ
| ETNA_RELOC_WRITE
;
441 op
.ts_addr
.bo
= src
->ts_bo
;
442 op
.ts_addr
.offset
= src_lev
->ts_offset
+ blit_info
->src
.box
.z
* src_lev
->ts_layer_stride
;
443 op
.ts_addr
.flags
= ETNA_RELOC_READ
;
444 op
.ts_clear_value
[0] = src_lev
->clear_value
;
445 op
.ts_clear_value
[1] = src_lev
->clear_value
;
446 op
.ts_mode
= src_lev
->ts_mode
;
447 op
.num_tiles
= DIV_ROUND_UP(src_lev
->size
, src_lev
->ts_mode
? 256 : 128);
448 op
.bpp
= util_format_get_blocksize(src
->base
.format
);
450 etna_set_state(ctx
->stream
, VIVS_GL_FLUSH_CACHE
, 0x00000c23);
451 etna_set_state(ctx
->stream
, VIVS_TS_FLUSH_CACHE
, 0x00000001);
452 emit_blt_inplace(ctx
->stream
, &op
);
455 struct blt_imgcopy_op op
= {};
457 op
.src
.addr
.bo
= src
->bo
;
458 op
.src
.addr
.offset
= src_lev
->offset
+ blit_info
->src
.box
.z
* src_lev
->layer_stride
;
459 op
.src
.addr
.flags
= ETNA_RELOC_READ
;
460 op
.src
.format
= format
;
461 op
.src
.stride
= src_lev
->stride
;
462 op
.src
.tiling
= src
->layout
;
463 for (unsigned x
=0; x
<4; ++x
)
464 op
.src
.swizzle
[x
] = x
;
466 if (src_lev
->ts_size
&& src_lev
->ts_valid
) {
468 op
.src
.ts_addr
.bo
= src
->ts_bo
;
469 op
.src
.ts_addr
.offset
= src_lev
->ts_offset
+ blit_info
->src
.box
.z
* src_lev
->ts_layer_stride
;
470 op
.src
.ts_addr
.flags
= ETNA_RELOC_READ
;
471 op
.src
.ts_clear_value
[0] = src_lev
->clear_value
;
472 op
.src
.ts_clear_value
[1] = src_lev
->clear_value
;
473 op
.src
.ts_mode
= src_lev
->ts_mode
;
474 op
.src
.ts_compress_fmt
= src_lev
->ts_compress_fmt
;
477 op
.dest
.addr
.bo
= dst
->bo
;
478 op
.dest
.addr
.offset
= dst_lev
->offset
+ blit_info
->dst
.box
.z
* dst_lev
->layer_stride
;
479 op
.dest
.addr
.flags
= ETNA_RELOC_WRITE
;
480 op
.dest
.format
= format
;
481 op
.dest
.stride
= dst_lev
->stride
;
482 op
.dest
.tiling
= dst
->layout
;
483 for (unsigned x
=0; x
<4; ++x
)
484 op
.dest
.swizzle
[x
] = x
;
486 op
.dest_x
= blit_info
->dst
.box
.x
;
487 op
.dest_y
= blit_info
->dst
.box
.y
;
488 op
.src_x
= blit_info
->src
.box
.x
;
489 op
.src_y
= blit_info
->src
.box
.y
;
490 op
.rect_w
= blit_info
->dst
.box
.width
;
491 op
.rect_h
= blit_info
->dst
.box
.height
;
493 if (blit_info
->src
.box
.height
< 0) { /* flipped? fix up base y */
495 op
.src_y
+= blit_info
->src
.box
.height
;
498 assert(op
.src_x
< src_lev
->padded_width
);
499 assert(op
.src_y
< src_lev
->padded_height
);
500 assert((op
.src_x
+ op
.rect_w
) <= src_lev
->padded_width
);
501 assert((op
.src_y
+ op
.rect_h
) <= src_lev
->padded_height
);
502 assert(op
.dest_x
< dst_lev
->padded_width
);
503 assert(op
.dest_y
< dst_lev
->padded_height
);
504 assert((op
.dest_x
+ op
.rect_w
) <= dst_lev
->padded_width
);
505 assert((op
.dest_y
+ op
.rect_h
) <= dst_lev
->padded_height
);
507 etna_set_state(ctx
->stream
, VIVS_GL_FLUSH_CACHE
, 0x00000c23);
508 etna_set_state(ctx
->stream
, VIVS_TS_FLUSH_CACHE
, 0x00000001);
509 emit_blt_copyimage(ctx
->stream
, &op
);
512 /* Make FE wait for BLT, in case we want to do something with the image next.
513 * This probably shouldn't be here, and depend on what is done with the resource.
515 etna_stall(ctx
->stream
, SYNC_RECIPIENT_FE
, SYNC_RECIPIENT_BLT
);
516 etna_set_state(ctx
->stream
, VIVS_GL_FLUSH_CACHE
, 0x00000c23);
518 resource_read(ctx
, &src
->base
);
519 resource_written(ctx
, &dst
->base
);
522 dst_lev
->ts_valid
= false;
523 mtx_unlock(&ctx
->lock
);
529 etna_blit_blt(struct pipe_context
*pctx
, const struct pipe_blit_info
*blit_info
)
531 struct etna_context
*ctx
= etna_context(pctx
);
532 struct pipe_blit_info info
= *blit_info
;
534 if (info
.src
.resource
->nr_samples
> 1 &&
535 info
.dst
.resource
->nr_samples
<= 1 &&
536 !util_format_is_depth_or_stencil(info
.src
.resource
->format
) &&
537 !util_format_is_pure_integer(info
.src
.resource
->format
)) {
538 DBG("color resolve unimplemented");
542 if (etna_try_blt_blit(pctx
, blit_info
))
545 if (util_try_blit_via_copy_region(pctx
, blit_info
))
548 if (info
.mask
& PIPE_MASK_S
) {
549 DBG("cannot blit stencil, skipping");
550 info
.mask
&= ~PIPE_MASK_S
;
553 if (!util_blitter_is_blit_supported(ctx
->blitter
, &info
)) {
554 DBG("blit unsupported %s -> %s",
555 util_format_short_name(info
.src
.resource
->format
),
556 util_format_short_name(info
.dst
.resource
->format
));
560 etna_blit_save_state(ctx
);
561 util_blitter_blit(ctx
->blitter
, &info
);
565 etna_clear_blit_blt_init(struct pipe_context
*pctx
)
567 DBG("etnaviv: Using BLT blit engine");
568 pctx
->clear
= etna_clear_blt
;
569 pctx
->blit
= etna_blit_blt
;