#include <assert.h>
-/* Currently, used BLT formats overlap 100% with RS formats */
-#define translate_blt_format translate_rs_format
+static uint32_t
+etna_compatible_blt_format(enum pipe_format fmt)
+{
+ /* YUYV and UYVY are blocksize 4, but 2 bytes per pixel */
+ if (fmt == PIPE_FORMAT_YUYV || fmt == PIPE_FORMAT_UYVY)
+ return BLT_FORMAT_R8G8;
+
+ switch (util_format_get_blocksize(fmt)) {
+ case 1: return BLT_FORMAT_R8;
+ case 2: return BLT_FORMAT_R8G8;
+ case 4: return BLT_FORMAT_A8R8G8B8;
+ case 8: return BLT_FORMAT_A16R16G16B16;
+ default: return ETNA_NO_MATCH;
+ }
+}
static inline uint32_t
blt_compute_stride_bits(const struct blt_imginfo *img)
tiling_bits |= for_dest ? BLT_IMAGE_CONFIG_TO_SUPER_TILED : BLT_IMAGE_CONFIG_FROM_SUPER_TILED;
}
- return BLT_IMAGE_CONFIG_CACHE_MODE(img->cache_mode) |
+ return BLT_IMAGE_CONFIG_TS_MODE(img->ts_mode) |
COND(img->use_ts, BLT_IMAGE_CONFIG_TS) |
- COND(img->compressed, BLT_IMAGE_CONFIG_COMPRESSION) |
- BLT_IMAGE_CONFIG_COMPRESSION_FORMAT(img->compress_fmt) |
+ COND(img->use_ts && img->ts_compress_fmt >= 0, BLT_IMAGE_CONFIG_COMPRESSION) |
+ BLT_IMAGE_CONFIG_COMPRESSION_FORMAT(img->ts_compress_fmt) |
COND(for_dest, BLT_IMAGE_CONFIG_UNK22) |
BLT_IMAGE_CONFIG_SWIZ_R(0) | /* not used? */
BLT_IMAGE_CONFIG_SWIZ_G(1) |
etna_cmd_stream_reserve(stream, 64*2); /* Never allow BLT sequences to be broken up */
etna_set_state(stream, VIVS_BLT_ENABLE, 0x00000001);
etna_set_state(stream, VIVS_BLT_CONFIG,
- VIVS_BLT_CONFIG_INPLACE_CACHE_MODE(op->cache_mode) |
+ VIVS_BLT_CONFIG_INPLACE_TS_MODE(op->ts_mode) |
VIVS_BLT_CONFIG_INPLACE_BOTH |
(util_logbase2(op->bpp) << VIVS_BLT_CONFIG_INPLACE_BPP__SHIFT));
etna_set_state(stream, VIVS_BLT_DEST_TS_CLEAR_VALUE0, op->ts_clear_value[0]);
{
struct etna_context *ctx = etna_context(pctx);
struct etna_surface *surf = etna_surface(dst);
- uint32_t new_clear_value = etna_clear_blit_pack_rgba(surf->base.format, color->f);
+ uint64_t new_clear_value = etna_clear_blit_pack_rgba(surf->base.format, color);
struct etna_resource *res = etna_resource(surf->base.texture);
struct blt_clear_op clr = {};
clr.dest.addr.flags = ETNA_RELOC_WRITE;
clr.dest.bpp = util_format_get_blocksize(surf->base.format);
clr.dest.stride = surf->surf.stride;
- /* TODO: color compression
- clr.dest.compressed = 1;
- clr.dest.compress_fmt = 3;
- */
clr.dest.tiling = res->layout;
- clr.dest.cache_mode = TS_CACHE_MODE_128; /* TODO: cache modes */
if (surf->surf.ts_size) {
clr.dest.use_ts = 1;
clr.dest.ts_addr.offset = 0;
clr.dest.ts_addr.flags = ETNA_RELOC_WRITE;
clr.dest.ts_clear_value[0] = new_clear_value;
- clr.dest.ts_clear_value[1] = new_clear_value;
+ clr.dest.ts_clear_value[1] = new_clear_value >> 32;
+ clr.dest.ts_mode = surf->level->ts_mode;
+ clr.dest.ts_compress_fmt = surf->level->ts_compress_fmt;
}
clr.clear_value[0] = new_clear_value;
- clr.clear_value[1] = new_clear_value;
+ clr.clear_value[1] = new_clear_value >> 32;
clr.clear_bits[0] = 0xffffffff; /* TODO: Might want to clear only specific channels? */
clr.clear_bits[1] = 0xffffffff;
clr.rect_x = 0; /* What about scissors? */
/* This made the TS valid */
if (surf->surf.ts_size) {
ctx->framebuffer.TS_COLOR_CLEAR_VALUE = new_clear_value;
+ ctx->framebuffer.TS_COLOR_CLEAR_VALUE_EXT = new_clear_value >> 32;
surf->level->ts_valid = true;
+ ctx->dirty |= ETNA_DIRTY_TS | ETNA_DIRTY_DERIVE_TS;
}
surf->level->clear_value = new_clear_value;
if (buffers & PIPE_CLEAR_STENCIL)
new_clear_bits |= clear_bits_stencil;
+ /* if all bits are cleared, update TS clear value */
+ if (new_clear_bits == 0xffffffff)
+ surf->level->clear_value = new_clear_value;
+
/* TODO unduplicate this */
struct etna_resource *res = etna_resource(surf->base.texture);
struct blt_clear_op clr = {};
clr.dest.addr.flags = ETNA_RELOC_WRITE;
clr.dest.bpp = util_format_get_blocksize(surf->base.format);
clr.dest.stride = surf->surf.stride;
-#if 0 /* TODO depth compression */
- clr.dest.compressed = 1;
- clr.dest.compress_fmt = COLOR_COMPRESSION_FORMAT_D24S8;
-#endif
clr.dest.tiling = res->layout;
- clr.dest.cache_mode = TS_CACHE_MODE_128; /* TODO: cache modes */
if (surf->surf.ts_size) {
clr.dest.use_ts = 1;
clr.dest.ts_addr.bo = res->ts_bo;
clr.dest.ts_addr.offset = 0;
clr.dest.ts_addr.flags = ETNA_RELOC_WRITE;
- clr.dest.ts_clear_value[0] = new_clear_value;
- clr.dest.ts_clear_value[1] = new_clear_value;
+ clr.dest.ts_clear_value[0] = surf->level->clear_value;
+ clr.dest.ts_clear_value[1] = surf->level->clear_value;
+ clr.dest.ts_mode = surf->level->ts_mode;
+ clr.dest.ts_compress_fmt = surf->level->ts_compress_fmt;
}
clr.clear_value[0] = new_clear_value;
/* This made the TS valid */
if (surf->surf.ts_size) {
- ctx->framebuffer.TS_DEPTH_CLEAR_VALUE = new_clear_value;
+ ctx->framebuffer.TS_DEPTH_CLEAR_VALUE = surf->level->clear_value;
surf->level->ts_valid = true;
+ ctx->dirty |= ETNA_DIRTY_TS | ETNA_DIRTY_DERIVE_TS;
}
- surf->level->clear_value = new_clear_value;
resource_written(ctx, surf->base.texture);
etna_resource(surf->base.texture)->seqno++;
}
const union pipe_color_union *color, double depth, unsigned stencil)
{
struct etna_context *ctx = etna_context(pctx);
+ mtx_lock(&ctx->lock);
etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, 0x00000c23);
etna_set_state(ctx->stream, VIVS_TS_FLUSH_CACHE, VIVS_TS_FLUSH_CACHE_FLUSH);
etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, 0x00000c23);
else
etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, 0x00000002);
+ mtx_unlock(&ctx->lock);
}
-
static bool
etna_try_blt_blit(struct pipe_context *pctx,
const struct pipe_blit_info *blit_info)
assert(blit_info->src.level <= src->base.last_level);
assert(blit_info->dst.level <= dst->base.last_level);
- if (!translate_samples_to_xyscale(src->base.nr_samples, &msaa_xscale, &msaa_yscale, NULL))
+ if (!translate_samples_to_xyscale(src->base.nr_samples, &msaa_xscale, &msaa_yscale))
return false;
/* The width/height are in pixels; they do not change as a result of
return false;
}
- /* TODO: 1 byte per pixel formats aren't handled by etna_compatible_rs_format nor
- * translate_rs_format.
- * Also this should be smarter about format conversions; etna_compatible_rs_format
- * assumes all 2-byte pixel format are laid out as 4444, all 4-byte pixel formats
- * are 8888.
+ /* Only support same format (used tiling/detiling) blits for now.
+ * TODO: figure out which different-format blits are possible and test them
+ * - need to use correct swizzle
+ * - set sRGB bits correctly
+ * - avoid trying to convert between float/int formats?
*/
- unsigned src_format = etna_compatible_rs_format(blit_info->src.format);
- unsigned dst_format = etna_compatible_rs_format(blit_info->dst.format);
- if (translate_blt_format(src_format) == ETNA_NO_MATCH ||
- translate_blt_format(dst_format) == ETNA_NO_MATCH ||
- blit_info->scissor_enable ||
+ if (blit_info->src.format != blit_info->dst.format)
+ return false;
+
+ uint32_t format = etna_compatible_blt_format(blit_info->dst.format);
+ if (format == ETNA_NO_MATCH)
+ return false;
+
+ if (blit_info->scissor_enable ||
blit_info->dst.box.depth != blit_info->src.box.depth ||
blit_info->dst.box.depth != 1) {
return false;
}
- /* Ensure that the Z coordinate is sane */
- assert(dst->base.target == PIPE_TEXTURE_CUBE || blit_info->dst.box.z == 0);
- assert(src->base.target == PIPE_TEXTURE_CUBE || blit_info->src.box.z == 0);
- assert(blit_info->src.box.z < src->base.array_size);
- assert(blit_info->dst.box.z < dst->base.array_size);
-
struct etna_resource_level *src_lev = &src->levels[blit_info->src.level];
struct etna_resource_level *dst_lev = &dst->levels[blit_info->dst.level];
- /* Kick off BLT here */
+ /* if we asked for in-place resolve, return immediately if ts isn't valid
+ * do this check separately because it applies when compression is used, but
+ * we can't use inplace resolve path with compression
+ */
if (src == dst) {
- /* Resolve-in-place */
assert(!memcmp(&blit_info->src, &blit_info->dst, sizeof(blit_info->src)));
if (!src_lev->ts_size || !src_lev->ts_valid) /* No TS, no worries */
return true;
+ }
+
+ mtx_lock(&ctx->lock);
+ /* Kick off BLT here */
+ if (src == dst && src_lev->ts_compress_fmt < 0) {
+ /* Resolve-in-place */
struct blt_inplace_op op = {};
op.addr.bo = src->bo;
op.ts_addr.flags = ETNA_RELOC_READ;
op.ts_clear_value[0] = src_lev->clear_value;
op.ts_clear_value[1] = src_lev->clear_value;
- op.cache_mode = TS_CACHE_MODE_128; /* TODO: cache modes */
- op.num_tiles = src_lev->size / 128; /* TODO: cache modes */
+ op.ts_mode = src_lev->ts_mode;
+ op.num_tiles = DIV_ROUND_UP(src_lev->size, src_lev->ts_mode ? 256 : 128);
op.bpp = util_format_get_blocksize(src->base.format);
etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, 0x00000c23);
op.src.addr.bo = src->bo;
op.src.addr.offset = src_lev->offset + blit_info->src.box.z * src_lev->layer_stride;
op.src.addr.flags = ETNA_RELOC_READ;
- op.src.format = translate_blt_format(src_format);
+ op.src.format = format;
op.src.stride = src_lev->stride;
op.src.tiling = src->layout;
- op.src.cache_mode = TS_CACHE_MODE_128; /* TODO: cache modes */
- const struct util_format_description *src_format_desc =
- util_format_description(blit_info->src.format);
for (unsigned x=0; x<4; ++x)
- op.src.swizzle[x] = src_format_desc->swizzle[x];
+ op.src.swizzle[x] = x;
if (src_lev->ts_size && src_lev->ts_valid) {
op.src.use_ts = 1;
op.src.ts_addr.flags = ETNA_RELOC_READ;
op.src.ts_clear_value[0] = src_lev->clear_value;
op.src.ts_clear_value[1] = src_lev->clear_value;
+ op.src.ts_mode = src_lev->ts_mode;
+ op.src.ts_compress_fmt = src_lev->ts_compress_fmt;
}
op.dest.addr.bo = dst->bo;
op.dest.addr.offset = dst_lev->offset + blit_info->dst.box.z * dst_lev->layer_stride;
op.dest.addr.flags = ETNA_RELOC_WRITE;
- op.dest.format = translate_blt_format(dst_format);
+ op.dest.format = format;
op.dest.stride = dst_lev->stride;
- /* TODO color compression
- op.dest.compressed = 1;
- op.dest.compress_fmt = 3;
- */
op.dest.tiling = dst->layout;
- op.dest.cache_mode = TS_CACHE_MODE_128; /* TODO cache modes */
- const struct util_format_description *dst_format_desc =
- util_format_description(blit_info->dst.format);
for (unsigned x=0; x<4; ++x)
- op.dest.swizzle[x] = dst_format_desc->swizzle[x];
+ op.dest.swizzle[x] = x;
op.dest_x = blit_info->dst.box.x;
op.dest_y = blit_info->dst.box.y;
dst->seqno++;
dst_lev->ts_valid = false;
+ mtx_unlock(&ctx->lock);
return true;
}