Browse Source

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.
pull/107/head
Vladimír Vondruš 11 years ago
parent
commit
16057eeaff
  1. 30
      src/Magnum/Platform/Sdl2Application.cpp
  2. 21
      src/Magnum/Platform/Sdl2Application.h

30
src/Magnum/Platform/Sdl2Application.cpp

@ -70,7 +70,11 @@ Sdl2Application::Sdl2Application(const Arguments& arguments, const Configuration
createContext(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 #ifdef CORRADE_TARGET_EMSCRIPTEN
CORRADE_ASSERT(!_instance, "Platform::Sdl2Application::Sdl2Application(): the instance is already created", ); CORRADE_ASSERT(!_instance, "Platform::Sdl2Application::Sdl2Application(): the instance is already created", );
_instance = this; _instance = this;
@ -222,14 +226,17 @@ Int Sdl2Application::swapInterval() const {
bool Sdl2Application::setSwapInterval(const Int interval) { bool Sdl2Application::setSwapInterval(const Int interval) {
if(SDL_GL_SetSwapInterval(interval) == -1) { if(SDL_GL_SetSwapInterval(interval) == -1) {
Error() << "Platform::Sdl2Application::setSwapInterval(): cannot set swap interval:" << SDL_GetError(); Error() << "Platform::Sdl2Application::setSwapInterval(): cannot set swap interval:" << SDL_GetError();
_flags &= ~Flag::VSyncEnabled;
return false; return false;
} }
if(SDL_GL_GetSwapInterval() != interval) { if(SDL_GL_GetSwapInterval() != interval) {
Error() << "Platform::Sdl2Application::setSwapInterval(): swap interval setting ignored by the driver"; Error() << "Platform::Sdl2Application::setSwapInterval(): swap interval setting ignored by the driver";
_flags &= ~Flag::VSyncEnabled;
return false; return false;
} }
_flags |= Flag::VSyncEnabled;
return true; return true;
} }
@ -265,8 +272,9 @@ void Sdl2Application::exit() {
} }
void Sdl2Application::mainLoop() { void Sdl2Application::mainLoop() {
SDL_Event event; const UnsignedInt timeBefore = _minimalLoopPeriod ? SDL_GetTicks() : 0;
SDL_Event event;
while(SDL_PollEvent(&event)) { while(SDL_PollEvent(&event)) {
switch(event.type) { switch(event.type) {
case SDL_WINDOWEVENT: case SDL_WINDOWEVENT:
@ -317,10 +325,28 @@ void Sdl2Application::mainLoop() {
if(_flags & Flag::Redraw) { if(_flags & Flag::Redraw) {
_flags &= ~Flag::Redraw; _flags &= ~Flag::Redraw;
drawEvent(); 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; return;
} }
#ifndef CORRADE_TARGET_EMSCRIPTEN #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); SDL_WaitEvent(nullptr);
#endif #endif
} }

21
src/Magnum/Platform/Sdl2Application.h

@ -291,9 +291,26 @@ class Sdl2Application {
* `-1` for late swap tearing. Prints error message and returns `false` * `-1` for late swap tearing. Prints error message and returns `false`
* if swap interval cannot be set, `true` otherwise. Default is * if swap interval cannot be set, `true` otherwise. Default is
* driver-dependent, you can query the value with @ref swapInterval(). * driver-dependent, you can query the value with @ref swapInterval().
* @see @ref setMinimalLoopPeriod()
*/ */
bool setSwapInterval(Int interval); 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 * @brief Redraw immediately
* *
@ -403,8 +420,9 @@ class Sdl2Application {
private: private:
enum class Flag: UnsignedByte { enum class Flag: UnsignedByte {
Redraw = 1 << 0, Redraw = 1 << 0,
VSyncEnabled = 1 << 1,
#ifndef CORRADE_TARGET_EMSCRIPTEN #ifndef CORRADE_TARGET_EMSCRIPTEN
Exit = 1 << 1 Exit = 1 << 2
#endif #endif
}; };
@ -421,6 +439,7 @@ class Sdl2Application {
#ifndef CORRADE_TARGET_EMSCRIPTEN #ifndef CORRADE_TARGET_EMSCRIPTEN
SDL_Window* _window; SDL_Window* _window;
SDL_GLContext _glContext; SDL_GLContext _glContext;
UnsignedInt _minimalLoopPeriod;
#else #else
SDL_Surface* _glContext; SDL_Surface* _glContext;
#endif #endif

Loading…
Cancel
Save