Skip to content

Commit

Permalink
Fix UWP compilation and implements alternate code to detect HDR displ…
Browse files Browse the repository at this point in the history
…ay capable/ON/OFF and toggle HDR in UWP

Fix Windows 7 x64 runtime crash due not supported IDXGISwapChain3 interface on this platform
  • Loading branch information
thexai committed Jan 14, 2020
1 parent 43dbc2a commit 482db5a
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 25 deletions.
87 changes: 85 additions & 2 deletions xbmc/platform/win32/WIN32Util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,12 @@ using namespace MEDIA_DETECT;
#include <ppltasks.h>
#include <winrt/Windows.Devices.Power.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Graphics.Display.Core.h>
#include <winrt/Windows.Storage.h>

using namespace winrt::Windows::Devices::Power;
using namespace winrt::Windows::Graphics::Display;
using namespace winrt::Windows::Graphics::Display::Core;
using namespace winrt::Windows::Storage;
#endif

Expand Down Expand Up @@ -1230,6 +1232,56 @@ bool CWIN32Util::SetThreadLocalLocale(bool enable /* = true */)

bool CWIN32Util::ToggleWindowsHDR()
{
#ifdef TARGET_WINDOWS_STORE
bool success = false;

auto hdmiDisplayInfo = HdmiDisplayInformation::GetForCurrentView();

if (hdmiDisplayInfo)
{
auto current = hdmiDisplayInfo.GetCurrentDisplayMode();

auto newColorSp = (current.ColorSpace() == HdmiDisplayColorSpace::BT2020)
? HdmiDisplayColorSpace::BT709
: HdmiDisplayColorSpace::BT2020;

auto hdmiModes = hdmiDisplayInfo.GetSupportedDisplayModes();

// Browse over all modes available like the current (resolution and refresh)
// but reciprocals HDR (color space and transfer).
// NOTE: transfer for HDR is here "fake HDR" (EotfSdr) to be
// able render SRD content with HDR ON, same as Windows HDR switch does.
// GUI-skin is SDR. The real HDR mode is activated later when playback begins.
for (unsigned i = 0; i < hdmiModes.Size(); i++)
{
auto mode = hdmiModes.GetAt(i);

if (mode.ColorSpace() == newColorSp &&
mode.ResolutionHeightInRawPixels() == current.ResolutionHeightInRawPixels() &&
mode.ResolutionWidthInRawPixels() == current.ResolutionWidthInRawPixels() &&
mode.StereoEnabled() == false && mode.RefreshRate() < (current.RefreshRate() + 0.1) &&
mode.RefreshRate() > (current.RefreshRate() - 0.1))
{
if (current.ColorSpace() == HdmiDisplayColorSpace::BT2020) // HDR is ON
{
CLog::LogF(LOGNOTICE, "Toggle Windows HDR Off (ON => OFF).");
hdmiDisplayInfo.RequestSetCurrentDisplayModeAsync(mode, HdmiDisplayHdrOption::None);
success = true;
}
else // HDR is OFF
{
CLog::LogF(LOGNOTICE, "Toggle Windows HDR On (OFF => ON).");
hdmiDisplayInfo.RequestSetCurrentDisplayModeAsync(mode, HdmiDisplayHdrOption::EotfSdr);
success = true;
}

break;
}
}
}

return success;
#else
uint32_t pathCount, modeCount;
bool success = false;

Expand Down Expand Up @@ -1264,7 +1316,7 @@ bool CWIN32Util::ToggleWindowsHDR()
DISPLAYCONFIG_DEVICE_INFO_HEADER* requestPacket =
reinterpret_cast<DISPLAYCONFIG_DEVICE_INFO_HEADER*>(request);

for (int i = 0; i < modeCount; i++)
for (unsigned i = 0; i < modeCount; i++)
{
if (modesArray[i].infoType == DISPLAYCONFIG_MODE_INFO_TYPE_TARGET)
{
Expand Down Expand Up @@ -1301,10 +1353,40 @@ bool CWIN32Util::ToggleWindowsHDR()
}
}
return success;
#endif
}

int CWIN32Util::GetWindowsHDRStatus()
{
#ifdef TARGET_WINDOWS_STORE
int status = 0;

auto displayInformation = DisplayInformation::GetForCurrentView();

if (displayInformation)
{
auto advancedColorInfo = displayInformation.GetAdvancedColorInfo();

if (advancedColorInfo)
{
if (advancedColorInfo.CurrentAdvancedColorKind() == AdvancedColorKind::HighDynamicRange)
{
status = 2;
if (CServiceBroker::IsServiceManagerUp())
CLog::LogF(LOGDEBUG, "CurrentAdvancedColorKind() = HDR, return status = {0:d}", status);
}
else if (advancedColorInfo.IsAdvancedColorKindAvailable(AdvancedColorKind::HighDynamicRange))
{
status = 1;
if (CServiceBroker::IsServiceManagerUp())
CLog::LogF(LOGDEBUG, "IsAdvancedColorKindAvailable(HDR) = true, return status = {0:d}",
status);
}
}
}

return status;
#else
uint32_t pathCount, modeCount;

uint8_t request[] = {0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x7C, 0x6F, 0x00,
Expand Down Expand Up @@ -1335,7 +1417,7 @@ int CWIN32Util::GetWindowsHDRStatus()
DISPLAYCONFIG_DEVICE_INFO_HEADER* requestPacket =
reinterpret_cast<DISPLAYCONFIG_DEVICE_INFO_HEADER*>(request);

for (int i = 0; i < modeCount; i++)
for (unsigned i = 0; i < modeCount; i++)
{
if (modesArray[i].infoType == DISPLAYCONFIG_MODE_INFO_TYPE_TARGET)
{
Expand Down Expand Up @@ -1380,4 +1462,5 @@ int CWIN32Util::GetWindowsHDRStatus()
}

return status;
#endif
}
45 changes: 25 additions & 20 deletions xbmc/rendering/dx/DeviceResources.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1178,32 +1178,37 @@ void DX::DeviceResources::SetHdrMetaData(DXGI_HDR_METADATA_HDR10& hdr10) const

void DX::DeviceResources::SetHdrColorSpace(const DXGI_COLOR_SPACE_TYPE colorSpace) const
{
ComPtr<IDXGISwapChain3> swapChain3;

if (m_swapChain == nullptr)
return;

DXGI_COLOR_SPACE_TYPE cs = colorSpace;
if (DX::Windowing()->UseLimitedColor())
if (SUCCEEDED(m_swapChain.As(&swapChain3)))
{
switch (cs)
DXGI_COLOR_SPACE_TYPE cs = colorSpace;
if (DX::Windowing()->UseLimitedColor())
{
case DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709:
cs = DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P709;
break;
case DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020:
cs = DXGI_COLOR_SPACE_RGB_STUDIO_G2084_NONE_P2020;
break;
case DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020:
cs = DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P2020;
break;
switch (cs)
{
case DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709:
cs = DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P709;
break;
case DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020:
cs = DXGI_COLOR_SPACE_RGB_STUDIO_G2084_NONE_P2020;
break;
case DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020:
cs = DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P2020;
break;
}
}
if (SUCCEEDED(swapChain3->SetColorSpace1(cs)))
{
CLog::LogF(LOGDEBUG, "DXGI SetColorSpace1 success");
}
else
{
CLog::LogF(LOGERROR, "DXGI SetColorSpace1 failed");
}
}
if (SUCCEEDED(m_swapChain->SetColorSpace1(cs)))
{
CLog::LogF(LOGDEBUG, "DXGI SetColorSpace1 success");
}
else
{
CLog::LogF(LOGERROR, "DXGI SetColorSpace1 failed");
}
}

Expand Down
2 changes: 1 addition & 1 deletion xbmc/rendering/dx/DeviceResources.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ namespace DX
Microsoft::WRL::ComPtr<ID3D11Device1> m_d3dDevice;
Microsoft::WRL::ComPtr<ID3D11DeviceContext1> m_d3dContext;
Microsoft::WRL::ComPtr<ID3D11DeviceContext1> m_deferrContext;
Microsoft::WRL::ComPtr<IDXGISwapChain3> m_swapChain;
Microsoft::WRL::ComPtr<IDXGISwapChain1> m_swapChain;
#ifdef _DEBUG
Microsoft::WRL::ComPtr<ID3D11Debug> m_d3dDebug;
#endif
Expand Down
45 changes: 45 additions & 0 deletions xbmc/windowing/win10/WinSystemWin10DX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "input/touch/generic/GenericTouchActionHandler.h"
#include "input/touch/generic/GenericTouchInputHandler.h"
#include "platform/win32/WIN32Util.h"
#include "rendering/dx/DirectXHelper.h"
#include "utils/log.h"

Expand Down Expand Up @@ -152,3 +153,47 @@ void CWinSystemWin10DX::UninitHooks()
void CWinSystemWin10DX::InitHooks(IDXGIOutput* pOutput)
{
}

bool CWinSystemWin10DX::SetHDR(const VideoPicture* videoPicture /*not used*/)
{
bool success = CWIN32Util::ToggleWindowsHDR();

if (success)
{
Sleep(2000); //Display is switching
m_deviceResources->ReCreateSwapChain();
}

return success;
}

bool CWinSystemWin10DX::IsHDRDisplay()
{
if (CWIN32Util::GetWindowsHDRStatus() > 0)
return true;

return false;
}

bool CWinSystemWin10DX::GetOSHDRStatus()
{
if (CWIN32Util::GetWindowsHDRStatus() == 2)
return true;

return false;
}

bool CWinSystemWin10DX::IsHDROutput() const
{
return m_deviceResources->IsHDROutput();
}

void CWinSystemWin10DX::SetHdrMetaData(DXGI_HDR_METADATA_HDR10& hdr10) const
{
m_deviceResources->SetHdrMetaData(hdr10);
}

void CWinSystemWin10DX::SetHdrColorSpace(const DXGI_COLOR_SPACE_TYPE colorSpace) const
{
m_deviceResources->SetHdrColorSpace(colorSpace);
}
10 changes: 10 additions & 0 deletions xbmc/windowing/win10/WinSystemWin10DX.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@ class CWinSystemWin10DX : public CWinSystemWin10, public CRenderSystemDX

void ShowSplash(const std::string& message) override;

// HDR OS/display override
bool SetHDR(const VideoPicture* videoPicture) override;
bool IsHDRDisplay() override;
bool GetOSHDRStatus() override;

// HDR support
bool IsHDROutput() const;
void SetHdrMetaData(DXGI_HDR_METADATA_HDR10& hdr10) const;
void SetHdrColorSpace(const DXGI_COLOR_SPACE_TYPE colorSpace) const;

protected:
void SetDeviceFullScreen(bool fullScreen, RESOLUTION_INFO& res) override;
void ReleaseBackBuffer() override;
Expand Down
7 changes: 5 additions & 2 deletions xbmc/windowing/windows/WinSystemWin32DX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -382,9 +382,12 @@ HRESULT APIENTRY HookOpenAdapter10_2(D3D10DDIARG_OPENADAPTER *pOpenData)
bool CWinSystemWin32DX::SetHDR(const VideoPicture* videoPicture /*not used*/)
{
bool success = CWIN32Util::ToggleWindowsHDR();
Sleep(2000); //Display is switching

m_deviceResources->ReCreateSwapChain();
if (success)
{
Sleep(2000); //Display is switching
m_deviceResources->ReCreateSwapChain();
}

return success;
}
Expand Down

0 comments on commit 482db5a

Please sign in to comment.