From ffe30282850146a8ae7c194f2ff85b71a801f8df Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 18 Apr 2018 15:33:56 +0200 Subject: [PATCH] [dxgi] GetDisplayModeList: Sort display mode list Some games, including Dark Souls 3, rely on display modes being returned in a specific order. This emulates Windows 10 behaviour. --- src/dxgi/dxgi_output.cpp | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/src/dxgi/dxgi_output.cpp b/src/dxgi/dxgi_output.cpp index 6da7a3209..a27b9d3c8 100644 --- a/src/dxgi/dxgi_output.cpp +++ b/src/dxgi/dxgi_output.cpp @@ -1,3 +1,5 @@ +#include + #include #include @@ -183,6 +185,8 @@ namespace dxvk { uint32_t srcModeId = 0; uint32_t dstModeId = 0; + std::vector modeList; + while (::EnumDisplaySettingsW(monInfo.szDevice, srcModeId++, &devMode)) { // Skip interlaced modes altogether if (devMode.dmDisplayFlags & DM_INTERLACED) @@ -192,11 +196,7 @@ namespace dxvk { if (devMode.dmBitsPerPel != GetFormatBpp(EnumFormat)) continue; - // Write back display mode if (pDesc != nullptr) { - if (dstModeId >= *pNumModes) - return DXGI_ERROR_MORE_DATA; - DXGI_MODE_DESC mode; mode.Width = devMode.dmPelsWidth; mode.Height = devMode.dmPelsHeight; @@ -204,13 +204,36 @@ namespace dxvk { mode.Format = EnumFormat; mode.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE; mode.Scaling = DXGI_MODE_SCALING_CENTERED; - - pDesc[dstModeId] = mode; + modeList.push_back(mode); } dstModeId += 1; } + // Sort display modes by width, height and refresh rate, + // in that order. Some games rely on correct ordering. + std::sort(modeList.begin(), modeList.end(), + [] (const DXGI_MODE_DESC& a, const DXGI_MODE_DESC& b) { + if (a.Width < b.Width) return true; + if (a.Width > b.Width) return false; + + if (a.Height < b.Height) return true; + if (a.Height > b.Height) return false; + + return (a.RefreshRate.Numerator / a.RefreshRate.Denominator) + < (b.RefreshRate.Numerator / b.RefreshRate.Denominator); + }); + + // If requested, write out the first set of display + // modes to the destination array. + if (pDesc != nullptr) { + for (uint32_t i = 0; i < *pNumModes && i < dstModeId; i++) + pDesc[i] = modeList[i]; + + if (dstModeId > *pNumModes) + return DXGI_ERROR_MORE_DATA; + } + *pNumModes = dstModeId; return S_OK; }