# HG changeset patch # User Sebastien Jodogne # Date 1575293525 -3600 # Node ID 6009c59d867672452d469e1098ab3a339225406f # Parent b519c1c878f178ad35026a7a709bb64ccb89580d fix to sdl diff -r b519c1c878f1 -r 6009c59d8676 Framework/OpenGL/SdlOpenGLContext.h --- a/Framework/OpenGL/SdlOpenGLContext.h Fri Nov 29 21:24:29 2019 +0100 +++ b/Framework/OpenGL/SdlOpenGLContext.h Mon Dec 02 14:32:05 2019 +0100 @@ -64,6 +64,11 @@ virtual unsigned int GetCanvasWidth() const ORTHANC_OVERRIDE; virtual unsigned int GetCanvasHeight() const ORTHANC_OVERRIDE; + + void ToggleMaximize() + { + window_.ToggleMaximize(); + } }; } diff -r b519c1c878f1 -r 6009c59d8676 Framework/Scene2D/Internals/CompositorHelper.cpp --- a/Framework/Scene2D/Internals/CompositorHelper.cpp Fri Nov 29 21:24:29 2019 +0100 +++ b/Framework/Scene2D/Internals/CompositorHelper.cpp Mon Dec 02 14:32:05 2019 +0100 @@ -115,7 +115,7 @@ { // This layer has already been rendered assert(found->second->GetLastRevision() <= layer.GetRevision()); - + if (found->second->GetLastRevision() < layer.GetRevision()) { found->second->UpdateRenderer(); diff -r b519c1c878f1 -r 6009c59d8676 Framework/Viewport/IViewport.h --- a/Framework/Viewport/IViewport.h Fri Nov 29 21:24:29 2019 +0100 +++ b/Framework/Viewport/IViewport.h Mon Dec 02 14:32:05 2019 +0100 @@ -54,13 +54,23 @@ virtual bool HasCompositor() const = 0; virtual ICompositor& GetCompositor() = 0; + + virtual void FitContent() = 0; }; virtual ~IViewport() { } - virtual void Refresh() = 0; + // 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() = 0; + + virtual void UpdateSize(unsigned int width, + unsigned int height) = 0; virtual ILock* Lock() = 0; }; diff -r b519c1c878f1 -r 6009c59d8676 Framework/Viewport/SdlViewport.cpp --- a/Framework/Viewport/SdlViewport.cpp Fri Nov 29 21:24:29 2019 +0100 +++ b/Framework/Viewport/SdlViewport.cpp Mon Dec 02 14:32:05 2019 +0100 @@ -24,6 +24,26 @@ namespace OrthancStone { + SdlViewport::SdlViewport() + { + refreshEvent_ = SDL_RegisterEvents(1); + + if (refreshEvent_ == static_cast(-1)) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + } + + + void SdlViewport::SendRefreshEvent() + { + SDL_Event event; + SDL_memset(&event, 0, sizeof(event)); + event.type = refreshEvent_; + SDL_PushEvent(&event); // This function is thread-safe, and can be called from other threads safely. + } + + SdlOpenGLViewport::SdlOpenGLViewport(const char* title, unsigned int width, unsigned int height, @@ -33,7 +53,12 @@ compositor_.reset(new OpenGLCompositor(context_, GetScene())); } - void SdlOpenGLViewport::Refresh() + void SdlOpenGLViewport::Invalidate() + { + SendRefreshEvent(); + } + + void SdlOpenGLViewport::Paint() { boost::mutex::scoped_lock lock(mutex_); compositor_->Refresh(); @@ -45,9 +70,9 @@ unsigned int height, bool allowDpiScaling) : window_(title, width, height, false /* enable OpenGL */, allowDpiScaling), - compositor_(GetScene(), width, height) + compositor_(GetScene(), width, height), + sdlSurface_(NULL) { - UpdateSdlSurfaceSize(width, height); } SdlCairoViewport::~SdlCairoViewport() @@ -58,16 +83,30 @@ } } - void SdlCairoViewport::RefreshInternal() // Assumes that the mutex is locked + void SdlCairoViewport::InvalidateInternal() // Assumes that the mutex is locked { compositor_.Refresh(); - window_.Render(sdlSurface_); + CreateSdlSurfaceFromCompositor(); } - void SdlCairoViewport::Refresh() + void SdlCairoViewport::Paint() { boost::mutex::scoped_lock lock(mutex_); - RefreshInternal(); + + if (sdlSurface_ != NULL) + { + window_.Render(sdlSurface_); + } + } + + void SdlCairoViewport::Invalidate() + { + { + boost::mutex::scoped_lock lock(mutex_); + InvalidateInternal(); + } + + SendRefreshEvent(); } void SdlCairoViewport::UpdateSize(unsigned int width, @@ -75,17 +114,34 @@ { boost::mutex::scoped_lock lock(mutex_); compositor_.UpdateSize(width, height); - UpdateSdlSurfaceSize(width, height); - RefreshInternal(); + InvalidateInternal(); } - void SdlCairoViewport::UpdateSdlSurfaceSize(unsigned int width, - unsigned int height) // Assumes that the mutex is locked + void SdlCairoViewport::CreateSdlSurfaceFromCompositor() // Assumes that the mutex is locked { 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(); + + if (sdlSurface_ != NULL) + { + if (sdlSurface_->pixels == compositor_.GetCanvas().GetBuffer() && + sdlSurface_->w == static_cast(width) && + sdlSurface_->h == static_cast(height) && + sdlSurface_->pitch == static_cast(compositor_.GetCanvas().GetPitch())) + { + // The image from the compositor has not changed, no need to update the surface + return; + } + else + { + SDL_FreeSurface(sdlSurface_); + } + } + sdlSurface_ = SDL_CreateRGBSurfaceFrom((void*)(compositor_.GetCanvas().GetBuffer()), width, height, 32, compositor_.GetCanvas().GetPitch(), rmask, gmask, bmask, 0); if (!sdlSurface_) diff -r b519c1c878f1 -r 6009c59d8676 Framework/Viewport/SdlViewport.h --- a/Framework/Viewport/SdlViewport.h Fri Nov 29 21:24:29 2019 +0100 +++ b/Framework/Viewport/SdlViewport.h Mon Dec 02 14:32:05 2019 +0100 @@ -41,27 +41,38 @@ #include "../Scene2D/CairoCompositor.h" #include "ViewportBase.h" +#include + namespace OrthancStone { class SdlViewport : public ViewportBase { - protected: - boost::mutex mutex_; + private: + uint32_t refreshEvent_; + protected: + void SendRefreshEvent(); + public: - SdlViewport() + 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: - SdlOpenGLContext context_; + boost::mutex mutex_; + SdlOpenGLContext context_; std::auto_ptr compositor_; class SdlLock : public LockBase @@ -95,7 +106,9 @@ unsigned int height, bool allowDpiScaling = true); - virtual void Refresh() ORTHANC_OVERRIDE; + virtual void Invalidate() ORTHANC_OVERRIDE; + + virtual void Paint() ORTHANC_OVERRIDE; virtual ILock* Lock() ORTHANC_OVERRIDE { @@ -106,6 +119,12 @@ { // nothing to do in OpenGL, the OpenGLCompositor::UpdateSize will be called automatically } + + virtual void ToggleMaximize() ORTHANC_OVERRIDE + { + boost::mutex::scoped_lock lock(mutex_); + context_.ToggleMaximize(); + } }; @@ -137,14 +156,14 @@ } }; + boost::mutex mutex_; SdlWindow window_; CairoCompositor compositor_; SDL_Surface* sdlSurface_; - void RefreshInternal(); + void InvalidateInternal(); - void UpdateSdlSurfaceSize(unsigned int width, - unsigned int height); + void CreateSdlSurfaceFromCompositor(); public: SdlCairoViewport(const char* title, @@ -154,9 +173,22 @@ ~SdlCairoViewport(); - virtual void Refresh() ORTHANC_OVERRIDE; + virtual void Invalidate() ORTHANC_OVERRIDE; + + virtual void Paint() ORTHANC_OVERRIDE; + + virtual ILock* Lock() ORTHANC_OVERRIDE + { + return new SdlLock(*this); + } virtual void UpdateSize(unsigned int width, unsigned int height) ORTHANC_OVERRIDE; + + virtual void ToggleMaximize() ORTHANC_OVERRIDE + { + boost::mutex::scoped_lock lock(mutex_); + window_.ToggleMaximize(); + } }; } diff -r b519c1c878f1 -r 6009c59d8676 Framework/Viewport/SdlWindow.cpp --- a/Framework/Viewport/SdlWindow.cpp Fri Nov 29 21:24:29 2019 +0100 +++ b/Framework/Viewport/SdlWindow.cpp Mon Dec 02 14:32:05 2019 +0100 @@ -156,7 +156,14 @@ void SdlWindow::Render(SDL_Surface* surface) { - //SDL_RenderClear(renderer_); + /** + * "You are strongly encouraged to call SDL_RenderClear() to + * initialize the backbuffer before starting each new frame's + * drawing, even if you plan to overwrite every pixel." + * https://wiki.libsdl.org/SDL_RenderPresent + **/ + SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 255); + SDL_RenderClear(renderer_); // Clear the entire screen to our selected color SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer_, surface); if (texture != NULL) diff -r b519c1c878f1 -r 6009c59d8676 Framework/Viewport/SdlWindow.h --- a/Framework/Viewport/SdlWindow.h Fri Nov 29 21:24:29 2019 +0100 +++ b/Framework/Viewport/SdlWindow.h Mon Dec 02 14:32:05 2019 +0100 @@ -58,6 +58,11 @@ unsigned int GetHeight() const; + /** + * WARNING: "Refresh()" cannot only be called from the main SDL + * thread, in which the window was created. Otherwise, the + * renderer displays nothing! + **/ void Render(struct SDL_Surface* surface); void ToggleMaximize(); diff -r b519c1c878f1 -r 6009c59d8676 Framework/Viewport/ViewportBase.cpp --- a/Framework/Viewport/ViewportBase.cpp Fri Nov 29 21:24:29 2019 +0100 +++ b/Framework/Viewport/ViewportBase.cpp Mon Dec 02 14:32:05 2019 +0100 @@ -40,4 +40,14 @@ return ScenePoint2D(0, 0); } } + + + void ViewportBase::LockBase::FitContent() + { + if (HasCompositor()) + { + ICompositor& compositor = GetCompositor(); + GetScene().FitContent(compositor.GetCanvasWidth(), compositor.GetCanvasHeight()); + } + } } diff -r b519c1c878f1 -r 6009c59d8676 Framework/Viewport/ViewportBase.h --- a/Framework/Viewport/ViewportBase.h Fri Nov 29 21:24:29 2019 +0100 +++ b/Framework/Viewport/ViewportBase.h Mon Dec 02 14:32:05 2019 +0100 @@ -49,6 +49,8 @@ } virtual ScenePoint2D GetPixelCenterCoordinates(int x, int y) ORTHANC_OVERRIDE; + + virtual void FitContent() ORTHANC_OVERRIDE; }; Scene2D& GetScene()