diff options
author | Lucas Stach <[email protected]> | 2017-09-06 14:24:30 +0200 |
---|---|---|
committer | Lucas Stach <[email protected]> | 2017-09-28 17:40:49 +0200 |
commit | 9df635844c98274609b4ed60bc44893fc64b08a1 (patch) | |
tree | 3901fb4251351b02d34d0dea440272e7fee8d418 /src/gallium/drivers | |
parent | 6ed61b8d3fa09f7b08505e62d5b92270aef3fb80 (diff) |
etnaviv: support tile aligned RS blits
The RS can blit abitrary tile aligned subregions of a resource by
adjusting the buffer offset.
Signed-off-by: Lucas Stach <[email protected]>
Reviewed-By: Wladimir J. van der Laan <[email protected]>
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r-- | src/gallium/drivers/etnaviv/etnaviv_clear_blit.c | 86 |
1 files changed, 78 insertions, 8 deletions
diff --git a/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c b/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c index d73d0e30b3e..237c35a22ae 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c +++ b/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c @@ -358,6 +358,59 @@ etna_manual_blit(struct etna_resource *dst, struct etna_resource_level *dst_lev, return true; } +static inline size_t +etna_compute_tileoffset(const struct pipe_box *box, enum pipe_format format, + size_t stride, enum etna_surface_layout layout) +{ + size_t offset; + unsigned int x = box->x, y = box->y; + unsigned int blocksize = util_format_get_blocksize(format); + + switch (layout) { + case ETNA_LAYOUT_LINEAR: + offset = y * stride + x * blocksize; + break; + case ETNA_LAYOUT_MULTI_TILED: + y >>= 1; + /* fall-through */ + case ETNA_LAYOUT_TILED: + assert(!(x & 0x03) && !(y & 0x03)); + offset = (y & ~0x03) * stride + blocksize * ((x & ~0x03) << 2); + break; + case ETNA_LAYOUT_MULTI_SUPERTILED: + y >>= 1; + /* fall-through */ + case ETNA_LAYOUT_SUPER_TILED: + assert(!(x & 0x3f) && !(y & 0x3f)); + offset = (y & ~0x3f) * stride + blocksize * ((x & ~0x3f) << 6); + break; + default: + unreachable("invalid resource layout"); + } + + return offset; +} + +static inline void +etna_get_rs_alignment_mask(const struct etna_context *ctx, + const enum etna_surface_layout layout, + unsigned int *width_mask, unsigned int *height_mask) +{ + unsigned int h_align, w_align; + + if (layout & ETNA_LAYOUT_BIT_SUPER) { + w_align = h_align = 64; + } else { + w_align = ETNA_RS_WIDTH_MASK + 1; + h_align = ETNA_RS_HEIGHT_MASK + 1; + } + + h_align *= ctx->screen->specs.pixel_pipes; + + *width_mask = w_align - 1; + *height_mask = h_align -1; +} + static bool etna_try_rs_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) @@ -399,14 +452,22 @@ etna_try_rs_blit(struct pipe_context *pctx, unsigned dst_format = etna_compatible_rs_format(blit_info->dst.format); if (translate_rs_format(src_format) == ETNA_NO_MATCH || translate_rs_format(dst_format) == ETNA_NO_MATCH || - blit_info->scissor_enable || blit_info->src.box.x != 0 || - blit_info->src.box.y != 0 || blit_info->dst.box.x != 0 || - blit_info->dst.box.y != 0 || + blit_info->scissor_enable || blit_info->dst.box.depth != blit_info->src.box.depth || blit_info->dst.box.depth != 1) { return FALSE; } + unsigned w_mask, h_mask; + + etna_get_rs_alignment_mask(ctx, src->layout, &w_mask, &h_mask); + if ((blit_info->src.box.x & w_mask) || (blit_info->src.box.y & h_mask)) + return FALSE; + + etna_get_rs_alignment_mask(ctx, dst->layout, &w_mask, &h_mask); + if ((blit_info->dst.box.x & w_mask) || (blit_info->dst.box.y & h_mask)) + return FALSE; + /* Ensure that the Z coordinate is sane */ if (dst->base.target != PIPE_TEXTURE_CUBE) assert(blit_info->dst.box.z == 0); @@ -426,10 +487,18 @@ etna_try_rs_blit(struct pipe_context *pctx, assert(blit_info->dst.box.x + blit_info->dst.box.width <= dst_lev->padded_width); assert(blit_info->dst.box.y + blit_info->dst.box.height <= dst_lev->padded_height); - unsigned src_offset = - src_lev->offset + blit_info->src.box.z * src_lev->layer_stride; - unsigned dst_offset = - dst_lev->offset + blit_info->dst.box.z * dst_lev->layer_stride; + unsigned src_offset = src_lev->offset + + blit_info->src.box.z * src_lev->layer_stride + + etna_compute_tileoffset(&blit_info->src.box, + blit_info->src.format, + src_lev->stride, + src->layout); + unsigned dst_offset = dst_lev->offset + + blit_info->dst.box.z * dst_lev->layer_stride + + etna_compute_tileoffset(&blit_info->dst.box, + blit_info->dst.format, + dst_lev->stride, + dst->layout); if (src_lev->padded_width <= ETNA_RS_WIDTH_MASK || dst_lev->padded_width <= ETNA_RS_WIDTH_MASK || @@ -503,7 +572,8 @@ etna_try_rs_blit(struct pipe_context *pctx, memset(&reloc, 0, sizeof(struct etna_reloc)); reloc.bo = src->bo; - reloc.offset = src_offset; + reloc.offset = src_lev->offset + + blit_info->src.box.z * src_lev->layer_stride; reloc.flags = ETNA_RELOC_READ; etna_set_state_reloc(ctx->stream, VIVS_TS_COLOR_SURFACE_BASE, &reloc); |