diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-12 14:27:29 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-13 09:35:20 +0000 |
commit | c30a6232df03e1efbd9f3b226777b07e087a1122 (patch) | |
tree | e992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/media/gpu/vaapi/vaapi_wrapper.cc | |
parent | 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff) | |
download | qtwebengine-chromium-85-based.tar.gz |
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/media/gpu/vaapi/vaapi_wrapper.cc')
-rw-r--r-- | chromium/media/gpu/vaapi/vaapi_wrapper.cc | 313 |
1 files changed, 142 insertions, 171 deletions
diff --git a/chromium/media/gpu/vaapi/vaapi_wrapper.cc b/chromium/media/gpu/vaapi/vaapi_wrapper.cc index f238e6f0851..ad898555fe7 100644 --- a/chromium/media/gpu/vaapi/vaapi_wrapper.cc +++ b/chromium/media/gpu/vaapi/vaapi_wrapper.cc @@ -10,6 +10,7 @@ #include <va/va.h> #include <va/va_drm.h> #include <va/va_drmcommon.h> +#include <va/va_str.h> #include <va/va_version.h> #include <algorithm> @@ -115,8 +116,10 @@ uint32_t BufferFormatToVAFourCC(gfx::BufferFormat fmt) { return VA_FOURCC_YV12; case gfx::BufferFormat::YUV_420_BIPLANAR: return VA_FOURCC_NV12; + case gfx::BufferFormat::P010: + return VA_FOURCC_P010; default: - NOTREACHED(); + NOTREACHED() << gfx::BufferFormatToString(fmt); return 0; } } @@ -142,6 +145,21 @@ namespace media { namespace { +// Returns true if the SoC has a Gen9 GPU. CPU model ID's are referenced from +// the following file in the kernel source: arch/x86/include/asm/intel-family.h. +bool IsGen9Gpu() { + constexpr int kPentiumAndLaterFamily = 0x06; + constexpr int kSkyLakeModelId = 0x5E; + constexpr int kSkyLake_LModelId = 0x4E; + constexpr int kApolloLakeModelId = 0x5c; + static base::NoDestructor<base::CPU> cpuid; + static const bool is_gen9_gpu = cpuid->family() == kPentiumAndLaterFamily && + (cpuid->model() == kSkyLakeModelId || + cpuid->model() == kSkyLake_LModelId || + cpuid->model() == kApolloLakeModelId); + return is_gen9_gpu; +} + // Returns true if the SoC has a 9.5 GPU. CPU model IDs are referenced from the // following file in the kernel source: arch/x86/include/asm/intel-family.h. bool IsGen95Gpu() { @@ -246,111 +264,18 @@ static const struct { {H264PROFILE_HIGH, VAProfileH264High}, {VP8PROFILE_ANY, VAProfileVP8Version0_3}, {VP9PROFILE_PROFILE0, VAProfileVP9Profile0}, - // VP9 hw encode/decode on profile 1 is not enabled on chromium-vaapi. + // Chrome does not support VP9 Profile 1, see b/153680337. // {VP9PROFILE_PROFILE1, VAProfileVP9Profile1}, - // TODO(crbug.com/1011454, crbug.com/1011469): Reenable VP9PROFILE_PROFILE2 - // and _PROFILE3 when P010 is completely supported. - //{VP9PROFILE_PROFILE2, VAProfileVP9Profile2}, - //{VP9PROFILE_PROFILE3, VAProfileVP9Profile3}, + {VP9PROFILE_PROFILE2, VAProfileVP9Profile2}, + {VP9PROFILE_PROFILE3, VAProfileVP9Profile3}, }; -// Converts the given |va_profile| to the corresponding string. -// See: http://go/gh/intel/libva/blob/master/va/va.h#L359 -std::string VAProfileToString(VAProfile va_profile) { - switch (va_profile) { - case VAProfileNone: - return "VAProfileNone"; - case VAProfileMPEG2Simple: - return "VAProfileMPEG2Simple"; - case VAProfileMPEG2Main: - return "VAProfileMPEG2Main"; - case VAProfileMPEG4Simple: - return "VAProfileMPEG4Simple"; - case VAProfileMPEG4AdvancedSimple: - return "VAProfileMPEG4AdvancedSimple"; - case VAProfileMPEG4Main: - return "VAProfileMPEG4Main"; - case VAProfileH264Baseline: - return "VAProfileH264Baseline"; - case VAProfileH264Main: - return "VAProfileH264Main"; - case VAProfileH264High: - return "VAProfileH264High"; - case VAProfileVC1Simple: - return "VAProfileVC1Simple"; - case VAProfileVC1Main: - return "VAProfileVC1Main"; - case VAProfileVC1Advanced: - return "VAProfileVC1Advanced"; - case VAProfileH263Baseline: - return "VAProfileH263Baseline"; - case VAProfileJPEGBaseline: - return "VAProfileJPEGBaseline"; - case VAProfileH264ConstrainedBaseline: - return "VAProfileH264ConstrainedBaseline"; - case VAProfileVP8Version0_3: - return "VAProfileVP8Version0_3"; - case VAProfileH264MultiviewHigh: - return "VAProfileH264MultiviewHigh"; - case VAProfileH264StereoHigh: - return "VAProfileH264StereoHigh"; - case VAProfileHEVCMain: - return "VAProfileHEVCMain"; - case VAProfileHEVCMain10: - return "VAProfileHEVCMain10"; - case VAProfileVP9Profile0: - return "VAProfileVP9Profile0"; - case VAProfileVP9Profile1: - return "VAProfileVP9Profile1"; - case VAProfileVP9Profile2: - return "VAProfileVP9Profile2"; - case VAProfileVP9Profile3: - return "VAProfileVP9Profile3"; -#if VA_MAJOR_VERSION >= 2 || (VA_MAJOR_VERSION == 1 && VA_MINOR_VERSION >= 2) - case VAProfileHEVCMain12: - return "VAProfileHEVCMain12"; - case VAProfileHEVCMain422_10: - return "VAProfileHEVCMain422_10"; - case VAProfileHEVCMain422_12: - return "VAProfileHEVCMain422_12"; - case VAProfileHEVCMain444: - return "VAProfileHEVCMain444"; - case VAProfileHEVCMain444_10: - return "VAProfileHEVCMain444_10"; - case VAProfileHEVCMain444_12: - return "VAProfileHEVCMain444_12"; - case VAProfileHEVCSccMain: - return "VAProfileHEVCSccMain"; - case VAProfileHEVCSccMain10: - return "VAProfileHEVCSccMain10"; - case VAProfileHEVCSccMain444: - return "VAProfileHEVCSccMain444"; -#endif - default: - NOTREACHED(); - return ""; - } -} - bool IsBlackListedDriver(const std::string& va_vendor_string, VaapiWrapper::CodecMode mode, VAProfile va_profile) { if (!IsModeEncoding(mode)) return false; - // TODO(crbug.com/828482): Remove once H264 encoder on AMD is enabled by - // default. - if (VendorStringToImplementationType(va_vendor_string) == - VAImplementation::kMesaGallium && - base::Contains(va_vendor_string, "AMD STONEY") && - !base::FeatureList::IsEnabled(kVaapiH264AMDEncoder)) { - constexpr VAProfile kH264Profiles[] = {VAProfileH264Baseline, - VAProfileH264Main, VAProfileH264High, - VAProfileH264ConstrainedBaseline}; - if (base::Contains(kH264Profiles, va_profile)) - return true; - } - // TODO(posciak): Remove once VP8 encoding is to be enabled by default. if (va_profile == VAProfileVP8Version0_3 && !base::FeatureList::IsEnabled(kVaapiVP8Encoder)) { @@ -639,8 +564,8 @@ static bool GetRequiredAttribs(const base::Lock* va_lock, VAStatus va_res = vaGetConfigAttributes(va_display, profile, entrypoint, &attrib, 1); if (va_res != VA_STATUS_SUCCESS) { - LOG(ERROR) << "GetConfigAttributes failed for va_profile " - << VAProfileToString(profile); + LOG(ERROR) << "vaGetConfigAttributes failed for " + << vaProfileStr(profile); return false; } @@ -761,7 +686,7 @@ VASupportedProfiles::VASupportedProfiles() static_assert(std::extent<decltype(supported_profiles_)>() == VaapiWrapper::kCodecModeMax, - "The array size of supported profile is incorrect."); + "|supported_profiles_| size is incorrect."); if (!display_state->Initialize()) return; @@ -793,6 +718,18 @@ VASupportedProfiles::GetSupportedProfileInfosForCodecModeInternal( VaapiWrapper::CodecMode mode) const { std::vector<ProfileInfo> supported_profile_infos; std::vector<VAProfile> va_profiles; + // VAProfiles supported by VaapiWrapper. + constexpr VAProfile kSupportedVaProfiles[] = { + VAProfileH264ConstrainedBaseline, + VAProfileH264Main, + VAProfileH264High, + VAProfileJPEGBaseline, + VAProfileVP8Version0_3, + VAProfileVP9Profile0, + // Chrome does not support VP9 Profile 1, see b/153680337. + // VAProfileVP9Profile1, + VAProfileVP9Profile2, + VAProfileVP9Profile3}; if (!GetSupportedVAProfiles(&va_profiles)) return supported_profile_infos; @@ -802,6 +739,10 @@ VASupportedProfiles::GetSupportedProfileInfosForCodecModeInternal( VADisplayState::Get()->va_vendor_string(); for (const auto& va_profile : va_profiles) { + if ((mode != VaapiWrapper::CodecMode::kVideoProcess) && + !base::Contains(kSupportedVaProfiles, va_profile)) { + continue; + } const std::vector<VAEntrypoint> supported_entrypoints = GetEntryPointsForProfile(va_lock_, va_display_, mode, va_profile); if (supported_entrypoints.empty()) @@ -824,8 +765,8 @@ VASupportedProfiles::GetSupportedProfileInfosForCodecModeInternal( if (!FillProfileInfo_Locked(va_profile, entrypoint, required_attribs, &profile_info)) { LOG(ERROR) << "FillProfileInfo_Locked failed for va_profile " - << VAProfileToString(va_profile) << " and entrypoint " - << entrypoint; + << vaProfileStr(va_profile) << " and entrypoint " + << vaEntrypointStr(entrypoint); continue; } supported_profile_infos.push_back(profile_info); @@ -1195,6 +1136,37 @@ bool VASupportedImageFormats::InitSupportedImageFormats_Locked() { return true; } +bool IsLowPowerEncSupported(VAProfile va_profile) { + constexpr VAProfile kSupportedLowPowerEncodeProfiles[] = { + VAProfileH264ConstrainedBaseline, + VAProfileH264Main, + VAProfileH264High, + VAProfileVP9Profile0, + VAProfileVP9Profile1, + VAProfileVP9Profile2, + VAProfileVP9Profile3}; + if (!base::Contains(kSupportedLowPowerEncodeProfiles, va_profile)) + return false; + + if ((IsGen95Gpu() || IsGen9Gpu()) && + !base::FeatureList::IsEnabled(kVaapiLowPowerEncoderGen9x)) { + return false; + } + + const std::vector<VASupportedProfiles::ProfileInfo>& encode_profile_infos = + VASupportedProfiles::Get().GetSupportedProfileInfosForCodecMode( + VaapiWrapper::kEncode); + + for (const auto& profile_info : encode_profile_infos) { + if (profile_info.va_profile == va_profile && + profile_info.va_entrypoint == VAEntrypointEncSliceLP) { + return true; + } + } + + return false; +} + } // namespace NativePixmapAndSizeInfo::NativePixmapAndSizeInfo() = default; @@ -1212,7 +1184,7 @@ scoped_refptr<VaapiWrapper> VaapiWrapper::Create( VAProfile va_profile, const base::Closure& report_error_to_uma_cb) { if (!VASupportedProfiles::Get().IsProfileSupported(mode, va_profile)) { - DVLOG(1) << "Unsupported va_profile: " << va_profile; + DVLOG(1) << "Unsupported va_profile: " << vaProfileStr(va_profile); return nullptr; } @@ -1222,7 +1194,7 @@ scoped_refptr<VaapiWrapper> VaapiWrapper::Create( return vaapi_wrapper; } LOG(ERROR) << "Failed to create VaapiWrapper for va_profile: " - << VAProfileToString(va_profile); + << vaProfileStr(va_profile); return nullptr; } @@ -1494,8 +1466,10 @@ VAEntrypoint VaapiWrapper::GetDefaultVaEntryPoint(CodecMode mode, case VaapiWrapper::kEncodeConstantQuantizationParameter: if (profile == VAProfileJPEGBaseline) return VAEntrypointEncPicture; - else - return VAEntrypointEncSlice; + DCHECK(IsModeEncoding(mode)); + if (IsLowPowerEncSupported(profile)) + return VAEntrypointEncSliceLP; + return VAEntrypointEncSlice; case VaapiWrapper::kVideoProcess: return VAEntrypointVideoProc; case VaapiWrapper::kCodecModeMax: @@ -1515,8 +1489,10 @@ uint32_t VaapiWrapper::BufferFormatToVARTFormat(gfx::BufferFormat fmt) { case gfx::BufferFormat::YVU_420: case gfx::BufferFormat::YUV_420_BIPLANAR: return VA_RT_FORMAT_YUV420; + case gfx::BufferFormat::P010: + return VA_RT_FORMAT_YUV420_10BPP; default: - NOTREACHED(); + NOTREACHED() << gfx::BufferFormatToString(fmt); return 0; } } @@ -2028,6 +2004,28 @@ bool VaapiWrapper::CreateVABuffer(size_t size, VABufferID* buffer_id) { return true; } +uint64_t VaapiWrapper::GetEncodedChunkSize(VABufferID buffer_id, + VASurfaceID sync_surface_id) { + TRACE_EVENT0("media,gpu", "VaapiWrapper::GetEncodedChunkSize"); + base::AutoLock auto_lock(*va_lock_); + TRACE_EVENT0("media,gpu", "VaapiWrapper::GetEncodedChunkSizeLocked"); + VAStatus va_res = vaSyncSurface(va_display_, sync_surface_id); + VA_SUCCESS_OR_RETURN(va_res, "vaSyncSurface", 0u); + + ScopedVABufferMapping mapping(va_lock_, va_display_, buffer_id); + if (!mapping.IsValid()) + return 0u; + + uint64_t coded_data_size = 0; + for (auto* buffer_segment = + reinterpret_cast<VACodedBufferSegment*>(mapping.data()); + buffer_segment; buffer_segment = reinterpret_cast<VACodedBufferSegment*>( + buffer_segment->next)) { + coded_data_size += buffer_segment->size; + } + return coded_data_size; +} + bool VaapiWrapper::DownloadFromVABuffer(VABufferID buffer_id, VASurfaceID sync_surface_id, uint8_t* target_ptr, @@ -2062,13 +2060,11 @@ bool VaapiWrapper::DownloadFromVABuffer(VABufferID buffer_id, << ", the buffer segment size: " << buffer_segment->size; break; } - memcpy(target_ptr, buffer_segment->buf, buffer_segment->size); target_ptr += buffer_segment->size; - *coded_data_size += buffer_segment->size; target_size -= buffer_segment->size; - + *coded_data_size += buffer_segment->size; buffer_segment = reinterpret_cast<VACodedBufferSegment*>(buffer_segment->next); } @@ -2113,10 +2109,28 @@ void VaapiWrapper::DestroyVABuffers() { va_buffers_.clear(); } +bool VaapiWrapper::IsRotationSupported() { + base::AutoLock auto_lock(*va_lock_); + VAProcPipelineCaps pipeline_caps; + memset(&pipeline_caps, 0, sizeof(pipeline_caps)); + VAStatus va_res = vaQueryVideoProcPipelineCaps(va_display_, va_context_id_, + nullptr, 0, &pipeline_caps); + if (va_res != VA_STATUS_SUCCESS) { + LOG_VA_ERROR_AND_REPORT(va_res, "vaQueryVideoProcPipelineCaps failed"); + return false; + } + if (!pipeline_caps.rotation_flags) { + DVLOG(2) << "VA-API driver doesn't support any rotation"; + return false; + } + return true; +} + bool VaapiWrapper::BlitSurface(const VASurface& va_surface_src, const VASurface& va_surface_dest, base::Optional<gfx::Rect> src_rect, - base::Optional<gfx::Rect> dest_rect) { + base::Optional<gfx::Rect> dest_rect, + VideoRotation rotation) { base::AutoLock auto_lock(*va_lock_); if (va_buffers_.empty()) { @@ -2165,6 +2179,21 @@ bool VaapiWrapper::BlitSurface(const VASurface& va_surface_src, pipeline_param->output_color_standard = VAProcColorStandardNone; pipeline_param->filter_flags = VA_FILTER_SCALING_DEFAULT; + switch (rotation) { + case VIDEO_ROTATION_0: + pipeline_param->rotation_state = VA_ROTATION_NONE; + break; + case VIDEO_ROTATION_90: + pipeline_param->rotation_state = VA_ROTATION_90; + break; + case VIDEO_ROTATION_180: + pipeline_param->rotation_state = VA_ROTATION_180; + break; + case VIDEO_ROTATION_270: + pipeline_param->rotation_state = VA_ROTATION_270; + break; + } + VA_SUCCESS_OR_RETURN(mapping.Unmap(), "Vpp Buffer unmapping", false); } @@ -2241,15 +2270,7 @@ bool VaapiWrapper::Initialize(CodecMode mode, VAProfile va_profile) { } #endif // DCHECK_IS_ON() - if (mode != kVideoProcess) - TryToSetVADisplayAttributeToLocalGPU(); - - VAEntrypoint entrypoint = GetDefaultVaEntryPoint(mode, va_profile); - if (IsModeEncoding(mode) && IsLowPowerEncSupported(va_profile, mode) && - base::FeatureList::IsEnabled(kVaapiLowPowerEncoder)) { - entrypoint = VAEntrypointEncSliceLP; - DVLOG(2) << "Enable VA-API Low-Power Encode Entrypoint"; - } + const VAEntrypoint entrypoint = GetDefaultVaEntryPoint(mode, va_profile); base::AutoLock auto_lock(*va_lock_); std::vector<VAConfigAttrib> required_attribs; @@ -2258,7 +2279,7 @@ bool VaapiWrapper::Initialize(CodecMode mode, VAProfile va_profile) { return false; } - VAStatus va_res = + const VAStatus va_res = vaCreateConfig(va_display_, va_profile, entrypoint, required_attribs.empty() ? nullptr : &required_attribs[0], required_attribs.size(), &va_config_id_); @@ -2456,54 +2477,4 @@ bool VaapiWrapper::Execute_Locked(VASurfaceID va_surface_id) { return true; } -void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { - base::AutoLock auto_lock(*va_lock_); - VADisplayAttribute item = {VADisplayAttribRenderMode, - 1, // At least support '_LOCAL_OVERLAY'. - -1, // The maximum possible support 'ALL'. - VA_RENDER_MODE_LOCAL_GPU, - VA_DISPLAY_ATTRIB_SETTABLE}; - - VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1); - if (va_res != VA_STATUS_SUCCESS) - DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; -} - -// Check the support for low-power encode -bool VaapiWrapper::IsLowPowerEncSupported(VAProfile va_profile, - CodecMode mode) const { - // Enabled only for H264/AVC & VP9 Encoders - if (va_profile != VAProfileH264ConstrainedBaseline && - va_profile != VAProfileH264Main && va_profile != VAProfileH264High && - va_profile != VAProfileVP9Profile0 && va_profile != VAProfileVP9Profile1) - return false; - - constexpr VAEntrypoint kLowPowerEncEntryPoint = VAEntrypointEncSliceLP; - std::vector<VAConfigAttrib> required_attribs; - - base::AutoLock auto_lock(*va_lock_); - GetRequiredAttribs(va_lock_, va_display_, mode, va_profile, - kLowPowerEncEntryPoint, &required_attribs); - // Query the driver for required attributes. - std::vector<VAConfigAttrib> attribs = required_attribs; - for (size_t i = 0; i < required_attribs.size(); ++i) - attribs[i].value = 0; - - VAStatus va_res = - vaGetConfigAttributes(va_display_, va_profile, kLowPowerEncEntryPoint, - &attribs[0], attribs.size()); - VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes", false); - - for (size_t i = 0; i < required_attribs.size(); ++i) { - if (attribs[i].type != required_attribs[i].type || - (attribs[i].value & required_attribs[i].value) != - required_attribs[i].value) { - DVLOG(1) << "Unsupported value " << required_attribs[i].value - << " for attribute type " << required_attribs[i].type; - return false; - } - } - return true; -} - } // namespace media |