diff --git a/src/panfrost/lib/pan_cs.c b/src/panfrost/lib/pan_cs.c index 4ca908dbcbb..880bb1878a8 100644 --- a/src/panfrost/lib/pan_cs.c +++ b/src/panfrost/lib/pan_cs.c @@ -206,7 +206,7 @@ pan_prepare_zs(const struct pan_fb_info *fb, #if PAN_ARCH >= 6 const struct pan_image_slice_layout *slice = &zs->image->layout.slices[level]; - ext->zs_afbc_row_stride = slice->afbc.row_stride / + ext->zs_afbc_row_stride = slice->row_stride / AFBC_HEADER_BYTES_PER_TILE; #else ext->zs_block_format = MALI_BLOCK_FORMAT_AFBC; @@ -448,7 +448,7 @@ pan_prepare_rt(const struct pan_fb_info *fb, unsigned idx, const struct pan_image_slice_layout *slice = &rt->image->layout.slices[level]; #if PAN_ARCH >= 6 - cfg->afbc.row_stride = slice->afbc.row_stride / + cfg->afbc.row_stride = slice->row_stride / AFBC_HEADER_BYTES_PER_TILE; cfg->afbc.afbc_wide_block_enable = panfrost_afbc_is_wide(rt->image->layout.modifier); diff --git a/src/panfrost/lib/pan_layout.c b/src/panfrost/lib/pan_layout.c index c6642b15669..ee135f2a511 100644 --- a/src/panfrost/lib/pan_layout.c +++ b/src/panfrost/lib/pan_layout.c @@ -169,9 +169,17 @@ panfrost_get_legacy_stride(const struct pan_image_layout *layout, unsigned level) { unsigned row_stride = layout->slices[level].row_stride; - unsigned bh = panfrost_block_size(layout->modifier, layout->format).height; + struct pan_block_size block_size = + panfrost_block_size(layout->modifier, layout->format); - return row_stride / bh; + if (drm_is_afbc(layout->modifier)) { + unsigned width = u_minify(layout->width, level); + width = ALIGN_POT(width, block_size.width); + + return width * util_format_get_blocksize(layout->format); + } else { + return row_stride / block_size.height; + } } unsigned @@ -179,7 +187,16 @@ panfrost_from_legacy_stride(unsigned legacy_stride, enum pipe_format format, uint64_t modifier) { - return legacy_stride * panfrost_block_size(modifier, format).height; + struct pan_block_size block_size = + panfrost_block_size(modifier, format); + + if (drm_is_afbc(modifier)) { + unsigned width = legacy_stride / util_format_get_blocksize(format); + + return (width / block_size.width) * AFBC_HEADER_BYTES_PER_TILE; + } else { + return legacy_stride * block_size.height; + } } /* Computes the offset into a texture at a particular level/face. Add to @@ -247,7 +264,7 @@ pan_image_layout_init(struct pan_image_layout *layout, unsigned row_stride = fmt_blocksize * effective_width * block_size.height; - if (explicit_layout) { + if (explicit_layout && !afbc) { /* Make sure the explicit stride is valid */ if (explicit_layout->row_stride < row_stride) return false; @@ -258,8 +275,6 @@ pan_image_layout_init(struct pan_image_layout *layout, row_stride = ALIGN_POT(row_stride, 64); } - slice->row_stride = row_stride; - unsigned slice_one_size = row_stride * (effective_height / block_size.height); /* Compute AFBC sizes if necessary */ @@ -268,10 +283,13 @@ pan_image_layout_init(struct pan_image_layout *layout, panfrost_afbc_header_size(width, height); /* Stride between two rows of AFBC headers */ - slice->afbc.row_stride = + slice->row_stride = (effective_width / block_size.width) * AFBC_HEADER_BYTES_PER_TILE; + if (explicit_layout && explicit_layout->row_stride < slice->row_stride) + return false; + /* AFBC body size */ slice->afbc.body_size = slice_one_size; @@ -289,6 +307,8 @@ pan_image_layout_init(struct pan_image_layout *layout, slice_one_size += slice->afbc.header_size; slice->afbc.surface_stride = slice_one_size; } + } else { + slice->row_stride = row_stride; } unsigned slice_full_size = diff --git a/src/panfrost/lib/pan_texture.c b/src/panfrost/lib/pan_texture.c index 9001389d5db..3709ce3b311 100644 --- a/src/panfrost/lib/pan_texture.c +++ b/src/panfrost/lib/pan_texture.c @@ -242,7 +242,7 @@ panfrost_get_surface_strides(const struct pan_image_layout *layout, if (drm_is_afbc(layout->modifier)) { /* Pre v7 don't have a row stride field. This field is * repurposed as a Y offset which we don't use */ - *row_stride = PAN_ARCH < 7 ? 0 : slice->afbc.row_stride; + *row_stride = PAN_ARCH < 7 ? 0 : slice->row_stride; *surf_stride = slice->afbc.surface_stride; } else { *row_stride = slice->row_stride; diff --git a/src/panfrost/lib/pan_texture.h b/src/panfrost/lib/pan_texture.h index 9c89923a689..c44777f7534 100644 --- a/src/panfrost/lib/pan_texture.h +++ b/src/panfrost/lib/pan_texture.h @@ -49,7 +49,17 @@ extern uint64_t pan_best_modifiers[PAN_MODIFIER_COUNT]; struct pan_image_slice_layout { unsigned offset; + + /* For AFBC images, the number of bytes between two rows of AFBC + * headers. + * + * For non-AFBC images, the number of bytes between two rows of texels. + * For linear images, this will equal the logical stride. For + * images that are compressed or interleaved, this will be greater than + * the logical stride. + */ unsigned row_stride; + unsigned surface_stride; struct { @@ -59,9 +69,6 @@ struct pan_image_slice_layout { /* Size of the AFBC body */ unsigned body_size; - /* Stride between two rows of AFBC headers */ - unsigned row_stride; - /* Stride between AFBC headers of two consecutive surfaces. * For 3D textures, this must be set to header size since * AFBC headers are allocated together, for 2D arrays this