mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-24 04:08:10 +02:00
pan/afbc: Properly validate format/parameter combinations
AFBC has a number of superblock sizes and valid layouts, with differing combinations allowed. It's quite clear that 16x16 is ambivalent about whether or not block-split mode is used. 64x4 prohibits block-split mode, and 32x8 either requires or prohibits it depending on the format. Add proper handling so we filter out the right combinations. Signed-off-by: Daniel Stone <daniels@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40886>
This commit is contained in:
parent
c5415c7aed
commit
4203b770b4
2 changed files with 113 additions and 30 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue