Mercurial > hg > orthanc-stone
changeset 56:9e3c2e75b870 wasm
extremely simplified SDL engine
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 28 Apr 2017 21:46:41 +0200 |
parents | f0f354a97581 |
children | d20e25cfcf3a |
files | Applications/BinarySemaphore.cpp Applications/BinarySemaphore.h Applications/Sdl/SdlBuffering.cpp Applications/Sdl/SdlBuffering.h Applications/Sdl/SdlEngine.cpp Applications/Sdl/SdlEngine.h Resources/CMake/OrthancStone.cmake Resources/Graveyard/Threading/BinarySemaphore.cpp Resources/Graveyard/Threading/BinarySemaphore.h Resources/Graveyard/Threading/SdlBuffering.cpp Resources/Graveyard/Threading/SdlBuffering.h |
diffstat | 11 files changed, 313 insertions(+), 393 deletions(-) [+] |
line wrap: on
line diff
--- a/Applications/BinarySemaphore.cpp Fri Apr 28 17:24:18 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017 Osimis, Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License - * as published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#include "BinarySemaphore.h" - -namespace OrthancStone -{ - BinarySemaphore::BinarySemaphore() : - proceed_(false) - { - } - - void BinarySemaphore::Signal() - { - //boost::mutex::scoped_lock lock(mutex_); - - proceed_ = true; - condition_.notify_one(); - } - - void BinarySemaphore::Wait() - { - boost::mutex::scoped_lock lock(mutex_); - - while (!proceed_) - { - condition_.wait(lock); - } - - proceed_ = false; - } -}
--- a/Applications/BinarySemaphore.h Fri Apr 28 17:24:18 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017 Osimis, Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License - * as published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include <boost/thread/mutex.hpp> -#include <boost/thread/condition.hpp> - -namespace OrthancStone -{ - class BinarySemaphore : public boost::noncopyable - { - private: - bool proceed_; - boost::mutex mutex_; - boost::condition_variable condition_; - - public: - explicit BinarySemaphore(); - - void Signal(); - - void Wait(); - }; -}
--- a/Applications/Sdl/SdlBuffering.cpp Fri Apr 28 17:24:18 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,134 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017 Osimis, Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License - * as published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#include "SdlBuffering.h" - -#if ORTHANC_ENABLE_SDL == 1 - -#include "../../../Resources/Orthanc/Core/Logging.h" -#include "../../../Resources/Orthanc/Core/OrthancException.h" - -namespace OrthancStone -{ - SdlBuffering::SdlBuffering() : - sdlSurface_(NULL), - pendingFrame_(false) - { - } - - - SdlBuffering::~SdlBuffering() - { - if (sdlSurface_) - { - SDL_FreeSurface(sdlSurface_); - } - } - - - void SdlBuffering::SetSize(unsigned int width, - unsigned int height, - IViewport& viewport) - { - boost::mutex::scoped_lock lock(mutex_); - - viewport.SetSize(width, height); - - if (offscreenSurface_.get() == NULL || - offscreenSurface_->GetWidth() != width || - offscreenSurface_->GetHeight() != height) - { - offscreenSurface_.reset(new CairoSurface(width, height)); - } - - if (onscreenSurface_.get() == NULL || - onscreenSurface_->GetWidth() != width || - onscreenSurface_->GetHeight() != height) - { - onscreenSurface_.reset(new CairoSurface(width, height)); - - // TODO Big endian? - static const uint32_t rmask = 0x00ff0000; - static const uint32_t gmask = 0x0000ff00; - static const uint32_t bmask = 0x000000ff; - - if (sdlSurface_) - { - SDL_FreeSurface(sdlSurface_); - } - - sdlSurface_ = SDL_CreateRGBSurfaceFrom(onscreenSurface_->GetBuffer(), width, height, 32, - onscreenSurface_->GetPitch(), rmask, gmask, bmask, 0); - if (!sdlSurface_) - { - LOG(ERROR) << "Cannot create a SDL surface from a Cairo surface"; - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - } - - pendingFrame_ = false; - } - - - bool SdlBuffering::RenderOffscreen(IViewport& viewport) - { - boost::mutex::scoped_lock lock(mutex_); - - if (offscreenSurface_.get() == NULL) - { - return false; - } - - Orthanc::ImageAccessor target = offscreenSurface_->GetAccessor(); - - if (viewport.Render(target) && - !pendingFrame_) - { - pendingFrame_ = true; - return true; - } - else - { - return false; - } - } - - - void SdlBuffering::SwapToScreen(SdlWindow& window) - { - if (!pendingFrame_ || - offscreenSurface_.get() == NULL || - onscreenSurface_.get() == NULL) - { - return; - } - - { - boost::mutex::scoped_lock lock(mutex_); - onscreenSurface_->Copy(*offscreenSurface_); - } - - window.Render(sdlSurface_); - pendingFrame_ = false; - } -} - -#endif
--- a/Applications/Sdl/SdlBuffering.h Fri Apr 28 17:24:18 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/** - * Stone of Orthanc - * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics - * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017 Osimis, Belgium - * - * This program is free software: you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License - * as published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#if ORTHANC_ENABLE_SDL == 1 - -#include "SdlWindow.h" -#include "../../Framework/Viewport/CairoSurface.h" -#include "../../Framework/Viewport/IViewport.h" - -#include <boost/thread/mutex.hpp> - -namespace OrthancStone -{ - class SdlBuffering : public boost::noncopyable - { - private: - boost::mutex mutex_; - std::auto_ptr<CairoSurface> offscreenSurface_; - std::auto_ptr<CairoSurface> onscreenSurface_; - SDL_Surface* sdlSurface_; - bool pendingFrame_; - - public: - SdlBuffering(); - - ~SdlBuffering(); - - void SetSize(unsigned int width, - unsigned int height, - IViewport& viewport); - - // Returns "true" if a new refresh of the display should be - // triggered afterwards - bool RenderOffscreen(IViewport& viewport); - - void SwapToScreen(SdlWindow& window); - }; -} - -#endif
--- a/Applications/Sdl/SdlEngine.cpp Fri Apr 28 17:24:18 2017 +0200 +++ b/Applications/Sdl/SdlEngine.cpp Fri Apr 28 21:46:41 2017 +0200 @@ -29,55 +29,27 @@ namespace OrthancStone { + void SdlEngine::SetSize(BasicApplicationContext::ViewportLocker& locker, + unsigned int width, + unsigned int height) + { + locker.GetViewport().SetSize(width, height); + surface_.SetSize(width, height); + } + + void SdlEngine::RenderFrame() { - if (!viewportChanged_) - { - return; - } - - viewportChanged_ = false; - - bool updated; - + if (viewportChanged_) { BasicApplicationContext::ViewportLocker locker(context_); - updated = buffering_.RenderOffscreen(locker.GetViewport()); - } + surface_.Render(locker.GetViewport()); - if (updated) - { - // Do not notify twice when a new frame was rendered, to avoid - // spoiling the SDL event queue - SDL_Event event; - SDL_memset(&event, 0, sizeof(event)); - event.type = refreshEvent_; - event.user.code = 0; - event.user.data1 = 0; - event.user.data2 = 0; - SDL_PushEvent(&event); + viewportChanged_ = false; } } - void SdlEngine::RenderThread(SdlEngine* that) - { - for (;;) - { - that->renderFrame_.Wait(); - - if (that->continue_) - { - that->RenderFrame(); - } - else - { - return; - } - } - } - - KeyboardModifiers SdlEngine::GetKeyboardModifiers(const uint8_t* keyboardState, const int scancodeCount) { @@ -126,55 +98,23 @@ } - void SdlEngine::SetSize(BasicApplicationContext::ViewportLocker& locker, - unsigned int width, - unsigned int height) - { - buffering_.SetSize(width, height, locker.GetViewport()); - viewportChanged_ = true; - Refresh(); - } - - - void SdlEngine::Stop() - { - if (continue_) - { - continue_ = false; - renderFrame_.Signal(); // Unlock the render thread - renderThread_.join(); - } - } - - - void SdlEngine::Refresh() - { - renderFrame_.Signal(); - } - - SdlEngine::SdlEngine(SdlWindow& window, BasicApplicationContext& context) : window_(window), context_(context), - continue_(true) + surface_(window), + viewportChanged_(true) { - refreshEvent_ = SDL_RegisterEvents(1); - { BasicApplicationContext::ViewportLocker locker(context_); SetSize(locker, window_.GetWidth(), window_.GetHeight()); locker.GetViewport().Register(*this); } - - renderThread_ = boost::thread(RenderThread, this); } SdlEngine::~SdlEngine() { - Stop(); - { BasicApplicationContext::ViewportLocker locker(context_); locker.GetViewport().Unregister(*this); @@ -190,11 +130,12 @@ bool stop = false; while (!stop) { - Refresh(); + RenderFrame(); SDL_Event event; - while (SDL_PollEvent(&event)) + while (!stop && + SDL_PollEvent(&event)) { BasicApplicationContext::ViewportLocker locker(context_); @@ -203,10 +144,6 @@ stop = true; break; } - else if (event.type == refreshEvent_) - { - buffering_.SwapToScreen(window_); - } else if (event.type == SDL_MOUSEBUTTONDOWN) { KeyboardModifiers modifiers = GetKeyboardModifiers(keyboardState, scancodeCount); @@ -273,7 +210,8 @@ locker.GetViewport().MouseWheel(MouseWheelDirection_Down, x, y, modifiers); } } - else if (event.type == SDL_KEYDOWN) + else if (event.type == SDL_KEYDOWN && + event.key.repeat == 0 /* Ignore key bounce */) { KeyboardModifiers modifiers = GetKeyboardModifiers(keyboardState, scancodeCount); @@ -311,11 +249,7 @@ } } } - - SDL_Delay(10); // Necessary for mouse wheel events to work } - - Stop(); }
--- a/Applications/Sdl/SdlEngine.h Fri Apr 28 17:24:18 2017 +0200 +++ b/Applications/Sdl/SdlEngine.h Fri Apr 28 21:46:41 2017 +0200 @@ -23,12 +23,9 @@ #if ORTHANC_ENABLE_SDL == 1 -#include "SdlBuffering.h" -#include "../BinarySemaphore.h" +#include "SdlSurface.h" #include "../BasicApplicationContext.h" -#include <boost/thread.hpp> - namespace OrthancStone { class SdlEngine : public IViewport::IChangeObserver @@ -36,27 +33,17 @@ private: SdlWindow& window_; BasicApplicationContext& context_; - SdlBuffering buffering_; - boost::thread renderThread_; - bool continue_; - BinarySemaphore renderFrame_; - uint32_t refreshEvent_; + SdlSurface surface_; bool viewportChanged_; - void RenderFrame(); - - static void RenderThread(SdlEngine* that); - - static KeyboardModifiers GetKeyboardModifiers(const uint8_t* keyboardState, - const int scancodeCount); - void SetSize(BasicApplicationContext::ViewportLocker& locker, unsigned int width, unsigned int height); + + void RenderFrame(); - void Stop(); - - void Refresh(); + static KeyboardModifiers GetKeyboardModifiers(const uint8_t* keyboardState, + const int scancodeCount); public: SdlEngine(SdlWindow& window,
--- a/Resources/CMake/OrthancStone.cmake Fri Apr 28 17:24:18 2017 +0200 +++ b/Resources/CMake/OrthancStone.cmake Fri Apr 28 21:46:41 2017 +0200 @@ -177,10 +177,9 @@ list(APPEND ORTHANC_STONE_SOURCES ${ORTHANC_STONE_DIR}/Applications/BasicApplicationContext.cpp - ${ORTHANC_STONE_DIR}/Applications/BinarySemaphore.cpp ${ORTHANC_STONE_DIR}/Applications/IBasicApplication.cpp - ${ORTHANC_STONE_DIR}/Applications/Sdl/SdlBuffering.cpp ${ORTHANC_STONE_DIR}/Applications/Sdl/SdlEngine.cpp + ${ORTHANC_STONE_DIR}/Applications/Sdl/SdlSurface.cpp ${ORTHANC_STONE_DIR}/Applications/Sdl/SdlWindow.cpp ${ORTHANC_STONE_DIR}/Framework/Layers/CircleMeasureTracker.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/Graveyard/Threading/BinarySemaphore.cpp Fri Apr 28 21:46:41 2017 +0200 @@ -0,0 +1,50 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017 Osimis, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "BinarySemaphore.h" + +namespace OrthancStone +{ + BinarySemaphore::BinarySemaphore() : + proceed_(false) + { + } + + void BinarySemaphore::Signal() + { + //boost::mutex::scoped_lock lock(mutex_); + + proceed_ = true; + condition_.notify_one(); + } + + void BinarySemaphore::Wait() + { + boost::mutex::scoped_lock lock(mutex_); + + while (!proceed_) + { + condition_.wait(lock); + } + + proceed_ = false; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/Graveyard/Threading/BinarySemaphore.h Fri Apr 28 21:46:41 2017 +0200 @@ -0,0 +1,43 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017 Osimis, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include <boost/thread/mutex.hpp> +#include <boost/thread/condition.hpp> + +namespace OrthancStone +{ + class BinarySemaphore : public boost::noncopyable + { + private: + bool proceed_; + boost::mutex mutex_; + boost::condition_variable condition_; + + public: + explicit BinarySemaphore(); + + void Signal(); + + void Wait(); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/Graveyard/Threading/SdlBuffering.cpp Fri Apr 28 21:46:41 2017 +0200 @@ -0,0 +1,134 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017 Osimis, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "SdlBuffering.h" + +#if ORTHANC_ENABLE_SDL == 1 + +#include "../../../Resources/Orthanc/Core/Logging.h" +#include "../../../Resources/Orthanc/Core/OrthancException.h" + +namespace OrthancStone +{ + SdlBuffering::SdlBuffering() : + sdlSurface_(NULL), + pendingFrame_(false) + { + } + + + SdlBuffering::~SdlBuffering() + { + if (sdlSurface_) + { + SDL_FreeSurface(sdlSurface_); + } + } + + + void SdlBuffering::SetSize(unsigned int width, + unsigned int height, + IViewport& viewport) + { + boost::mutex::scoped_lock lock(mutex_); + + viewport.SetSize(width, height); + + if (offscreenSurface_.get() == NULL || + offscreenSurface_->GetWidth() != width || + offscreenSurface_->GetHeight() != height) + { + offscreenSurface_.reset(new CairoSurface(width, height)); + } + + if (onscreenSurface_.get() == NULL || + onscreenSurface_->GetWidth() != width || + onscreenSurface_->GetHeight() != height) + { + onscreenSurface_.reset(new CairoSurface(width, height)); + + // TODO Big endian? + static const uint32_t rmask = 0x00ff0000; + static const uint32_t gmask = 0x0000ff00; + static const uint32_t bmask = 0x000000ff; + + if (sdlSurface_) + { + SDL_FreeSurface(sdlSurface_); + } + + sdlSurface_ = SDL_CreateRGBSurfaceFrom(onscreenSurface_->GetBuffer(), width, height, 32, + onscreenSurface_->GetPitch(), rmask, gmask, bmask, 0); + if (!sdlSurface_) + { + LOG(ERROR) << "Cannot create a SDL surface from a Cairo surface"; + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + } + + pendingFrame_ = false; + } + + + bool SdlBuffering::RenderOffscreen(IViewport& viewport) + { + boost::mutex::scoped_lock lock(mutex_); + + if (offscreenSurface_.get() == NULL) + { + return false; + } + + Orthanc::ImageAccessor target = offscreenSurface_->GetAccessor(); + + if (viewport.Render(target) && + !pendingFrame_) + { + pendingFrame_ = true; + return true; + } + else + { + return false; + } + } + + + void SdlBuffering::SwapToScreen(SdlWindow& window) + { + if (!pendingFrame_ || + offscreenSurface_.get() == NULL || + onscreenSurface_.get() == NULL) + { + return; + } + + { + boost::mutex::scoped_lock lock(mutex_); + onscreenSurface_->Copy(*offscreenSurface_); + } + + window.Render(sdlSurface_); + pendingFrame_ = false; + } +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/Graveyard/Threading/SdlBuffering.h Fri Apr 28 21:46:41 2017 +0200 @@ -0,0 +1,60 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017 Osimis, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#if ORTHANC_ENABLE_SDL == 1 + +#include "SdlWindow.h" +#include "../../Framework/Viewport/CairoSurface.h" +#include "../../Framework/Viewport/IViewport.h" + +#include <boost/thread/mutex.hpp> + +namespace OrthancStone +{ + class SdlBuffering : public boost::noncopyable + { + private: + boost::mutex mutex_; + std::auto_ptr<CairoSurface> offscreenSurface_; + std::auto_ptr<CairoSurface> onscreenSurface_; + SDL_Surface* sdlSurface_; + bool pendingFrame_; + + public: + SdlBuffering(); + + ~SdlBuffering(); + + void SetSize(unsigned int width, + unsigned int height, + IViewport& viewport); + + // Returns "true" if a new refresh of the display should be + // triggered afterwards + bool RenderOffscreen(IViewport& viewport); + + void SwapToScreen(SdlWindow& window); + }; +} + +#endif