6#include <QtCore/qt_windows.h>
7#include <QtCore/private/qsystemerror_p.h>
11QDxgiHdrInfo::QDxgiHdrInfo()
13 HRESULT hr = CreateDXGIFactory2(0, __uuidof(IDXGIFactory2),
reinterpret_cast<
void **>(&m_factory));
15 qWarning(
"QDxgiHdrInfo: CreateDXGIFactory2 failed: %s", qPrintable(QSystemError::windowsComString(hr)));
25QDxgiHdrInfo::QDxgiHdrInfo(LUID luid)
27 HRESULT hr = CreateDXGIFactory2(0, __uuidof(IDXGIFactory2),
reinterpret_cast<
void **>(&m_factory));
29 qWarning(
"QDxgiHdrInfo: CreateDXGIFactory2 failed: %s", qPrintable(QSystemError::windowsComString(hr)));
34 for (
int adapterIndex = 0; m_factory->EnumAdapters1(UINT(adapterIndex), &ad) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
35 DXGI_ADAPTER_DESC1 desc;
37 if (desc.AdapterLuid.LowPart == luid.LowPart && desc.AdapterLuid.HighPart == luid.HighPart) {
45 qWarning(
"QDxgiHdrInfo: No adapter found");
48QDxgiHdrInfo::QDxgiHdrInfo(IDXGIAdapter1 *adapter)
54QDxgiHdrInfo::~QDxgiHdrInfo()
63bool QDxgiHdrInfo::isHdrCapable(QWindow *w)
65 if (!m_adapter && m_factory) {
66 IDXGIAdapter1 *adapter;
67 for (
int adapterIndex = 0; m_factory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
68 DXGI_OUTPUT_DESC1 desc1;
69 const bool ok = outputDesc1ForWindow(w, adapter, &desc1) && desc1.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
74 }
else if (m_adapter) {
75 DXGI_OUTPUT_DESC1 desc1;
76 if (outputDesc1ForWindow(w, m_adapter, &desc1)) {
78 if (desc1.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020) {
88QRhiSwapChainHdrInfo QDxgiHdrInfo::queryHdrInfo(QWindow *w)
90 QRhiSwapChainHdrInfo info;
91 info.limitsType = QRhiSwapChainHdrInfo::LuminanceInNits;
92 info.limits.luminanceInNits.minLuminance = 0.0f;
93 info.limits.luminanceInNits.maxLuminance = 1000.0f;
94 info.luminanceBehavior = QRhiSwapChainHdrInfo::SceneReferred;
95 info.sdrWhiteLevel = 200.0f;
97 DXGI_OUTPUT_DESC1 hdrOutputDesc;
99 if (!m_adapter && m_factory) {
100 IDXGIAdapter1 *adapter;
101 for (
int adapterIndex = 0; m_factory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
102 ok = outputDesc1ForWindow(w, adapter, &hdrOutputDesc);
107 }
else if (m_adapter) {
108 ok = outputDesc1ForWindow(w, m_adapter, &hdrOutputDesc);
111 info.limitsType = QRhiSwapChainHdrInfo::LuminanceInNits;
112 info.limits.luminanceInNits.minLuminance = hdrOutputDesc.MinLuminance;
113 info.limits.luminanceInNits.maxLuminance = hdrOutputDesc.MaxLuminance;
114 info.luminanceBehavior = QRhiSwapChainHdrInfo::SceneReferred;
115 info.sdrWhiteLevel = sdrWhiteLevelInNits(hdrOutputDesc);
121bool QDxgiHdrInfo::output6ForWindow(QWindow *w, IDXGIAdapter1 *adapter, IDXGIOutput6 **result)
127 HMONITOR monitor =
nullptr;
131 monitor = MonitorFromWindow(
reinterpret_cast<HWND>(w->winId()), MONITOR_DEFAULTTONEAREST);
133 QRect wr = w->geometry();
134 wr = QRect(wr.topLeft() * w->devicePixelRatio(), wr.size() * w->devicePixelRatio());
135 center = wr.center();
137 IDXGIOutput *currentOutput =
nullptr;
138 IDXGIOutput *output =
nullptr;
139 for (UINT i = 0; adapter->EnumOutputs(i, &output) != DXGI_ERROR_NOT_FOUND; ++i) {
142 DXGI_OUTPUT_DESC desc;
143 if (FAILED(output->GetDesc(&desc))) {
147 const RECT r = desc.DesktopCoordinates;
148 const QRect dr(QPoint(r.left, r.top), QSize(r.right - r.left, r.bottom - r.top));
149 if ((monitor && desc.Monitor == monitor) || (!monitor && dr.contains(center))) {
150 currentOutput = output;
157 ok = SUCCEEDED(currentOutput->QueryInterface(__uuidof(IDXGIOutput6),
reinterpret_cast<
void **>(result)));
158 currentOutput->Release();
163bool QDxgiHdrInfo::outputDesc1ForWindow(QWindow *w, IDXGIAdapter1 *adapter, DXGI_OUTPUT_DESC1 *result)
166 IDXGIOutput6 *out6 =
nullptr;
167 if (output6ForWindow(w, adapter, &out6)) {
168 ok = SUCCEEDED(out6->GetDesc1(result));
174float QDxgiHdrInfo::sdrWhiteLevelInNits(
const DXGI_OUTPUT_DESC1 &outputDesc)
176 QVector<DISPLAYCONFIG_PATH_INFO> pathInfos;
177 uint32_t pathInfoCount, modeInfoCount;
180 if (GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathInfoCount, &modeInfoCount) == ERROR_SUCCESS) {
181 pathInfos.resize(pathInfoCount);
182 QVector<DISPLAYCONFIG_MODE_INFO> modeInfos(modeInfoCount);
183 result = QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &pathInfoCount, pathInfos.data(), &modeInfoCount, modeInfos.data(),
nullptr);
187 }
while (result == ERROR_INSUFFICIENT_BUFFER);
189 MONITORINFOEX monitorInfo = {};
190 monitorInfo.cbSize =
sizeof(monitorInfo);
191 GetMonitorInfo(outputDesc.Monitor, &monitorInfo);
193 for (
const DISPLAYCONFIG_PATH_INFO &info : pathInfos) {
194 DISPLAYCONFIG_SOURCE_DEVICE_NAME deviceName = {};
195 deviceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
196 deviceName.header.size =
sizeof(deviceName);
197 deviceName.header.adapterId = info.sourceInfo.adapterId;
198 deviceName.header.id = info.sourceInfo.id;
199 if (DisplayConfigGetDeviceInfo(&deviceName.header) == ERROR_SUCCESS) {
200 if (!wcscmp(monitorInfo.szDevice, deviceName.viewGdiDeviceName)) {
201 DISPLAYCONFIG_SDR_WHITE_LEVEL whiteLevel = {};
202 whiteLevel.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL;
203 whiteLevel.header.size =
sizeof(DISPLAYCONFIG_SDR_WHITE_LEVEL);
204 whiteLevel.header.adapterId = info.targetInfo.adapterId;
205 whiteLevel.header.id = info.targetInfo.id;
206 if (DisplayConfigGetDeviceInfo(&whiteLevel.header) == ERROR_SUCCESS)
207 return whiteLevel.SDRWhiteLevel * 80 / 1000.0f;
Combined button and popup list for selecting options.