From eb8ef1fdf73804c488f5952c5f86d71e7ab48455 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Fri, 13 Jan 2017 13:06:31 +0100 Subject: [PATCH] Use refresh rate setting + attempt to improve window/fullscreen apply logic --- Aquaria/DSQ.cpp | 36 +++++++--- Aquaria/InGameMenu.cpp | 32 +++++---- BBGE/Core.cpp | 151 ++++++++++++++++++++++++----------------- BBGE/Core.h | 7 +- 4 files changed, 136 insertions(+), 90 deletions(-) diff --git a/Aquaria/DSQ.cpp b/Aquaria/DSQ.cpp index ea7a7d6..6d497b1 100644 --- a/Aquaria/DSQ.cpp +++ b/Aquaria/DSQ.cpp @@ -777,6 +777,8 @@ void DSQ::setVersionLabelText() static bool sdlVideoModeOK(int disp, const int w, const int h, const int bpp) { + if(!w && !h) + return true; #ifdef BBGE_BUILD_SDL2 SDL_DisplayMode mode; const int modecount = SDL_GetNumDisplayModes(disp); @@ -869,7 +871,6 @@ This build is not yet final, and as such there are a couple things lacking. They this->setBaseTextureDirectory("gfx/"); - bool fullscreen = true; voiceOversEnabled = true; @@ -878,7 +879,7 @@ This build is not yet final, and as such there are a couple things lacking. They particleManager->setSize(user.video.numParticles); - fullscreen = user.video.full; + bool fullscreen = user.video.full; useFrameBuffer = user.video.fbuffer; if (isDeveloperKeys()) @@ -899,17 +900,32 @@ This build is not yet final, and as such there are a couple things lacking. They SDL_Init(SDL_INIT_VIDEO); if (fullscreen && !sdlVideoModeOK(user.video.displayindex, user.video.resx, user.video.resy, user.video.bits)) { - // maybe we can force a sane resolution if SetVideoMode is going to fail... - user.video.resx = 800; - user.video.resy = 600; - user.video.hz = 60; - user.video.displayindex = 0; - if (!sdlVideoModeOK(0, user.video.resx, user.video.resy, user.video.bits)) - fullscreen = false; // last chance. + SDL_DisplayMode mode, closest; + mode.format = 0; + mode.driverdata = 0; + mode.w = user.video.resx; + mode.h = user.video.resy; + mode.refresh_rate = user.video.hz; + if(SDL_GetClosestDisplayMode(user.video.displayindex, &mode, &closest)) + { + user.video.resx = closest.w; + user.video.resy = closest.h; + user.video.hz = closest.refresh_rate; + } + else + { + // maybe we can force a sane resolution if SetVideoMode is going to fail... + user.video.resx = 800; + user.video.resy = 600; + user.video.hz = 60; + user.video.displayindex = 0; + if (!sdlVideoModeOK(0, user.video.resx, user.video.resy, user.video.bits)) + fullscreen = false; // last chance. + } } debugLog("Init Graphics Library..."); - initGraphicsLibrary(user.video.resx, user.video.resy, fullscreen, user.video.vsync, user.video.bits, user.video.displayindex); + initGraphicsLibrary(user.video.resx, user.video.resy, fullscreen, user.video.vsync, user.video.bits, user.video.displayindex, user.video.hz); debugLog("OK"); debugLog("Init Sound Library..."); diff --git a/Aquaria/InGameMenu.cpp b/Aquaria/InGameMenu.cpp index 276e719..9e8ec45 100644 --- a/Aquaria/InGameMenu.cpp +++ b/Aquaria/InGameMenu.cpp @@ -3292,24 +3292,30 @@ void InGameMenu::onOptionsSave() dsq->user.apply(); - if (dsq->user.video.resx != dsq->user_backup.video.resx - || dsq->user.video.resy != dsq->user_backup.video.resy - || dsq->user.video.bits != dsq->user_backup.video.bits - || dsq->user.video.full != dsq->user_backup.video.full - || dsq->user.video.vsync != dsq->user_backup.video.vsync) + const UserSettings::Video& bv = dsq->user_backup.video; + UserSettings::Video& v = dsq->user.video; + + if (v.resx != bv.resx + || v.resy != bv.resy + || v.bits != bv.bits + || v.full != bv.full + || v.vsync != bv.vsync + || v.hz != bv.hz + ) { - dsq->initGraphics(dsq->user.video.resx, dsq->user.video.resy, dsq->user.video.full); + dsq->initGraphics(v.resx, v.resy, v.full, v.vsync, v.bits, -1, v.hz); if (dsq->confirm("", "graphics", false, 10)) { } else { - dsq->user.video.resx = dsq->user_backup.video.resx; - dsq->user.video.resy = dsq->user_backup.video.resy; - dsq->user.video.bits = dsq->user_backup.video.bits; - dsq->user.video.full = dsq->user_backup.video.full; - dsq->user.video.vsync = dsq->user_backup.video.vsync; + v.resx = bv.resx; + v.resy = bv.resy; + v.bits = bv.bits; + v.full = bv.full; + v.vsync = bv.vsync; + v.hz = bv.hz; dsq->user.apply(); - dsq->initGraphics(dsq->user.video.resx, dsq->user.video.resy, dsq->user.video.full); + dsq->initGraphics(v.resx, v.resy, v.full); } } @@ -3909,7 +3915,7 @@ void InGameMenu::toggleOptionsMenu(bool f, bool skipBackup, bool isKeyConfig) if (resBox) { // Note: This adds one past the original list (core->screenModes) - ScreenMode m = core->isDesktopResolution() ? ScreenMode(0,0,0) : ScreenMode(core->width, core->height, 0); + ScreenMode m = core->isDesktopResolution() ? ScreenMode(0,0,0) : ScreenMode(core->width, core->height, core->getRefreshRate()); std::string mstr = screenModeStr(m); if (!resBox->setSelectedItem(mstr)) { diff --git a/BBGE/Core.cpp b/BBGE/Core.cpp index 7c8ef41..314914e 100644 --- a/BBGE/Core.cpp +++ b/BBGE/Core.cpp @@ -146,37 +146,32 @@ void Core::setup_opengl() } -void Core::initGraphics(int w, int h, int fullscreen, int vsync, int bpp, int display) +void Core::initGraphics(int w, int h, int fullscreen, int vsync, int bpp, int display, int hz) { assert(lib_graphics); const int oldDisplay = getDisplayIndex(); + assert(oldDisplay >= 0); if(display == -1) display = oldDisplay; - int screenw = 0, screenh = 0; - if(display >= 0) + SDL_DisplayMode displaymode; + if(SDL_GetDesktopDisplayMode(display, &displaymode) != 0) { - SDL_DisplayMode desktop; - if(SDL_GetDesktopDisplayMode(display, &desktop) == 0) - { - screenw = desktop.w; - screenh = desktop.h; - } - else // fail-safe - { - screenw = 800; - screenh = 600; - display = oldDisplay; - } + // fail-safe + displaymode.w = 800; + displaymode.h = 600; + displaymode.driverdata = 0; + displaymode.refresh_rate = 0; + displaymode.format = 0; + display = oldDisplay; + } - // Move window to specified display if necessary - if(display != oldDisplay) - { - SDL_Rect bounds; - SDL_GetDisplayBounds(display,&bounds); - SDL_SetWindowPosition(gScreen, bounds.x, bounds.y); - } + // Move window to specified display if necessary + if(display != oldDisplay) + { + int center = SDL_WINDOWPOS_CENTERED_DISPLAY(display); + SDL_SetWindowPosition(gScreen, center, center); } const int oldw = width; @@ -186,6 +181,9 @@ void Core::initGraphics(int w, int h, int fullscreen, int vsync, int bpp, int di const bool useDesktop = w == 0 || h == 0 || (oldw && w == -1 && oldh && h == -1 && _useDesktopResolution); const bool wasFullscreen = _fullscreen; + if(hz == -1) + hz = _refreshRate; + if (fullscreen == -1) fullscreen = _fullscreen; @@ -194,8 +192,8 @@ void Core::initGraphics(int w, int h, int fullscreen, int vsync, int bpp, int di if(useDesktop) { - w = screenw; - h = screenh; + w = displaymode.w; + h = displaymode.h; } if (w == -1) @@ -210,6 +208,8 @@ void Core::initGraphics(int w, int h, int fullscreen, int vsync, int bpp, int di _vsync = vsync; _fullscreen = fullscreen; _bpp = bpp; + _refreshRate = hz; + displaymode.refresh_rate = hz; #ifdef BBGE_BUILD_SDL2 if(vsync) @@ -221,44 +221,54 @@ void Core::initGraphics(int w, int h, int fullscreen, int vsync, int bpp, int di SDL_GL_SetSwapInterval(0); // Record window position so we can properly restore it when leaving fullscreen - if(fullscreen && !wasFullscreen) - SDL_GetWindowPosition(gScreen, &winPosX, &winPosY); + //if(fullscreen && !wasFullscreen) + // SDL_GetWindowPosition(gScreen, &winPosX, &winPosY); - if(!!fullscreen != wasFullscreen) - { - int screenflags = 0; - if(fullscreen) - { - screenflags |= useDesktop ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_FULLSCREEN; - } - - SDL_SetWindowFullscreen(gScreen, screenflags); - - if(!fullscreen && wasFullscreen) - { - // Need to do this; else the window ends up at (0, 0) with the title bar outside the screen area - SDL_SetWindowPosition(gScreen, winPosX, winPosY); - } - } + SDL_SetWindowFullscreen(gScreen, 0); bool resize = true; bool reloadRes = false; + bool maximize = true; if(useDesktop != _useDesktopResolution) { - if(useDesktop) - createWindow(oldw, oldh, true, fullscreen); - else - createWindow(w, h, false, fullscreen); + int usew = 0, useh = 0; + bool maximize = !fullscreen; + if(!useDesktop) + { + usew = w; + useh = h; + maximize = false; + } + if(useDesktop && !fullscreen && wasFullscreen) + { + usew = oldw; + useh = oldh; + maximize = false; + } + createWindow(usew, useh, useDesktop, false); reloadRes = true; - if(useDesktop) - { - SDL_MaximizeWindow(gScreen); - resize = false; - } } - // First time called + windowed mode --> maximize window - else if(!oldw && !oldh && useDesktop && !fullscreen) + + if(fullscreen) + { + int screenflags = useDesktop ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_FULLSCREEN; + displaymode.w = w; + displaymode.h = h; + // must not be already in fullscreen here, otherwise new display mode doesn't apply properly + SDL_SetWindowSize(gScreen, w, h); + SDL_SetWindowDisplayMode(gScreen, &displaymode); + SDL_SetWindowFullscreen(gScreen, screenflags); + maximize = false; + } + + if(!fullscreen && wasFullscreen) + { + // Need to do this; else the window ends up at (0, 0) with the title bar outside the screen area + int c = SDL_WINDOWPOS_CENTERED_DISPLAY(display); + SDL_SetWindowPosition(gScreen, c, c); + } + if(maximize) { SDL_MaximizeWindow(gScreen); resize = false; @@ -282,7 +292,8 @@ void Core::initGraphics(int w, int h, int fullscreen, int vsync, int bpp, int di _useDesktopResolution = useDesktop; - SDL_GetWindowSize(gScreen, &w, &h); + if(!resize) + SDL_GetWindowSize(gScreen, &w, &h); updateWindowDrawSize(w, h); @@ -501,6 +512,8 @@ Core::Core(const std::string &filesystem, const std::string& extraDataDir, int n baseCullRadius = 1; width = height = 0; _fullscreen = false; + _refreshRate = 0; + _useDesktopResolution = false; afterEffectManagerLayer = 0; renderObjectLayers.resize(1); invGlobalScale = 1.0; @@ -655,12 +668,18 @@ bool Core::isDesktopResolution() int Core::getDisplayIndex() { #ifdef BBGE_BUILD_SDL2 - return SDL_GetWindowDisplayIndex(gScreen); + int display = SDL_GetWindowDisplayIndex(gScreen); + return display < 0 ? 0 : display; // if there's an error, assume primary display #else return 0; #endif } +int Core::getRefreshRate() +{ + return _refreshRate; +} + bool Core::isShuttingDown() { return shuttingDown; @@ -827,7 +846,7 @@ void Core::setClearColor(const Vector &c) } -bool Core::initGraphicsLibrary(int width, int height, bool fullscreen, bool vsync, int bpp, int display) +bool Core::initGraphicsLibrary(int width, int height, bool fullscreen, bool vsync, int bpp, int display, int hz) { assert(!gScreen); @@ -886,7 +905,7 @@ bool Core::initGraphicsLibrary(int width, int height, bool fullscreen, bool vsyn enumerateScreenModes(); - initGraphics(width, height, fullscreen, vsync, bpp, display); + initGraphics(width, height, fullscreen, vsync, bpp, display, hz); _hasFocus = true; @@ -896,11 +915,6 @@ bool Core::initGraphicsLibrary(int width, int height, bool fullscreen, bool vsyn void Core::createWindow(int w, int h, bool resizable, bool fullscreen) { - if(w <= 0) - w = 640; - if(h <= 0) - h = 480; - #ifdef BBGE_BUILD_SDL2 if(gScreen) { @@ -916,8 +930,17 @@ void Core::createWindow(int w, int h, bool resizable, bool fullscreen) Uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN; if(resizable) flags |= SDL_WINDOW_RESIZABLE; - //if(fullscreen) // Ignore fullscreen setting here, it's applied later - // flags |= SDL_WINDOW_FULLSCREEN; + if(fullscreen) + { + if(!w && !h) + flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; + else + flags |= SDL_WINDOW_FULLSCREEN; + } + if(w <= 0) + w = 640; + if(h <= 0) + h = 480; gScreen = SDL_CreateWindow(appName.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, w, h, flags); if (gScreen == NULL) { diff --git a/BBGE/Core.h b/BBGE/Core.h index c7cd382..f46b24b 100644 --- a/BBGE/Core.h +++ b/BBGE/Core.h @@ -278,7 +278,7 @@ public: unsigned getTicks(); - void initGraphics(int w, int h, int fullscreen=-1, int vsync=-1, int bpp=-1, int display=-1); // pass 0x0 for desktop resolution + void initGraphics(int w, int h, int fullscreen=-1, int vsync=-1, int bpp=-1, int display=-1, int hz=-1); // pass 0x0 for desktop resolution void updateWindowDrawSize(int w, int h); Vector getGameCursorPosition(); @@ -416,6 +416,7 @@ public: bool isFullscreen(); bool isDesktopResolution(); int getDisplayIndex(); + int getRefreshRate(); int getVirtualOffX(); int getVirtualOffY(); @@ -483,7 +484,7 @@ protected: bool initSoundLibrary(const std::string &defaultDevice); bool initInputLibrary(); void initJoystickLibrary(); - bool initGraphicsLibrary(int w, int h, bool fullscreen, bool vsync, int bpp, int display); + bool initGraphicsLibrary(int w, int h, bool fullscreen, bool vsync, int bpp, int display, int hz); void createWindow(int w, int h, bool resizable, bool fullscreen); void shutdownInputLibrary(); void shutdownJoystickLibrary(); @@ -513,7 +514,7 @@ protected: int nowTicks, thenTicks; - int _vsync, _bpp; + int _vsync, _bpp, _refreshRate; bool _fullscreen, _useDesktopResolution; int winPosX, winPosY; // pre-fullscreen