If try_blorp_blit() previously returned that a blit was too large, shrink_surface_params() will be used to update the surface parameters for the smaller blit so the blit operation can proceed.
Signed-off-by: Jordan Justen <jordan.l.jus...@intel.com> --- src/intel/blorp/blorp_blit.c | 124 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 121 insertions(+), 3 deletions(-) diff --git a/src/intel/blorp/blorp_blit.c b/src/intel/blorp/blorp_blit.c index caa3e33..383b64e 100644 --- a/src/intel/blorp/blorp_blit.c +++ b/src/intel/blorp/blorp_blit.c @@ -1521,6 +1521,12 @@ dump_blorp_surf(const struct blorp_context *blorp, blorp->unmap(blorp, &surf->aux_addr); } +static bool +can_shrink_surfaces(const struct blorp_params *params) +{ + return false; +} + struct blt_axis { float src0, src1, dst0, dst1; bool mirror; @@ -1767,12 +1773,114 @@ adjust_split_coords(const struct blt_axis *orig, split_coords->src1 = orig->src1 + (scale >= 0.0 ? delta1 : delta0); } +static const struct isl_extent2d +get_px_size_sa(const struct isl_surf *surf) +{ + static const struct isl_extent2d one_to_one = { .w = 1, .h = 1 }; + + if (surf->msaa_layout != ISL_MSAA_LAYOUT_INTERLEAVED) + return one_to_one; + else + return isl_get_interleaved_msaa_px_size_sa(surf->samples); +} + +static void +shrink_surface_params(const struct isl_device *dev, + struct brw_blorp_surface_info *info, + int rgb_offset, + float *x0, float *x1, float *y0, float *y1) +{ + uint32_t byte_offset, x_offset_sa, y_offset_sa, size; + struct isl_extent2d px_size_sa; + int adjust; + + uint32_t rgb_adjust = MAX2(rgb_offset, 0); + + surf_convert_to_single_slice(dev, info); + + px_size_sa = get_px_size_sa(&info->surf); + + x_offset_sa = + (uint32_t)*x0 * px_size_sa.w + info->tile_x_sa - rgb_adjust; + y_offset_sa = (uint32_t)*y0 * px_size_sa.h + info->tile_y_sa; + isl_tiling_get_intratile_offset_sa(dev, info->surf.tiling, + info->surf.format, info->surf.row_pitch, + x_offset_sa, y_offset_sa, + &byte_offset, + &info->tile_x_sa, &info->tile_y_sa); + + info->addr.offset += byte_offset; + + adjust = (int)info->tile_x_sa / px_size_sa.w - (int)*x0; + uint32_t rgb_x_tile_offset = + rgb_offset >= 0 ? (((int)*x0 + adjust) % 3) : 0u; + adjust += (int)rgb_adjust - rgb_x_tile_offset; + *x0 += adjust; + assert(rgb_offset < 0 || (uint32_t)*x0 % 3 == rgb_adjust); + *x1 += adjust; + info->tile_x_sa = rgb_x_tile_offset; + + adjust = (int)info->tile_y_sa / px_size_sa.h - (int)*y0; + *y0 += adjust; + *y1 += adjust; + info->tile_y_sa = 0; + + size = ceilf(*x1 + rgb_x_tile_offset); + size = MIN2(size, info->surf.logical_level0_px.width); + float phys_scale = + info->surf.phys_level0_sa.width / info->surf.logical_level0_px.width; + info->surf.logical_level0_px.width = size; + info->surf.phys_level0_sa.width = + (uint32_t)ceilf(phys_scale * size); + + size = ceilf(*y1); + size = MIN2(size, info->surf.logical_level0_px.height); + phys_scale = + info->surf.phys_level0_sa.height / info->surf.logical_level0_px.height; + info->surf.logical_level0_px.height = (uint32_t)ceilf(size); + info->surf.phys_level0_sa.height = + (uint32_t)ceilf(phys_scale * size); +} + +static void +shrink_surfaces(const struct isl_device *dev, + struct blorp_params *params, + struct brw_blorp_blit_prog_key *wm_prog_key, + const struct blt_coords *orig_coords, + struct blt_coords *coords) +{ + /* Shrink source surface */ + shrink_surface_params(dev, + ¶ms->src, + -1, + &coords->x.src0, + &coords->x.src1, + &coords->y.src0, + &coords->y.src1); + wm_prog_key->need_src_offset = false; + + /* Shrink destination surface */ + int rgb_offset = + wm_prog_key->dst_rgb ? + (uint32_t)(coords->x.dst0 - orig_coords->x.dst0) % 3 : -1; + shrink_surface_params(dev, + ¶ms->dst, + rgb_offset, + &coords->x.dst0, + &coords->x.dst1, + &coords->y.dst0, + &coords->y.dst1); + wm_prog_key->need_dst_offset = wm_prog_key->dst_rgb; +} + static void do_blorp_blit(struct blorp_batch *batch, - struct blorp_params *params, + const struct blorp_params *orig_params, struct brw_blorp_blit_prog_key *wm_prog_key, const struct blt_coords *orig) { + struct blorp_params params; + struct blt_coords blit_coords; struct blt_coords split_coords = *orig; float w = orig->x.dst1 - orig->x.dst0; float h = orig->y.dst1 - orig->y.dst0; @@ -1784,9 +1892,16 @@ do_blorp_blit(struct blorp_batch *batch, y_scale = -y_scale; bool x_done, y_done; + bool shrink = false; do { + params = *orig_params; + blit_coords = split_coords; + if (shrink) { + shrink_surfaces(batch->blorp->isl_dev, ¶ms, wm_prog_key, orig, + &blit_coords); + } unsigned result = - try_blorp_blit(batch, params, wm_prog_key, &split_coords); + try_blorp_blit(batch, ¶ms, wm_prog_key, &blit_coords); if (result & BLIT_WIDTH_TOO_LARGE) { w /= 2.0; @@ -1801,8 +1916,11 @@ do_blorp_blit(struct blorp_batch *batch, adjust_split_coords(&orig->y, &split_coords.y, y_scale); } - if (result != 0) + if (result != 0) { + assert(can_shrink_surfaces(orig_params)); + shrink = true; continue; + } y_done = (orig->y.dst1 - split_coords.y.dst1 < 0.5); x_done = y_done && (orig->x.dst1 - split_coords.x.dst1 < 0.5); -- 2.10.2 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev