Path: blob/21.2-virgl/src/gallium/drivers/etnaviv/etnaviv_blt.c
4570 views
/*1* Copyright (c) 2017 Etnaviv Project2* Copyright (C) 2017 Zodiac Inflight Innovations3*4* Permission is hereby granted, free of charge, to any person obtaining a5* copy of this software and associated documentation files (the "Software"),6* to deal in the Software without restriction, including without limitation7* the rights to use, copy, modify, merge, publish, distribute, sub license,8* and/or sell copies of the Software, and to permit persons to whom the9* Software is furnished to do so, subject to the following conditions:10*11* The above copyright notice and this permission notice (including the12* next paragraph) shall be included in all copies or substantial portions13* of the Software.14*15* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL18* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER19* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING20* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER21* DEALINGS IN THE SOFTWARE.22*23* Authors:24* Wladimir J. van der Laan <[email protected]>25*/26#include "etnaviv_blt.h"2728#include "etnaviv_emit.h"29#include "etnaviv_clear_blit.h"30#include "etnaviv_context.h"31#include "etnaviv_emit.h"32#include "etnaviv_format.h"33#include "etnaviv_resource.h"34#include "etnaviv_surface.h"35#include "etnaviv_translate.h"3637#include "util/u_math.h"38#include "pipe/p_defines.h"39#include "pipe/p_state.h"40#include "util/u_blitter.h"41#include "util/u_inlines.h"42#include "util/u_memory.h"43#include "util/u_surface.h"4445#include "hw/common_3d.xml.h"46#include "hw/state_blt.xml.h"47#include "hw/common.xml.h"4849#include <assert.h>5051static uint32_t52etna_compatible_blt_format(enum pipe_format fmt)53{54/* YUYV and UYVY are blocksize 4, but 2 bytes per pixel */55if (fmt == PIPE_FORMAT_YUYV || fmt == PIPE_FORMAT_UYVY)56return BLT_FORMAT_R8G8;5758switch (util_format_get_blocksize(fmt)) {59case 1: return BLT_FORMAT_R8;60case 2: return BLT_FORMAT_R8G8;61case 4: return BLT_FORMAT_A8R8G8B8;62case 8: return BLT_FORMAT_A16R16G16B16;63default: return ETNA_NO_MATCH;64}65}6667static inline uint32_t68blt_compute_stride_bits(const struct blt_imginfo *img)69{70return VIVS_BLT_DEST_STRIDE_TILING(img->tiling == ETNA_LAYOUT_LINEAR ? 0 : 3) | /* 1/3? */71VIVS_BLT_DEST_STRIDE_FORMAT(img->format) |72VIVS_BLT_DEST_STRIDE_STRIDE(img->stride);73}7475static inline uint32_t76blt_compute_img_config_bits(const struct blt_imginfo *img, bool for_dest)77{78uint32_t tiling_bits = 0;79if (img->tiling == ETNA_LAYOUT_SUPER_TILED) {80tiling_bits |= for_dest ? BLT_IMAGE_CONFIG_TO_SUPER_TILED : BLT_IMAGE_CONFIG_FROM_SUPER_TILED;81}8283return BLT_IMAGE_CONFIG_TS_MODE(img->ts_mode) |84COND(img->use_ts, BLT_IMAGE_CONFIG_TS) |85COND(img->use_ts && img->ts_compress_fmt >= 0, BLT_IMAGE_CONFIG_COMPRESSION) |86BLT_IMAGE_CONFIG_COMPRESSION_FORMAT(img->ts_compress_fmt) |87COND(for_dest, BLT_IMAGE_CONFIG_UNK22) |88BLT_IMAGE_CONFIG_SWIZ_R(0) | /* not used? */89BLT_IMAGE_CONFIG_SWIZ_G(1) |90BLT_IMAGE_CONFIG_SWIZ_B(2) |91BLT_IMAGE_CONFIG_SWIZ_A(3) |92tiling_bits;93}9495static inline uint32_t96blt_compute_swizzle_bits(const struct blt_imginfo *img, bool for_dest)97{98uint32_t swiz = VIVS_BLT_SWIZZLE_SRC_R(img->swizzle[0]) |99VIVS_BLT_SWIZZLE_SRC_G(img->swizzle[1]) |100VIVS_BLT_SWIZZLE_SRC_B(img->swizzle[2]) |101VIVS_BLT_SWIZZLE_SRC_A(img->swizzle[3]);102return for_dest ? (swiz << 12) : swiz;103}104105/* Clear (part of) an image */106static void107emit_blt_clearimage(struct etna_cmd_stream *stream, const struct blt_clear_op *op)108{109etna_cmd_stream_reserve(stream, 64*2); /* Make sure BLT op doesn't get broken up */110111etna_set_state(stream, VIVS_BLT_ENABLE, 0x00000001);112assert(op->dest.bpp);113etna_set_state(stream, VIVS_BLT_CONFIG, VIVS_BLT_CONFIG_CLEAR_BPP(op->dest.bpp-1));114/* NB: blob sets format to 1 in dest/src config for clear, and the swizzle to RRRR.115* does this matter? It seems to just be ignored. But if we run into issues with BLT116* behaving stragely, it's something to look at.117*/118etna_set_state(stream, VIVS_BLT_DEST_STRIDE, blt_compute_stride_bits(&op->dest));119etna_set_state(stream, VIVS_BLT_DEST_CONFIG, blt_compute_img_config_bits(&op->dest, true));120etna_set_state_reloc(stream, VIVS_BLT_DEST_ADDR, &op->dest.addr);121etna_set_state(stream, VIVS_BLT_SRC_STRIDE, blt_compute_stride_bits(&op->dest));122etna_set_state(stream, VIVS_BLT_SRC_CONFIG, blt_compute_img_config_bits(&op->dest, false));123etna_set_state_reloc(stream, VIVS_BLT_SRC_ADDR, &op->dest.addr);124etna_set_state(stream, VIVS_BLT_DEST_POS, VIVS_BLT_DEST_POS_X(op->rect_x) | VIVS_BLT_DEST_POS_Y(op->rect_y));125etna_set_state(stream, VIVS_BLT_IMAGE_SIZE, VIVS_BLT_IMAGE_SIZE_WIDTH(op->rect_w) | VIVS_BLT_IMAGE_SIZE_HEIGHT(op->rect_h));126etna_set_state(stream, VIVS_BLT_CLEAR_COLOR0, op->clear_value[0]);127etna_set_state(stream, VIVS_BLT_CLEAR_COLOR1, op->clear_value[1]);128etna_set_state(stream, VIVS_BLT_CLEAR_BITS0, op->clear_bits[0]);129etna_set_state(stream, VIVS_BLT_CLEAR_BITS1, op->clear_bits[1]);130if (op->dest.use_ts) {131etna_set_state_reloc(stream, VIVS_BLT_DEST_TS, &op->dest.ts_addr);132etna_set_state_reloc(stream, VIVS_BLT_SRC_TS, &op->dest.ts_addr);133etna_set_state(stream, VIVS_BLT_DEST_TS_CLEAR_VALUE0, op->dest.ts_clear_value[0]);134etna_set_state(stream, VIVS_BLT_DEST_TS_CLEAR_VALUE1, op->dest.ts_clear_value[1]);135etna_set_state(stream, VIVS_BLT_SRC_TS_CLEAR_VALUE0, op->dest.ts_clear_value[0]);136etna_set_state(stream, VIVS_BLT_SRC_TS_CLEAR_VALUE1, op->dest.ts_clear_value[1]);137}138etna_set_state(stream, VIVS_BLT_SET_COMMAND, 0x00000003);139etna_set_state(stream, VIVS_BLT_COMMAND, VIVS_BLT_COMMAND_COMMAND_CLEAR_IMAGE);140etna_set_state(stream, VIVS_BLT_SET_COMMAND, 0x00000003);141etna_set_state(stream, VIVS_BLT_ENABLE, 0x00000000);142}143144/* Copy (a subset of) an image to another image. */145static void146emit_blt_copyimage(struct etna_cmd_stream *stream, const struct blt_imgcopy_op *op)147{148etna_cmd_stream_reserve(stream, 64*2); /* Never allow BLT sequences to be broken up */149150etna_set_state(stream, VIVS_BLT_ENABLE, 0x00000001);151etna_set_state(stream, VIVS_BLT_CONFIG,152VIVS_BLT_CONFIG_SRC_ENDIAN(op->src.endian_mode) |153VIVS_BLT_CONFIG_DEST_ENDIAN(op->dest.endian_mode));154etna_set_state(stream, VIVS_BLT_SRC_STRIDE, blt_compute_stride_bits(&op->src));155etna_set_state(stream, VIVS_BLT_SRC_CONFIG, blt_compute_img_config_bits(&op->src, false));156etna_set_state(stream, VIVS_BLT_SWIZZLE,157blt_compute_swizzle_bits(&op->src, false) |158blt_compute_swizzle_bits(&op->dest, true));159etna_set_state(stream, VIVS_BLT_UNK140A0, 0x00040004);160etna_set_state(stream, VIVS_BLT_UNK1409C, 0x00400040);161if (op->src.use_ts) {162etna_set_state_reloc(stream, VIVS_BLT_SRC_TS, &op->src.ts_addr);163etna_set_state(stream, VIVS_BLT_SRC_TS_CLEAR_VALUE0, op->src.ts_clear_value[0]);164etna_set_state(stream, VIVS_BLT_SRC_TS_CLEAR_VALUE1, op->src.ts_clear_value[1]);165}166etna_set_state_reloc(stream, VIVS_BLT_SRC_ADDR, &op->src.addr);167etna_set_state(stream, VIVS_BLT_DEST_STRIDE, blt_compute_stride_bits(&op->dest));168etna_set_state(stream, VIVS_BLT_DEST_CONFIG,169blt_compute_img_config_bits(&op->dest, true) |170COND(op->flip_y, BLT_IMAGE_CONFIG_FLIP_Y));171assert(!op->dest.use_ts); /* Dest TS path doesn't work for copies? */172if (op->dest.use_ts) {173etna_set_state_reloc(stream, VIVS_BLT_DEST_TS, &op->dest.ts_addr);174etna_set_state(stream, VIVS_BLT_DEST_TS_CLEAR_VALUE0, op->dest.ts_clear_value[0]);175etna_set_state(stream, VIVS_BLT_DEST_TS_CLEAR_VALUE1, op->dest.ts_clear_value[1]);176}177etna_set_state_reloc(stream, VIVS_BLT_DEST_ADDR, &op->dest.addr);178etna_set_state(stream, VIVS_BLT_SRC_POS, VIVS_BLT_DEST_POS_X(op->src_x) | VIVS_BLT_DEST_POS_Y(op->src_y));179etna_set_state(stream, VIVS_BLT_DEST_POS, VIVS_BLT_DEST_POS_X(op->dest_x) | VIVS_BLT_DEST_POS_Y(op->dest_y));180etna_set_state(stream, VIVS_BLT_IMAGE_SIZE, VIVS_BLT_IMAGE_SIZE_WIDTH(op->rect_w) | VIVS_BLT_IMAGE_SIZE_HEIGHT(op->rect_h));181etna_set_state(stream, VIVS_BLT_UNK14058, 0xffffffff);182etna_set_state(stream, VIVS_BLT_UNK1405C, 0xffffffff);183etna_set_state(stream, VIVS_BLT_SET_COMMAND, 0x00000003);184etna_set_state(stream, VIVS_BLT_COMMAND, VIVS_BLT_COMMAND_COMMAND_COPY_IMAGE);185etna_set_state(stream, VIVS_BLT_SET_COMMAND, 0x00000003);186etna_set_state(stream, VIVS_BLT_ENABLE, 0x00000000);187}188189/* Emit in-place resolve using BLT. */190static void191emit_blt_inplace(struct etna_cmd_stream *stream, const struct blt_inplace_op *op)192{193assert(op->bpp > 0 && util_is_power_of_two_nonzero(op->bpp));194etna_cmd_stream_reserve(stream, 64*2); /* Never allow BLT sequences to be broken up */195etna_set_state(stream, VIVS_BLT_ENABLE, 0x00000001);196etna_set_state(stream, VIVS_BLT_CONFIG,197VIVS_BLT_CONFIG_INPLACE_TS_MODE(op->ts_mode) |198VIVS_BLT_CONFIG_INPLACE_BOTH |199(util_logbase2(op->bpp) << VIVS_BLT_CONFIG_INPLACE_BPP__SHIFT));200etna_set_state(stream, VIVS_BLT_DEST_TS_CLEAR_VALUE0, op->ts_clear_value[0]);201etna_set_state(stream, VIVS_BLT_DEST_TS_CLEAR_VALUE1, op->ts_clear_value[1]);202etna_set_state_reloc(stream, VIVS_BLT_DEST_ADDR, &op->addr);203etna_set_state_reloc(stream, VIVS_BLT_DEST_TS, &op->ts_addr);204etna_set_state(stream, 0x14068, op->num_tiles);205etna_set_state(stream, VIVS_BLT_SET_COMMAND, 0x00000003);206etna_set_state(stream, VIVS_BLT_COMMAND, 0x00000004);207etna_set_state(stream, VIVS_BLT_SET_COMMAND, 0x00000003);208etna_set_state(stream, VIVS_BLT_ENABLE, 0x00000000);209}210211static void212etna_blit_clear_color_blt(struct pipe_context *pctx, struct pipe_surface *dst,213const union pipe_color_union *color)214{215struct etna_context *ctx = etna_context(pctx);216struct etna_surface *surf = etna_surface(dst);217uint64_t new_clear_value = etna_clear_blit_pack_rgba(surf->base.format, color);218219struct etna_resource *res = etna_resource(surf->base.texture);220struct blt_clear_op clr = {};221clr.dest.addr.bo = res->bo;222clr.dest.addr.offset = surf->surf.offset;223clr.dest.addr.flags = ETNA_RELOC_WRITE;224clr.dest.bpp = util_format_get_blocksize(surf->base.format);225clr.dest.stride = surf->surf.stride;226clr.dest.tiling = res->layout;227228if (surf->surf.ts_size) {229clr.dest.use_ts = 1;230clr.dest.ts_addr.bo = res->ts_bo;231clr.dest.ts_addr.offset = surf->level->ts_offset;232clr.dest.ts_addr.flags = ETNA_RELOC_WRITE;233clr.dest.ts_clear_value[0] = new_clear_value;234clr.dest.ts_clear_value[1] = new_clear_value >> 32;235clr.dest.ts_mode = surf->level->ts_mode;236clr.dest.ts_compress_fmt = surf->level->ts_compress_fmt;237}238239clr.clear_value[0] = new_clear_value;240clr.clear_value[1] = new_clear_value >> 32;241clr.clear_bits[0] = 0xffffffff; /* TODO: Might want to clear only specific channels? */242clr.clear_bits[1] = 0xffffffff;243clr.rect_x = 0; /* What about scissors? */244clr.rect_y = 0;245clr.rect_w = surf->surf.width;246clr.rect_h = surf->surf.height;247248emit_blt_clearimage(ctx->stream, &clr);249250/* This made the TS valid */251if (surf->surf.ts_size) {252ctx->framebuffer.TS_COLOR_CLEAR_VALUE = new_clear_value;253ctx->framebuffer.TS_COLOR_CLEAR_VALUE_EXT = new_clear_value >> 32;254surf->level->ts_valid = true;255ctx->dirty |= ETNA_DIRTY_TS | ETNA_DIRTY_DERIVE_TS;256}257258surf->level->clear_value = new_clear_value;259resource_written(ctx, surf->base.texture);260etna_resource(surf->base.texture)->seqno++;261}262263static void264etna_blit_clear_zs_blt(struct pipe_context *pctx, struct pipe_surface *dst,265unsigned buffers, double depth, unsigned stencil)266{267struct etna_context *ctx = etna_context(pctx);268struct etna_surface *surf = etna_surface(dst);269uint32_t new_clear_value = translate_clear_depth_stencil(surf->base.format, depth, stencil);270uint32_t new_clear_bits = 0, clear_bits_depth, clear_bits_stencil;271272/* Get the channels to clear */273switch (surf->base.format) {274case PIPE_FORMAT_Z16_UNORM:275case PIPE_FORMAT_X8Z24_UNORM:276clear_bits_depth = 0xffffffff;277clear_bits_stencil = 0x00000000;278break;279case PIPE_FORMAT_S8_UINT_Z24_UNORM:280clear_bits_depth = 0xffffff00;281clear_bits_stencil = 0x000000ff;282break;283default:284clear_bits_depth = clear_bits_stencil = 0xffffffff;285break;286}287288if (buffers & PIPE_CLEAR_DEPTH)289new_clear_bits |= clear_bits_depth;290if (buffers & PIPE_CLEAR_STENCIL)291new_clear_bits |= clear_bits_stencil;292293/* if all bits are cleared, update TS clear value */294if (new_clear_bits == 0xffffffff)295surf->level->clear_value = new_clear_value;296297/* TODO unduplicate this */298struct etna_resource *res = etna_resource(surf->base.texture);299struct blt_clear_op clr = {};300clr.dest.addr.bo = res->bo;301clr.dest.addr.offset = surf->surf.offset;302clr.dest.addr.flags = ETNA_RELOC_WRITE;303clr.dest.bpp = util_format_get_blocksize(surf->base.format);304clr.dest.stride = surf->surf.stride;305clr.dest.tiling = res->layout;306307if (surf->surf.ts_size) {308clr.dest.use_ts = 1;309clr.dest.ts_addr.bo = res->ts_bo;310clr.dest.ts_addr.offset = surf->level->ts_offset;311clr.dest.ts_addr.flags = ETNA_RELOC_WRITE;312clr.dest.ts_clear_value[0] = surf->level->clear_value;313clr.dest.ts_clear_value[1] = surf->level->clear_value;314clr.dest.ts_mode = surf->level->ts_mode;315clr.dest.ts_compress_fmt = surf->level->ts_compress_fmt;316}317318clr.clear_value[0] = new_clear_value;319clr.clear_value[1] = new_clear_value;320clr.clear_bits[0] = new_clear_bits;321clr.clear_bits[1] = new_clear_bits;322clr.rect_x = 0; /* What about scissors? */323clr.rect_y = 0;324clr.rect_w = surf->surf.width;325clr.rect_h = surf->surf.height;326327emit_blt_clearimage(ctx->stream, &clr);328329/* This made the TS valid */330if (surf->surf.ts_size) {331ctx->framebuffer.TS_DEPTH_CLEAR_VALUE = surf->level->clear_value;332surf->level->ts_valid = true;333ctx->dirty |= ETNA_DIRTY_TS | ETNA_DIRTY_DERIVE_TS;334}335336resource_written(ctx, surf->base.texture);337etna_resource(surf->base.texture)->seqno++;338}339340static void341etna_clear_blt(struct pipe_context *pctx, unsigned buffers, const struct pipe_scissor_state *scissor_state,342const union pipe_color_union *color, double depth, unsigned stencil)343{344struct etna_context *ctx = etna_context(pctx);345mtx_lock(&ctx->lock);346347etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, 0x00000c23);348etna_set_state(ctx->stream, VIVS_TS_FLUSH_CACHE, VIVS_TS_FLUSH_CACHE_FLUSH);349350if (buffers & PIPE_CLEAR_COLOR) {351for (int idx = 0; idx < ctx->framebuffer_s.nr_cbufs; ++idx) {352etna_blit_clear_color_blt(pctx, ctx->framebuffer_s.cbufs[idx],353&color[idx]);354}355}356357if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && ctx->framebuffer_s.zsbuf != NULL)358etna_blit_clear_zs_blt(pctx, ctx->framebuffer_s.zsbuf, buffers, depth, stencil);359360etna_stall(ctx->stream, SYNC_RECIPIENT_RA, SYNC_RECIPIENT_BLT);361362if ((buffers & PIPE_CLEAR_COLOR) && (buffers & PIPE_CLEAR_DEPTH))363etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, 0x00000c23);364else365etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, 0x00000002);366mtx_unlock(&ctx->lock);367}368369static bool370etna_try_blt_blit(struct pipe_context *pctx,371const struct pipe_blit_info *blit_info)372{373struct etna_context *ctx = etna_context(pctx);374struct etna_resource *src = etna_resource(blit_info->src.resource);375struct etna_resource *dst = etna_resource(blit_info->dst.resource);376int msaa_xscale = 1, msaa_yscale = 1;377378/* Ensure that the level is valid */379assert(blit_info->src.level <= src->base.last_level);380assert(blit_info->dst.level <= dst->base.last_level);381382if (!translate_samples_to_xyscale(src->base.nr_samples, &msaa_xscale, &msaa_yscale))383return false;384385/* The width/height are in pixels; they do not change as a result of386* multi-sampling. So, when blitting from a 4x multisampled surface387* to a non-multisampled surface, the width and height will be388* identical. As we do not support scaling, reject different sizes.389* TODO: could handle 2x downsample here with emit_blt_genmipmaps */390if (blit_info->dst.box.width != blit_info->src.box.width ||391blit_info->dst.box.height != abs(blit_info->src.box.height)) { /* allow y flip for glTexImage2D */392DBG("scaling requested: source %dx%d destination %dx%d",393blit_info->src.box.width, blit_info->src.box.height,394blit_info->dst.box.width, blit_info->dst.box.height);395return false;396}397398/* No masks - not sure if BLT can copy individual channels */399unsigned mask = util_format_get_mask(blit_info->dst.format);400if ((blit_info->mask & mask) != mask) {401DBG("sub-mask requested: 0x%02x vs format mask 0x%02x", blit_info->mask, mask);402return false;403}404405/* Only support same format (used tiling/detiling) blits for now.406* TODO: figure out which different-format blits are possible and test them407* - need to use correct swizzle408* - set sRGB bits correctly409* - avoid trying to convert between float/int formats?410*/411if (blit_info->src.format != blit_info->dst.format)412return false;413414uint32_t format = etna_compatible_blt_format(blit_info->dst.format);415if (format == ETNA_NO_MATCH)416return false;417418if (blit_info->scissor_enable ||419blit_info->dst.box.depth != blit_info->src.box.depth ||420blit_info->dst.box.depth != 1) {421return false;422}423424struct etna_resource_level *src_lev = &src->levels[blit_info->src.level];425struct etna_resource_level *dst_lev = &dst->levels[blit_info->dst.level];426427/* if we asked for in-place resolve, return immediately if ts isn't valid428* do this check separately because it applies when compression is used, but429* we can't use inplace resolve path with compression430*/431if (src == dst) {432assert(!memcmp(&blit_info->src, &blit_info->dst, sizeof(blit_info->src)));433if (!src_lev->ts_size || !src_lev->ts_valid) /* No TS, no worries */434return true;435}436437mtx_lock(&ctx->lock);438/* Kick off BLT here */439if (src == dst && src_lev->ts_compress_fmt < 0) {440/* Resolve-in-place */441struct blt_inplace_op op = {};442443op.addr.bo = src->bo;444op.addr.offset = src_lev->offset + blit_info->src.box.z * src_lev->layer_stride;445op.addr.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;446op.ts_addr.bo = src->ts_bo;447op.ts_addr.offset = src_lev->ts_offset + blit_info->src.box.z * src_lev->ts_layer_stride;448op.ts_addr.flags = ETNA_RELOC_READ;449op.ts_clear_value[0] = src_lev->clear_value;450op.ts_clear_value[1] = src_lev->clear_value;451op.ts_mode = src_lev->ts_mode;452op.num_tiles = DIV_ROUND_UP(src_lev->size, src_lev->ts_mode ? 256 : 128);453op.bpp = util_format_get_blocksize(src->base.format);454455etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, 0x00000c23);456etna_set_state(ctx->stream, VIVS_TS_FLUSH_CACHE, 0x00000001);457emit_blt_inplace(ctx->stream, &op);458} else {459/* Copy op */460struct blt_imgcopy_op op = {};461462op.src.addr.bo = src->bo;463op.src.addr.offset = src_lev->offset + blit_info->src.box.z * src_lev->layer_stride;464op.src.addr.flags = ETNA_RELOC_READ;465op.src.format = format;466op.src.stride = src_lev->stride;467op.src.tiling = src->layout;468for (unsigned x=0; x<4; ++x)469op.src.swizzle[x] = x;470471if (src_lev->ts_size && src_lev->ts_valid) {472op.src.use_ts = 1;473op.src.ts_addr.bo = src->ts_bo;474op.src.ts_addr.offset = src_lev->ts_offset + blit_info->src.box.z * src_lev->ts_layer_stride;475op.src.ts_addr.flags = ETNA_RELOC_READ;476op.src.ts_clear_value[0] = src_lev->clear_value;477op.src.ts_clear_value[1] = src_lev->clear_value;478op.src.ts_mode = src_lev->ts_mode;479op.src.ts_compress_fmt = src_lev->ts_compress_fmt;480}481482op.dest.addr.bo = dst->bo;483op.dest.addr.offset = dst_lev->offset + blit_info->dst.box.z * dst_lev->layer_stride;484op.dest.addr.flags = ETNA_RELOC_WRITE;485op.dest.format = format;486op.dest.stride = dst_lev->stride;487op.dest.tiling = dst->layout;488for (unsigned x=0; x<4; ++x)489op.dest.swizzle[x] = x;490491op.dest_x = blit_info->dst.box.x;492op.dest_y = blit_info->dst.box.y;493op.src_x = blit_info->src.box.x;494op.src_y = blit_info->src.box.y;495op.rect_w = blit_info->dst.box.width;496op.rect_h = blit_info->dst.box.height;497498if (blit_info->src.box.height < 0) { /* flipped? fix up base y */499op.flip_y = 1;500op.src_y += blit_info->src.box.height;501}502503assert(op.src_x < src_lev->padded_width);504assert(op.src_y < src_lev->padded_height);505assert((op.src_x + op.rect_w) <= src_lev->padded_width);506assert((op.src_y + op.rect_h) <= src_lev->padded_height);507assert(op.dest_x < dst_lev->padded_width);508assert(op.dest_y < dst_lev->padded_height);509assert((op.dest_x + op.rect_w) <= dst_lev->padded_width);510assert((op.dest_y + op.rect_h) <= dst_lev->padded_height);511512etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, 0x00000c23);513etna_set_state(ctx->stream, VIVS_TS_FLUSH_CACHE, 0x00000001);514emit_blt_copyimage(ctx->stream, &op);515}516517/* Make FE wait for BLT, in case we want to do something with the image next.518* This probably shouldn't be here, and depend on what is done with the resource.519*/520etna_stall(ctx->stream, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_BLT);521etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, 0x00000c23);522523resource_read(ctx, &src->base);524resource_written(ctx, &dst->base);525526dst->seqno++;527dst_lev->ts_valid = false;528mtx_unlock(&ctx->lock);529530return true;531}532533static bool534etna_blit_blt(struct pipe_context *pctx, const struct pipe_blit_info *blit_info)535{536if (blit_info->src.resource->nr_samples > 1 &&537blit_info->dst.resource->nr_samples <= 1 &&538!util_format_is_depth_or_stencil(blit_info->src.resource->format) &&539!util_format_is_pure_integer(blit_info->src.resource->format)) {540DBG("color resolve unimplemented");541return false;542}543544return etna_try_blt_blit(pctx, blit_info);545}546547void548etna_clear_blit_blt_init(struct pipe_context *pctx)549{550struct etna_context *ctx = etna_context(pctx);551552DBG("etnaviv: Using BLT blit engine");553pctx->clear = etna_clear_blt;554ctx->blit = etna_blit_blt;555}556557558