diff --git a/src/gallium/drivers/panfrost/pan_screen.c b/src/gallium/drivers/panfrost/pan_screen.c index f2dc2ef8be7..2d5d7e399e0 100644 --- a/src/gallium/drivers/panfrost/pan_screen.c +++ b/src/gallium/drivers/panfrost/pan_screen.c @@ -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 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; diff --git a/src/panfrost/lib/kmod/panthor_kmod.c b/src/panfrost/lib/kmod/panthor_kmod.c index 95c17f8f825..3dae874a8b5 100644 --- a/src/panfrost/lib/kmod/panthor_kmod.c +++ b/src/panfrost/lib/kmod/panthor_kmod.c @@ -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, };