6#include <QtCore/private/qsystemerror_p.h>
10QDxgiHdrInfo::QDxgiHdrInfo()
12 HRESULT hr = CreateDXGIFactory2(0, __uuidof(IDXGIFactory2),
reinterpret_cast<
void **>(&m_factory));
14 qWarning(
"QDxgiHdrInfo: CreateDXGIFactory2 failed: %s", qPrintable(QSystemError::windowsComString(hr)));
24QDxgiHdrInfo::QDxgiHdrInfo(LUID luid)
26 HRESULT hr = CreateDXGIFactory2(0, __uuidof(IDXGIFactory2),
reinterpret_cast<
void **>(&m_factory));
28 qWarning(
"QDxgiHdrInfo: CreateDXGIFactory2 failed: %s", qPrintable(QSystemError::windowsComString(hr)));
33 for (
int adapterIndex = 0; m_factory->EnumAdapters1(UINT(adapterIndex), &ad) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
34 DXGI_ADAPTER_DESC1 desc;
36 if (desc.AdapterLuid.LowPart == luid.LowPart && desc.AdapterLuid.HighPart == luid.HighPart) {
44 qWarning(
"QDxgiHdrInfo: No adapter found");
47QDxgiHdrInfo::QDxgiHdrInfo(IDXGIAdapter1 *adapter)
53QDxgiHdrInfo::~QDxgiHdrInfo()
62bool QDxgiHdrInfo::isHdrCapable(QWindow *w)
64 if (!m_adapter && m_factory) {
65 IDXGIAdapter1 *adapter;
66 for (
int adapterIndex = 0; m_factory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
67 DXGI_OUTPUT_DESC1 desc1;
68 const bool ok = outputDesc1ForWindow(w, adapter, &desc1) && desc1.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
73 }
else if (m_adapter) {
74 DXGI_OUTPUT_DESC1 desc1;
75 if (outputDesc1ForWindow(w, m_adapter, &desc1)) {
77 if (desc1.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020) {
87QRhiSwapChainHdrInfo QDxgiHdrInfo::queryHdrInfo(QWindow *w)
89 QRhiSwapChainHdrInfo info;
90 info.limitsType = QRhiSwapChainHdrInfo::LuminanceInNits;
91 info.limits.luminanceInNits.minLuminance = 0.0f;
92 info.limits.luminanceInNits.maxLuminance = 1000.0f;
93 info.luminanceBehavior = QRhiSwapChainHdrInfo::SceneReferred;
94 info.sdrWhiteLevel = 200.0f;
96 DXGI_OUTPUT_DESC1 hdrOutputDesc;
98 if (!m_adapter && m_factory) {
99 IDXGIAdapter1 *adapter;
100 for (
int adapterIndex = 0; m_factory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
101 ok = outputDesc1ForWindow(w, adapter, &hdrOutputDesc);
106 }
else if (m_adapter) {
107 ok = outputDesc1ForWindow(w, m_adapter, &hdrOutputDesc);
110 info.limitsType = QRhiSwapChainHdrInfo::LuminanceInNits;
111 info.limits.luminanceInNits.minLuminance = hdrOutputDesc.MinLuminance;
112 info.limits.luminanceInNits.maxLuminance = hdrOutputDesc.MaxLuminance;
113 info.luminanceBehavior = QRhiSwapChainHdrInfo::SceneReferred;
114 info.sdrWhiteLevel = sdrWhiteLevelInNits(hdrOutputDesc);
120bool QDxgiHdrInfo::output6ForWindow(QWindow *w, IDXGIAdapter1 *adapter, IDXGIOutput6 **result)
126 QRect wr = w->geometry();
127 wr = QRect(wr.topLeft() * w->devicePixelRatio(), wr.size() * w->devicePixelRatio());
128 const QPoint center = wr.center();
129 IDXGIOutput *currentOutput =
nullptr;
130 IDXGIOutput *output =
nullptr;
131 for (UINT i = 0; adapter->EnumOutputs(i, &output) != DXGI_ERROR_NOT_FOUND; ++i) {
134 DXGI_OUTPUT_DESC desc;
135 output->GetDesc(&desc);
136 const RECT r = desc.DesktopCoordinates;
137 const QRect dr(QPoint(r.left, r.top), QPoint(r.right - 1, r.bottom - 1));
138 if (dr.contains(center)) {
139 currentOutput = output;
146 ok = SUCCEEDED(currentOutput->QueryInterface(__uuidof(IDXGIOutput6),
reinterpret_cast<
void **>(result)));
147 currentOutput->Release();
152bool QDxgiHdrInfo::outputDesc1ForWindow(QWindow *w, IDXGIAdapter1 *adapter, DXGI_OUTPUT_DESC1 *result)
155 IDXGIOutput6 *out6 =
nullptr;
156 if (output6ForWindow(w, adapter, &out6)) {
157 ok = SUCCEEDED(out6->GetDesc1(result));
163float QDxgiHdrInfo::sdrWhiteLevelInNits(
const DXGI_OUTPUT_DESC1 &outputDesc)
165 QVector<DISPLAYCONFIG_PATH_INFO> pathInfos;
166 uint32_t pathInfoCount, modeInfoCount;
169 if (GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathInfoCount, &modeInfoCount) == ERROR_SUCCESS) {
170 pathInfos.resize(pathInfoCount);
171 QVector<DISPLAYCONFIG_MODE_INFO> modeInfos(modeInfoCount);
172 result = QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &pathInfoCount, pathInfos.data(), &modeInfoCount, modeInfos.data(),
nullptr);
176 }
while (result == ERROR_INSUFFICIENT_BUFFER);
178 MONITORINFOEX monitorInfo = {};
179 monitorInfo.cbSize =
sizeof(monitorInfo);
180 GetMonitorInfo(outputDesc.Monitor, &monitorInfo);
182 for (
const DISPLAYCONFIG_PATH_INFO &info : pathInfos) {
183 DISPLAYCONFIG_SOURCE_DEVICE_NAME deviceName = {};
184 deviceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
185 deviceName.header.size =
sizeof(deviceName);
186 deviceName.header.adapterId = info.sourceInfo.adapterId;
187 deviceName.header.id = info.sourceInfo.id;
188 if (DisplayConfigGetDeviceInfo(&deviceName.header) == ERROR_SUCCESS) {
189 if (!wcscmp(monitorInfo.szDevice, deviceName.viewGdiDeviceName)) {
190 DISPLAYCONFIG_SDR_WHITE_LEVEL whiteLevel = {};
191 whiteLevel.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL;
192 whiteLevel.header.size =
sizeof(DISPLAYCONFIG_SDR_WHITE_LEVEL);
193 whiteLevel.header.adapterId = info.targetInfo.adapterId;
194 whiteLevel.header.id = info.targetInfo.id;
195 if (DisplayConfigGetDeviceInfo(&whiteLevel.header) == ERROR_SUCCESS)
196 return whiteLevel.SDRWhiteLevel * 80 / 1000.0f;
Combined button and popup list for selecting options.