1/* 2 * Copyright (c) 2017 Etnaviv Project 3 * Copyright (C) 2017 Zodiac Inflight Innovations 4 * 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: 11 * 12 * The above copyright notice and this permission notice (including the 13 * next paragraph) shall be included in all copies or substantial portions 14 * of the Software. 15 * 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. 23 * 24 * Authors: 25 * Wladimir J. van der Laan <laanwj@gmail.com> 26 */ 27#include "etnaviv_blt.h" 28 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" 37 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" 45 46#include "hw/common_3d.xml.h" 47#include "hw/state_blt.xml.h" 48#include "hw/common.xml.h" 49 50#include <assert.h> 51 52static uint32_t 53etna_compatible_blt_format(enum pipe_format fmt) 54{ 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; 58 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; 65 } 66} 67 68static inline uint32_t 69blt_compute_stride_bits(const struct blt_imginfo *img) 70{ 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); 74} 75 76static inline uint32_t 77blt_compute_img_config_bits(const struct blt_imginfo *img, bool for_dest) 78{ 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; 82 } 83 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) | 93 tiling_bits; 94} 95 96static inline uint32_t 97blt_compute_swizzle_bits(const struct blt_imginfo *img, bool for_dest) 98{ 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; 104} 105 106/* Clear (part of) an image */ 107static void 108emit_blt_clearimage(struct etna_cmd_stream *stream, const struct blt_clear_op *op) 109{ 110 etna_cmd_stream_reserve(stream, 64*2); /* Make sure BLT op doesn't get broken up */ 111 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. 118 */ 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]); 138 } 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); 143} 144 145/* Copy (a subset of) an image to another image. */ 146static void 147emit_blt_copyimage(struct etna_cmd_stream *stream, const struct blt_imgcopy_op *op) 148{ 149 etna_cmd_stream_reserve(stream, 64*2); /* Never allow BLT sequences to be broken up */ 150 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]); 166 } 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]); 177 } 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); 188} 189 190/* Emit in-place resolve using BLT. */ 191static void 192emit_blt_inplace(struct etna_cmd_stream *stream, const struct blt_inplace_op *op) 193{ 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); 210} 211 212static void 213etna_blit_clear_color_blt(struct pipe_context *pctx, struct pipe_surface *dst, 214 const union pipe_color_union *color) 215{ 216 struct etna_context *ctx = etna_context(pctx); 217 struct etna_surface *surf = etna_surface(dst); 218 uint64_t new_clear_value = etna_clear_blit_pack_rgba(surf->base.format, color); 219 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; 228 229 if (surf->surf.ts_size) { 230 clr.dest.use_ts = 1; 231 clr.dest.ts_addr.bo = res->ts_bo; 232 clr.dest.ts_addr.offset = surf->level->ts_offset; 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 >> 32; 236 clr.dest.ts_mode = surf->level->ts_mode; 237 clr.dest.ts_compress_fmt = surf->level->ts_compress_fmt; 238 } 239 240 clr.clear_value[0] = new_clear_value; 241 clr.clear_value[1] = new_clear_value >> 32; 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? */ 245 clr.rect_y = 0; 246 clr.rect_w = surf->surf.width; 247 clr.rect_h = surf->surf.height; 248 249 emit_blt_clearimage(ctx->stream, &clr); 250 251 /* This made the TS valid */ 252 if (surf->surf.ts_size) { 253 ctx->framebuffer.TS_COLOR_CLEAR_VALUE = new_clear_value; 254 ctx->framebuffer.TS_COLOR_CLEAR_VALUE_EXT = new_clear_value >> 32; 255 surf->level->ts_valid = true; 256 ctx->dirty |= ETNA_DIRTY_TS | ETNA_DIRTY_DERIVE_TS; 257 } 258 259 surf->level->clear_value = new_clear_value; 260 resource_written(ctx, surf->base.texture); 261 etna_resource(surf->base.texture)->seqno++; 262} 263 264static void 265etna_blit_clear_zs_blt(struct pipe_context *pctx, struct pipe_surface *dst, 266 unsigned buffers, double depth, unsigned stencil) 267{ 268 struct etna_context *ctx = etna_context(pctx); 269 struct etna_surface *surf = etna_surface(dst); 270 uint32_t new_clear_value = translate_clear_depth_stencil(surf->base.format, depth, stencil); 271 uint32_t new_clear_bits = 0, clear_bits_depth, clear_bits_stencil; 272 273 /* Get the channels to clear */ 274 switch (surf->base.format) { 275 case PIPE_FORMAT_Z16_UNORM: 276 case PIPE_FORMAT_X8Z24_UNORM: 277 clear_bits_depth = 0xffffffff; 278 clear_bits_stencil = 0x00000000; 279 break; 280 case PIPE_FORMAT_S8_UINT_Z24_UNORM: 281 clear_bits_depth = 0xffffff00; 282 clear_bits_stencil = 0x000000ff; 283 break; 284 default: 285 clear_bits_depth = clear_bits_stencil = 0xffffffff; 286 break; 287 } 288 289 if (buffers & PIPE_CLEAR_DEPTH) 290 new_clear_bits |= clear_bits_depth; 291 if (buffers & PIPE_CLEAR_STENCIL) 292 new_clear_bits |= clear_bits_stencil; 293 294 /* if all bits are cleared, update TS clear value */ 295 if (new_clear_bits == 0xffffffff) 296 surf->level->clear_value = new_clear_value; 297 298 /* TODO unduplicate this */ 299 struct etna_resource *res = etna_resource(surf->base.texture); 300 struct blt_clear_op clr = {}; 301 clr.dest.addr.bo = res->bo; 302 clr.dest.addr.offset = surf->surf.offset; 303 clr.dest.addr.flags = ETNA_RELOC_WRITE; 304 clr.dest.bpp = util_format_get_blocksize(surf->base.format); 305 clr.dest.stride = surf->surf.stride; 306 clr.dest.tiling = res->layout; 307 308 if (surf->surf.ts_size) { 309 clr.dest.use_ts = 1; 310 clr.dest.ts_addr.bo = res->ts_bo; 311 clr.dest.ts_addr.offset = surf->level->ts_offset; 312 clr.dest.ts_addr.flags = ETNA_RELOC_WRITE; 313 clr.dest.ts_clear_value[0] = surf->level->clear_value; 314 clr.dest.ts_clear_value[1] = surf->level->clear_value; 315 clr.dest.ts_mode = surf->level->ts_mode; 316 clr.dest.ts_compress_fmt = surf->level->ts_compress_fmt; 317 } 318 319 clr.clear_value[0] = new_clear_value; 320 clr.clear_value[1] = new_clear_value; 321 clr.clear_bits[0] = new_clear_bits; 322 clr.clear_bits[1] = new_clear_bits; 323 clr.rect_x = 0; /* What about scissors? */ 324 clr.rect_y = 0; 325 clr.rect_w = surf->surf.width; 326 clr.rect_h = surf->surf.height; 327 328 emit_blt_clearimage(ctx->stream, &clr); 329 330 /* This made the TS valid */ 331 if (surf->surf.ts_size) { 332 ctx->framebuffer.TS_DEPTH_CLEAR_VALUE = surf->level->clear_value; 333 surf->level->ts_valid = true; 334 ctx->dirty |= ETNA_DIRTY_TS | ETNA_DIRTY_DERIVE_TS; 335 } 336 337 resource_written(ctx, surf->base.texture); 338 etna_resource(surf->base.texture)->seqno++; 339} 340 341static void 342etna_clear_blt(struct pipe_context *pctx, unsigned buffers, const struct pipe_scissor_state *scissor_state, 343 const union pipe_color_union *color, double depth, unsigned stencil) 344{ 345 struct etna_context *ctx = etna_context(pctx); 346 mtx_lock(&ctx->lock); 347 348 etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, 0x00000c23); 349 etna_set_state(ctx->stream, VIVS_TS_FLUSH_CACHE, VIVS_TS_FLUSH_CACHE_FLUSH); 350 351 if (buffers & PIPE_CLEAR_COLOR) { 352 for (int idx = 0; idx < ctx->framebuffer_s.nr_cbufs; ++idx) { 353 etna_blit_clear_color_blt(pctx, ctx->framebuffer_s.cbufs[idx], 354 &color[idx]); 355 } 356 } 357 358 if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && ctx->framebuffer_s.zsbuf != NULL) 359 etna_blit_clear_zs_blt(pctx, ctx->framebuffer_s.zsbuf, buffers, depth, stencil); 360 361 etna_stall(ctx->stream, SYNC_RECIPIENT_RA, SYNC_RECIPIENT_BLT); 362 363 if ((buffers & PIPE_CLEAR_COLOR) && (buffers & PIPE_CLEAR_DEPTH)) 364 etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, 0x00000c23); 365 else 366 etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, 0x00000002); 367 mtx_unlock(&ctx->lock); 368} 369 370static bool 371etna_try_blt_blit(struct pipe_context *pctx, 372 const struct pipe_blit_info *blit_info) 373{ 374 struct etna_context *ctx = etna_context(pctx); 375 struct etna_resource *src = etna_resource(blit_info->src.resource); 376 struct etna_resource *dst = etna_resource(blit_info->dst.resource); 377 int msaa_xscale = 1, msaa_yscale = 1; 378 379 /* Ensure that the level is valid */ 380 assert(blit_info->src.level <= src->base.last_level); 381 assert(blit_info->dst.level <= dst->base.last_level); 382 383 if (!translate_samples_to_xyscale(src->base.nr_samples, &msaa_xscale, &msaa_yscale)) 384 return false; 385 386 /* The width/height are in pixels; they do not change as a result of 387 * multi-sampling. So, when blitting from a 4x multisampled surface 388 * to a non-multisampled surface, the width and height will be 389 * identical. As we do not support scaling, reject different sizes. 390 * TODO: could handle 2x downsample here with emit_blt_genmipmaps */ 391 if (blit_info->dst.box.width != blit_info->src.box.width || 392 blit_info->dst.box.height != abs(blit_info->src.box.height)) { /* allow y flip for glTexImage2D */ 393 DBG("scaling requested: source %dx%d destination %dx%d", 394 blit_info->src.box.width, blit_info->src.box.height, 395 blit_info->dst.box.width, blit_info->dst.box.height); 396 return false; 397 } 398 399 /* No masks - not sure if BLT can copy individual channels */ 400 unsigned mask = util_format_get_mask(blit_info->dst.format); 401 if ((blit_info->mask & mask) != mask) { 402 DBG("sub-mask requested: 0x%02x vs format mask 0x%02x", blit_info->mask, mask); 403 return false; 404 } 405 406 /* Only support same format (used tiling/detiling) blits for now. 407 * TODO: figure out which different-format blits are possible and test them 408 * - need to use correct swizzle 409 * - set sRGB bits correctly 410 * - avoid trying to convert between float/int formats? 411 */ 412 if (blit_info->src.format != blit_info->dst.format) 413 return false; 414 415 uint32_t format = etna_compatible_blt_format(blit_info->dst.format); 416 if (format == ETNA_NO_MATCH) 417 return false; 418 419 if (blit_info->scissor_enable || 420 blit_info->dst.box.depth != blit_info->src.box.depth || 421 blit_info->dst.box.depth != 1) { 422 return false; 423 } 424 425 struct etna_resource_level *src_lev = &src->levels[blit_info->src.level]; 426 struct etna_resource_level *dst_lev = &dst->levels[blit_info->dst.level]; 427 428 /* if we asked for in-place resolve, return immediately if ts isn't valid 429 * do this check separately because it applies when compression is used, but 430 * we can't use inplace resolve path with compression 431 */ 432 if (src == dst) { 433 assert(!memcmp(&blit_info->src, &blit_info->dst, sizeof(blit_info->src))); 434 if (!src_lev->ts_size || !src_lev->ts_valid) /* No TS, no worries */ 435 return true; 436 } 437 438 mtx_lock(&ctx->lock); 439 /* Kick off BLT here */ 440 if (src == dst && src_lev->ts_compress_fmt < 0) { 441 /* Resolve-in-place */ 442 struct blt_inplace_op op = {}; 443 444 op.addr.bo = src->bo; 445 op.addr.offset = src_lev->offset + blit_info->src.box.z * src_lev->layer_stride; 446 op.addr.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; 447 op.ts_addr.bo = src->ts_bo; 448 op.ts_addr.offset = src_lev->ts_offset + blit_info->src.box.z * src_lev->ts_layer_stride; 449 op.ts_addr.flags = ETNA_RELOC_READ; 450 op.ts_clear_value[0] = src_lev->clear_value; 451 op.ts_clear_value[1] = src_lev->clear_value; 452 op.ts_mode = src_lev->ts_mode; 453 op.num_tiles = DIV_ROUND_UP(src_lev->size, src_lev->ts_mode ? 256 : 128); 454 op.bpp = util_format_get_blocksize(src->base.format); 455 456 etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, 0x00000c23); 457 etna_set_state(ctx->stream, VIVS_TS_FLUSH_CACHE, 0x00000001); 458 emit_blt_inplace(ctx->stream, &op); 459 } else { 460 /* Copy op */ 461 struct blt_imgcopy_op op = {}; 462 463 op.src.addr.bo = src->bo; 464 op.src.addr.offset = src_lev->offset + blit_info->src.box.z * src_lev->layer_stride; 465 op.src.addr.flags = ETNA_RELOC_READ; 466 op.src.format = format; 467 op.src.stride = src_lev->stride; 468 op.src.tiling = src->layout; 469 for (unsigned x=0; x<4; ++x) 470 op.src.swizzle[x] = x; 471 472 if (src_lev->ts_size && src_lev->ts_valid) { 473 op.src.use_ts = 1; 474 op.src.ts_addr.bo = src->ts_bo; 475 op.src.ts_addr.offset = src_lev->ts_offset + blit_info->src.box.z * src_lev->ts_layer_stride; 476 op.src.ts_addr.flags = ETNA_RELOC_READ; 477 op.src.ts_clear_value[0] = src_lev->clear_value; 478 op.src.ts_clear_value[1] = src_lev->clear_value; 479 op.src.ts_mode = src_lev->ts_mode; 480 op.src.ts_compress_fmt = src_lev->ts_compress_fmt; 481 } 482 483 op.dest.addr.bo = dst->bo; 484 op.dest.addr.offset = dst_lev->offset + blit_info->dst.box.z * dst_lev->layer_stride; 485 op.dest.addr.flags = ETNA_RELOC_WRITE; 486 op.dest.format = format; 487 op.dest.stride = dst_lev->stride; 488 op.dest.tiling = dst->layout; 489 for (unsigned x=0; x<4; ++x) 490 op.dest.swizzle[x] = x; 491 492 op.dest_x = blit_info->dst.box.x; 493 op.dest_y = blit_info->dst.box.y; 494 op.src_x = blit_info->src.box.x; 495 op.src_y = blit_info->src.box.y; 496 op.rect_w = blit_info->dst.box.width; 497 op.rect_h = blit_info->dst.box.height; 498 499 if (blit_info->src.box.height < 0) { /* flipped? fix up base y */ 500 op.flip_y = 1; 501 op.src_y += blit_info->src.box.height; 502 } 503 504 assert(op.src_x < src_lev->padded_width); 505 assert(op.src_y < src_lev->padded_height); 506 assert((op.src_x + op.rect_w) <= src_lev->padded_width); 507 assert((op.src_y + op.rect_h) <= src_lev->padded_height); 508 assert(op.dest_x < dst_lev->padded_width); 509 assert(op.dest_y < dst_lev->padded_height); 510 assert((op.dest_x + op.rect_w) <= dst_lev->padded_width); 511 assert((op.dest_y + op.rect_h) <= dst_lev->padded_height); 512 513 etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, 0x00000c23); 514 etna_set_state(ctx->stream, VIVS_TS_FLUSH_CACHE, 0x00000001); 515 emit_blt_copyimage(ctx->stream, &op); 516 } 517 518 /* Make FE wait for BLT, in case we want to do something with the image next. 519 * This probably shouldn't be here, and depend on what is done with the resource. 520 */ 521 etna_stall(ctx->stream, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_BLT); 522 etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, 0x00000c23); 523 524 resource_read(ctx, &src->base); 525 resource_written(ctx, &dst->base); 526 527 dst->seqno++; 528 dst_lev->ts_valid = false; 529 mtx_unlock(&ctx->lock); 530 531 return true; 532} 533 534static bool 535etna_blit_blt(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) 536{ 537 if (blit_info->src.resource->nr_samples > 1 && 538 blit_info->dst.resource->nr_samples <= 1 && 539 !util_format_is_depth_or_stencil(blit_info->src.resource->format) && 540 !util_format_is_pure_integer(blit_info->src.resource->format)) { 541 DBG("color resolve unimplemented"); 542 return false; 543 } 544 545 return etna_try_blt_blit(pctx, blit_info); 546} 547 548void 549etna_clear_blit_blt_init(struct pipe_context *pctx) 550{ 551 struct etna_context *ctx = etna_context(pctx); 552 553 DBG("etnaviv: Using BLT blit engine"); 554 pctx->clear = etna_clear_blt; 555 ctx->blit = etna_blit_blt; 556} 557