handle rounded refresh rates like 59.94 Hz

disable refresh adjust option for macOS
This commit is contained in:
thrust26 2020-05-23 12:29:31 +02:00
parent 94b1800cc4
commit 137ba30593
4 changed files with 100 additions and 5 deletions

View File

@ -234,8 +234,6 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
return false;
const bool fullScreen = mode.fsIndex != -1;
const bool shouldAdapt = fullScreen && myOSystem.settings().getBool("tia.fs_refresh")
&& gameRefreshRate() && refreshRate() % gameRefreshRate() != 0;
bool forceCreateRenderer = false;
// Get windowed window's last display
@ -272,8 +270,17 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
posY = BSPF::clamp(posY, y0 + 50, y1 - 50);
}
#ifndef BSPF_MACOS
// macOS does not allow to change the display refresh rate
SDL_DisplayMode adaptedSdlMode;
const bool shouldAdapt = fullScreen && myOSystem.settings().getBool("tia.fs_refresh")
&& gameRefreshRate()
// take care of 59.94 Hz
&& refreshRate() % gameRefreshRate() != 0 && refreshRate() % (gameRefreshRate() - 1) != 0;
const bool adaptRefresh = shouldAdapt && adaptRefreshRate(displayIndex, adaptedSdlMode);
#else
const bool adaptRefresh = false;
#endif
const uInt32 flags = SDL_WINDOW_ALLOW_HIGHDPI
| (fullScreen ? adaptRefresh ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
@ -331,6 +338,7 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
setWindowIcon();
}
#ifndef BSPF_MACOS
if(adaptRefresh)
{
// Switch to mode for adapted refresh rate
@ -346,10 +354,11 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
Logger::info(msg.str());
}
}
#endif
return createRenderer(forceCreateRenderer);
}
#ifndef BSPF_MACOS
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferSDL2::adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& adaptedSdlMode)
{
@ -363,7 +372,10 @@ bool FrameBufferSDL2::adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& adap
const int currentRefreshRate = sdlMode.refresh_rate;
const int wantedRefreshRate = gameRefreshRate();
float factor = float(currentRefreshRate) / wantedRefreshRate;
// Take care of rounded refresh rates (e.g. 59.94 Hz)
float factor = std::min(float(currentRefreshRate) / wantedRefreshRate,
float(currentRefreshRate) / (wantedRefreshRate - 1));
// Calculate difference taking care of integer factors (e.g. 100/120)
float bestDiff = std::abs(factor - std::round(factor)) / factor;
bool adapt = false;
@ -382,6 +394,8 @@ bool FrameBufferSDL2::adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& adap
return adapt;
}
factor = float(closestSdlMode.refresh_rate) / sdlMode.refresh_rate;
factor = std::min(float(sdlMode.refresh_rate) / sdlMode.refresh_rate,
float(sdlMode.refresh_rate) / (sdlMode.refresh_rate - 1));
const float diff = std::abs(factor - std::round(factor)) / factor;
if(diff < bestDiff)
{
@ -399,7 +413,74 @@ bool FrameBufferSDL2::adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& adap
// Only change if the display supports a better refresh rate
return adapt;
#if 0
// Adapting resfresh rate and display size
const bool hiDpi = myOSystem.settings().getBool("hidpi");
const float mult = float(font().getFontHeight()) / getFontDesc("medium").height * hiDpi ? 2 : 1;
const Int32 minWidth = FBMinimum::Width * mult;
const Int32 minHeight = FBMinimum::Height * mult;
SDL_DisplayMode sdlMode;
if(SDL_GetCurrentDisplayMode(displayIndex, &sdlMode) != 0)
{
Logger::error("ERROR: Display mode could not be retrieved");
return false;
}
const int numModes = SDL_GetNumDisplayModes(displayIndex);
if(numModes < 0)
{
Logger::error("ERROR: Number of display modes could not be retrieved");
return false;
}
const int currentRefreshRate = sdlMode.refresh_rate;
const int wantedRefreshRate = gameRefreshRate();
// Take care of rounded refresh rates (e.g. 59.94)
float factor = std::min(float(currentRefreshRate) / wantedRefreshRate,
float(currentRefreshRate) / (wantedRefreshRate - 1));
// Calculate difference taking care of integer factors (e.g. 100/120)
float bestDiff = std::abs(factor - std::round(factor)) / factor;
bool adapt = false;
for(int mode = 0; mode < numModes; ++mode)
{
// Note: Display modes returned are sorted by width, height,... refresh_rate
if(SDL_GetDisplayMode(displayIndex, mode, &sdlMode) != 0)
{
Logger::error("ERROR: Display modes could not be retrieved");
return false;
}
// skip too small modes
if(sdlMode.w < minWidth || sdlMode.h < minHeight)
continue;
cerr << sdlMode.w << "x" << sdlMode.h << " " << sdlMode.refresh_rate << " Hz" << endl;
factor = std::min(float(sdlMode.refresh_rate) / wantedRefreshRate,
float(sdlMode.refresh_rate) / (wantedRefreshRate - 1));
const float diff = std::abs(factor - std::round(factor)) / factor;
if(diff < bestDiff)
{
bestDiff = diff;
adaptedSdlMode = sdlMode;
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;
#endif
}
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferSDL2::createRenderer(bool force)
@ -540,7 +621,7 @@ int FrameBufferSDL2::gameRefreshRate() const
const string format = myOSystem.console().getFormatString();
const bool isNtsc = format == "NTSC" || format == "PAL60" || format == "SECAM60";
return isNtsc ? 60 : 50;
return isNtsc ? 60 : 50; // The code will take care of 59/49 Hz
}
return 0;
}

View File

@ -181,6 +181,7 @@ class FrameBufferSDL2 : public FrameBuffer
*/
bool setVideoMode(const string& title, const VideoMode& mode) override;
#ifndef BSPF_MACOS
/**
Checks if the display refresh rate should be adapted to game refresh rate in (real) fullscreen mode
@ -190,6 +191,7 @@ class FrameBufferSDL2 : public FrameBuffer
@return True if the refresh rate should be changed
*/
bool adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& adaptedSdlMode);
#endif
/**
Create a new renderer if required

View File

@ -153,10 +153,12 @@ void VideoAudioDialog::addDisplayTab()
myUseStretch = new CheckboxWidget(myTab, _font, xpos + INDENT, ypos + 1, "Stretch");
wid.push_back(myUseStretch);
#ifndef BSPF_MACOS
// Adapt refresh rate
ypos += lineHeight + VGAP;
myRefreshAdapt = new CheckboxWidget(myTab, _font, xpos + INDENT, ypos + 1, "Adapt display refresh rate");
wid.push_back(myRefreshAdapt);
#endif
// FS overscan
ypos += lineHeight + VGAP;
@ -484,8 +486,10 @@ void VideoAudioDialog::loadConfig()
myFullScreenMode->setSelected(mode);*/
// Fullscreen stretch setting
myUseStretch->setState(instance().settings().getBool("tia.fs_stretch"));
#ifndef BSPF_MACOS
// Adapt refresh rate
myRefreshAdapt->setState(instance().settings().getBool("tia.fs_refresh"));
#endif
// Fullscreen overscan setting
myTVOverscan->setValue(instance().settings().getInt("tia.fs_overscan"));
handleFullScreenChange();
@ -597,8 +601,10 @@ void VideoAudioDialog::saveConfig()
instance().settings().setValue("fullscreen", myFullscreen->getState());
// Fullscreen stretch setting
instance().settings().setValue("tia.fs_stretch", myUseStretch->getState());
#ifndef BSPF_MACOS
// Adapt refresh rate
instance().settings().setValue("tia.fs_refresh", myRefreshAdapt->getState());
#endif
// Fullscreen overscan
instance().settings().setValue("tia.fs_overscan", myTVOverscan->getValueLabel());
@ -712,7 +718,9 @@ void VideoAudioDialog::setDefaults()
myFullscreen->setState(false);
//myFullScreenMode->setSelectedIndex(0);
myUseStretch->setState(false);
#ifndef BSPF_MACOS
myRefreshAdapt->setState(false);
#endif
myTVOverscan->setValue(0);
myTIAZoom->setValue(300);
myVSizeAdjust->setValue(0);
@ -838,7 +846,9 @@ void VideoAudioDialog::handleFullScreenChange()
{
bool enable = myFullscreen->getState();
myUseStretch->setEnabled(enable);
#ifndef BSPF_MACOS
myRefreshAdapt->setEnabled(enable);
#endif
myTVOverscan->setEnabled(enable);
}

View File

@ -73,7 +73,9 @@ class VideoAudioDialog : public Dialog
CheckboxWidget* myFullscreen{nullptr};
CheckboxWidget* myUseStretch{nullptr};
SliderWidget* myTVOverscan{nullptr};
#ifndef BSPF_MACOS
CheckboxWidget* myRefreshAdapt{nullptr};
#endif
SliderWidget* myTIAZoom{nullptr};
SliderWidget* myVSizeAdjust{nullptr};