mirror of https://github.com/stella-emu/stella.git
handle rounded refresh rates like 59.94 Hz
disable refresh adjust option for macOS
This commit is contained in:
parent
94b1800cc4
commit
137ba30593
|
@ -234,8 +234,6 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const bool fullScreen = mode.fsIndex != -1;
|
const bool fullScreen = mode.fsIndex != -1;
|
||||||
const bool shouldAdapt = fullScreen && myOSystem.settings().getBool("tia.fs_refresh")
|
|
||||||
&& gameRefreshRate() && refreshRate() % gameRefreshRate() != 0;
|
|
||||||
bool forceCreateRenderer = false;
|
bool forceCreateRenderer = false;
|
||||||
|
|
||||||
// Get windowed window's last display
|
// 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);
|
posY = BSPF::clamp(posY, y0 + 50, y1 - 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef BSPF_MACOS
|
||||||
|
// macOS does not allow to change the display refresh rate
|
||||||
SDL_DisplayMode adaptedSdlMode;
|
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);
|
const bool adaptRefresh = shouldAdapt && adaptRefreshRate(displayIndex, adaptedSdlMode);
|
||||||
|
#else
|
||||||
|
const bool adaptRefresh = false;
|
||||||
|
#endif
|
||||||
const uInt32 flags = SDL_WINDOW_ALLOW_HIGHDPI
|
const uInt32 flags = SDL_WINDOW_ALLOW_HIGHDPI
|
||||||
| (fullScreen ? adaptRefresh ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
|
| (fullScreen ? adaptRefresh ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
|
||||||
|
|
||||||
|
@ -331,6 +338,7 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
|
||||||
|
|
||||||
setWindowIcon();
|
setWindowIcon();
|
||||||
}
|
}
|
||||||
|
#ifndef BSPF_MACOS
|
||||||
if(adaptRefresh)
|
if(adaptRefresh)
|
||||||
{
|
{
|
||||||
// Switch to mode for adapted refresh rate
|
// Switch to mode for adapted refresh rate
|
||||||
|
@ -346,10 +354,11 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
|
||||||
Logger::info(msg.str());
|
Logger::info(msg.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return createRenderer(forceCreateRenderer);
|
return createRenderer(forceCreateRenderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef BSPF_MACOS
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool FrameBufferSDL2::adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& adaptedSdlMode)
|
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 currentRefreshRate = sdlMode.refresh_rate;
|
||||||
const int wantedRefreshRate = gameRefreshRate();
|
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;
|
float bestDiff = std::abs(factor - std::round(factor)) / factor;
|
||||||
bool adapt = false;
|
bool adapt = false;
|
||||||
|
|
||||||
|
@ -382,6 +394,8 @@ bool FrameBufferSDL2::adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& adap
|
||||||
return adapt;
|
return adapt;
|
||||||
}
|
}
|
||||||
factor = float(closestSdlMode.refresh_rate) / sdlMode.refresh_rate;
|
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;
|
const float diff = std::abs(factor - std::round(factor)) / factor;
|
||||||
if(diff < bestDiff)
|
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
|
// Only change if the display supports a better refresh rate
|
||||||
return adapt;
|
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)
|
bool FrameBufferSDL2::createRenderer(bool force)
|
||||||
|
@ -540,7 +621,7 @@ int FrameBufferSDL2::gameRefreshRate() const
|
||||||
const string format = myOSystem.console().getFormatString();
|
const string format = myOSystem.console().getFormatString();
|
||||||
const bool isNtsc = format == "NTSC" || format == "PAL60" || format == "SECAM60";
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,6 +181,7 @@ class FrameBufferSDL2 : public FrameBuffer
|
||||||
*/
|
*/
|
||||||
bool setVideoMode(const string& title, const VideoMode& mode) override;
|
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
|
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
|
@return True if the refresh rate should be changed
|
||||||
*/
|
*/
|
||||||
bool adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& adaptedSdlMode);
|
bool adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& adaptedSdlMode);
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Create a new renderer if required
|
Create a new renderer if required
|
||||||
|
|
|
@ -153,10 +153,12 @@ void VideoAudioDialog::addDisplayTab()
|
||||||
myUseStretch = new CheckboxWidget(myTab, _font, xpos + INDENT, ypos + 1, "Stretch");
|
myUseStretch = new CheckboxWidget(myTab, _font, xpos + INDENT, ypos + 1, "Stretch");
|
||||||
wid.push_back(myUseStretch);
|
wid.push_back(myUseStretch);
|
||||||
|
|
||||||
|
#ifndef BSPF_MACOS
|
||||||
// Adapt refresh rate
|
// Adapt refresh rate
|
||||||
ypos += lineHeight + VGAP;
|
ypos += lineHeight + VGAP;
|
||||||
myRefreshAdapt = new CheckboxWidget(myTab, _font, xpos + INDENT, ypos + 1, "Adapt display refresh rate");
|
myRefreshAdapt = new CheckboxWidget(myTab, _font, xpos + INDENT, ypos + 1, "Adapt display refresh rate");
|
||||||
wid.push_back(myRefreshAdapt);
|
wid.push_back(myRefreshAdapt);
|
||||||
|
#endif
|
||||||
|
|
||||||
// FS overscan
|
// FS overscan
|
||||||
ypos += lineHeight + VGAP;
|
ypos += lineHeight + VGAP;
|
||||||
|
@ -484,8 +486,10 @@ void VideoAudioDialog::loadConfig()
|
||||||
myFullScreenMode->setSelected(mode);*/
|
myFullScreenMode->setSelected(mode);*/
|
||||||
// Fullscreen stretch setting
|
// Fullscreen stretch setting
|
||||||
myUseStretch->setState(instance().settings().getBool("tia.fs_stretch"));
|
myUseStretch->setState(instance().settings().getBool("tia.fs_stretch"));
|
||||||
|
#ifndef BSPF_MACOS
|
||||||
// Adapt refresh rate
|
// Adapt refresh rate
|
||||||
myRefreshAdapt->setState(instance().settings().getBool("tia.fs_refresh"));
|
myRefreshAdapt->setState(instance().settings().getBool("tia.fs_refresh"));
|
||||||
|
#endif
|
||||||
// Fullscreen overscan setting
|
// Fullscreen overscan setting
|
||||||
myTVOverscan->setValue(instance().settings().getInt("tia.fs_overscan"));
|
myTVOverscan->setValue(instance().settings().getInt("tia.fs_overscan"));
|
||||||
handleFullScreenChange();
|
handleFullScreenChange();
|
||||||
|
@ -597,8 +601,10 @@ void VideoAudioDialog::saveConfig()
|
||||||
instance().settings().setValue("fullscreen", myFullscreen->getState());
|
instance().settings().setValue("fullscreen", myFullscreen->getState());
|
||||||
// Fullscreen stretch setting
|
// Fullscreen stretch setting
|
||||||
instance().settings().setValue("tia.fs_stretch", myUseStretch->getState());
|
instance().settings().setValue("tia.fs_stretch", myUseStretch->getState());
|
||||||
|
#ifndef BSPF_MACOS
|
||||||
// Adapt refresh rate
|
// Adapt refresh rate
|
||||||
instance().settings().setValue("tia.fs_refresh", myRefreshAdapt->getState());
|
instance().settings().setValue("tia.fs_refresh", myRefreshAdapt->getState());
|
||||||
|
#endif
|
||||||
// Fullscreen overscan
|
// Fullscreen overscan
|
||||||
instance().settings().setValue("tia.fs_overscan", myTVOverscan->getValueLabel());
|
instance().settings().setValue("tia.fs_overscan", myTVOverscan->getValueLabel());
|
||||||
|
|
||||||
|
@ -712,7 +718,9 @@ void VideoAudioDialog::setDefaults()
|
||||||
myFullscreen->setState(false);
|
myFullscreen->setState(false);
|
||||||
//myFullScreenMode->setSelectedIndex(0);
|
//myFullScreenMode->setSelectedIndex(0);
|
||||||
myUseStretch->setState(false);
|
myUseStretch->setState(false);
|
||||||
|
#ifndef BSPF_MACOS
|
||||||
myRefreshAdapt->setState(false);
|
myRefreshAdapt->setState(false);
|
||||||
|
#endif
|
||||||
myTVOverscan->setValue(0);
|
myTVOverscan->setValue(0);
|
||||||
myTIAZoom->setValue(300);
|
myTIAZoom->setValue(300);
|
||||||
myVSizeAdjust->setValue(0);
|
myVSizeAdjust->setValue(0);
|
||||||
|
@ -838,7 +846,9 @@ void VideoAudioDialog::handleFullScreenChange()
|
||||||
{
|
{
|
||||||
bool enable = myFullscreen->getState();
|
bool enable = myFullscreen->getState();
|
||||||
myUseStretch->setEnabled(enable);
|
myUseStretch->setEnabled(enable);
|
||||||
|
#ifndef BSPF_MACOS
|
||||||
myRefreshAdapt->setEnabled(enable);
|
myRefreshAdapt->setEnabled(enable);
|
||||||
|
#endif
|
||||||
myTVOverscan->setEnabled(enable);
|
myTVOverscan->setEnabled(enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,9 @@ class VideoAudioDialog : public Dialog
|
||||||
CheckboxWidget* myFullscreen{nullptr};
|
CheckboxWidget* myFullscreen{nullptr};
|
||||||
CheckboxWidget* myUseStretch{nullptr};
|
CheckboxWidget* myUseStretch{nullptr};
|
||||||
SliderWidget* myTVOverscan{nullptr};
|
SliderWidget* myTVOverscan{nullptr};
|
||||||
|
#ifndef BSPF_MACOS
|
||||||
CheckboxWidget* myRefreshAdapt{nullptr};
|
CheckboxWidget* myRefreshAdapt{nullptr};
|
||||||
|
#endif
|
||||||
SliderWidget* myTIAZoom{nullptr};
|
SliderWidget* myTIAZoom{nullptr};
|
||||||
SliderWidget* myVSizeAdjust{nullptr};
|
SliderWidget* myVSizeAdjust{nullptr};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue