mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-06 07:18:17 +02:00
panfrost: Use pan_image_test_modifier_with_format() to do our modifier check
Now that we have pan_image_test_modifier_with_format(), use it do our native modifier check. This involves fully describing the YUV lowering even for formats that don't have a native YUV-as-RGB fallback. Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com> Reviewed-by: Lars-Ivar Hesselberg Simonsen <lars-ivar.simonsen@arm.com> Reviewed-by: Eric R. Smith <eric.smith@collabora.com> Acked-by: Daniel Stone <daniels@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35761>
This commit is contained in:
parent
6c0e72ba5a
commit
590ad83b98
2 changed files with 135 additions and 95 deletions
|
|
@ -257,54 +257,116 @@ panfrost_lower_yuv_format(struct panfrost_device *dev,
|
|||
assert(util_format_is_yuv(format));
|
||||
|
||||
switch (format) {
|
||||
#define SINGLE_RES(__in, __out) \
|
||||
case PIPE_FORMAT_##__in: \
|
||||
if (dev->formats[PIPE_FORMAT_##__out].bind & PAN_BIND_SAMPLER_VIEW) { \
|
||||
#define TRY_LOWERING(...) \
|
||||
do { \
|
||||
const enum pipe_format out_fmts__[] = {__VA_ARGS__}; \
|
||||
bool supported__ = true; \
|
||||
for (unsigned r__ = 0; r__ < ARRAY_SIZE(out_fmts__); r__++) { \
|
||||
supported__ &= \
|
||||
!!(dev->formats[out_fmts__[r__]].bind & PAN_BIND_SAMPLER_VIEW); \
|
||||
} \
|
||||
if (supported__) { \
|
||||
return (struct panfrost_yuv_format_lowering){ \
|
||||
.nres = 1, \
|
||||
.res_formats[0] = PIPE_FORMAT_##__out, \
|
||||
.nres = ARRAY_SIZE(out_fmts__), \
|
||||
.res_formats = {__VA_ARGS__}, \
|
||||
}; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
case PIPE_FORMAT_AYUV:
|
||||
TRY_LOWERING(PIPE_FORMAT_RGBA8888_UNORM);
|
||||
break;
|
||||
case PIPE_FORMAT_XYUV:
|
||||
TRY_LOWERING(PIPE_FORMAT_RGBX8888_UNORM);
|
||||
break;
|
||||
case PIPE_FORMAT_Y410:
|
||||
TRY_LOWERING(PIPE_FORMAT_R10G10B10A2_UNORM);
|
||||
break;
|
||||
case PIPE_FORMAT_Y412:
|
||||
case PIPE_FORMAT_Y416:
|
||||
TRY_LOWERING(PIPE_FORMAT_R16G16B16A16_UNORM);
|
||||
break;
|
||||
case PIPE_FORMAT_YUYV:
|
||||
TRY_LOWERING(PIPE_FORMAT_R8G8_R8B8_UNORM);
|
||||
TRY_LOWERING(PIPE_FORMAT_RG88_UNORM, PIPE_FORMAT_BGRA8888_UNORM);
|
||||
break;
|
||||
case PIPE_FORMAT_UYVY:
|
||||
TRY_LOWERING(PIPE_FORMAT_G8R8_B8R8_UNORM);
|
||||
TRY_LOWERING(PIPE_FORMAT_RG88_UNORM, PIPE_FORMAT_RGBA8888_UNORM);
|
||||
break;
|
||||
case PIPE_FORMAT_YVYU:
|
||||
TRY_LOWERING(PIPE_FORMAT_R8B8_R8G8_UNORM);
|
||||
TRY_LOWERING(PIPE_FORMAT_RG88_UNORM, PIPE_FORMAT_BGRA8888_UNORM);
|
||||
break;
|
||||
case PIPE_FORMAT_VYUY:
|
||||
TRY_LOWERING(PIPE_FORMAT_B8R8_G8R8_UNORM);
|
||||
TRY_LOWERING(PIPE_FORMAT_RG88_UNORM, PIPE_FORMAT_RGBA8888_UNORM);
|
||||
break;
|
||||
case PIPE_FORMAT_NV12:
|
||||
TRY_LOWERING(PIPE_FORMAT_R8_G8B8_420_UNORM);
|
||||
TRY_LOWERING(PIPE_FORMAT_R8_UNORM, PIPE_FORMAT_RG88_UNORM);
|
||||
break;
|
||||
case PIPE_FORMAT_NV21:
|
||||
TRY_LOWERING(PIPE_FORMAT_R8_B8G8_420_UNORM);
|
||||
TRY_LOWERING(PIPE_FORMAT_R8_UNORM, PIPE_FORMAT_RG88_UNORM);
|
||||
break;
|
||||
case PIPE_FORMAT_NV16:
|
||||
TRY_LOWERING(PIPE_FORMAT_R8_G8B8_422_UNORM);
|
||||
TRY_LOWERING(PIPE_FORMAT_R8_UNORM, PIPE_FORMAT_RG88_UNORM);
|
||||
break;
|
||||
case PIPE_FORMAT_NV15:
|
||||
TRY_LOWERING(PIPE_FORMAT_R10_G10B10_420_UNORM);
|
||||
break;
|
||||
case PIPE_FORMAT_NV20:
|
||||
TRY_LOWERING(PIPE_FORMAT_R10_G10B10_422_UNORM);
|
||||
break;
|
||||
case PIPE_FORMAT_IYUV:
|
||||
TRY_LOWERING(PIPE_FORMAT_R8_G8_B8_420_UNORM);
|
||||
TRY_LOWERING(PIPE_FORMAT_R8_UNORM, PIPE_FORMAT_R8_UNORM, PIPE_FORMAT_R8_UNORM);
|
||||
break;
|
||||
case PIPE_FORMAT_YV12:
|
||||
TRY_LOWERING(PIPE_FORMAT_R8_B8_G8_420_UNORM);
|
||||
TRY_LOWERING(PIPE_FORMAT_R8_UNORM, PIPE_FORMAT_R8_UNORM, PIPE_FORMAT_R8_UNORM);
|
||||
break;
|
||||
case PIPE_FORMAT_Y8U8V8_420_UNORM_PACKED:
|
||||
TRY_LOWERING(PIPE_FORMAT_R8G8B8_420_UNORM_PACKED);
|
||||
break;
|
||||
case PIPE_FORMAT_Y10U10V10_420_UNORM_PACKED:
|
||||
TRY_LOWERING(PIPE_FORMAT_R10G10B10_420_UNORM_PACKED);
|
||||
break;
|
||||
case PIPE_FORMAT_Y210:
|
||||
case PIPE_FORMAT_Y212:
|
||||
case PIPE_FORMAT_Y216:
|
||||
TRY_LOWERING(PIPE_FORMAT_RG1616_UNORM, PIPE_FORMAT_R16G16B16A16_UNORM);
|
||||
break;
|
||||
case PIPE_FORMAT_P010:
|
||||
case PIPE_FORMAT_P012:
|
||||
case PIPE_FORMAT_P016:
|
||||
case PIPE_FORMAT_P030:
|
||||
TRY_LOWERING(PIPE_FORMAT_R16_UNORM, PIPE_FORMAT_RG1616_UNORM);
|
||||
break;
|
||||
|
||||
SINGLE_RES(AYUV, RGBA8888_UNORM)
|
||||
SINGLE_RES(XYUV, RGBX8888_UNORM)
|
||||
SINGLE_RES(YUYV, R8G8_R8B8_UNORM)
|
||||
SINGLE_RES(UYVY, G8R8_B8R8_UNORM)
|
||||
SINGLE_RES(YVYU, R8B8_R8G8_UNORM)
|
||||
SINGLE_RES(VYUY, B8R8_G8R8_UNORM)
|
||||
SINGLE_RES(NV12, R8_G8B8_420_UNORM)
|
||||
SINGLE_RES(NV21, R8_B8G8_420_UNORM)
|
||||
SINGLE_RES(NV16, R8_G8B8_422_UNORM)
|
||||
SINGLE_RES(NV15, R10_G10B10_420_UNORM)
|
||||
SINGLE_RES(NV20, R10_G10B10_422_UNORM)
|
||||
SINGLE_RES(IYUV, R8_G8_B8_420_UNORM)
|
||||
SINGLE_RES(YV12, R8_B8_G8_420_UNORM)
|
||||
SINGLE_RES(Y8U8V8_420_UNORM_PACKED, R8G8B8_420_UNORM_PACKED)
|
||||
SINGLE_RES(Y10U10V10_420_UNORM_PACKED, R10G10B10_420_UNORM_PACKED)
|
||||
case PIPE_FORMAT_Y10X6_U10X6_V10X6_420_UNORM:
|
||||
case PIPE_FORMAT_Y10X6_U10X6_V10X6_422_UNORM:
|
||||
case PIPE_FORMAT_Y10X6_U10X6_V10X6_444_UNORM:
|
||||
case PIPE_FORMAT_Y12X4_U12X4_V12X4_420_UNORM:
|
||||
case PIPE_FORMAT_Y12X4_U12X4_V12X4_422_UNORM:
|
||||
case PIPE_FORMAT_Y12X4_U12X4_V12X4_444_UNORM:
|
||||
case PIPE_FORMAT_Y16_U16_V16_420_UNORM:
|
||||
case PIPE_FORMAT_Y16_U16_V16_422_UNORM:
|
||||
case PIPE_FORMAT_Y16_U16_V16_444_UNORM:
|
||||
TRY_LOWERING(PIPE_FORMAT_R16_UNORM, PIPE_FORMAT_R16_UNORM,
|
||||
PIPE_FORMAT_R16_UNORM);
|
||||
break;
|
||||
|
||||
#undef SINGLE_RES
|
||||
#undef TRY_LOWERING
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
struct panfrost_yuv_format_lowering lowering = {0};
|
||||
unsigned nplanes = util_format_get_num_planes(format);
|
||||
for (unsigned i = 0; i < nplanes; i++) {
|
||||
lowering.res_formats[lowering.nres++] =
|
||||
util_format_get_plane_format(format, i);
|
||||
|
||||
/* If there's no YUV-as-RGB lowering available, the original YUV format
|
||||
* will be returned, and only LINEAR will be allowed. */
|
||||
if (i == 0 && lowering.res_formats[i] == format)
|
||||
return lowering;
|
||||
|
||||
/* If plane0 got lowered, so should planeX. */
|
||||
assert(lowering.res_formats[i] != format);
|
||||
}
|
||||
|
||||
return lowering;
|
||||
mesa_loge("%s is not supported\n", util_format_name(format));
|
||||
return (struct panfrost_yuv_format_lowering){0};
|
||||
}
|
||||
|
||||
/* We always support linear and tiled operations, both external and internal.
|
||||
|
|
@ -325,83 +387,61 @@ panfrost_walk_dmabuf_modifiers(struct pipe_screen *screen,
|
|||
yuv_lowering =
|
||||
panfrost_lower_yuv_format(dev, format);
|
||||
|
||||
/* If we get there, format support must have been validated beforehand,
|
||||
* and the lowering can't return 0 resouces. Similarly, it can't be a YUV
|
||||
* format either. */
|
||||
assert(yuv_lowering.nres >= 1);
|
||||
for (unsigned i = 0; i < yuv_lowering.nres; i++)
|
||||
assert(!util_format_is_yuv(yuv_lowering.res_formats[i]));
|
||||
|
||||
if (yuv_lowering.nres == 1)
|
||||
format = yuv_lowering.res_formats[0];
|
||||
}
|
||||
|
||||
/* Query AFBC status */
|
||||
bool afbc = dev->has_afbc;
|
||||
bool ytr = afbc && !is_yuv;
|
||||
bool tiled_afbc = pan_afbc_can_tile(dev->arch);
|
||||
bool afrc = allow_afrc && dev->has_afrc;
|
||||
|
||||
if (is_yuv && yuv_lowering.nres > 1) {
|
||||
for (unsigned i = 0; i < yuv_lowering.nres; i++) {
|
||||
enum pipe_format plane_format = yuv_lowering.res_formats[i];
|
||||
|
||||
afbc &= pan_afbc_supports_format(dev->arch, plane_format);
|
||||
}
|
||||
} else {
|
||||
afbc &= pan_afbc_supports_format(dev->arch, format);
|
||||
ytr &= pan_afbc_can_ytr(format);
|
||||
afrc &= !is_yuv && pan_afrc_supports_format(format);
|
||||
}
|
||||
|
||||
PANFROST_EMULATED_MODIFIERS(emulated_mods);
|
||||
PAN_SUPPORTED_MODIFIERS(native_mods);
|
||||
unsigned count = 0;
|
||||
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(native_mods); ++i) {
|
||||
if (drm_is_afbc(native_mods[i])) {
|
||||
if (!afbc)
|
||||
continue;
|
||||
uint64_t mod = native_mods[i];
|
||||
|
||||
if ((native_mods[i] & AFBC_FORMAT_MOD_SPLIT)) {
|
||||
unsigned nplanes = util_format_get_num_planes(format);
|
||||
bool can_split = true;
|
||||
if ((dev->debug & PAN_DBG_NO_AFBC) && drm_is_afbc(mod))
|
||||
continue;
|
||||
|
||||
for (unsigned p = 0; p < nplanes; p++) {
|
||||
if (is_yuv && yuv_lowering.nres > 1) {
|
||||
can_split &= pan_afbc_can_split(
|
||||
dev->arch, yuv_lowering.res_formats[p], native_mods[i], 0);
|
||||
} else {
|
||||
can_split &=
|
||||
pan_afbc_can_split(dev->arch, format, native_mods[i], p);
|
||||
}
|
||||
}
|
||||
if (!allow_afrc && drm_is_afrc(mod))
|
||||
continue;
|
||||
|
||||
if (!can_split)
|
||||
continue;
|
||||
/* Some single-plane subsampled YUV formats need to be lowered to two
|
||||
* resources pointing to the same image. Such aliasing only works with
|
||||
* linear images, so bail out early if that's the case and the modifier is
|
||||
* not linear. */
|
||||
if (yuv_lowering.nres > util_format_get_num_planes(format) &&
|
||||
mod != DRM_FORMAT_MOD_LINEAR)
|
||||
continue;
|
||||
|
||||
/* Defer the <modifier,format> test to the mod handler. */
|
||||
bool supported;
|
||||
if (is_yuv && yuv_lowering.nres > 1) {
|
||||
supported = true;
|
||||
for (unsigned r = 0; r < yuv_lowering.nres; r++) {
|
||||
enum pipe_format res_format = yuv_lowering.res_formats[r];
|
||||
|
||||
supported &= pan_image_test_modifier_with_format(&dev->kmod.props,
|
||||
mod, res_format);
|
||||
}
|
||||
|
||||
if ((native_mods[i] & AFBC_FORMAT_MOD_YTR) && !ytr)
|
||||
continue;
|
||||
|
||||
if ((native_mods[i] & AFBC_FORMAT_MOD_TILED) && !tiled_afbc)
|
||||
continue;
|
||||
} else {
|
||||
supported =
|
||||
pan_image_test_modifier_with_format(&dev->kmod.props, mod, format);
|
||||
}
|
||||
|
||||
if (drm_is_afrc(native_mods[i]) && !afrc)
|
||||
if (!supported)
|
||||
continue;
|
||||
|
||||
/* If the format is still YUV after lowering, the SW emulation might
|
||||
* involve plane aliasing which we can't do with U_TILED. */
|
||||
if (util_format_is_yuv(format) &&
|
||||
native_mods[i] == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED)
|
||||
continue;
|
||||
|
||||
/* Some formats only work with AFBC. */
|
||||
if ((native_mods[i] == DRM_FORMAT_MOD_LINEAR ||
|
||||
native_mods[i] == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) &&
|
||||
!pan_u_tiled_or_linear_supports_format(format))
|
||||
continue;
|
||||
|
||||
if (test_modifier != DRM_FORMAT_MOD_INVALID &&
|
||||
test_modifier != native_mods[i])
|
||||
if (test_modifier != DRM_FORMAT_MOD_INVALID && test_modifier != mod)
|
||||
continue;
|
||||
|
||||
if (max > (int)count) {
|
||||
modifiers[count] = native_mods[i];
|
||||
modifiers[count] = mod;
|
||||
|
||||
if (external_only)
|
||||
external_only[count] = is_yuv;
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ panthor_kmod_dev_create(int fd, uint32_t flags, drmVersionPtr version,
|
|||
}
|
||||
|
||||
/* Map the LATEST_FLUSH_ID register at device creation time. */
|
||||
if (version->version_major > 1 || version->version_minor >= 5) {
|
||||
if (version->version_major > 1 || version->version_minor >= 10) {
|
||||
struct drm_panthor_set_user_mmio_offset user_mmio_offset = {
|
||||
.offset = DRM_PANTHOR_USER_MMIO_OFFSET,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue