diff options
-rw-r--r-- | addons/resource.language.en_gb/resources/strings.po | 20 | ||||
-rwxr-xr-x | system/settings/settings.xml | 47 | ||||
-rw-r--r-- | xbmc/guilib/GUIShaderDX.cpp | 3 | ||||
-rw-r--r-- | xbmc/platform/win32/WIN32Util.cpp | 98 | ||||
-rw-r--r-- | xbmc/platform/win32/WIN32Util.h | 1 | ||||
-rw-r--r-- | xbmc/rendering/dx/DeviceResources.cpp | 3 | ||||
-rw-r--r-- | xbmc/settings/SettingConditions.cpp | 9 | ||||
-rw-r--r-- | xbmc/settings/Settings.cpp | 1 | ||||
-rw-r--r-- | xbmc/settings/Settings.h | 2 | ||||
-rw-r--r-- | xbmc/windowing/WinSystem.h | 2 | ||||
-rw-r--r-- | xbmc/windowing/win10/WinSystemWin10.cpp | 35 | ||||
-rw-r--r-- | xbmc/windowing/win10/WinSystemWin10.h | 7 | ||||
-rw-r--r-- | xbmc/windowing/windows/WinSystemWin32.cpp | 44 | ||||
-rw-r--r-- | xbmc/windowing/windows/WinSystemWin32.h | 7 |
14 files changed, 256 insertions, 23 deletions
diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po index a98a144b82..b4bf45268d 100644 --- a/addons/resource.language.en_gb/resources/strings.po +++ b/addons/resource.language.en_gb/resources/strings.po @@ -18960,7 +18960,13 @@ msgctxt "#36053" msgid "Tuner Device" msgstr "" -#empty strings from id 36054 to 36096 +#empty strings from id 36054 to 36095 + +#. Label of setting "System / Display / Use system HDR/SDR brightness balance" +#: system/settings/settings.xml +msgctxt "#36096" +msgid "Use system HDR/SDR brightness balance" +msgstr "" #. Label of setting "System / Display / GUI peak luminance in HDR PQ mode" #: system/settings/settings.xml @@ -23415,3 +23421,15 @@ msgstr "" msgctxt "#39189" msgid "Available only with manual subtitle position" msgstr "" + +#. Help text for setting "Use system HDR/SDR brightness balance" of label #36096 +#: system/settings/settings.xml +msgctxt "#39190" +msgid "[ON] The brightness of the GUI in HDR mode follows the system's setting. This affects all OSD, subtitles and graphics that are SDR in origin.[CR][OFF] Set the max brightness manually." +msgstr "" + +#. System / Display "HDR" settings group label +#: system/settings/settings.xml +msgctxt "#39191" +msgid "HDR" +msgstr "" diff --git a/system/settings/settings.xml b/system/settings/settings.xml index 51daf1ec2d..4cb005acb6 100755 --- a/system/settings/settings.xml +++ b/system/settings/settings.xml @@ -2592,17 +2592,6 @@ </constraints> <control type="spinner" format="string" /> </setting> - <setting id="videoscreen.guisdrpeakluminance" type="integer" label="36097" help="36547"> - <requirement>HAS_DX</requirement> - <dependencies> - <dependency type="visible"> - <condition on="property" name="ishdrdisplay" /> - </dependency> - </dependencies> - <level>2</level> - <default>60</default> - <control type="slider" format="percentage" range="0,100" /> - </setting> <setting id="videoscreen.10bitsurfaces" type="integer" label="36098" help="36578"> <requirement>HAS_DX</requirement> <level>3</level> @@ -2821,7 +2810,37 @@ <control type="spinner" format="integer" /> </setting> </group> - <group id="2" label="14126"> + <group id="2" label="39191"> + <setting id="videoscreen.usesystemsdrpeakluminance" type="boolean" label="36096" help="39190"> + <level>2</level> + <default>true</default> + <dependencies> + <dependency type="visible"> + <and> + <condition on="property" name="ishdrdisplay" /> + <condition on="property" name="hassystemsdrpeakluminance" /> + </and> + </dependency> + </dependencies> + <control type="toggle" /> + </setting> + <setting id="videoscreen.guisdrpeakluminance" type="integer" label="36097" help="36547"> + <requirement>HAS_DX</requirement> + <dependencies> + <dependency type="visible" on="property" name="ishdrdisplay"/> + <dependency type="enable"> + <or> + <condition on="property" name="hassystemsdrpeakluminance" operator="!is" /> + <condition setting="videoscreen.usesystemsdrpeakluminance" operator="is">false</condition> + </or> + </dependency> + </dependencies> + <level>2</level> + <default>60</default> + <control type="slider" format="percentage" range="0,100" /> + </setting> + </group> + <group id="3" label="14126"> <setting id="videoscreen.whitelist" type="list[string]" parent="videoscreen.screen" label="14126" help="36443"> <level>3</level> <default></default> @@ -2851,7 +2870,7 @@ <control type="toggle" /> </setting> </group> - <group id="3" label="14232"> + <group id="4" label="14232"> <setting id="videoscreen.stereoscopicmode" type="integer" label="36500" help="36539"> <level>2</level> <default>0</default> @@ -2872,7 +2891,7 @@ <control type="list" format="integer"/> </setting> </group> - <group id="4" label="496"> + <group id="5" label="496"> <setting id="videoscreen.noofbuffers" type="integer" label="36043" help="36552"> <level>2</level> <default>3</default> <!-- triple buffers --> diff --git a/xbmc/guilib/GUIShaderDX.cpp b/xbmc/guilib/GUIShaderDX.cpp index b9e801ecc9..f5e7adf221 100644 --- a/xbmc/guilib/GUIShaderDX.cpp +++ b/xbmc/guilib/GUIShaderDX.cpp @@ -334,7 +334,8 @@ void CGUIShaderDX::ApplyChanges(void) buffer->wvp = worldViewProj; buffer->blackLevel = (DX::Windowing()->UseLimitedColor() ? 16.f / 255.f : 0.f); buffer->colorRange = (DX::Windowing()->UseLimitedColor() ? (235.f - 16.f) / 255.f : 1.0f); - buffer->sdrPeakLum = (100 - DX::Windowing()->GetGuiSdrPeakLuminance()) + 10; + if (DX::Windowing()->IsTransferPQ()) + buffer->sdrPeakLum = 10000.0f / DX::Windowing()->GetGuiSdrPeakLuminance(); buffer->PQ = (DX::Windowing()->IsTransferPQ() ? 1 : 0); pContext->Unmap(m_pWVPBuffer.Get(), 0); diff --git a/xbmc/platform/win32/WIN32Util.cpp b/xbmc/platform/win32/WIN32Util.cpp index ae8dc94a34..faadae57ad 100644 --- a/xbmc/platform/win32/WIN32Util.cpp +++ b/xbmc/platform/win32/WIN32Util.cpp @@ -1424,6 +1424,104 @@ HDR_STATUS CWIN32Util::GetWindowsHDRStatus() return status; } +/*! + * \brief Retrieve from the system the max luminance of SDR content in HDR. + * + * Retrieve from the system the max luminance of SDR content in HDR. + * Note: always returns 80 nits when the screen is in SDR mode. + * + * \param gdiDeviceName The screen to retrieve the information for + * \param sdrWhiteLevel Max luminance in nits, clamped to 10000 + * \return true if a value could be read from the system and copied to sdrWhiteLevel, false otherwise +*/ +bool CWIN32Util::GetSystemSdrWhiteLevel(const std::wstring& gdiDeviceName, float* sdrWhiteLevel) +{ +#ifdef TARGET_WINDOWS_STORE + auto displayInformation = DisplayInformation::GetForCurrentView(); + + if (displayInformation) + { + auto advancedColorInfo = displayInformation.GetAdvancedColorInfo(); + + if (advancedColorInfo) + { + const float sdrNits = advancedColorInfo.SdrWhiteLevelInNits(); + if (sdrWhiteLevel) + { + if (sdrNits > 10000.0f) + *sdrWhiteLevel = 10000.0f; + else + *sdrWhiteLevel = sdrNits; + } + return true; + } + } + return false; +#else + // DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL was added in Windows 10 1709 + + uint32_t pathCount{0}; + uint32_t modeCount{0}; + std::vector<DISPLAYCONFIG_PATH_INFO> paths; + std::vector<DISPLAYCONFIG_MODE_INFO> modes; + + uint32_t flags = QDC_ONLY_ACTIVE_PATHS; + LONG result = ERROR_SUCCESS; + + do + { + if (GetDisplayConfigBufferSizes(flags, &pathCount, &modeCount) != ERROR_SUCCESS) + return false; + + paths.resize(pathCount); + modes.resize(modeCount); + + result = QueryDisplayConfig(flags, &pathCount, paths.data(), &modeCount, modes.data(), nullptr); + } while (result == ERROR_INSUFFICIENT_BUFFER); + + if (result == ERROR_SUCCESS) + { + paths.resize(pathCount); + modes.resize(modeCount); + + for (const auto& path : paths) + { + DISPLAYCONFIG_SOURCE_DEVICE_NAME source{}; + source.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME; + source.header.size = sizeof(source); + source.header.adapterId = path.sourceInfo.adapterId; + source.header.id = path.sourceInfo.id; + + if (DisplayConfigGetDeviceInfo(&source.header) == ERROR_SUCCESS) + { + if (gdiDeviceName == source.viewGdiDeviceName) + { + DISPLAYCONFIG_SDR_WHITE_LEVEL config{}; + config.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL; + config.header.size = sizeof(config); + config.header.adapterId = path.targetInfo.adapterId; + config.header.id = path.targetInfo.id; + if (DisplayConfigGetDeviceInfo(&config.header) == ERROR_SUCCESS) + { + if (sdrWhiteLevel) + { + const float sdrNits = static_cast<const float>(config.SDRWhiteLevel * 80 / 1000); + if (sdrNits > 10000.0f) + *sdrWhiteLevel = 10000.0f; + else + *sdrWhiteLevel = sdrNits; + } + return true; + } + break; + } + } + } + } + return (false); +#endif +} + void CWIN32Util::PlatformSyslog() { CLog::Log(LOGINFO, "System has {:.1f} GB of RAM installed", diff --git a/xbmc/platform/win32/WIN32Util.h b/xbmc/platform/win32/WIN32Util.h index 247d42c754..4cd0ec5ba2 100644 --- a/xbmc/platform/win32/WIN32Util.h +++ b/xbmc/platform/win32/WIN32Util.h @@ -78,6 +78,7 @@ public: // HDR display support static HDR_STATUS ToggleWindowsHDR(DXGI_MODE_DESC& modeDesc); static HDR_STATUS GetWindowsHDRStatus(); + static bool GetSystemSdrWhiteLevel(const std::wstring& gdiDeviceName, float* sdrWhiteLevel); static void PlatformSyslog(); diff --git a/xbmc/rendering/dx/DeviceResources.cpp b/xbmc/rendering/dx/DeviceResources.cpp index 96ca0568f8..c479b4b49d 100644 --- a/xbmc/rendering/dx/DeviceResources.cpp +++ b/xbmc/rendering/dx/DeviceResources.cpp @@ -1273,6 +1273,9 @@ void DX::DeviceResources::SetHdrColorSpace(const DXGI_COLOR_SPACE_TYPE colorSpac { m_IsTransferPQ = (colorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020); + if (m_IsTransferPQ) + DX::Windowing()->CacheSystemSdrPeakLuminance(); + CLog::LogF(LOGDEBUG, "DXGI SetColorSpace1 success"); } else diff --git a/xbmc/settings/SettingConditions.cpp b/xbmc/settings/SettingConditions.cpp index f0a78a8829..cc7181604c 100644 --- a/xbmc/settings/SettingConditions.cpp +++ b/xbmc/settings/SettingConditions.cpp @@ -102,6 +102,14 @@ bool HasPowerOffFeature(const std::string& condition, return CServiceBroker::GetPeripherals().SupportsFeature(PERIPHERALS::FEATURE_POWER_OFF); } +bool HasSystemSdrPeakLuminance(const std::string& condition, + const std::string& value, + const SettingConstPtr& setting, + void* data) +{ + return CServiceBroker::GetWinSystem()->HasSystemSdrPeakLuminance(); +} + bool IsFullscreen(const std::string& condition, const std::string& value, const SettingConstPtr& setting, @@ -447,6 +455,7 @@ void CSettingConditions::Initialize() m_complexConditions.emplace("hasrumblefeature", HasRumbleFeature); m_complexConditions.emplace("hasrumblecontroller", HasRumbleController); m_complexConditions.emplace("haspowerofffeature", HasPowerOffFeature); + m_complexConditions.emplace("hassystemsdrpeakluminance", HasSystemSdrPeakLuminance); m_complexConditions.emplace("isfullscreen", IsFullscreen); m_complexConditions.emplace("ishdrdisplay", IsHDRDisplay); m_complexConditions.emplace("ismasteruser", IsMasterUser); diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp index b403b63bdf..e4a2c9d59c 100644 --- a/xbmc/settings/Settings.cpp +++ b/xbmc/settings/Settings.cpp @@ -366,6 +366,7 @@ constexpr const char* CSettings::SETTING_VIDEOSCREEN_TESTPATTERN; constexpr const char* CSettings::SETTING_VIDEOSCREEN_LIMITEDRANGE; constexpr const char* CSettings::SETTING_VIDEOSCREEN_FRAMEPACKING; constexpr const char* CSettings::SETTING_VIDEOSCREEN_10BITSURFACES; +constexpr const char* CSettings::SETTING_VIDEOSCREEN_USESYSTEMSDRPEAKLUMINANCE; constexpr const char* CSettings::SETTING_VIDEOSCREEN_GUISDRPEAKLUMINANCE; constexpr const char* CSettings::SETTING_AUDIOOUTPUT_AUDIODEVICE; constexpr const char* CSettings::SETTING_AUDIOOUTPUT_CHANNELS; diff --git a/xbmc/settings/Settings.h b/xbmc/settings/Settings.h index cdd2d31ae3..f710d0fd2f 100644 --- a/xbmc/settings/Settings.h +++ b/xbmc/settings/Settings.h @@ -365,6 +365,8 @@ public: static constexpr auto SETTING_VIDEOSCREEN_LIMITEDRANGE = "videoscreen.limitedrange"; static constexpr auto SETTING_VIDEOSCREEN_FRAMEPACKING = "videoscreen.framepacking"; static constexpr auto SETTING_VIDEOSCREEN_10BITSURFACES = "videoscreen.10bitsurfaces"; + static constexpr auto SETTING_VIDEOSCREEN_USESYSTEMSDRPEAKLUMINANCE = + "videoscreen.usesystemsdrpeakluminance"; static constexpr auto SETTING_VIDEOSCREEN_GUISDRPEAKLUMINANCE = "videoscreen.guisdrpeakluminance"; static constexpr auto SETTING_AUDIOOUTPUT_AUDIODEVICE = "audiooutput.audiodevice"; static constexpr auto SETTING_AUDIOOUTPUT_CHANNELS = "audiooutput.channels"; diff --git a/xbmc/windowing/WinSystem.h b/xbmc/windowing/WinSystem.h index cac94b06d6..f3d0fb90fe 100644 --- a/xbmc/windowing/WinSystem.h +++ b/xbmc/windowing/WinSystem.h @@ -173,8 +173,8 @@ public: virtual HDR_STATUS ToggleHDR() { return HDR_STATUS::HDR_UNSUPPORTED; } virtual HDR_STATUS GetOSHDRStatus() { return HDR_STATUS::HDR_UNSUPPORTED; } virtual CHDRCapabilities GetDisplayHDRCapabilities() const { return {}; } - static const char* SETTING_WINSYSTEM_IS_HDR_DISPLAY; + virtual bool HasSystemSdrPeakLuminance() { return false; } // Gets debug info from video renderer virtual DEBUG_INFO_RENDER GetDebugInfo() { return {}; } diff --git a/xbmc/windowing/win10/WinSystemWin10.cpp b/xbmc/windowing/win10/WinSystemWin10.cpp index 6de3f78737..14e539a385 100644 --- a/xbmc/windowing/win10/WinSystemWin10.cpp +++ b/xbmc/windowing/win10/WinSystemWin10.cpp @@ -9,6 +9,7 @@ #include "WinSystemWin10.h" #include "ServiceBroker.h" +#include "WIN32Util.h" #include "WinEventsWin10.h" #include "application/Application.h" #include "cores/AudioEngine/AESinkFactory.h" @@ -650,11 +651,41 @@ bool CWinSystemWin10::MessagePump() return m_winEvents->MessagePump(); } -int CWinSystemWin10::GetGuiSdrPeakLuminance() const +/*! + * \brief Max luminance for GUI SDR content in HDR mode. + * \return Max luminance in nits, lower than 10000. +*/ +float CWinSystemWin10::GetGuiSdrPeakLuminance() const { const auto settings = CServiceBroker::GetSettingsComponent()->GetSettings(); - return settings->GetInt(CSettings::SETTING_VIDEOSCREEN_GUISDRPEAKLUMINANCE); + // use cached system value as this is called for each frame + if (settings->GetBool(CSettings::SETTING_VIDEOSCREEN_USESYSTEMSDRPEAKLUMINANCE) && + m_validSystemSdrPeakLuminance) + return m_systemSdrPeakLuminance; + + // Max nits for 100% UI setting = 1000 nits, < 10000 nits, min 80 nits for 0% + int guiSdrPeak = settings->GetInt(CSettings::SETTING_VIDEOSCREEN_GUISDRPEAKLUMINANCE); + return 10000.0f / ((100 - guiSdrPeak) * 1.15f + 10); +} + +/*! + * \brief Test support of the OS for a SDR max luminance in HDR mode setting + * \return true when the OS supports that setting, false otherwise +*/ +bool CWinSystemWin10::HasSystemSdrPeakLuminance() +{ + return CWIN32Util::GetSystemSdrWhiteLevel(std::wstring(), nullptr); +} + +/*! + * \brief Cache the system HDR/SDR balance for use during rendering, instead of querying the API + for each frame. +*/ +void CWinSystemWin10::CacheSystemSdrPeakLuminance() +{ + m_validSystemSdrPeakLuminance = + CWIN32Util::GetSystemSdrWhiteLevel(std::wstring(), &m_systemSdrPeakLuminance); } #pragma pack(pop) diff --git a/xbmc/windowing/win10/WinSystemWin10.h b/xbmc/windowing/win10/WinSystemWin10.h index 0f2b41e70a..d8560b3a7f 100644 --- a/xbmc/windowing/win10/WinSystemWin10.h +++ b/xbmc/windowing/win10/WinSystemWin10.h @@ -81,6 +81,7 @@ public: bool Show(bool raise = true) override; std::string GetClipboardText() override; bool UseLimitedColor() override; + bool HasSystemSdrPeakLuminance() override; // videosync std::unique_ptr<CVideoSync> GetVideoSync(void *clock) override; @@ -96,7 +97,8 @@ public: virtual bool DPIChanged(WORD dpi, RECT windowRect) const; bool IsMinimized() const { return m_bMinimized; } void SetMinimized(bool minimized) { m_bMinimized = minimized; } - int GetGuiSdrPeakLuminance() const; + float GetGuiSdrPeakLuminance() const; + void CacheSystemSdrPeakLuminance(); bool CanDoWindowed() override; @@ -150,6 +152,9 @@ protected: bool m_bFirstResChange = true; winrt::Windows::UI::Core::CoreWindow m_coreWindow = nullptr; + + bool m_validSystemSdrPeakLuminance{false}; + float m_systemSdrPeakLuminance{.0f}; }; #pragma pack(pop) diff --git a/xbmc/windowing/windows/WinSystemWin32.cpp b/xbmc/windowing/windows/WinSystemWin32.cpp index c75aa2a0c8..cb7dcfe257 100644 --- a/xbmc/windowing/windows/WinSystemWin32.cpp +++ b/xbmc/windowing/windows/WinSystemWin32.cpp @@ -1304,9 +1304,49 @@ RECT CWinSystemWin32::GetVirtualScreenRect() return rect; } -int CWinSystemWin32::GetGuiSdrPeakLuminance() const +/*! + * \brief Max luminance for GUI SDR content in HDR mode. + * \return Max luminance in nits, lower than 10000. +*/ +float CWinSystemWin32::GetGuiSdrPeakLuminance() const { const auto settings = CServiceBroker::GetSettingsComponent()->GetSettings(); - return settings->GetInt(CSettings::SETTING_VIDEOSCREEN_GUISDRPEAKLUMINANCE); + // use cached system value as this is called for each frame + if (settings->GetBool(CSettings::SETTING_VIDEOSCREEN_USESYSTEMSDRPEAKLUMINANCE) && + m_validSystemSdrPeakLuminance) + return m_systemSdrPeakLuminance; + + // Max nits for 100% UI setting = 1000 nits, < 10000 nits, min 80 nits for 0% + int guiSdrPeak = settings->GetInt(CSettings::SETTING_VIDEOSCREEN_GUISDRPEAKLUMINANCE); + return 10000.0f / ((100 - guiSdrPeak) * 1.15f + 10); +} + +/*! + * \brief Test support of the OS for a SDR max luminance in HDR mode setting + * \return true when the OS supports that setting, false otherwise +*/ +bool CWinSystemWin32::HasSystemSdrPeakLuminance() +{ + MONITOR_DETAILS* md = GetDisplayDetails(m_hMonitor); + if (md) + return CWIN32Util::GetSystemSdrWhiteLevel(md->DeviceNameW, nullptr); + + return false; +} + +/*! + * \brief Cache the system HDR/SDR balance for use during rendering, instead of querying the API + for each frame. +*/ +void CWinSystemWin32::CacheSystemSdrPeakLuminance() +{ + m_validSystemSdrPeakLuminance = false; + + MONITOR_DETAILS* md = GetDisplayDetails(m_hMonitor); + if (md) + { + m_validSystemSdrPeakLuminance = + CWIN32Util::GetSystemSdrWhiteLevel(md->DeviceNameW, &m_systemSdrPeakLuminance); + } } diff --git a/xbmc/windowing/windows/WinSystemWin32.h b/xbmc/windowing/windows/WinSystemWin32.h index 170115942d..85e62dab7a 100644 --- a/xbmc/windowing/windows/WinSystemWin32.h +++ b/xbmc/windowing/windows/WinSystemWin32.h @@ -95,6 +95,7 @@ public: bool Show(bool raise = true) override; std::string GetClipboardText() override; bool UseLimitedColor() override; + bool HasSystemSdrPeakLuminance() override; // videosync std::unique_ptr<CVideoSync> GetVideoSync(void *clock) override; @@ -112,7 +113,8 @@ public: virtual bool DPIChanged(WORD dpi, RECT windowRect) const; bool IsMinimized() const { return m_bMinimized; } void SetMinimized(bool minimized); - int GetGuiSdrPeakLuminance() const; + float GetGuiSdrPeakLuminance() const; + void CacheSystemSdrPeakLuminance(); void SetSizeMoveMode(bool mode) { m_bSizeMoveEnabled = mode; } bool IsInSizeMoveMode() const { return m_bSizeMoveEnabled; } @@ -190,6 +192,9 @@ protected: static const char* SETTING_WINDOW_TOP; static const char* SETTING_WINDOW_LEFT; + + bool m_validSystemSdrPeakLuminance{false}; + float m_systemSdrPeakLuminance{.0f}; }; extern HWND g_hWnd; |