diff --git a/src/panfrost/lib/pan_afbc.h b/src/panfrost/lib/pan_afbc.h index f0328a0ba44..393b59009c0 100644 --- a/src/panfrost/lib/pan_afbc.h +++ b/src/panfrost/lib/pan_afbc.h @@ -638,21 +638,103 @@ pan_afbc_can_ytr(enum pipe_format format) } static inline bool -pan_afbc_can_split(unsigned arch, enum pan_afbc_mode mode, uint64_t modifier) +pan_afbc_check_params(enum pan_afbc_mode mode, uint64_t modifier) { unsigned block_width = pan_afbc_superblock_width(modifier); + bool is_split = modifier & AFBC_FORMAT_MOD_SPLIT; - if (arch < 6) - return false; - - if (block_width == 16) { - return true; - } else if (block_width == 32) { - return (mode == PAN_AFBC_MODE_R8G8B8A8 || - mode == PAN_AFBC_MODE_R10G10B10A2); + /* YTR is not useful on RGB formats, nor with one- or two-channel + * formats */ + bool is_ytr = modifier & AFBC_FORMAT_MOD_YTR; + switch (mode) { + case PAN_AFBC_MODE_YUV420_6C8: + case PAN_AFBC_MODE_YUV420_2C8: + case PAN_AFBC_MODE_YUV420_1C8: + case PAN_AFBC_MODE_YUV420_6C10: + case PAN_AFBC_MODE_YUV420_2C10: + case PAN_AFBC_MODE_YUV420_1C10: + case PAN_AFBC_MODE_YUV422_4C8: + case PAN_AFBC_MODE_YUV422_2C8: + case PAN_AFBC_MODE_YUV422_1C8: + case PAN_AFBC_MODE_YUV422_4C10: + case PAN_AFBC_MODE_YUV422_2C10: + case PAN_AFBC_MODE_YUV422_1C10: + case PAN_AFBC_MODE_R8: + case PAN_AFBC_MODE_R8G8: + case PAN_AFBC_MODE_R16: + case PAN_AFBC_MODE_R16G16: + if (is_ytr) + return false; + break; + default: + break; } - return false; + /* 16x16 superblocks are universally compatible */ + if (block_width == 16) + return true; + + /* 64x4 blocks are only usable for multi-planar YUV formats, + * and not in block-split mode. */ + if (block_width == 64) { + switch (mode) { + case PAN_AFBC_MODE_YUV420_2C8: + case PAN_AFBC_MODE_YUV420_1C8: + case PAN_AFBC_MODE_YUV420_2C10: + case PAN_AFBC_MODE_YUV420_1C10: + case PAN_AFBC_MODE_YUV422_2C8: + case PAN_AFBC_MODE_YUV422_1C8: + case PAN_AFBC_MODE_YUV422_2C10: + case PAN_AFBC_MODE_YUV422_1C10: + return !is_split; + default: + return false; + } + } + + assert(block_width == 32); + + /* 32x8 superblocks have different requirements based on the format: + * block-split mode is required for effective bpp >16, and prohibited + * for effective bpp <= 16. */ + switch (mode) { + case PAN_AFBC_MODE_R8G8B8: + case PAN_AFBC_MODE_R8G8B8A8: + case PAN_AFBC_MODE_R10G10B10A2: + case PAN_AFBC_MODE_R11G11B10: + case PAN_AFBC_MODE_R16G16: + case PAN_AFBC_MODE_R16G16B16: + case PAN_AFBC_MODE_R16G16B16A16: + return is_split; + case PAN_AFBC_MODE_R8: + case PAN_AFBC_MODE_R8G8: + case PAN_AFBC_MODE_R5G6B5: + case PAN_AFBC_MODE_R4G4B4A4: + case PAN_AFBC_MODE_R5G5B5A1: + case PAN_AFBC_MODE_R16: + case PAN_AFBC_MODE_YUV420_6C8: + case PAN_AFBC_MODE_YUV420_6C10: + case PAN_AFBC_MODE_YUV422_4C8: + case PAN_AFBC_MODE_YUV422_4C10: + return !is_split; + /* The following split luma/chroma layouts require + * AFBC_FORMAT_MOD_BLOCK_SIZE_32x8_64x4 to be usable, since the luma + * planes require non-split 32x8, and the chroma planes require 64x4. + */ + case PAN_AFBC_MODE_YUV420_1C8: + case PAN_AFBC_MODE_YUV420_1C10: + case PAN_AFBC_MODE_YUV422_1C8: + case PAN_AFBC_MODE_YUV422_1C10: + return !is_split; + case PAN_AFBC_MODE_YUV420_2C8: + case PAN_AFBC_MODE_YUV420_2C10: + case PAN_AFBC_MODE_YUV422_2C8: + case PAN_AFBC_MODE_YUV422_2C10: + return false; + default: + assert(!"unknown mode in pan_afbc_check_params()"); + return false; + } } /* Only support packing for RGB formats for now. */ @@ -675,6 +757,15 @@ pan_afbc_can_tile(unsigned arch) return arch >= 7; } +/* + * Check if a gen supports AFBC with split-block mode. + */ +static inline bool +pan_afbc_can_split(unsigned arch) +{ + return arch >= 6; +} + #if PAN_ARCH >= 9 static inline enum mali_afbc_compression_mode pan_afbc_compression_mode(enum pan_afbc_mode mode) diff --git a/src/panfrost/lib/pan_mod.c b/src/panfrost/lib/pan_mod.c index b0f51d7ba3f..0424a7670dd 100644 --- a/src/panfrost/lib/pan_mod.c +++ b/src/panfrost/lib/pan_mod.c @@ -190,28 +190,20 @@ pan_mod_afbc_test_props(const struct pan_kmod_dev_props *dprops, if ((iprops->modifier & AFBC_FORMAT_MOD_TILED) && !pan_afbc_can_tile(PAN_ARCH)) return PAN_MOD_NOT_SUPPORTED; - unsigned plane_count = util_format_get_num_planes(iprops->format); - const struct util_format_description *fdesc = - util_format_description(iprops->format); - - /* Check if the format supports AFBC */ - enum pan_afbc_mode plane_modes[3]; - for (unsigned p = 0; p < plane_count; p++) { - plane_modes[p] = pan_afbc_format(PAN_ARCH, iprops->format, p); - if (plane_modes[p] == PAN_AFBC_MODE_INVALID) - return PAN_MOD_NOT_SUPPORTED; - - if ((iprops->modifier & AFBC_FORMAT_MOD_SPLIT) && - !pan_afbc_can_split(PAN_ARCH, plane_modes[p], iprops->modifier)) { - return PAN_MOD_NOT_SUPPORTED; - } - } - - /* YTR is only useful on RGB formats. */ - if ((iprops->modifier & AFBC_FORMAT_MOD_YTR) && - (pan_format_is_yuv(iprops->format) || fdesc->nr_channels < 3)) + /* ... or split mode */ + if ((iprops->modifier & AFBC_FORMAT_MOD_SPLIT) && !pan_afbc_can_split(PAN_ARCH)) return PAN_MOD_NOT_SUPPORTED; + /* Check compatibility between formats and parameters */ + unsigned plane_count = util_format_get_num_planes(iprops->format); + for (unsigned p = 0; p < plane_count; p++) { + enum pan_afbc_mode mode = pan_afbc_format(PAN_ARCH, iprops->format, p); + if (mode == PAN_AFBC_MODE_INVALID) + return PAN_MOD_NOT_SUPPORTED; + if (!pan_afbc_check_params(mode, iprops->modifier)) + return PAN_MOD_NOT_SUPPORTED; + } + /* AFBC can't do multisampling. */ if (iprops->nr_samples > 1) return PAN_MOD_NOT_SUPPORTED;