diff --git a/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c b/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c index c85ada92669..c62287b1339 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c +++ b/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c @@ -591,6 +591,7 @@ etna_try_rs_blit(struct pipe_context *pctx, .source = src->bo, .source_offset = src_offset, .source_stride = src_lev->stride, + .source_padded_width = src_lev->padded_width, .source_padded_height = src_lev->padded_height, .dest_format = translate_rs_format(dst_format), .dest_tiling = dst->layout, diff --git a/src/gallium/drivers/etnaviv/etnaviv_emit.c b/src/gallium/drivers/etnaviv/etnaviv_emit.c index c2117d563d1..707b1e73491 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_emit.c +++ b/src/gallium/drivers/etnaviv/etnaviv_emit.c @@ -173,7 +173,14 @@ etna_submit_rs_state(struct etna_context *ctx, ctx->stats.rs_operations++; - if (screen->specs.pixel_pipes == 1) { + if (cs->RS_KICKER_INPLACE) { + etna_cmd_stream_reserve(stream, 6); + etna_coalesce_start(stream, &coalesce); + /* 0/1 */ EMIT_STATE(RS_EXTRA_CONFIG, cs->RS_EXTRA_CONFIG); + /* 2/3 */ EMIT_STATE(RS_SOURCE_STRIDE, cs->RS_SOURCE_STRIDE); + /* 4/5 */ EMIT_STATE(RS_KICKER_INPLACE, cs->RS_KICKER_INPLACE); + etna_coalesce_end(stream, &coalesce); + } else if (screen->specs.pixel_pipes == 1) { etna_cmd_stream_reserve(stream, 22); etna_coalesce_start(stream, &coalesce); /* 0/1 */ EMIT_STATE(RS_CONFIG, cs->RS_CONFIG); diff --git a/src/gallium/drivers/etnaviv/etnaviv_rs.c b/src/gallium/drivers/etnaviv/etnaviv_rs.c index 5c108a6c7a2..c9072c2645e 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_rs.c +++ b/src/gallium/drivers/etnaviv/etnaviv_rs.c @@ -118,10 +118,21 @@ etna_compile_rs_state(struct etna_context *ctx, struct compiled_rs_state *cs, cs->RS_FILL_VALUE[3] = rs->clear_value[3]; cs->RS_EXTRA_CONFIG = VIVS_RS_EXTRA_CONFIG_AA(rs->aa) | VIVS_RS_EXTRA_CONFIG_ENDIAN(rs->endian_mode); - /* TODO: cs->RS_UNK016B0 = s->size / 64 ? - * The blob does this consistently but there seems to be no currently supported - * model that needs it. + + /* If source the same as destination, and the hardware supports this, + * do an in-place resolve to fill in unrendered tiles. */ + if (ctx->specs.single_buffer && rs->source == rs->dest && + rs->source_offset == rs->dest_offset && + rs->source_format == rs->dest_format && + rs->source_tiling == rs->dest_tiling && + rs->source_stride == rs->dest_stride && + !rs->downsample_x && !rs->downsample_y && + !rs->swap_rb && !rs->flip && + !rs->clear_mode && rs->source_padded_width) { + /* Total number of tiles (same as for autodisable) */ + cs->RS_KICKER_INPLACE = rs->source_padded_width * rs->source_padded_height / 16; + } } void diff --git a/src/gallium/drivers/etnaviv/etnaviv_rs.h b/src/gallium/drivers/etnaviv/etnaviv_rs.h index ec5b659ccd4..171d3fa0095 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_rs.h +++ b/src/gallium/drivers/etnaviv/etnaviv_rs.h @@ -43,6 +43,7 @@ struct rs_state { struct etna_bo *source; uint32_t source_offset; uint32_t source_stride; + uint32_t source_padded_width; /* total padded width (only needed for source) */ uint32_t source_padded_height; /* total padded height */ struct etna_bo *dest; uint32_t dest_offset; @@ -69,6 +70,7 @@ struct compiled_rs_state { uint32_t RS_FILL_VALUE[4]; uint32_t RS_EXTRA_CONFIG; uint32_t RS_PIPE_OFFSET[2]; + uint32_t RS_KICKER_INPLACE; /* Set if source is destination */ struct etna_reloc source[2]; struct etna_reloc dest[2];