[dxgi] Normalize display metadata to something rational

Sometimes we can't get an EDID if things aren't plumbed fully, or some displays just have broken EDIDs.

This accounts for both of those cases by using some dummy data if we are missing information.

Fixes value reporting to match Windows on common displays such as LG OLEDs.
This commit is contained in:
Joshua Ashton 2023-01-06 10:34:08 +00:00 committed by Philip Rebohle
parent f453d6ee2a
commit f25475d05e
1 changed files with 59 additions and 0 deletions

View File

@ -19,6 +19,61 @@
#include "../util/util_time.h"
namespace dxvk {
static void NormalizeDisplayMetadata(wsi::WsiDisplayMetadata& metadata) {
// Use some dummy info when we have no hdr static metadata for the
// display or we were unable to obtain an EDID.
//
// These dummy values are the same as what Windows DXGI will output
// for panels with broken EDIDs such as LG OLEDs displays which
// have an entirely zeroed out luminance section in the hdr static
// metadata block.
//
// (Spec has 0 as 'undefined', which isn't really useful for an app
// to tonemap against.)
if (metadata.minLuminance == 0.0f)
metadata.minLuminance = 0.01f;
if (metadata.maxLuminance == 0.0f)
metadata.maxLuminance = 1499.0f;
if (metadata.maxFullFrameLuminance == 0.0f)
metadata.maxFullFrameLuminance = 799.0f;
// If we have no RedPrimary/GreenPrimary/BluePrimary/WhitePoint due to
// the lack of a monitor exposing the chroma block or the lack of an EDID,
// simply just fall back to Rec.709 or Rec.2020 values depending on the default
// ColorSpace we started in.
// (Don't change based on punting, as this should be static for a display.)
if (metadata.redPrimary[0] == 0.0f && metadata.redPrimary[1] == 0.0f
&& metadata.greenPrimary[0] == 0.0f && metadata.greenPrimary[1] == 0.0f
&& metadata.bluePrimary[0] == 0.0f && metadata.bluePrimary[1] == 0.0f
&& metadata.whitePoint[0] == 0.0f && metadata.whitePoint[1] == 0.0f) {
if (DxgiMonitorInfo::DefaultColorSpace() == DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709) {
// sRGB ColorSpace -> Rec.709 Primaries
metadata.redPrimary[0] = 0.640f;
metadata.redPrimary[1] = 0.330f;
metadata.greenPrimary[0] = 0.300f;
metadata.greenPrimary[1] = 0.600f;
metadata.bluePrimary[0] = 0.150f;
metadata.bluePrimary[1] = 0.060f;
metadata.whitePoint[0] = 0.3127f;
metadata.whitePoint[1] = 0.3290f;
} else {
// HDR10 ColorSpace -> Rec.2020 Primaries
// (Notably much bigger than any display is actually going to expose.)
metadata.redPrimary[0] = 0.708f;
metadata.redPrimary[1] = 0.292f;
metadata.greenPrimary[0] = 0.170f;
metadata.greenPrimary[1] = 0.797f;
metadata.bluePrimary[0] = 0.131f;
metadata.bluePrimary[1] = 0.046f;
metadata.whitePoint[0] = 0.3127f;
metadata.whitePoint[1] = 0.3290f;
}
}
}
DxgiOutput::DxgiOutput(
const Com<DxgiFactory>& factory,
@ -665,6 +720,10 @@ namespace dxvk {
else
Logger::err("DXGI: Failed to parse display metadata + colorimetry info, using blank.");
// Normalize either the display metadata we got back, or our
// blank one to get something sane here.
NormalizeDisplayMetadata(m_metadata);
monitorData.FrameStats.SyncQPCTime.QuadPart = dxvk::high_resolution_clock::get_counter();
monitorData.GammaCurve.Scale = { 1.0f, 1.0f, 1.0f };
monitorData.GammaCurve.Offset = { 0.0f, 0.0f, 0.0f };