5#include <QtCore/private/qsystemerror_p.h>
9QDxgiHdrInfo::QDxgiHdrInfo()
11 HRESULT hr = CreateDXGIFactory2(0, __uuidof(IDXGIFactory2),
reinterpret_cast<
void **>(&m_factory));
13 qWarning(
"QDxgiHdrInfo: CreateDXGIFactory2 failed: %s", qPrintable(QSystemError::windowsComString(hr)));
23QDxgiHdrInfo::QDxgiHdrInfo(LUID luid)
25 HRESULT hr = CreateDXGIFactory2(0, __uuidof(IDXGIFactory2),
reinterpret_cast<
void **>(&m_factory));
27 qWarning(
"QDxgiHdrInfo: CreateDXGIFactory2 failed: %s", qPrintable(QSystemError::windowsComString(hr)));
32 for (
int adapterIndex = 0; m_factory->EnumAdapters1(UINT(adapterIndex), &ad) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
33 DXGI_ADAPTER_DESC1 desc;
35 if (desc.AdapterLuid.LowPart == luid.LowPart && desc.AdapterLuid.HighPart == luid.HighPart) {
43 qWarning(
"QDxgiHdrInfo: No adapter found");
46QDxgiHdrInfo::QDxgiHdrInfo(IDXGIAdapter1 *adapter)
52QDxgiHdrInfo::~QDxgiHdrInfo()
61bool QDxgiHdrInfo::isHdrCapable(QWindow *w)
63 if (!m_adapter && m_factory) {
64 IDXGIAdapter1 *adapter;
65 for (
int adapterIndex = 0; m_factory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
66 DXGI_OUTPUT_DESC1 desc1;
67 const bool ok = outputDesc1ForWindow(w, adapter, &desc1) && desc1.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
72 }
else if (m_adapter) {
73 DXGI_OUTPUT_DESC1 desc1;
74 if (outputDesc1ForWindow(w, m_adapter, &desc1)) {
76 if (desc1.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020) {
86QRhiSwapChainHdrInfo QDxgiHdrInfo::queryHdrInfo(QWindow *w)
88 QRhiSwapChainHdrInfo info;
89 info.limitsType = QRhiSwapChainHdrInfo::LuminanceInNits;
90 info.limits.luminanceInNits.minLuminance = 0.0f;
91 info.limits.luminanceInNits.maxLuminance = 1000.0f;
92 info.luminanceBehavior = QRhiSwapChainHdrInfo::SceneReferred;
93 info.sdrWhiteLevel = 200.0f;
95 DXGI_OUTPUT_DESC1 hdrOutputDesc;
97 if (!m_adapter && m_factory) {
98 IDXGIAdapter1 *adapter;
99 for (
int adapterIndex = 0; m_factory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
100 ok = outputDesc1ForWindow(w, adapter, &hdrOutputDesc);
105 }
else if (m_adapter) {
106 ok = outputDesc1ForWindow(w, m_adapter, &hdrOutputDesc);
109 info.limitsType = QRhiSwapChainHdrInfo::LuminanceInNits;
110 info.limits.luminanceInNits.minLuminance = hdrOutputDesc.MinLuminance;
111 info.limits.luminanceInNits.maxLuminance = hdrOutputDesc.MaxLuminance;
112 info.luminanceBehavior = QRhiSwapChainHdrInfo::SceneReferred;
113 info.sdrWhiteLevel = sdrWhiteLevelInNits(hdrOutputDesc);
119bool QDxgiHdrInfo::output6ForWindow(QWindow *w, IDXGIAdapter1 *adapter, IDXGIOutput6 **result)
125 QRect wr = w->geometry();
126 wr = QRect(wr.topLeft() * w->devicePixelRatio(), wr.size() * w->devicePixelRatio());
127 const QPoint center = wr.center();
128 IDXGIOutput *currentOutput =
nullptr;
129 IDXGIOutput *output =
nullptr;
130 for (UINT i = 0; adapter->EnumOutputs(i, &output) != DXGI_ERROR_NOT_FOUND; ++i) {
133 DXGI_OUTPUT_DESC desc;
134 output->GetDesc(&desc);
135 const RECT r = desc.DesktopCoordinates;
136 const QRect dr(QPoint(r.left, r.top), QPoint(r.right - 1, r.bottom - 1));
137 if (dr.contains(center)) {
138 currentOutput = output;
145 ok = SUCCEEDED(currentOutput->QueryInterface(__uuidof(IDXGIOutput6),
reinterpret_cast<
void **>(result)));
146 currentOutput->Release();
151bool QDxgiHdrInfo::outputDesc1ForWindow(QWindow *w, IDXGIAdapter1 *adapter, DXGI_OUTPUT_DESC1 *result)
154 IDXGIOutput6 *out6 =
nullptr;
155 if (output6ForWindow(w, adapter, &out6)) {
156 ok = SUCCEEDED(out6->GetDesc1(result));
162float QDxgiHdrInfo::sdrWhiteLevelInNits(
const DXGI_OUTPUT_DESC1 &outputDesc)
164 QVector<DISPLAYCONFIG_PATH_INFO> pathInfos;
165 uint32_t pathInfoCount, modeInfoCount;
168 if (GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathInfoCount, &modeInfoCount) == ERROR_SUCCESS) {
169 pathInfos.resize(pathInfoCount);
170 QVector<DISPLAYCONFIG_MODE_INFO> modeInfos(modeInfoCount);
171 result = QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &pathInfoCount, pathInfos.data(), &modeInfoCount, modeInfos.data(),
nullptr);
175 }
while (result == ERROR_INSUFFICIENT_BUFFER);
177 MONITORINFOEX monitorInfo = {};
178 monitorInfo.cbSize =
sizeof(monitorInfo);
179 GetMonitorInfo(outputDesc.Monitor, &monitorInfo);
181 for (
const DISPLAYCONFIG_PATH_INFO &info : pathInfos) {
182 DISPLAYCONFIG_SOURCE_DEVICE_NAME deviceName = {};
183 deviceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
184 deviceName.header.size =
sizeof(deviceName);
185 deviceName.header.adapterId = info.sourceInfo.adapterId;
186 deviceName.header.id = info.sourceInfo.id;
187 if (DisplayConfigGetDeviceInfo(&deviceName.header) == ERROR_SUCCESS) {
188 if (!wcscmp(monitorInfo.szDevice, deviceName.viewGdiDeviceName)) {
189 DISPLAYCONFIG_SDR_WHITE_LEVEL whiteLevel = {};
190 whiteLevel.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL;
191 whiteLevel.header.size =
sizeof(DISPLAYCONFIG_SDR_WHITE_LEVEL);
192 whiteLevel.header.adapterId = info.targetInfo.adapterId;
193 whiteLevel.header.id = info.targetInfo.id;
194 if (DisplayConfigGetDeviceInfo(&whiteLevel.header) == ERROR_SUCCESS)
195 return whiteLevel.SDRWhiteLevel * 80 / 1000.0f;