mirror of
https://github.com/EduApps-CDG/OpenDX
synced 2024-12-30 09:45:37 +01:00
[dxgi] Enumerate scaled and centered display modes correctly
Fixes fullscreen mode in Dark Souls 3.
This commit is contained in:
parent
87d6fde5c4
commit
19e0829a37
@ -64,16 +64,23 @@ namespace dxvk {
|
|||||||
|
|
||||||
// If no format was specified, fall back to a standard
|
// If no format was specified, fall back to a standard
|
||||||
// SRGB format, which is supported on all devices.
|
// SRGB format, which is supported on all devices.
|
||||||
DXGI_FORMAT formatToMatch = pModeToMatch->Format;
|
DXGI_FORMAT targetFormat = pModeToMatch->Format;
|
||||||
|
|
||||||
if (formatToMatch == DXGI_FORMAT_UNKNOWN)
|
if (targetFormat == DXGI_FORMAT_UNKNOWN)
|
||||||
formatToMatch = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
targetFormat = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||||
|
|
||||||
|
UINT targetRefreshRate = 0;
|
||||||
|
|
||||||
|
if (pModeToMatch->RefreshRate.Denominator != 0
|
||||||
|
&& pModeToMatch->RefreshRate.Numerator != 0) {
|
||||||
|
targetRefreshRate = pModeToMatch->RefreshRate.Numerator
|
||||||
|
/ pModeToMatch->RefreshRate.Denominator;
|
||||||
|
}
|
||||||
|
|
||||||
// List all supported modes and filter
|
// List all supported modes and filter
|
||||||
// out those we don't actually need
|
// out those we don't actually need
|
||||||
DXGI_MODE_DESC modeToMatch = *pModeToMatch;
|
|
||||||
UINT modeCount = 0;
|
UINT modeCount = 0;
|
||||||
GetDisplayModeList(formatToMatch, 0, &modeCount, nullptr);
|
GetDisplayModeList(targetFormat, DXGI_ENUM_MODES_SCALING, &modeCount, nullptr);
|
||||||
|
|
||||||
if (modeCount == 0) {
|
if (modeCount == 0) {
|
||||||
Logger::err("DxgiOutput::FindClosestMatchingMode: No modes found");
|
Logger::err("DxgiOutput::FindClosestMatchingMode: No modes found");
|
||||||
@ -81,23 +88,23 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<DXGI_MODE_DESC> modes(modeCount);
|
std::vector<DXGI_MODE_DESC> modes(modeCount);
|
||||||
GetDisplayModeList(formatToMatch, 0, &modeCount, modes.data());
|
GetDisplayModeList(targetFormat, DXGI_ENUM_MODES_SCALING, &modeCount, modes.data());
|
||||||
|
|
||||||
// Filter out modes with different refresh rate
|
for (auto it = modes.begin(); it != modes.end(); ) {
|
||||||
if (modeToMatch.RefreshRate.Denominator != 0
|
bool skipMode = false;
|
||||||
&& modeToMatch.RefreshRate.Numerator != 0) {
|
|
||||||
UINT targetRefreshRate = modeToMatch.RefreshRate.Numerator
|
|
||||||
/ modeToMatch.RefreshRate.Denominator;
|
|
||||||
|
|
||||||
for (auto it = modes.begin(); it != modes.end(); ) {
|
// Remove modes with a different refresh rate
|
||||||
|
if (targetRefreshRate != 0) {
|
||||||
UINT modeRefreshRate = it->RefreshRate.Numerator
|
UINT modeRefreshRate = it->RefreshRate.Numerator
|
||||||
/ it->RefreshRate.Denominator;
|
/ it->RefreshRate.Denominator;
|
||||||
|
skipMode |= modeRefreshRate != targetRefreshRate;
|
||||||
if (modeRefreshRate != targetRefreshRate)
|
|
||||||
it = modes.erase(it);
|
|
||||||
else
|
|
||||||
it++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove modes with incorrect scaling
|
||||||
|
if (pModeToMatch->Scaling != DXGI_MODE_SCALING_UNSPECIFIED)
|
||||||
|
skipMode |= it->Scaling != pModeToMatch->Scaling;
|
||||||
|
|
||||||
|
it = skipMode ? modes.erase(it) : ++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
// No matching modes found
|
// No matching modes found
|
||||||
@ -106,9 +113,10 @@ namespace dxvk {
|
|||||||
|
|
||||||
// Select mode with minimal height+width difference
|
// Select mode with minimal height+width difference
|
||||||
UINT minDifference = UINT_MAX;
|
UINT minDifference = UINT_MAX;
|
||||||
|
|
||||||
for (auto& mode : modes) {
|
for (auto& mode : modes) {
|
||||||
UINT currDifference = abs((int)(modeToMatch.Width - mode.Width))
|
UINT currDifference = std::abs(int(pModeToMatch->Width - mode.Width))
|
||||||
+ abs((int)(modeToMatch.Height - mode.Height));
|
+ std::abs(int(pModeToMatch->Height - mode.Height));
|
||||||
|
|
||||||
if (currDifference < minDifference) {
|
if (currDifference < minDifference) {
|
||||||
minDifference = currDifference;
|
minDifference = currDifference;
|
||||||
@ -125,8 +133,8 @@ namespace dxvk {
|
|||||||
return DXGI_ERROR_INVALID_CALL;
|
return DXGI_ERROR_INVALID_CALL;
|
||||||
|
|
||||||
::MONITORINFOEX monInfo;
|
::MONITORINFOEX monInfo;
|
||||||
|
|
||||||
monInfo.cbSize = sizeof(monInfo);
|
monInfo.cbSize = sizeof(monInfo);
|
||||||
|
|
||||||
if (!::GetMonitorInfo(m_monitor, &monInfo)) {
|
if (!::GetMonitorInfo(m_monitor, &monInfo)) {
|
||||||
Logger::err("DxgiOutput: Failed to query monitor info");
|
Logger::err("DxgiOutput: Failed to query monitor info");
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
@ -150,14 +158,11 @@ namespace dxvk {
|
|||||||
DXGI_MODE_DESC *pDesc) {
|
DXGI_MODE_DESC *pDesc) {
|
||||||
if (pNumModes == nullptr)
|
if (pNumModes == nullptr)
|
||||||
return DXGI_ERROR_INVALID_CALL;
|
return DXGI_ERROR_INVALID_CALL;
|
||||||
|
|
||||||
if (Flags != 0)
|
|
||||||
Logger::warn("DxgiOutput::GetDisplayModeList: flags are ignored");
|
|
||||||
|
|
||||||
// Query monitor info to get the device name
|
// Query monitor info to get the device name
|
||||||
::MONITORINFOEX monInfo;
|
::MONITORINFOEX monInfo;
|
||||||
|
|
||||||
monInfo.cbSize = sizeof(monInfo);
|
monInfo.cbSize = sizeof(monInfo);
|
||||||
|
|
||||||
if (!::GetMonitorInfo(m_monitor, &monInfo)) {
|
if (!::GetMonitorInfo(m_monitor, &monInfo)) {
|
||||||
Logger::err("DxgiOutput: Failed to query monitor info");
|
Logger::err("DxgiOutput: Failed to query monitor info");
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
@ -170,6 +175,8 @@ namespace dxvk {
|
|||||||
uint32_t srcModeId = 0;
|
uint32_t srcModeId = 0;
|
||||||
uint32_t dstModeId = 0;
|
uint32_t dstModeId = 0;
|
||||||
|
|
||||||
|
const bool includeStretchedModes = (Flags & DXGI_ENUM_MODES_SCALING);
|
||||||
|
|
||||||
while (::EnumDisplaySettings(monInfo.szDevice, srcModeId++, &devMode)) {
|
while (::EnumDisplaySettings(monInfo.szDevice, srcModeId++, &devMode)) {
|
||||||
// Skip interlaced modes altogether
|
// Skip interlaced modes altogether
|
||||||
if (devMode.dmDisplayFlags & DM_INTERLACED)
|
if (devMode.dmDisplayFlags & DM_INTERLACED)
|
||||||
@ -179,6 +186,13 @@ namespace dxvk {
|
|||||||
if (devMode.dmBitsPerPel != GetFormatBpp(EnumFormat))
|
if (devMode.dmBitsPerPel != GetFormatBpp(EnumFormat))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Skip stretched modes unless they are requested
|
||||||
|
const bool isStretched = devMode.dmPelsWidth != UINT(monInfo.rcMonitor.right - monInfo.rcMonitor.left)
|
||||||
|
|| devMode.dmPelsHeight != UINT(monInfo.rcMonitor.bottom - monInfo.rcMonitor.top);
|
||||||
|
|
||||||
|
if (isStretched && !includeStretchedModes)
|
||||||
|
continue;
|
||||||
|
|
||||||
// Write back display mode
|
// Write back display mode
|
||||||
if (pDesc != nullptr) {
|
if (pDesc != nullptr) {
|
||||||
if (dstModeId >= *pNumModes)
|
if (dstModeId >= *pNumModes)
|
||||||
@ -190,7 +204,10 @@ namespace dxvk {
|
|||||||
mode.RefreshRate = { devMode.dmDisplayFrequency, 1 };
|
mode.RefreshRate = { devMode.dmDisplayFrequency, 1 };
|
||||||
mode.Format = EnumFormat;
|
mode.Format = EnumFormat;
|
||||||
mode.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE;
|
mode.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE;
|
||||||
mode.Scaling = DXGI_MODE_SCALING_CENTERED;
|
mode.Scaling = isStretched
|
||||||
|
? DXGI_MODE_SCALING_STRETCHED
|
||||||
|
: DXGI_MODE_SCALING_CENTERED;
|
||||||
|
|
||||||
pDesc[dstModeId] = mode;
|
pDesc[dstModeId] = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,17 +99,18 @@ int WINAPI WinMain(HINSTANCE hInstance,
|
|||||||
for (auto mode : modes) {
|
for (auto mode : modes) {
|
||||||
std::cout << str::format(" ",
|
std::cout << str::format(" ",
|
||||||
mode.Width, "x", mode.Height, " @ ",
|
mode.Width, "x", mode.Height, " @ ",
|
||||||
mode.RefreshRate.Numerator / mode.RefreshRate.Denominator) << std::endl;
|
mode.RefreshRate.Numerator / mode.RefreshRate.Denominator,
|
||||||
|
mode.Scaling == DXGI_MODE_SCALING_CENTERED ? " (native)" : "") << std::endl;
|
||||||
|
|
||||||
//test matching modes
|
//test matching modes
|
||||||
DXGI_MODE_DESC matched_mode{ 0 };
|
DXGI_MODE_DESC matched_mode{ 0 };
|
||||||
status = output->FindClosestMatchingMode(&mode, &matched_mode, nullptr);
|
status = output->FindClosestMatchingMode(&mode, &matched_mode, nullptr);
|
||||||
|
|
||||||
if (status != S_OK) {
|
if (status != S_OK) {
|
||||||
std::cerr << "Failed to get DXGI matched mode" << std::endl;
|
std::cerr << "Failed to get matching mode" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (matched_mode.Width != mode.Width ||
|
if (matched_mode.Width != mode.Width ||
|
||||||
matched_mode.Height != mode.Height ||
|
matched_mode.Height != mode.Height ||
|
||||||
matched_mode.RefreshRate.Numerator != mode.RefreshRate.Numerator ||
|
matched_mode.RefreshRate.Numerator != mode.RefreshRate.Numerator ||
|
||||||
|
Loading…
x
Reference in New Issue
Block a user