From 16057eeaffd36446bebef6f5babbdfcd6d64c4b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 10 Jun 2015 20:59:00 +0200 Subject: [PATCH] Platform: ability to cap main loop period directly on Sdl2Application. Complement to VSync in case it cannot be enabled or when no drawing is done and the app is just waiting for an event. --- src/Magnum/Platform/Sdl2Application.cpp | 30 +++++++++++++++++++++++-- src/Magnum/Platform/Sdl2Application.h | 21 ++++++++++++++++- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/Magnum/Platform/Sdl2Application.cpp b/src/Magnum/Platform/Sdl2Application.cpp index 1ee227793..2efc506fa 100644 --- a/src/Magnum/Platform/Sdl2Application.cpp +++ b/src/Magnum/Platform/Sdl2Application.cpp @@ -70,7 +70,11 @@ Sdl2Application::Sdl2Application(const Arguments& arguments, const Configuration createContext(configuration); } -Sdl2Application::Sdl2Application(const Arguments&, std::nullptr_t): _glContext{nullptr}, _flags{Flag::Redraw} { +Sdl2Application::Sdl2Application(const Arguments&, std::nullptr_t): _glContext{nullptr}, + #ifndef CORRADE_TARGET_EMSCRIPTEN + _minimalLoopPeriod{0}, + #endif + _flags{Flag::Redraw} { #ifdef CORRADE_TARGET_EMSCRIPTEN CORRADE_ASSERT(!_instance, "Platform::Sdl2Application::Sdl2Application(): the instance is already created", ); _instance = this; @@ -222,14 +226,17 @@ Int Sdl2Application::swapInterval() const { bool Sdl2Application::setSwapInterval(const Int interval) { if(SDL_GL_SetSwapInterval(interval) == -1) { Error() << "Platform::Sdl2Application::setSwapInterval(): cannot set swap interval:" << SDL_GetError(); + _flags &= ~Flag::VSyncEnabled; return false; } if(SDL_GL_GetSwapInterval() != interval) { Error() << "Platform::Sdl2Application::setSwapInterval(): swap interval setting ignored by the driver"; + _flags &= ~Flag::VSyncEnabled; return false; } + _flags |= Flag::VSyncEnabled; return true; } @@ -265,8 +272,9 @@ void Sdl2Application::exit() { } void Sdl2Application::mainLoop() { - SDL_Event event; + const UnsignedInt timeBefore = _minimalLoopPeriod ? SDL_GetTicks() : 0; + SDL_Event event; while(SDL_PollEvent(&event)) { switch(event.type) { case SDL_WINDOWEVENT: @@ -317,10 +325,28 @@ void Sdl2Application::mainLoop() { if(_flags & Flag::Redraw) { _flags &= ~Flag::Redraw; drawEvent(); + + #ifndef CORRADE_TARGET_EMSCRIPTEN + /* If VSync is not enabled, delay to prevent CPU hogging (if set) */ + if(!(_flags & Flag::VSyncEnabled) && _minimalLoopPeriod) { + const UnsignedInt loopTime = SDL_GetTicks() - timeBefore; + if(loopTime < _minimalLoopPeriod) + SDL_Delay(_minimalLoopPeriod - loopTime); + } + #endif + return; } #ifndef CORRADE_TARGET_EMSCRIPTEN + /* If not drawing anything, delay to prevent CPU hogging (if set) */ + if(_minimalLoopPeriod) { + const UnsignedInt loopTime = SDL_GetTicks() - timeBefore; + if(loopTime < _minimalLoopPeriod) + SDL_Delay(_minimalLoopPeriod - loopTime); + } + + /* Then wait indefinitely for next input event */ SDL_WaitEvent(nullptr); #endif } diff --git a/src/Magnum/Platform/Sdl2Application.h b/src/Magnum/Platform/Sdl2Application.h index 0f94d67d3..0e03c121e 100644 --- a/src/Magnum/Platform/Sdl2Application.h +++ b/src/Magnum/Platform/Sdl2Application.h @@ -291,9 +291,26 @@ class Sdl2Application { * `-1` for late swap tearing. Prints error message and returns `false` * if swap interval cannot be set, `true` otherwise. Default is * driver-dependent, you can query the value with @ref swapInterval(). + * @see @ref setMinimalLoopPeriod() */ bool setSwapInterval(Int interval); + #ifndef CORRADE_TARGET_EMSCRIPTEN + /** + * @brief Set minimal loop period + * + * This setting reduces the main loop frequency in case VSync is + * not/cannot be enabled or no drawing is done. Default is `0` (i.e. + * looping at maximum frequency). + * @note Not available in @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten", + * the browser is managing the frequency instead. + * @see @ref setSwapInterval() + */ + void setMinimalLoopPeriod(UnsignedInt milliseconds) { + _minimalLoopPeriod = milliseconds; + } + #endif + /** * @brief Redraw immediately * @@ -403,8 +420,9 @@ class Sdl2Application { private: enum class Flag: UnsignedByte { Redraw = 1 << 0, + VSyncEnabled = 1 << 1, #ifndef CORRADE_TARGET_EMSCRIPTEN - Exit = 1 << 1 + Exit = 1 << 2 #endif }; @@ -421,6 +439,7 @@ class Sdl2Application { #ifndef CORRADE_TARGET_EMSCRIPTEN SDL_Window* _window; SDL_GLContext _glContext; + UnsignedInt _minimalLoopPeriod; #else SDL_Surface* _glContext; #endif