diff -Nru kodi-21.0+git20230427.0301-9164f7ee91/addons/skin.estuary/xml/MyPVRTimers.xml kodi-21.0+git20230429.0301-54e9471bc6/addons/skin.estuary/xml/MyPVRTimers.xml --- kodi-21.0+git20230427.0301-9164f7ee91/addons/skin.estuary/xml/MyPVRTimers.xml 2013-05-12 08:41:54.000000000 +0000 +++ kodi-21.0+git20230429.0301-54e9471bc6/addons/skin.estuary/xml/MyPVRTimers.xml 2013-05-12 08:41:54.000000000 +0000 @@ -57,29 +57,29 @@ - - - - - - - - - 20 - OpenClose_Right - 10 - 850 - 60 - - black - right - center - true - font27 - - - MediaMenuCommon - PVRSideBar + + + + + + + + 20 + OpenClose_Right + 10 + 850 + 60 + + black + right + center + true + font27 + + + MediaMenuCommon + PVRSideBar + diff -Nru kodi-21.0+git20230427.0301-9164f7ee91/BUILDDATE kodi-21.0+git20230429.0301-54e9471bc6/BUILDDATE --- kodi-21.0+git20230427.0301-9164f7ee91/BUILDDATE 2013-05-12 08:41:54.000000000 +0000 +++ kodi-21.0+git20230429.0301-54e9471bc6/BUILDDATE 2013-05-12 08:41:54.000000000 +0000 @@ -1 +1 @@ -20230427 +20230429 diff -Nru kodi-21.0+git20230427.0301-9164f7ee91/debian/changelog kodi-21.0+git20230429.0301-54e9471bc6/debian/changelog --- kodi-21.0+git20230427.0301-9164f7ee91/debian/changelog 2013-05-12 08:41:54.000000000 +0000 +++ kodi-21.0+git20230429.0301-54e9471bc6/debian/changelog 2013-05-12 08:41:54.000000000 +0000 @@ -1,4 +1,4 @@ -kodi (6:21.0+git20230427.0301-9164f7ee91-0~kinetic) kinetic; urgency=medium +kodi (6:21.0+git20230429.0301-54e9471bc6-0~kinetic) kinetic; urgency=medium [ kodi ] * autogenerated dummy changelog diff -Nru kodi-21.0+git20230427.0301-9164f7ee91/VERSION kodi-21.0+git20230429.0301-54e9471bc6/VERSION --- kodi-21.0+git20230427.0301-9164f7ee91/VERSION 2013-05-12 08:41:54.000000000 +0000 +++ kodi-21.0+git20230429.0301-54e9471bc6/VERSION 2013-05-12 08:41:54.000000000 +0000 @@ -1 +1 @@ -9164f7ee91 +54e9471bc6 diff -Nru kodi-21.0+git20230427.0301-9164f7ee91/xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.cpp kodi-21.0+git20230429.0301-54e9471bc6/xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.cpp --- kodi-21.0+git20230427.0301-9164f7ee91/xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-21.0+git20230429.0301-54e9471bc6/xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -20,6 +20,19 @@ namespace DRMPRIME { +KODI::UTILS::Colorimetry GetColorimetry(const VideoPicture& picture) +{ + switch (picture.color_space) + { + case AVCOL_SPC_BT2020_CL: + return KODI::UTILS::Colorimetry::BT2020_CYCC; + case AVCOL_SPC_BT2020_NCL: + return KODI::UTILS::Colorimetry::BT2020_YCC; + default: + return KODI::UTILS::Colorimetry::DEFAULT; + } +} + std::string GetColorEncoding(const VideoPicture& picture) { switch (picture.color_space) diff -Nru kodi-21.0+git20230427.0301-9164f7ee91/xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.h kodi-21.0+git20230429.0301-54e9471bc6/xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.h --- kodi-21.0+git20230427.0301-9164f7ee91/xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-21.0+git20230429.0301-54e9471bc6/xbmc/cores/VideoPlayer/Buffers/VideoBufferDRMPRIME.h 2013-05-12 08:41:54.000000000 +0000 @@ -35,6 +35,7 @@ HDMI_EOTF_BT_2100_HLG, }; +KODI::UTILS::Colorimetry GetColorimetry(const VideoPicture& picture); std::string GetColorEncoding(const VideoPicture& picture); std::string GetColorRange(const VideoPicture& picture); KODI::UTILS::Eotf GetEOTF(const VideoPicture& picture); diff -Nru kodi-21.0+git20230427.0301-9164f7ee91/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.cpp kodi-21.0+git20230429.0301-54e9471bc6/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.cpp --- kodi-21.0+git20230427.0301-9164f7ee91/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-21.0+git20230429.0301-54e9471bc6/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -17,6 +17,7 @@ #include "VideoRenderers/RenderManager.h" #include "VideoRenderers/windows/RendererBase.h" #include "rendering/dx/RenderContext.h" +#include "utils/StringUtils.h" #include "utils/log.h" #include @@ -64,6 +65,7 @@ void CProcessorHD::Close() { std::unique_lock lock(m_section); + m_pEnumerator1 = nullptr; m_pEnumerator = nullptr; m_pVideoProcessor = nullptr; m_pVideoContext = nullptr; @@ -105,6 +107,7 @@ m_pVideoDevice = nullptr; m_pVideoContext = nullptr; m_pEnumerator = nullptr; + m_pEnumerator1 = nullptr; ComPtr pD3DDeviceContext = DX::DeviceResources::Get()->GetImmediateContext(); ComPtr pD3DDevice = DX::DeviceResources::Get()->GetD3DDevice(); @@ -140,6 +143,12 @@ return false; } + if (FAILED(hr = m_pEnumerator.As(&m_pEnumerator1))) + { + CLog::LogF(LOGDEBUG, "ID3D11VideoProcessorEnumerator1 not available on this system. Message {}", + DX::GetErrorDescription(hr)); + } + if (CServiceBroker::GetLogging().IsLogLevelLogged(LOGDEBUG)) { std::string inputFormats{}; @@ -259,33 +268,31 @@ } } - ComPtr pEnumerator1; - - if (SUCCEEDED(m_pEnumerator.As(&pEnumerator1))) + if (m_pEnumerator1) { DXGI_FORMAT format = DX::Windowing()->GetBackBuffer().GetFormat(); BOOL supported = 0; HRESULT hr; // Check if HLG color space conversion is supported by driver - hr = pEnumerator1->CheckVideoProcessorFormatConversion( + hr = m_pEnumerator1->CheckVideoProcessorFormatConversion( DXGI_FORMAT_P010, DXGI_COLOR_SPACE_YCBCR_STUDIO_GHLG_TOPLEFT_P2020, format, DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709, &supported); m_bSupportHLG = SUCCEEDED(hr) && !!supported; // Check if HDR10 RGB limited range output is supported by driver - hr = pEnumerator1->CheckVideoProcessorFormatConversion( + hr = m_pEnumerator1->CheckVideoProcessorFormatConversion( DXGI_FORMAT_P010, DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020, format, DXGI_COLOR_SPACE_RGB_STUDIO_G2084_NONE_P2020, &supported); m_bSupportHDR10Limited = SUCCEEDED(hr) && !!supported; // Check if driver prefers YCbCr TOP LEFT for 10 bit BT.2020 - hr = pEnumerator1->CheckVideoProcessorFormatConversion( + hr = m_pEnumerator1->CheckVideoProcessorFormatConversion( DXGI_FORMAT_P010, DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020, format, DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709, &supported); const bool left = SUCCEEDED(hr) && static_cast(supported); - hr = pEnumerator1->CheckVideoProcessorFormatConversion( + hr = m_pEnumerator1->CheckVideoProcessorFormatConversion( DXGI_FORMAT_P010, DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_TOPLEFT_P2020, format, DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709, &supported); const bool topLeft = SUCCEEDED(hr) && static_cast(supported); @@ -326,40 +333,35 @@ bool CProcessorHD::IsFormatConversionSupported(DXGI_FORMAT inputFormat, DXGI_FORMAT outputFormat, - const VideoPicture& picture) const + const VideoPicture& picture) { + std::unique_lock lock(m_section); + // accept the conversion unless the API can be called successfully and disallows it BOOL supported{TRUE}; - ComPtr enumerator1; - if (SUCCEEDED(m_pEnumerator.As(&enumerator1))) - { - ProcColorSpaces spaces = CalculateDXGIColorSpaces(DXGIColorSpaceArgs(picture)); + if (!m_pEnumerator1) + return true; - HRESULT hr; - if (SUCCEEDED(hr = enumerator1->CheckVideoProcessorFormatConversion( - inputFormat, spaces.inputColorSpace, outputFormat, spaces.outputColorSpace, - &supported))) - { - CLog::LogF(LOGDEBUG, "conversion from {} / {} to {} / {} is {}supported.", - DX::DXGIFormatToString(inputFormat), - DX::DXGIColorSpaceTypeToString(spaces.inputColorSpace), - DX::DXGIFormatToString(outputFormat), - DX::DXGIColorSpaceTypeToString(spaces.outputColorSpace), supported ? "" : "not "); - } - else - { - CLog::LogF(LOGERROR, "unable to validate the format conversion, error {}", - DX::GetErrorDescription(hr)); - } + ProcColorSpaces spaces = CalculateDXGIColorSpaces(DXGIColorSpaceArgs(picture)); + + HRESULT hr; + if (SUCCEEDED(hr = m_pEnumerator1->CheckVideoProcessorFormatConversion( + inputFormat, spaces.inputColorSpace, outputFormat, spaces.outputColorSpace, + &supported))) + { + CLog::LogF( + LOGDEBUG, "conversion from {} / {} to {} / {} is {}supported.", + DX::DXGIFormatToString(inputFormat), DX::DXGIColorSpaceTypeToString(spaces.inputColorSpace), + DX::DXGIFormatToString(outputFormat), + DX::DXGIColorSpaceTypeToString(spaces.outputColorSpace), supported == TRUE ? "" : "NOT "); } else { - CLog::LogF( - LOGDEBUG, - "ID3D11VideoProcessorEnumerator1 not available on this system, accepting the conversion."); + CLog::LogF(LOGERROR, "unable to validate the format conversion, error {}", + DX::GetErrorDescription(hr)); } - return supported; + return supported == TRUE; } bool CProcessorHD::Open(UINT width, UINT height) @@ -814,3 +816,216 @@ "Input color space BT.2020 is not supported by video processor. DXVA will not be used."); return false; } + +void CProcessorHD::ListSupportedConversions(const DXGI_FORMAT& inputFormat, + const DXGI_FORMAT& heuristicsOutputFormat, + const VideoPicture& picture) +{ + std::unique_lock lock(m_section); + + // Windows 8 and above compatible code + if (!m_pEnumerator) + return; + + HRESULT hr; + UINT uiFlags; + + if (FAILED(hr = m_pEnumerator->CheckVideoProcessorFormat(inputFormat, &uiFlags))) + { + CLog::LogF(LOGDEBUG, "unable to retrieve processor support of input format {}. Error {}", + DX::DXGIFormatToString(inputFormat), DX::GetErrorDescription(hr)); + return; + } + else if (!(uiFlags & D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT_INPUT)) + { + CLog::LogF(LOGERROR, "input format {} not supported by the processor. No conversion possible.", + DX::DXGIFormatToString(inputFormat)); + return; + } + + // Windows 10 and above from this point on + if (!m_pEnumerator1) + return; + + const DXGIColorSpaceArgs csArgs = DXGIColorSpaceArgs(picture); + + // Defaults used by Kodi + const ProcColorSpaces heuristicsCS = CalculateDXGIColorSpaces(csArgs); + BOOL supported{FALSE}; + + const DXGI_COLOR_SPACE_TYPE inputNativeCS = AvToDxgiColorSpace(csArgs); + CLog::LogF(LOGDEBUG, "The source is {} / {}", DX::DXGIFormatToString(inputFormat), + DX::DXGIColorSpaceTypeToString(inputNativeCS)); + + if (SUCCEEDED(hr = m_pEnumerator1->CheckVideoProcessorFormatConversion( + inputFormat, inputNativeCS, heuristicsOutputFormat, + heuristicsCS.outputColorSpace, &supported))) + { + CLog::LogF(LOGDEBUG, "conversion from {} / {} to {} / {} is {}supported.", + DX::DXGIFormatToString(inputFormat), DX::DXGIColorSpaceTypeToString(inputNativeCS), + DX::DXGIFormatToString(heuristicsOutputFormat), + DX::DXGIColorSpaceTypeToString(heuristicsCS.outputColorSpace), + supported == TRUE ? "" : "NOT "); + } + else + { + CLog::LogF(LOGERROR, "unable to validate the default format conversion, error {}", + DX::GetErrorDescription(hr)); + } + + // Possible input color spaces: YCbCr only + std::vector ycbcrColorSpaces; + // Possible output color spaces: RGB only + std::vector rgbColorSpaces; + + for (UINT colorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; + colorSpace < DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_TOPLEFT_P2020; ++colorSpace) + { + DXGI_COLOR_SPACE_TYPE cs = static_cast(colorSpace); + + constexpr std::string_view rgb("RGB_"); + if (DX::DXGIColorSpaceTypeToString(cs).compare(0, rgb.size(), rgb) == 0) + rgbColorSpaces.push_back(cs); + + constexpr std::string_view ycbcr("YCBCR_"); + if (DX::DXGIColorSpaceTypeToString(cs).compare(0, ycbcr.size(), ycbcr) == 0) + ycbcrColorSpaces.push_back(cs); + } + + // Only probe the output formats of RGB/BGR type supported by the processor. + std::vector outputFormats; + for (const auto& format : GetProcessorOutputFormats()) + { + std::string name = DX::DXGIFormatToString(format); + if (name.find('R') != std::string::npos && name.find('G') != std::string::npos && + name.find('B') != std::string::npos) + outputFormats.push_back(format); + } + + // Color spaces supported directly by the swap chain - as a set for easy lookup + std::vector bbcs = DX::DeviceResources::Get()->GetSwapChainColorSpaces(); + std::set backbufferColorSpaces(bbcs.begin(), bbcs.end()); + + std::string conversions; + + // The input format cannot be worked around and is fixed. + // Loop over the lists of: + // - input color spaces + // - output formats + // - output color spaces + for (const DXGI_COLOR_SPACE_TYPE& inputCS : ycbcrColorSpaces) + { + for (const DXGI_FORMAT& outputFormat : outputFormats) + { + for (const DXGI_COLOR_SPACE_TYPE& outputCS : rgbColorSpaces) + { + if (SUCCEEDED(m_pEnumerator1->CheckVideoProcessorFormatConversion( + inputFormat, inputCS, outputFormat, outputCS, &supported)) && + supported == TRUE) + { + conversions.append("\n"); + conversions.append(StringUtils::Format( + "{} {} / {}{} {:<{}} to {} {:<{}} / {}{} {:<{}}", "*", + DX::DXGIFormatToString(inputFormat), + (inputCS == heuristicsCS.inputColorSpace) ? "*" : " ", + (inputCS == inputNativeCS) ? "N" : " ", DX::DXGIColorSpaceTypeToString(inputCS), 32, + (outputFormat == heuristicsOutputFormat) ? "*" : " ", + DX::DXGIFormatToString(outputFormat), 26, + (outputCS == heuristicsCS.outputColorSpace) ? "*" : " ", + (backbufferColorSpaces.find(outputCS) != backbufferColorSpaces.end()) ? "bb" : " ", + DX::DXGIColorSpaceTypeToString(outputCS), 32)); + } + } + } + } + + CLog::LogF(LOGDEBUG, + "supported conversions from format {}\n(*: values picked by " + "heuristics, N native input color space, bb supported as swap chain backbuffer){}", + DX::DXGIFormatToString(inputFormat), conversions); +} + +std::vector CProcessorHD::GetProcessorOutputFormats() const +{ + std::vector result; + + UINT uiFlags; + for (int fmt = DXGI_FORMAT_UNKNOWN; fmt <= DXGI_FORMAT_V408; fmt++) + { + DXGI_FORMAT dxgiFormat = static_cast(fmt); + if (S_OK == m_pEnumerator->CheckVideoProcessorFormat(dxgiFormat, &uiFlags) && + uiFlags & D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT_OUTPUT) + result.push_back(dxgiFormat); + } + return result; +} + +DXGI_COLOR_SPACE_TYPE CProcessorHD::AvToDxgiColorSpace(const DXGIColorSpaceArgs& csArgs) +{ + // RGB + if (csArgs.color_space == AVCOL_SPC_RGB) + { + if (!csArgs.full_range) + { + if (csArgs.primaries == AVCOL_PRI_BT2020) + { + if (csArgs.color_transfer == AVCOL_TRC_SMPTEST2084) + return DXGI_COLOR_SPACE_RGB_STUDIO_G2084_NONE_P2020; + + return DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P2020; + } + return DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P709; + } + + if (csArgs.primaries == AVCOL_PRI_BT2020) + { + if (csArgs.color_transfer == AVCOL_TRC_SMPTEST2084) + return DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; + + return DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020; + } + if (csArgs.color_transfer == AVCOL_TRC_LINEAR || csArgs.color_transfer == AVCOL_TRC_LOG) + return DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709; + + return DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; + } + // UHDTV + if (csArgs.primaries == AVCOL_PRI_BT2020) + { + if (csArgs.color_transfer == AVCOL_TRC_SMPTEST2084) + // Full range DXGI_COLOR_SPACE_YCBCR_FULL_G2084_LEFT_P2020 does not exist at this time + return DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020; + + // HLG transfer can be used for HLG source in SDR display if is supported + if (csArgs.color_transfer == AVCOL_TRC_ARIB_STD_B67) + { + if (csArgs.full_range) + return DXGI_COLOR_SPACE_YCBCR_FULL_GHLG_TOPLEFT_P2020; + else + return DXGI_COLOR_SPACE_YCBCR_STUDIO_GHLG_TOPLEFT_P2020; + } + + if (csArgs.full_range) + return DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020; + else + return DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020; + } + // SDTV + if (csArgs.primaries == AVCOL_PRI_BT470BG || csArgs.primaries == AVCOL_PRI_SMPTE170M) + { + if (csArgs.full_range) + return DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601; + + return DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601; + } + // HDTV + if (csArgs.full_range) + { + if (csArgs.color_transfer == AVCOL_TRC_SMPTE170M) + return DXGI_COLOR_SPACE_YCBCR_FULL_G22_NONE_P709_X601; + + return DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709; + } + + return DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709; +} diff -Nru kodi-21.0+git20230427.0301-9164f7ee91/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.h kodi-21.0+git20230429.0301-54e9471bc6/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.h --- kodi-21.0+git20230427.0301-9164f7ee91/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-21.0+git20230429.0301-54e9471bc6/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.h 2013-05-12 08:41:54.000000000 +0000 @@ -95,12 +95,21 @@ * Always returns true when the Windows 10+ API is not available or cannot be called successfully. * \param inputFormat The source format * \param outputFormat The destination format - * \param picture Picutre information used to derive the color spaces + * \param picture Picture information used to derive the color spaces * \return true if the conversion is supported, false otherwise */ bool IsFormatConversionSupported(DXGI_FORMAT inputFormat, DXGI_FORMAT outputFormat, - const VideoPicture& picture) const; + const VideoPicture& picture); + /*! + * \brief Outputs in the log a list of conversions supported by the DXVA processor. + * \param inputFormat The source format + * \param outputFormat The destination format + * \param picture Picture information used to derive the color spaces + */ + void ListSupportedConversions(const DXGI_FORMAT& inputFormat, + const DXGI_FORMAT& outputFormat, + const VideoPicture& picture); // ID3DResource overrides void OnCreateDevice() override {} @@ -132,6 +141,17 @@ DXGI_COLOR_SPACE_TYPE GetDXGIColorSpaceTarget(const DXGIColorSpaceArgs& csArgs, bool supportHDR, bool limitedRange) const; + /*! + * \brief Converts ffmpeg AV parameters to a DXGI color space + * \param csArgs ffmpeg AV picture parameters + * \return DXGI color space + */ + static DXGI_COLOR_SPACE_TYPE AvToDxgiColorSpace(const DXGIColorSpaceArgs& csArgs); + /*! + * \brief Retrieve the list of DXGI_FORMAT supported as output by the DXVA processor + * \return Vector of formats + */ + std::vector GetProcessorOutputFormats() const; CCriticalSection m_section; @@ -155,6 +175,7 @@ Microsoft::WRL::ComPtr m_pVideoDevice; Microsoft::WRL::ComPtr m_pVideoContext; Microsoft::WRL::ComPtr m_pEnumerator; + Microsoft::WRL::ComPtr m_pEnumerator1; Microsoft::WRL::ComPtr m_pVideoProcessor; }; diff -Nru kodi-21.0+git20230427.0301-9164f7ee91/xbmc/cores/VideoPlayer/VideoRenderers/windows/RendererDXVA.cpp kodi-21.0+git20230429.0301-54e9471bc6/xbmc/cores/VideoPlayer/VideoRenderers/windows/RendererDXVA.cpp --- kodi-21.0+git20230427.0301-9164f7ee91/xbmc/cores/VideoPlayer/VideoRenderers/windows/RendererDXVA.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-21.0+git20230429.0301-54e9471bc6/xbmc/cores/VideoPlayer/VideoRenderers/windows/RendererDXVA.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -111,10 +111,13 @@ // create processor m_processor = std::make_unique(); if (m_processor->PreInit() && m_processor->Open(m_sourceWidth, m_sourceHeight) && - m_processor->IsFormatSupported(dxgi_format, support_type) && - m_processor->IsFormatConversionSupported(dxgi_format, dest_format, picture)) + m_processor->IsFormatSupported(dxgi_format, support_type)) { - return true; + if (CServiceBroker::GetLogging().IsLogLevelLogged(LOGDEBUG)) + m_processor->ListSupportedConversions(dxgi_format, dest_format, picture); + + if (m_processor->IsFormatConversionSupported(dxgi_format, dest_format, picture)) + return true; } CLog::LogF(LOGERROR, "unable to create DXVA processor"); diff -Nru kodi-21.0+git20230427.0301-9164f7ee91/xbmc/rendering/dx/DeviceResources.cpp kodi-21.0+git20230429.0301-54e9471bc6/xbmc/rendering/dx/DeviceResources.cpp --- kodi-21.0+git20230427.0301-9164f7ee91/xbmc/rendering/dx/DeviceResources.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-21.0+git20230429.0301-54e9471bc6/xbmc/rendering/dx/DeviceResources.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -716,26 +716,13 @@ if (CServiceBroker::GetLogging().IsLogLevelLogged(LOGDEBUG)) { - ComPtr swapChain4; - if (SUCCEEDED(m_swapChain.As(&swapChain4))) + std::string colorSpaces; + for (const DXGI_COLOR_SPACE_TYPE& colorSpace : GetSwapChainColorSpaces()) { - UINT colorSpaceSupport = 0; - std::string colorSpaces{}; - for (UINT colorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; - colorSpace < DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_TOPLEFT_P2020; colorSpace++) - { - if (SUCCEEDED(swapChain4->CheckColorSpaceSupport( - static_cast(colorSpace), &colorSpaceSupport)) && - (colorSpaceSupport & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT) == - DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT) - { - colorSpaces.append("\n"); - colorSpaces.append( - DX::DXGIColorSpaceTypeToString(static_cast(colorSpace))); - } - } - CLog::LogF(LOGDEBUG, "Color spaces supported by the swap chain:{}", colorSpaces); + colorSpaces.append("\n"); + colorSpaces.append(DX::DXGIColorSpaceTypeToString(colorSpace)); } + CLog::LogF(LOGDEBUG, "Color spaces supported by the swap chain:{}", colorSpaces); } // Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and @@ -1384,8 +1371,8 @@ "Swapchain: {} buffers, flip {}, {}, EOTF: {} (Windows HDR {})", desc.BufferCount, (desc.SwapEffect == DXGI_SWAP_EFFECT_FLIP_DISCARD) ? "discard" : "sequential", Windowing()->IsFullScreen() - ? ((desc.Flags == DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH) ? "fullscreen exclusive" - : "fullscreen windowed") + ? ((desc.Flags & DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH) ? "fullscreen exclusive" + : "fullscreen windowed") : "windowed screen", m_IsTransferPQ ? "PQ" : "SDR", m_IsHDROutput ? "on" : "off"); @@ -1399,3 +1386,31 @@ return info; } + +std::vector DX::DeviceResources::GetSwapChainColorSpaces() const +{ + if (!m_swapChain) + return {}; + + std::vector result; + HRESULT hr; + + ComPtr swapChain3; + if (SUCCEEDED(hr = m_swapChain.As(&swapChain3))) + { + UINT colorSpaceSupport = 0; + for (UINT colorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; + colorSpace < DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_TOPLEFT_P2020; colorSpace++) + { + DXGI_COLOR_SPACE_TYPE cs = static_cast(colorSpace); + if (SUCCEEDED(swapChain3->CheckColorSpaceSupport(cs, &colorSpaceSupport)) && + (colorSpaceSupport & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT)) + result.push_back(cs); + } + } + else + { + CLog::LogF(LOGDEBUG, "IDXGISwapChain3 is not available. Error {}", DX::GetErrorDescription(hr)); + } + return result; +} diff -Nru kodi-21.0+git20230427.0301-9164f7ee91/xbmc/rendering/dx/DeviceResources.h kodi-21.0+git20230429.0301-54e9471bc6/xbmc/rendering/dx/DeviceResources.h --- kodi-21.0+git20230427.0301-9164f7ee91/xbmc/rendering/dx/DeviceResources.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-21.0+git20230429.0301-54e9471bc6/xbmc/rendering/dx/DeviceResources.h 2013-05-12 08:41:54.000000000 +0000 @@ -117,6 +117,7 @@ // Gets debug info from swapchain DEBUG_INFO_RENDER GetDebugInfo() const; + std::vector GetSwapChainColorSpaces() const; private: class CBackBuffer : public CD3DTexture diff -Nru kodi-21.0+git20230427.0301-9164f7ee91/xbmc/utils/DisplayInfo.cpp kodi-21.0+git20230429.0301-54e9471bc6/xbmc/utils/DisplayInfo.cpp --- kodi-21.0+git20230427.0301-9164f7ee91/xbmc/utils/DisplayInfo.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-21.0+git20230429.0301-54e9471bc6/xbmc/utils/DisplayInfo.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -103,6 +103,12 @@ switch (cta_tag) { + case DI_CTA_DATA_BLOCK_COLORIMETRY: + { + m_colorimetry = di_cta_data_block_get_colorimetry(block); + + break; + } case DI_CTA_DATA_BLOCK_HDR_STATIC_METADATA: { m_hdr_static_metadata = di_cta_data_block_get_hdr_static_metadata(block); @@ -144,6 +150,21 @@ m_hdr_static_metadata->desired_content_max_frame_avg_luminance, m_hdr_static_metadata->desired_content_max_luminance); } + + if (m_colorimetry) + { + CLog::Log(LOGINFO, "[display-info] supported colorimetry:"); + CLog::Log(LOGINFO, "[display-info] xvycc_601: {}", m_colorimetry->xvycc_601); + CLog::Log(LOGINFO, "[display-info] xvycc_709: {}", m_colorimetry->xvycc_709); + CLog::Log(LOGINFO, "[display-info] sycc_601: {}", m_colorimetry->sycc_601); + CLog::Log(LOGINFO, "[display-info] opycc_601: {}", m_colorimetry->opycc_601); + CLog::Log(LOGINFO, "[display-info] oprgb: {}", m_colorimetry->oprgb); + CLog::Log(LOGINFO, "[display-info] bt2020_cycc: {}", m_colorimetry->bt2020_cycc); + CLog::Log(LOGINFO, "[display-info] bt2020_ycc: {}", m_colorimetry->bt2020_ycc); + CLog::Log(LOGINFO, "[display-info] bt2020_rgb: {}", m_colorimetry->bt2020_rgb); + CLog::Log(LOGINFO, "[display-info] st2113_rgb: {}", m_colorimetry->st2113_rgb); + CLog::Log(LOGINFO, "[display-info] ictcp: {}", m_colorimetry->ictcp); + } } bool CDisplayInfo::SupportsHDRStaticMetadataType1() const @@ -172,4 +193,36 @@ default: return false; } +} + +bool CDisplayInfo::SupportsColorimetry(Colorimetry colorimetry) const +{ + if (!m_colorimetry) + return false; + + switch (colorimetry) + { + case Colorimetry::XVYCC_601: + return m_colorimetry->xvycc_601; + case Colorimetry::XVYCC_709: + return m_colorimetry->xvycc_709; + case Colorimetry::SYCC_601: + return m_colorimetry->sycc_601; + case Colorimetry::OPYCC_601: + return m_colorimetry->opycc_601; + case Colorimetry::OPRGB: + return m_colorimetry->oprgb; + case Colorimetry::BT2020_CYCC: + return m_colorimetry->bt2020_cycc; + case Colorimetry::BT2020_YCC: + return m_colorimetry->bt2020_ycc; + case Colorimetry::BT2020_RGB: + return m_colorimetry->bt2020_rgb; + case Colorimetry::ST2113_RGB: + return m_colorimetry->st2113_rgb; + case Colorimetry::ICTCP: + return m_colorimetry->ictcp; + default: + return false; + } } diff -Nru kodi-21.0+git20230427.0301-9164f7ee91/xbmc/utils/DisplayInfo.h kodi-21.0+git20230429.0301-54e9471bc6/xbmc/utils/DisplayInfo.h --- kodi-21.0+git20230427.0301-9164f7ee91/xbmc/utils/DisplayInfo.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-21.0+git20230429.0301-54e9471bc6/xbmc/utils/DisplayInfo.h 2013-05-12 08:41:54.000000000 +0000 @@ -14,6 +14,7 @@ #include struct di_info; +struct di_cta_colorimetry_block; struct di_cta_hdr_static_metadata_block; namespace KODI @@ -29,6 +30,21 @@ HLG, }; +enum class Colorimetry +{ + DEFAULT, + XVYCC_601, + XVYCC_709, + SYCC_601, + OPYCC_601, + OPRGB, + BT2020_CYCC, + BT2020_YCC, + BT2020_RGB, + ST2113_RGB, + ICTCP, +}; + class CDisplayInfo { public: @@ -40,6 +56,8 @@ bool SupportsEOTF(Eotf eotf) const; + bool SupportsColorimetry(Colorimetry colorimetry) const; + private: explicit CDisplayInfo(const std::vector& edid); @@ -57,6 +75,7 @@ std::string m_make; std::string m_model; + const di_cta_colorimetry_block* m_colorimetry = nullptr; const di_cta_hdr_static_metadata_block* m_hdr_static_metadata = nullptr; }; diff -Nru kodi-21.0+git20230427.0301-9164f7ee91/xbmc/windowing/gbm/drm/DRMObject.cpp kodi-21.0+git20230429.0301-54e9471bc6/xbmc/windowing/gbm/drm/DRMObject.cpp --- kodi-21.0+git20230427.0301-9164f7ee91/xbmc/windowing/gbm/drm/DRMObject.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-21.0+git20230429.0301-54e9471bc6/xbmc/windowing/gbm/drm/DRMObject.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -80,8 +80,8 @@ return true; } -std::optional CDRMObject::GetPropertyValue(const std::string& name, - const std::string& valueName) const +std::optional CDRMObject::GetPropertyValue(std::string_view name, + std::string_view valueName) const { auto property = std::find_if(m_propsInfo.begin(), m_propsInfo.end(), [&name](const auto& prop) { return prop->name == name; }); diff -Nru kodi-21.0+git20230427.0301-9164f7ee91/xbmc/windowing/gbm/drm/DRMObject.h kodi-21.0+git20230429.0301-54e9471bc6/xbmc/windowing/gbm/drm/DRMObject.h --- kodi-21.0+git20230427.0301-9164f7ee91/xbmc/windowing/gbm/drm/DRMObject.h 2013-05-12 08:41:54.000000000 +0000 +++ kodi-21.0+git20230429.0301-54e9471bc6/xbmc/windowing/gbm/drm/DRMObject.h 2013-05-12 08:41:54.000000000 +0000 @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -35,8 +36,7 @@ uint32_t GetId() const { return m_id; } uint32_t GetPropertyId(const std::string& name) const; - std::optional GetPropertyValue(const std::string& name, - const std::string& valueName) const; + std::optional GetPropertyValue(std::string_view name, std::string_view valueName) const; bool SetProperty(const std::string& name, uint64_t value); bool SupportsProperty(const std::string& name); diff -Nru kodi-21.0+git20230427.0301-9164f7ee91/xbmc/windowing/gbm/WinSystemGbm.cpp kodi-21.0+git20230429.0301-54e9471bc6/xbmc/windowing/gbm/WinSystemGbm.cpp --- kodi-21.0+git20230427.0301-9164f7ee91/xbmc/windowing/gbm/WinSystemGbm.cpp 2013-05-12 08:41:54.000000000 +0000 +++ kodi-21.0+git20230429.0301-54e9471bc6/xbmc/windowing/gbm/WinSystemGbm.cpp 2013-05-12 08:41:54.000000000 +0000 @@ -22,6 +22,7 @@ #include "settings/SettingsComponent.h" #include "settings/lib/Setting.h" #include "utils/DisplayInfo.h" +#include "utils/Map.h" #include "utils/StringUtils.h" #include "utils/log.h" #include "windowing/GraphicContext.h" @@ -62,6 +63,27 @@ using namespace std::chrono_literals; +namespace +{ + +// These map to the definitions in the linux kernel +// drivers/gpu/drm/drm_connector.c + +constexpr auto ColorimetryMap = make_map({ + {KODI::UTILS::Colorimetry::DEFAULT, "Default"}, + {KODI::UTILS::Colorimetry::XVYCC_601, "XVYCC_601"}, + {KODI::UTILS::Colorimetry::XVYCC_709, "XVYCC_709"}, + {KODI::UTILS::Colorimetry::SYCC_601, "SYCC_601"}, + {KODI::UTILS::Colorimetry::OPYCC_601, "opYCC_601"}, + {KODI::UTILS::Colorimetry::OPRGB, "opRGB"}, + {KODI::UTILS::Colorimetry::BT2020_CYCC, "BT2020_CYCC"}, + {KODI::UTILS::Colorimetry::BT2020_YCC, "BT2020_YCC"}, + {KODI::UTILS::Colorimetry::BT2020_RGB, "BT2020_RGB"}, + {KODI::UTILS::Colorimetry::ST2113_RGB, "Default"}, + {KODI::UTILS::Colorimetry::ICTCP, "Default"}, +}); +} // namespace + CWinSystemGbm::CWinSystemGbm() : m_DRM(nullptr), m_GBM(new CGBMUtils), @@ -343,9 +365,23 @@ if (!drm) return false; + auto connector = drm->GetConnector(); + if (!connector) + return false; + if (!videoPicture) { - auto connector = drm->GetConnector(); + if (connector->SupportsProperty("Colorspace")) + { + std::optional colorspace = connector->GetPropertyValue("Colorspace", "Default"); + if (colorspace) + { + CLog::LogF(LOGDEBUG, "setting connector colorspace to Default"); + drm->AddProperty(connector, "Colorspace", colorspace.value()); + drm->SetActive(true); + } + } + if (connector->SupportsProperty("HDR_OUTPUT_METADATA")) { drm->AddProperty(connector, "HDR_OUTPUT_METADATA", 0); @@ -359,9 +395,23 @@ return true; } + KODI::UTILS::Colorimetry colorimetry = DRMPRIME::GetColorimetry(*videoPicture); + + if (connector->SupportsProperty("Colorspace") && m_info && + m_info->SupportsColorimetry(colorimetry)) + { + std::optional colorspace = + connector->GetPropertyValue("Colorspace", ColorimetryMap.at(colorimetry)); + if (colorspace) + { + CLog::LogF(LOGDEBUG, "setting connector colorspace to {}", ColorimetryMap.at(colorimetry)); + drm->AddProperty(connector, "Colorspace", colorspace.value()); + drm->SetActive(true); + } + } + KODI::UTILS::Eotf eotf = DRMPRIME::GetEOTF(*videoPicture); - auto connector = drm->GetConnector(); if (connector->SupportsProperty("HDR_OUTPUT_METADATA") && m_info && m_info->SupportsHDRStaticMetadataType1() && m_info->SupportsEOTF(eotf)) {