+/* Helper function of si_flush_depth_texture: decompress the given levels
+ * of Z and/or S planes in place.
+ */
+static void
+si_blit_decompress_zs_in_place(struct si_context *sctx,
+ struct r600_texture *texture,
+ unsigned levels_z, unsigned levels_s,
+ unsigned first_layer, unsigned last_layer)
+{
+ unsigned both = levels_z & levels_s;
+
+ /* First, do combined Z & S decompresses for levels that need it. */
+ if (both) {
+ si_blit_decompress_zs_planes_in_place(
+ sctx, texture, PIPE_MASK_Z | PIPE_MASK_S,
+ both,
+ first_layer, last_layer);
+ levels_z &= ~both;
+ levels_s &= ~both;
+ }
+
+ /* Now do separate Z and S decompresses. */
+ if (levels_z) {
+ si_blit_decompress_zs_planes_in_place(
+ sctx, texture, PIPE_MASK_Z,
+ levels_z,
+ first_layer, last_layer);
+ }
+
+ if (levels_s) {
+ si_blit_decompress_zs_planes_in_place(
+ sctx, texture, PIPE_MASK_S,
+ levels_s,
+ first_layer, last_layer);
+ }
+}
+
+static void
+si_flush_depth_texture(struct si_context *sctx,
+ struct r600_texture *tex,
+ unsigned required_planes,
+ unsigned first_level, unsigned last_level,
+ unsigned first_layer, unsigned last_layer)
+{
+ unsigned inplace_planes = 0;
+ unsigned copy_planes = 0;
+ unsigned level_mask = u_bit_consecutive(first_level, last_level - first_level + 1);
+ unsigned levels_z = 0;
+ unsigned levels_s = 0;
+
+ if (required_planes & PIPE_MASK_Z) {
+ levels_z = level_mask & tex->dirty_level_mask;
+
+ if (levels_z) {
+ if (r600_can_sample_zs(tex, false))
+ inplace_planes |= PIPE_MASK_Z;
+ else
+ copy_planes |= PIPE_MASK_Z;
+ }
+ }
+ if (required_planes & PIPE_MASK_S) {
+ levels_s = level_mask & tex->stencil_dirty_level_mask;
+
+ if (levels_s) {
+ if (r600_can_sample_zs(tex, true))
+ inplace_planes |= PIPE_MASK_S;
+ else
+ copy_planes |= PIPE_MASK_S;
+ }
+ }
+
+ assert(!tex->tc_compatible_htile || levels_z == 0);
+
+ /* We may have to allocate the flushed texture here when called from
+ * si_decompress_subresource.
+ */
+ if (copy_planes &&
+ (tex->flushed_depth_texture ||
+ r600_init_flushed_depth_texture(&sctx->b.b, &tex->resource.b.b, NULL))) {
+ struct r600_texture *dst = tex->flushed_depth_texture;
+ unsigned fully_copied_levels;
+ unsigned levels = 0;
+
+ assert(tex->flushed_depth_texture);
+
+ if (util_format_is_depth_and_stencil(dst->resource.b.b.format))
+ copy_planes = PIPE_MASK_Z | PIPE_MASK_S;
+
+ if (copy_planes & PIPE_MASK_Z) {
+ levels |= levels_z;
+ levels_z = 0;
+ }
+ if (copy_planes & PIPE_MASK_S) {
+ levels |= levels_s;
+ levels_s = 0;
+ }
+
+ fully_copied_levels = si_blit_dbcb_copy(
+ sctx, tex, dst, copy_planes, levels,
+ first_layer, last_layer,
+ 0, u_max_sample(&tex->resource.b.b));
+
+ if (copy_planes & PIPE_MASK_Z)
+ tex->dirty_level_mask &= ~fully_copied_levels;
+ if (copy_planes & PIPE_MASK_S)
+ tex->stencil_dirty_level_mask &= ~fully_copied_levels;
+ }
+
+ if (inplace_planes) {
+ si_blit_decompress_zs_in_place(
+ sctx, tex,
+ levels_z, levels_s,
+ first_layer, last_layer);
+ }
+}
+
+static void
+si_flush_depth_textures(struct si_context *sctx,
+ struct si_textures_info *textures)