added refresh rate adapt for integer factors of the game's refresh rate

This commit is contained in:
thrust26 2020-05-20 10:19:31 +02:00
parent 4afe92e96d
commit 85c3cf59bc
2 changed files with 65 additions and 42 deletions

View File

@ -220,7 +220,7 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
const bool fullScreen = mode.fsIndex != -1;
const bool shouldAdapt = fullScreen && myOSystem.settings().getBool("tia.fs_refresh")
&& gameRefreshRate() && refreshRate() != gameRefreshRate();
&& gameRefreshRate() && refreshRate() % gameRefreshRate() != 0;
bool forceCreateRenderer = false;
// Get windowed window's last display
@ -277,7 +277,7 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
SDL_GetWindowSize(myWindow, &w, &h);
if(d != displayIndex || uInt32(w) != mode.screen.w || uInt32(h) != mode.screen.h
|| shouldAdapt)
|| adaptRefresh)
{
SDL_DestroyWindow(myWindow);
myWindow = nullptr;
@ -335,6 +335,57 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
return createRenderer(forceCreateRenderer);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferSDL2::adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& adaptedSdlMode)
{
SDL_DisplayMode sdlMode;
if(SDL_GetCurrentDisplayMode(displayIndex, &sdlMode) != 0)
{
Logger::error("ERROR: Display mode could not be retrieved");
return false;
}
const int currentRefreshRate = sdlMode.refresh_rate;
const int wantedRefreshRate = gameRefreshRate();
float factor = float(currentRefreshRate) / wantedRefreshRate;
float bestDiff = std::abs(factor - std::round(factor)) / factor;
bool adapt = false;
// Display refresh rate should be an integer factor of the game's refresh rate
// Note: Modes are scanned with size being first priority,
// therefore the size will never change.
// Check for integer factors 1 (60/50 Hz) and 2 (120/100 Hz)
for(int m = 1; m <= 2; ++m)
{
SDL_DisplayMode closestSdlMode;
sdlMode.refresh_rate = wantedRefreshRate * m;
if(SDL_GetClosestDisplayMode(displayIndex, &sdlMode, &closestSdlMode) == NULL)
{
Logger::error("ERROR: Closest display mode could not be retrieved");
return adapt;
}
factor = float(closestSdlMode.refresh_rate) / sdlMode.refresh_rate;
const float diff = std::abs(factor - std::round(factor)) / factor;
if(diff < bestDiff)
{
bestDiff = diff;
adaptedSdlMode = closestSdlMode;
adapt = true;
}
}
cerr << "refresh rate adapt ";
if(adapt)
cerr << "required (" << currentRefreshRate << " Hz -> " << adaptedSdlMode.refresh_rate << " Hz)";
else
cerr << "not required/possible";
cerr << endl;
// Only change if the display supports a better refresh rate
return adapt;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferSDL2::createRenderer(bool force)
{
@ -359,7 +410,7 @@ bool FrameBufferSDL2::createRenderer(bool force)
if(recreate)
{
//cerr << "Create new renderer " << int(myBufferType) << endl;
cerr << "Create new renderer " << int(myBufferType) << endl;
if(myRenderer)
SDL_DestroyRenderer(myRenderer);
@ -388,37 +439,6 @@ bool FrameBufferSDL2::createRenderer(bool force)
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferSDL2::adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& closestSdlMode)
{
SDL_DisplayMode sdlMode;
if(SDL_GetCurrentDisplayMode(displayIndex, &sdlMode) != 0)
{
Logger::error("ERROR: Display mode could not be retrieved");
return false;
}
const int currentRefreshRate = sdlMode.refresh_rate;
sdlMode.refresh_rate = gameRefreshRate();
if(currentRefreshRate != sdlMode.refresh_rate)
{
// Note: Modes are scanned with size being first priority,
// therefore the size will never change.
if(SDL_GetClosestDisplayMode(displayIndex, &sdlMode, &closestSdlMode) == NULL)
{
Logger::error("ERROR: Closest display mode could not be retrieved");
return false;
}
// Only change if the display supports a better refresh rate
return currentRefreshRate != closestSdlMode.refresh_rate;
// TODO: check for multiples e.g. 120/100 too
}
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferSDL2::setTitle(const string& title)
{
@ -503,7 +523,7 @@ int FrameBufferSDL2::gameRefreshRate() const
const string format = myOSystem.console().getFormatString();
const bool isNtsc = format == "NTSC" || format == "PAL60" || format == "SECAM60";
return isNtsc ? 60 : 50; // TODO: check for multiples e.g. 120/100 too
return isNtsc ? 60 : 50;
}
return 0;
}

View File

@ -181,6 +181,16 @@ class FrameBufferSDL2 : public FrameBuffer
*/
bool setVideoMode(const string& title, const VideoMode& mode) override;
/**
Checks if the display refresh rate should be adapted to game refresh rate in (real) fullscreen mode
@param displayIndex The display which should be checked
@adaptedSdlMode The best matching mode if the refresh rate should be changed
@return True if the refresh rate should be changed
*/
bool adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& adaptedSdlMode);
/**
Create a new renderer if required
@ -190,13 +200,6 @@ class FrameBufferSDL2 : public FrameBuffer
*/
bool createRenderer(bool force);
/**
Checks if the display refresh rate should be adapted to game refresh rate in (real) fullscreen mode
@return True if the refresh rate should be changed
*/
bool adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& closestSdlMode);
/**
This method is called to create a surface with the given attributes.