# HG changeset patch # User Sebastien Jodogne # Date 1575560200 -3600 # Node ID 5147277850cfd227934268ef985c038c8ae85a5d # Parent 9efa66d8d3f8b3e3a55c0d11422c01785137703e better abstraction for IViewport diff -r 9efa66d8d3f8 -r 5147277850cf Framework/Scene2DViewport/MeasureCommands.h --- a/Framework/Scene2DViewport/MeasureCommands.h Wed Dec 04 20:12:15 2019 +0100 +++ b/Framework/Scene2DViewport/MeasureCommands.h Thu Dec 05 16:36:40 2019 +0100 @@ -47,6 +47,8 @@ protected: boost::shared_ptr GetController(); + + private: boost::weak_ptr controllerW_; }; diff -r 9efa66d8d3f8 -r 5147277850cf Framework/Scene2DViewport/ViewportController.cpp --- a/Framework/Scene2DViewport/ViewportController.cpp Wed Dec 04 20:12:15 2019 +0100 +++ b/Framework/Scene2DViewport/ViewportController.cpp Thu Dec 05 16:36:40 2019 +0100 @@ -64,6 +64,12 @@ } + ViewportController::ViewportController() : + undoStackW_(boost::make_shared()), + canvasToSceneFactor_(1) + { + } + ViewportController::ViewportController(boost::weak_ptr undoStackW) : undoStackW_(undoStackW) , canvasToSceneFactor_(1) diff -r 9efa66d8d3f8 -r 5147277850cf Framework/Scene2DViewport/ViewportController.h --- a/Framework/Scene2DViewport/ViewportController.h Wed Dec 04 20:12:15 2019 +0100 +++ b/Framework/Scene2DViewport/ViewportController.h Thu Dec 05 16:36:40 2019 +0100 @@ -109,6 +109,8 @@ ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, \ SceneTransformChanged, ViewportController); + ViewportController(); + ViewportController(boost::weak_ptr undoStackW); ~ViewportController(); diff -r 9efa66d8d3f8 -r 5147277850cf Framework/Viewport/IViewport.h --- a/Framework/Viewport/IViewport.h Wed Dec 04 20:12:15 2019 +0100 +++ b/Framework/Viewport/IViewport.h Thu Dec 05 16:36:40 2019 +0100 @@ -21,8 +21,7 @@ #pragma once #include "../Scene2D/ICompositor.h" -#include "../Scene2D/Scene2D.h" -#include "../Scene2D/ScenePoint2D.h" +#include "../Scene2DViewport/ViewportController.h" namespace OrthancStone { @@ -50,22 +49,16 @@ virtual bool HasCompositor() const = 0; virtual ICompositor& GetCompositor() = 0; + + virtual ViewportController& GetController() = 0; + + virtual void Invalidate() = 0; }; virtual ~IViewport() { } - // Can be invoked from any thread (notably from the thread of the - // Stone context) - virtual void Invalidate() = 0; - - // Must be invoked from the main (GUI) thread - virtual void Paint(const Scene2D& scene) = 0; - - virtual void UpdateSize(unsigned int width, - unsigned int height) = 0; - virtual ILock* Lock() = 0; }; } diff -r 9efa66d8d3f8 -r 5147277850cf Framework/Viewport/SdlViewport.cpp --- a/Framework/Viewport/SdlViewport.cpp Wed Dec 04 20:12:15 2019 +0100 +++ b/Framework/Viewport/SdlViewport.cpp Thu Dec 05 16:36:40 2019 +0100 @@ -24,7 +24,33 @@ namespace OrthancStone { - SdlViewport::SdlViewport() + ICompositor& SdlViewport::SdlLock::GetCompositor() + { + if (that_.compositor_.get() == NULL) + { + // The derived class should have called "AcquireCompositor()" + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + else + { + return *that_.compositor_; + } + } + + + void SdlViewport::AcquireCompositor(ICompositor* compositor /* takes ownership */) + { + if (compositor == NULL) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); + } + + compositor_.reset(compositor); + } + + + SdlViewport::SdlViewport() : + controller_(new ViewportController) { refreshEvent_ = SDL_RegisterEvents(1); @@ -50,29 +76,52 @@ bool allowDpiScaling) : context_(title, width, height, allowDpiScaling) { - compositor_.reset(new OpenGLCompositor(context_)); + AcquireCompositor(new OpenGLCompositor(context_)); // (*) + } + + + SdlOpenGLViewport::~SdlOpenGLViewport() + { + // Make sure that the "OpenGLCompositor" is destroyed BEFORE the + // "OpenGLContext" it references (*) + ClearCompositor(); + } + + + void SdlOpenGLViewport::Paint() + { + SdlLock lock(*this); + lock.GetCompositor().Refresh(lock.GetController().GetScene()); } - void SdlOpenGLViewport::Invalidate() + + void SdlOpenGLViewport::UpdateSize(unsigned int width, + unsigned int height) { - SendRefreshEvent(); + // nothing to do in OpenGL, the OpenGLCompositor::UpdateSize will be called automatically + SdlLock lock(*this); + lock.Invalidate(); } - void SdlOpenGLViewport::Paint(const Scene2D& scene) + + void SdlOpenGLViewport::ToggleMaximize() { - boost::mutex::scoped_lock lock(mutex_); - compositor_->Refresh(scene); + // No need to call "Invalidate()" here, as "UpdateSize()" will + // be invoked after event "SDL_WINDOWEVENT_SIZE_CHANGED" + SdlLock lock(*this); + context_.ToggleMaximize(); } + SdlCairoViewport::SdlCairoViewport(const char* title, unsigned int width, unsigned int height, bool allowDpiScaling) : window_(title, width, height, false /* enable OpenGL */, allowDpiScaling), - compositor_(width, height), sdlSurface_(NULL) { + AcquireCompositor(new CairoCompositor(width, height)); } SdlCairoViewport::~SdlCairoViewport() @@ -83,50 +132,56 @@ } } - void SdlCairoViewport::Paint(const Scene2D& scene) + void SdlCairoViewport::Paint() { - boost::mutex::scoped_lock lock(mutex_); + SdlLock lock(*this); - compositor_.Refresh(scene); - CreateSdlSurfaceFromCompositor(); + lock.GetCompositor().Refresh(lock.GetController().GetScene()); + CreateSdlSurfaceFromCompositor(dynamic_cast(lock.GetCompositor())); if (sdlSurface_ != NULL) { window_.Render(sdlSurface_); - } + } } - void SdlCairoViewport::Invalidate() - { - SendRefreshEvent(); - } void SdlCairoViewport::UpdateSize(unsigned int width, unsigned int height) { - { - boost::mutex::scoped_lock lock(mutex_); - compositor_.UpdateSize(width, height); - } - - Invalidate(); + SdlLock lock(*this); + dynamic_cast(lock.GetCompositor()).UpdateSize(width, height); + lock.Invalidate(); } - void SdlCairoViewport::CreateSdlSurfaceFromCompositor() // Assumes that the mutex is locked + + void SdlCairoViewport::ToggleMaximize() + { + // No need to call "Invalidate()" here, as "UpdateSize()" will + // be invoked after event "SDL_WINDOWEVENT_SIZE_CHANGED" + SdlLock lock(*this); + window_.ToggleMaximize(); + } + + + // Assumes that the mutex is locked + void SdlCairoViewport::CreateSdlSurfaceFromCompositor(CairoCompositor& compositor) { static const uint32_t rmask = 0x00ff0000; static const uint32_t gmask = 0x0000ff00; static const uint32_t bmask = 0x000000ff; - const unsigned int width = compositor_.GetCanvas().GetWidth(); - const unsigned int height = compositor_.GetCanvas().GetHeight(); + const unsigned int width = compositor.GetCanvas().GetWidth(); + const unsigned int height = compositor.GetCanvas().GetHeight(); + + printf("%dx%d\n", width, height); if (sdlSurface_ != NULL) { - if (sdlSurface_->pixels == compositor_.GetCanvas().GetBuffer() && + if (sdlSurface_->pixels == compositor.GetCanvas().GetBuffer() && sdlSurface_->w == static_cast(width) && sdlSurface_->h == static_cast(height) && - sdlSurface_->pitch == static_cast(compositor_.GetCanvas().GetPitch())) + sdlSurface_->pitch == static_cast(compositor.GetCanvas().GetPitch())) { // The image from the compositor has not changed, no need to update the surface return; @@ -137,8 +192,8 @@ } } - sdlSurface_ = SDL_CreateRGBSurfaceFrom((void*)(compositor_.GetCanvas().GetBuffer()), width, height, 32, - compositor_.GetCanvas().GetPitch(), rmask, gmask, bmask, 0); + sdlSurface_ = SDL_CreateRGBSurfaceFrom((void*)(compositor.GetCanvas().GetBuffer()), width, height, 32, + compositor.GetCanvas().GetPitch(), rmask, gmask, bmask, 0); if (!sdlSurface_) { LOG(ERROR) << "Cannot create a SDL surface from a Cairo surface"; diff -r 9efa66d8d3f8 -r 5147277850cf Framework/Viewport/SdlViewport.h --- a/Framework/Viewport/SdlViewport.h Wed Dec 04 20:12:15 2019 +0100 +++ b/Framework/Viewport/SdlViewport.h Thu Dec 05 16:36:40 2019 +0100 @@ -48,43 +48,24 @@ class SdlViewport : public IViewport { private: - uint32_t refreshEvent_; + boost::mutex mutex_; + uint32_t refreshEvent_; + boost::shared_ptr controller_; + std::auto_ptr compositor_; + + void SendRefreshEvent(); protected: - void SendRefreshEvent(); - - public: - SdlViewport(); - - bool IsRefreshEvent(const SDL_Event& event) const - { - return (event.type == refreshEvent_); - } - - virtual void UpdateSize(unsigned int width, - unsigned int height) = 0; - - virtual void ToggleMaximize() = 0; - }; - - - class SdlOpenGLViewport : public SdlViewport - { - private: - boost::mutex mutex_; - SdlOpenGLContext context_; - std::auto_ptr compositor_; - class SdlLock : public ILock { private: - SdlOpenGLViewport& that_; - boost::mutex::scoped_lock lock_; - + SdlViewport& that_; + boost::mutex::scoped_lock lock_; + public: - SdlLock(SdlOpenGLViewport& viewport) : - that_(viewport), - lock_(viewport.mutex_) + SdlLock(SdlViewport& that) : + that_(that), + lock_(that.mutex_) { } @@ -93,73 +74,78 @@ return true; } - virtual ICompositor& GetCompositor() ORTHANC_OVERRIDE + virtual ICompositor& GetCompositor() ORTHANC_OVERRIDE; + + virtual ViewportController& GetController() ORTHANC_OVERRIDE { - return *that_.compositor_; + return *that_.controller_; + } + + virtual void Invalidate() ORTHANC_OVERRIDE + { + that_.SendRefreshEvent(); } }; - + + void ClearCompositor() + { + compositor_.reset(); + } + + void AcquireCompositor(ICompositor* compositor /* takes ownership */); + public: - SdlOpenGLViewport(const char* title, - unsigned int width, - unsigned int height, - bool allowDpiScaling = true); + SdlViewport(); - virtual void Invalidate() ORTHANC_OVERRIDE; - - virtual void Paint(const Scene2D& scene) ORTHANC_OVERRIDE; + bool IsRefreshEvent(const SDL_Event& event) const + { + return (event.type == refreshEvent_); + } virtual ILock* Lock() ORTHANC_OVERRIDE { return new SdlLock(*this); } - virtual void UpdateSize(unsigned int width, unsigned int height) ORTHANC_OVERRIDE - { - // nothing to do in OpenGL, the OpenGLCompositor::UpdateSize will be called automatically - } + virtual void UpdateSize(unsigned int width, + unsigned int height) = 0; + + virtual void ToggleMaximize() = 0; + + // Must be invoked from the main SDL thread + virtual void Paint() = 0; + }; + + + class SdlOpenGLViewport : public SdlViewport + { + private: + SdlOpenGLContext context_; - virtual void ToggleMaximize() ORTHANC_OVERRIDE - { - boost::mutex::scoped_lock lock(mutex_); - context_.ToggleMaximize(); - } + public: + SdlOpenGLViewport(const char* title, + unsigned int width, + unsigned int height, + bool allowDpiScaling = true); + + virtual ~SdlOpenGLViewport(); + + virtual void Paint() ORTHANC_OVERRIDE; + + virtual void UpdateSize(unsigned int width, + unsigned int height) ORTHANC_OVERRIDE; + + virtual void ToggleMaximize() ORTHANC_OVERRIDE; }; class SdlCairoViewport : public SdlViewport { private: - class SdlLock : public ILock - { - private: - SdlCairoViewport& that_; - boost::mutex::scoped_lock lock_; - - public: - SdlLock(SdlCairoViewport& viewport) : - that_(viewport), - lock_(viewport.mutex_) - { - } + SdlWindow window_; + SDL_Surface* sdlSurface_; - virtual bool HasCompositor() const ORTHANC_OVERRIDE - { - return true; - } - - virtual ICompositor& GetCompositor() ORTHANC_OVERRIDE - { - return that_.compositor_; - } - }; - - boost::mutex mutex_; - SdlWindow window_; - CairoCompositor compositor_; - SDL_Surface* sdlSurface_; - - void CreateSdlSurfaceFromCompositor(); + void CreateSdlSurfaceFromCompositor(CairoCompositor& compositor); public: SdlCairoViewport(const char* title, @@ -167,24 +153,13 @@ unsigned int height, bool allowDpiScaling = true); - ~SdlCairoViewport(); - - virtual void Invalidate() ORTHANC_OVERRIDE; + virtual ~SdlCairoViewport(); - virtual void Paint(const Scene2D& scene) ORTHANC_OVERRIDE; - - virtual ILock* Lock() ORTHANC_OVERRIDE - { - return new SdlLock(*this); - } + virtual void Paint() ORTHANC_OVERRIDE; virtual void UpdateSize(unsigned int width, unsigned int height) ORTHANC_OVERRIDE; - virtual void ToggleMaximize() ORTHANC_OVERRIDE - { - boost::mutex::scoped_lock lock(mutex_); - window_.ToggleMaximize(); - } + virtual void ToggleMaximize() ORTHANC_OVERRIDE; }; }