diff --git a/src/common/FrameBufferSDL2.cxx b/src/common/FrameBufferSDL2.cxx index a912b8ad3..9bb0dae57 100644 --- a/src/common/FrameBufferSDL2.cxx +++ b/src/common/FrameBufferSDL2.cxx @@ -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; } diff --git a/src/common/FrameBufferSDL2.hxx b/src/common/FrameBufferSDL2.hxx index 7904ed0ee..282cf2100 100644 --- a/src/common/FrameBufferSDL2.hxx +++ b/src/common/FrameBufferSDL2.hxx @@ -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 diff --git a/src/gui/VideoAudioDialog.cxx b/src/gui/VideoAudioDialog.cxx index 46203783a..edce71e10 100644 --- a/src/gui/VideoAudioDialog.cxx +++ b/src/gui/VideoAudioDialog.cxx @@ -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); } diff --git a/src/gui/VideoAudioDialog.hxx b/src/gui/VideoAudioDialog.hxx index 0961f776e..c20b39438 100644 --- a/src/gui/VideoAudioDialog.hxx +++ b/src/gui/VideoAudioDialog.hxx @@ -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};