Skip to content

Commit

Permalink
Improves stability in NVIDIA HDR full screen switching.
Browse files Browse the repository at this point in the history
Improves detection of HDR display in some multi-screen escenarios.
  • Loading branch information
thexai committed Jan 18, 2020
1 parent b040eb2 commit 2ec9ce1
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ void CRendererBase::Render(CD3DTexture& target, const CRect& sourceRect, const C
DX::DeviceResources::Get()->SetHdrMetaData(hdr10);
CLog::LogF(LOGNOTICE, "Switching to HDR rendering");
DX::Windowing()->SetHdrColorSpace(DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020);
DX::Windowing()->ReSetFullScreen(m_fps);
m_isHdrEnabled = true;
m_lastHdr10 = hdr10;
}
Expand All @@ -241,6 +242,7 @@ void CRendererBase::Render(CD3DTexture& target, const CRect& sourceRect, const C
// Switch to HLG rendering (internally converts HLG to HDR10)
CLog::LogF(LOGNOTICE, "Switching to HLG rendering");
DX::Windowing()->SetHdrColorSpace(DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020);
DX::Windowing()->ReSetFullScreen(m_fps);
m_isHlgEnabled = true;
}
}
Expand Down
94 changes: 52 additions & 42 deletions xbmc/platform/win32/WIN32Util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1326,24 +1326,24 @@ bool CWIN32Util::ToggleWindowsHDR()
requestPacket->adapterId.HighPart = modesArray[i].adapterId.HighPart;
requestPacket->adapterId.LowPart = modesArray[i].adapterId.LowPart;
requestPacket->id = modesArray[i].id;
}
}

if (ERROR_SUCCESS == DisplayConfigGetDeviceInfo(requestPacket))
{
if (request[20] == 0xD1) // HDR is OFF
{
set[20] = 1;
CLog::LogF(LOGNOTICE, "Toggle Windows HDR On (OFF => ON).");
DisplayConfigSetDeviceInfo(setPacket);
success = true;
}
else if (request[20] == 0xD3) // HDR is ON
{
set[20] = 0;
CLog::LogF(LOGNOTICE, "Toggle Windows HDR Off (ON => OFF).");
DisplayConfigSetDeviceInfo(setPacket);
success = true;
if (ERROR_SUCCESS == DisplayConfigGetDeviceInfo(requestPacket))
{
if (request[20] == 0xD1) // HDR is OFF
{
set[20] = 1;
CLog::LogF(LOGNOTICE, "Toggle Windows HDR On (OFF => ON).");
DisplayConfigSetDeviceInfo(setPacket);
success = true;
}
else if (request[20] == 0xD3) // HDR is ON
{
set[20] = 0;
CLog::LogF(LOGNOTICE, "Toggle Windows HDR Off (ON => OFF).");
DisplayConfigSetDeviceInfo(setPacket);
success = true;
}
}
}
}
}
Expand Down Expand Up @@ -1385,12 +1385,13 @@ int CWIN32Util::GetWindowsHDRStatus()

return status;
#else
uint32_t pathCount, modeCount;
uint32_t pathCount, modeCount, targetCount;

uint8_t request[] = {0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x7C, 0x6F, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0xDB, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00};

uint8_t targetArray[10] = {};
int status = 0;

if (ERROR_SUCCESS == GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathCount, &modeCount))
Expand All @@ -1415,44 +1416,53 @@ int CWIN32Util::GetWindowsHDRStatus()
DISPLAYCONFIG_DEVICE_INFO_HEADER* requestPacket =
reinterpret_cast<DISPLAYCONFIG_DEVICE_INFO_HEADER*>(request);

targetCount = 0;
for (unsigned i = 0; i < modeCount; i++)
{
if (modesArray[i].infoType == DISPLAYCONFIG_MODE_INFO_TYPE_TARGET)
{
requestPacket->adapterId.HighPart = modesArray[i].adapterId.HighPart;
requestPacket->adapterId.LowPart = modesArray[i].adapterId.LowPart;
requestPacket->id = modesArray[i].id;
if (ERROR_SUCCESS == DisplayConfigGetDeviceInfo(requestPacket))
{
targetArray[targetCount] = request[20];
targetCount ++;
}
}
}

if (ERROR_SUCCESS == DisplayConfigGetDeviceInfo(requestPacket))
uint8_t targetStatus = 0xD0;
for (int i = 0; i < targetCount; i++)
{
std::string txDeviceInfo;
switch (request[20])
if (targetArray[i] == 0xD1 || targetArray[i] == 0xD3)
{
case 0xD0: // display is not HDR capable
status = 0;
txDeviceInfo = "No HDR capable";
break;
case 0xD1: // capable and HDR is OFF
status = 1;
txDeviceInfo = "HDR capable and OFF";
break;
case 0xD3: // capable and HDR is ON
status = 2;
txDeviceInfo = "HDR capable and ON";
break;
default:
status = 0;
txDeviceInfo = "UNKNOWN";
break;
targetStatus = targetArray[i];
break;
}
if (CServiceBroker::IsServiceManagerUp())
CLog::LogF(LOGDEBUG,
"DisplayConfigGetDeviceInfo returned value 0x{0:2X} \"{1:s}\" (return "
"status = {2:d})",
request[20], txDeviceInfo, status);
}

std::string txDeviceInfo;
switch (targetStatus)
{
case 0xD0: // display is not HDR capable
status = 0;
txDeviceInfo = "No HDR capable";
break;
case 0xD1: // capable and HDR is OFF
status = 1;
txDeviceInfo = "HDR capable and OFF";
break;
case 0xD3: // capable and HDR is ON
status = 2;
txDeviceInfo = "HDR capable and ON";
break;
}
if (CServiceBroker::IsServiceManagerUp())
CLog::LogF(LOGDEBUG,
"DisplayConfigGetDeviceInfo returned value 0x{0:2X} \"{1:s}\" (return status "
"= {2:d})",
request[20], txDeviceInfo, status);
}
std::free(pathsArray);
std::free(modesArray);
Expand Down
80 changes: 80 additions & 0 deletions xbmc/rendering/dx/DeviceResources.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1231,3 +1231,83 @@ void DX::DeviceResources::ReCreateSwapChain()

CreateWindowSizeDependentResources();
}

void DX::DeviceResources::ReSetFullScreen(float refreshRate)
{
if (m_swapChain == nullptr)
return;

DXGI_ADAPTER_DESC id = {};
GetAdapterDesc(&id);

if (id.VendorId != 0x10DE) // Only need for NVIDIA
return;

CLog::LogF(LOGDEBUG, "Re-set full screen due SDR -> HDR switch");

BOOL bFullcreen = 0;
m_swapChain->GetFullscreenState(&bFullcreen, nullptr);
if (!!bFullcreen)
{
DXGI_RATIONAL rRate;
DXGI_MODE_DESC md = {};
DXGI_SWAP_CHAIN_DESC1 scd = {};

m_swapChain->GetDesc1(&scd);

if (abs((24000.0f / 1001.0f) - refreshRate) < 0.001f)
{
rRate.Numerator = 24000u;
rRate.Denominator = 1001u;
}
else if (abs((24000.0f / 1000.0f) - refreshRate) < 0.001f)
{
rRate.Numerator = 24u;
rRate.Denominator = 1u;
}
else if (abs((25000.0f / 1000.0f) - refreshRate) < 0.001f)
{
rRate.Numerator = 25u;
rRate.Denominator = 1u;
}
else if (abs((30000.0f / 1001.0f) - refreshRate) < 0.001f)
{
rRate.Numerator = 30000u;
rRate.Denominator = 1001u;
}
else if (abs((30000.0f / 1000.0f) - refreshRate) < 0.001f)
{
rRate.Numerator = 30u;
rRate.Denominator = 1u;
}
else if (abs((50000.0f / 1000.0f) - refreshRate) < 0.001f)
{
rRate.Numerator = 50u;
rRate.Denominator = 1u;
}
else if (abs((60000.0f / 1001.0f) - refreshRate) < 0.001f)
{
rRate.Numerator = 60000u;
rRate.Denominator = 1001u;
}
else if (abs((60000.0f / 1000.0f) - refreshRate) < 0.001f)
{
rRate.Numerator = 60u;
rRate.Denominator = 1u;
}

md.Format = DXGI_FORMAT_UNKNOWN;
md.RefreshRate = rRate;
md.Height = scd.Height;
md.Width = scd.Width;
m_swapChain->ResizeTarget(&md);
m_swapChain->SetFullscreenState(true, nullptr);
md.RefreshRate.Numerator = 0;
md.RefreshRate.Denominator = 1;
m_swapChain->ResizeTarget(&md);

ComPtr<IDXGIOutput> output;
m_swapChain->GetFullscreenState(&bFullcreen, &output);
output.As(&m_output);
}
}
1 change: 1 addition & 0 deletions xbmc/rendering/dx/DeviceResources.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ namespace DX
void ReCreateSwapChain();

bool SetFullScreen(bool fullscreen, RESOLUTION_INFO& res);
void ReSetFullScreen(float refreshRate);

// HDR display support
void SetHdrMetaData(DXGI_HDR_METADATA_HDR10& hdr10) const;
Expand Down
5 changes: 5 additions & 0 deletions xbmc/windowing/win10/WinSystemWin10DX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,3 +197,8 @@ void CWinSystemWin10DX::SetHdrColorSpace(const DXGI_COLOR_SPACE_TYPE colorSpace)
{
m_deviceResources->SetHdrColorSpace(colorSpace);
}

void CWinSystemWin10DX::ReSetFullScreen(float refreshRate) const
{
m_deviceResources->ReSetFullScreen(refreshRate);
}
1 change: 1 addition & 0 deletions xbmc/windowing/win10/WinSystemWin10DX.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class CWinSystemWin10DX : public CWinSystemWin10, public CRenderSystemDX
bool IsHDROutput() const;
void SetHdrMetaData(DXGI_HDR_METADATA_HDR10& hdr10) const;
void SetHdrColorSpace(const DXGI_COLOR_SPACE_TYPE colorSpace) const;
void ReSetFullScreen(float refreshRate) const;

protected:
void SetDeviceFullScreen(bool fullScreen, RESOLUTION_INFO& res) override;
Expand Down
5 changes: 5 additions & 0 deletions xbmc/windowing/windows/WinSystemWin32DX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -422,3 +422,8 @@ void CWinSystemWin32DX::SetHdrColorSpace(const DXGI_COLOR_SPACE_TYPE colorSpace)
{
m_deviceResources->SetHdrColorSpace(colorSpace);
}

void CWinSystemWin32DX::ReSetFullScreen(float refreshRate) const
{
m_deviceResources->ReSetFullScreen(refreshRate);
}
1 change: 1 addition & 0 deletions xbmc/windowing/windows/WinSystemWin32DX.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ class CWinSystemWin32DX : public CWinSystemWin32, public CRenderSystemDX
bool IsHDROutput() const;
void SetHdrMetaData(DXGI_HDR_METADATA_HDR10& hdr10) const;
void SetHdrColorSpace(const DXGI_COLOR_SPACE_TYPE colorSpace) const;
void ReSetFullScreen(float refreshRate) const;

protected:
void SetDeviceFullScreen(bool fullScreen, RESOLUTION_INFO& res) override;
Expand Down

0 comments on commit 2ec9ce1

Please sign in to comment.