1
0
mirror of https://github.com/EduApps-CDG/OpenDX synced 2024-12-30 09:45:37 +01:00

[dxgi] FindClosestMatchingMode: Fall back to 8-bit SRGB format

Fixes errors in various games which rely on this method.
This commit is contained in:
Philip Rebohle 2018-03-24 11:31:39 +01:00
parent 7f7eedac35
commit 87d6fde5c4
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99

View File

@ -61,70 +61,61 @@ namespace dxvk {
Logger::err("DxgiOutput::FindClosestMatchingMode: no pointer to device was provided for DXGI_FORMAT_UNKNOWN format"); Logger::err("DxgiOutput::FindClosestMatchingMode: no pointer to device was provided for DXGI_FORMAT_UNKNOWN format");
return DXGI_ERROR_INVALID_CALL; return DXGI_ERROR_INVALID_CALL;
} }
if (pModeToMatch->Format == DXGI_FORMAT_UNKNOWN) { // If no format was specified, fall back to a standard
/* TODO: perform additional format matching // SRGB format, which is supported on all devices.
https://msdn.microsoft.com/en-us/library/windows/desktop/bb174547(v=vs.85).aspx?f=255&MSPPError=-2147217396 DXGI_FORMAT formatToMatch = pModeToMatch->Format;
> If pConcernedDevice is NULL, Format CANNOT be DXGI_FORMAT_UNKNOWN.
and vice versa if (formatToMatch == DXGI_FORMAT_UNKNOWN)
>If pConcernedDevice is NOT NULL, Format COULD be DXGI_FORMAT_UNKNOWN. formatToMatch = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
But Format in structures from GetDisplayModeList() cannot be // List all supported modes and filter
DXGI_FORMAT_UNKNOWN by definition. // out those we don't actually need
There is way in case of DXGI_FORMAT_UNKNOWN and pDevice != nullptr we
should perform additional format matching. It may be just ignoring of
Format field or using some range of formats but MSDN nothing says
about of criteria.
*/
Logger::err("DxgiOutput::FindClosestMatchingMode: matching formats to device currently is not supported");
return DXGI_ERROR_UNSUPPORTED;
}
DXGI_MODE_DESC modeToMatch = *pModeToMatch; DXGI_MODE_DESC modeToMatch = *pModeToMatch;
UINT modesCount = 0; UINT modeCount = 0;
GetDisplayModeList(pModeToMatch->Format, 0, &modesCount, nullptr); GetDisplayModeList(formatToMatch, 0, &modeCount, nullptr);
if (modesCount == 0) { if (modeCount == 0) {
Logger::err("DxgiOutput::FindClosestMatchingMode: no device formats were found"); Logger::err("DxgiOutput::FindClosestMatchingMode: No modes found");
return DXGI_ERROR_NOT_FOUND; return DXGI_ERROR_NOT_FOUND;
} }
std::vector<DXGI_MODE_DESC> modes(modesCount); std::vector<DXGI_MODE_DESC> modes(modeCount);
GetDisplayModeList(pModeToMatch->Format, 0, &modesCount, modes.data()); GetDisplayModeList(formatToMatch, 0, &modeCount, modes.data());
/* TODO: add scaling and scanline filter when we implement they */ // Filter out modes with different refresh rate
if (modeToMatch.RefreshRate.Denominator != 0
//filter out modes with different refresh rate if it was set && modeToMatch.RefreshRate.Numerator != 0) {
if (modeToMatch.RefreshRate.Denominator != 0 && modeToMatch.RefreshRate.Numerator != 0) { UINT targetRefreshRate = modeToMatch.RefreshRate.Numerator
UINT targetRefreshRate = modeToMatch.RefreshRate.Numerator / modeToMatch.RefreshRate.Denominator; / modeToMatch.RefreshRate.Denominator;
for (auto it = modes.begin(); it != modes.end();) {
UINT modeRefreshRate = it->RefreshRate.Numerator / it->RefreshRate.Denominator; for (auto it = modes.begin(); it != modes.end(); ) {
UINT modeRefreshRate = it->RefreshRate.Numerator
/ it->RefreshRate.Denominator;
if (modeRefreshRate != targetRefreshRate) if (modeRefreshRate != targetRefreshRate)
it = modes.erase(it); it = modes.erase(it);
else else
++it; it++;
} }
} }
// return error when there is no modes with target refresh rate and scanline order // No matching modes found
if(modes.size() == 0) { if (modes.size() == 0)
Logger::err("DxgiOutput::FindClosestMatchingMode: no matched formats were found");
return DXGI_ERROR_NOT_FOUND; return DXGI_ERROR_NOT_FOUND;
}
//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 = abs((int)(modeToMatch.Width - mode.Width))
+ abs((int)(modeToMatch.Height - mode.Height)); + abs((int)(modeToMatch.Height - mode.Height));
if (currDifference < minDifference) { if (currDifference < minDifference) {
minDifference = currDifference; minDifference = currDifference;
*pClosestMatch = mode; *pClosestMatch = mode;
} }
} }
return S_OK; return S_OK;
} }