changeset 1211:d10d2acb8a02 broker

compositors do not keep a reference to the scene anymore
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 04 Dec 2019 16:47:21 +0100
parents 644baa70373d
children ab06dfdf3b75
files Framework/Scene2D/CairoCompositor.cpp Framework/Scene2D/CairoCompositor.h Framework/Scene2D/ICompositor.h Framework/Scene2D/Internals/CompositorHelper.cpp Framework/Scene2D/Internals/CompositorHelper.h Framework/Scene2D/OpenGLCompositor.cpp Framework/Scene2D/OpenGLCompositor.h Framework/Scene2D/Scene2D.cpp Framework/Scene2D/Scene2D.h Framework/Viewport/SdlViewport.cpp
diffstat 10 files changed, 80 insertions(+), 49 deletions(-) [+]
line wrap: on
line diff
--- a/Framework/Scene2D/CairoCompositor.cpp	Wed Dec 04 16:13:10 2019 +0100
+++ b/Framework/Scene2D/CairoCompositor.cpp	Wed Dec 04 16:47:21 2019 +0100
@@ -85,11 +85,10 @@
   }
 
 
-  CairoCompositor::CairoCompositor(const Scene2D& scene,
-                                   unsigned int canvasWidth,
-                                   unsigned int canvasHeight) :
-    helper_(scene, *this)
+  CairoCompositor::CairoCompositor(unsigned int canvasWidth,
+                                   unsigned int canvasHeight)
   {
+    ResetScene();
     UpdateSize(canvasWidth, canvasHeight);
   }
 
@@ -154,7 +153,7 @@
 #endif
 
 
-  void CairoCompositor::Refresh()
+  void CairoCompositor::Refresh(const Scene2D& scene)
   {
     context_.reset(new CairoContext(canvas_));
 
@@ -162,7 +161,7 @@
     cairo_set_source_rgba(context_->GetObject(), 0, 0, 0, 255);
     cairo_paint(context_->GetObject());
 
-    helper_.Refresh(canvas_.GetWidth(), canvas_.GetHeight());
+    helper_->Refresh(scene, canvas_.GetWidth(), canvas_.GetHeight());
     context_.reset();
   }
 
--- a/Framework/Scene2D/CairoCompositor.h	Wed Dec 04 16:13:10 2019 +0100
+++ b/Framework/Scene2D/CairoCompositor.h	Wed Dec 04 16:47:21 2019 +0100
@@ -37,7 +37,7 @@
   private:
     typedef std::map<size_t, GlyphBitmapAlphabet*>   Fonts;
 
-    Internals::CompositorHelper  helper_;
+    std::auto_ptr<Internals::CompositorHelper>  helper_;
     CairoSurface                 canvas_;
     Fonts                        fonts_;
 
@@ -49,8 +49,7 @@
     virtual Internals::CompositorHelper::ILayerRenderer* Create(const ISceneLayer& layer) ORTHANC_OVERRIDE;
 
   public:
-    CairoCompositor(const Scene2D& scene,
-                    unsigned int canvasWidth,
+    CairoCompositor(unsigned int canvasWidth,
                     unsigned int canvasHeight);
     
     virtual ~CairoCompositor();
@@ -80,7 +79,12 @@
                          Orthanc::Encoding codepage) ORTHANC_OVERRIDE;
 #endif
 
-    virtual void Refresh() ORTHANC_OVERRIDE;
+    virtual void Refresh(const Scene2D& scene) ORTHANC_OVERRIDE;
+
+    virtual void ResetScene() ORTHANC_OVERRIDE
+    {
+      helper_.reset(new Internals::CompositorHelper(*this));
+    }
 
     void UpdateSize(unsigned int canvasWidth,
                     unsigned int canvasHeight);
--- a/Framework/Scene2D/ICompositor.h	Wed Dec 04 16:13:10 2019 +0100
+++ b/Framework/Scene2D/ICompositor.h	Wed Dec 04 16:47:21 2019 +0100
@@ -1,8 +1,8 @@
 #pragma once
 
-#include <boost/noncopyable.hpp>
+#include "Scene2D.h"
+
 #include <EmbeddedResources.h>
-#include <Core/Enumerations.h>
 
 namespace OrthancStone
 {
@@ -17,7 +17,14 @@
 
     virtual unsigned int GetCanvasHeight() const = 0;
 
-    virtual void Refresh() = 0;
+    /**
+     * WARNING: "Refresh()" must always be called with the same
+     * scene. If the scene changes, a call to "ResetScene()" must be
+     * done to reset the tracking of the revisions of the layers.
+     **/
+    virtual void Refresh(const Scene2D& scene) = 0;
+
+    virtual void ResetScene() = 0;
 
 #if ORTHANC_ENABLE_LOCALE == 1
     virtual void SetFont(size_t index,
--- a/Framework/Scene2D/Internals/CompositorHelper.cpp	Wed Dec 04 16:13:10 2019 +0100
+++ b/Framework/Scene2D/Internals/CompositorHelper.cpp	Wed Dec 04 16:47:21 2019 +0100
@@ -80,12 +80,13 @@
     };
 
 
-    void CompositorHelper::Visit(const ISceneLayer& layer,
+    void CompositorHelper::Visit(const Scene2D& scene,
+                                 const ISceneLayer& layer,
                                  uint64_t layerIdentifier,
                                  int depth)
     {
       // "Visit()" is only applied to layers existing in the scene
-      assert(scene_.HasLayer(depth)); 
+      assert(scene.HasLayer(depth)); 
 
       Content::iterator found = content_.find(depth);
 
@@ -141,18 +142,34 @@
     }
 
   
-    void CompositorHelper::Refresh(unsigned int canvasWidth,
+    void CompositorHelper::Refresh(const Scene2D& scene,
+                                   unsigned int canvasWidth,
                                    unsigned int canvasHeight)
     {
+      /**
+       * Safeguard mechanism to enforce the fact that the same scene
+       * is always used with the compositor. Note that the safeguard
+       * is not 100% bullet-proof, as a new scene might reuse the same
+       * address as a previous scene.
+       **/
+      if (lastScene_ != NULL &&
+          lastScene_ != &scene)
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls,
+                                        "ICompositor::ResetScene() should have been called");
+      }
+
+      lastScene_ = &scene;
+
       // Bring coordinate (0,0) to the center of the canvas
       AffineTransform2D offset = AffineTransform2D::CreateOffset(
         static_cast<double>(canvasWidth) / 2.0,
         static_cast<double>(canvasHeight) / 2.0);
 
-      sceneTransform_ = AffineTransform2D::Combine(offset, scene_.GetSceneToCanvasTransform());
+      sceneTransform_ = AffineTransform2D::Combine(offset, scene.GetSceneToCanvasTransform());
       canvasWidth_ = canvasWidth;
       canvasHeight_ = canvasHeight;
-      scene_.Apply(*this);
+      scene.Apply(*this);
     }
   }
 }
--- a/Framework/Scene2D/Internals/CompositorHelper.h	Wed Dec 04 16:13:10 2019 +0100
+++ b/Framework/Scene2D/Internals/CompositorHelper.h	Wed Dec 04 16:47:21 2019 +0100
@@ -64,9 +64,9 @@
 
       typedef std::map<int, Item*>  Content;
 
-      const Scene2D&     scene_;
       IRendererFactory&  factory_;
       Content            content_;
+      const Scene2D*     lastScene_;   // This is only a safeguard, don't use it!
 
       // Only valid during a call to Refresh()
       AffineTransform2D  sceneTransform_;
@@ -74,21 +74,22 @@
       unsigned int       canvasHeight_;
       
     protected:
-      virtual void Visit(const ISceneLayer& layer,
+      virtual void Visit(const Scene2D& scene,
+                         const ISceneLayer& layer,
                          uint64_t layerIdentifier,
                          int depth);
 
     public:
-      CompositorHelper(const Scene2D& scene,
-                       IRendererFactory& factory) :
-        scene_(scene),
-        factory_(factory)
+      CompositorHelper(IRendererFactory& factory) :
+      factory_(factory),
+      lastScene_(NULL)
       {
       }
 
       ~CompositorHelper();
 
-      void Refresh(unsigned int canvasWidth,
+      void Refresh(const Scene2D& scene,
+                   unsigned int canvasWidth,
                    unsigned int canvasHeight);
     };
   }
--- a/Framework/Scene2D/OpenGLCompositor.cpp	Wed Dec 04 16:13:10 2019 +0100
+++ b/Framework/Scene2D/OpenGLCompositor.cpp	Wed Dec 04 16:47:21 2019 +0100
@@ -128,10 +128,8 @@
     }
   }
 
-  OpenGLCompositor::OpenGLCompositor(OpenGL::IOpenGLContext& context,
-                                     const Scene2D& scene) :
+  OpenGLCompositor::OpenGLCompositor(OpenGL::IOpenGLContext& context) :
     context_(context),
-    helper_(scene, *this),
     colorTextureProgram_(context),
     floatTextureProgram_(context),
     linesProgram_(context),
@@ -139,6 +137,7 @@
     canvasWidth_(0),
     canvasHeight_(0)
   {
+    ResetScene();
   }
 
   OpenGLCompositor::~OpenGLCompositor()
@@ -154,7 +153,7 @@
     }
   }
 
-  void OpenGLCompositor::Refresh()
+  void OpenGLCompositor::Refresh(const Scene2D& scene)
   {
     if (!context_.IsContextLost())
     {
@@ -167,11 +166,10 @@
       glClearColor(0, 0, 0, 1);
       glClear(GL_COLOR_BUFFER_BIT);
 
-      helper_.Refresh(canvasWidth_, canvasHeight_);
+      helper_->Refresh(scene, canvasWidth_, canvasHeight_);
 
       context_.SwapBuffer();
     }
-
   }
 
   void OpenGLCompositor::SetFont(size_t index,
--- a/Framework/Scene2D/OpenGLCompositor.h	Wed Dec 04 16:13:10 2019 +0100
+++ b/Framework/Scene2D/OpenGLCompositor.h	Wed Dec 04 16:47:21 2019 +0100
@@ -37,27 +37,31 @@
 
     typedef std::map<size_t, Font*>  Fonts;
 
-    OpenGL::IOpenGLContext&               context_;
-    Fonts                                 fonts_;
-    Internals::CompositorHelper           helper_;
-    Internals::OpenGLColorTextureProgram  colorTextureProgram_;
-    Internals::OpenGLFloatTextureProgram  floatTextureProgram_;
-    Internals::OpenGLLinesProgram         linesProgram_;
-    Internals::OpenGLTextProgram          textProgram_;
-    unsigned int                          canvasWidth_;
-    unsigned int                          canvasHeight_;
+    OpenGL::IOpenGLContext&                     context_;
+    Fonts                                       fonts_;
+    std::auto_ptr<Internals::CompositorHelper>  helper_;
+    Internals::OpenGLColorTextureProgram        colorTextureProgram_;
+    Internals::OpenGLFloatTextureProgram        floatTextureProgram_;
+    Internals::OpenGLLinesProgram               linesProgram_;
+    Internals::OpenGLTextProgram                textProgram_;
+    unsigned int                                canvasWidth_;
+    unsigned int                                canvasHeight_;
 
     const Font* GetFont(size_t fontIndex) const;
 
     virtual Internals::CompositorHelper::ILayerRenderer* Create(const ISceneLayer& layer) ORTHANC_OVERRIDE;
 
   public:
-    OpenGLCompositor(OpenGL::IOpenGLContext& context,
-                     const Scene2D& scene);
+    OpenGLCompositor(OpenGL::IOpenGLContext& context);
 
     virtual ~OpenGLCompositor();
 
-    virtual void Refresh() ORTHANC_OVERRIDE;
+    virtual void Refresh(const Scene2D& scene) ORTHANC_OVERRIDE;
+
+    virtual void ResetScene() ORTHANC_OVERRIDE
+    {
+      helper_.reset(new Internals::CompositorHelper(*this));
+    }
 
     void SetFont(size_t index, const GlyphBitmapAlphabet& dict);
 
--- a/Framework/Scene2D/Scene2D.cpp	Wed Dec 04 16:13:10 2019 +0100
+++ b/Framework/Scene2D/Scene2D.cpp	Wed Dec 04 16:47:21 2019 +0100
@@ -208,7 +208,7 @@
          it != content_.end(); ++it)
     {
       assert(it->second != NULL);
-      visitor.Visit(it->second->GetLayer(), it->second->GetIdentifier(), it->first);
+      visitor.Visit(*this, it->second->GetLayer(), it->second->GetIdentifier(), it->first);
     }
   }
 
--- a/Framework/Scene2D/Scene2D.h	Wed Dec 04 16:13:10 2019 +0100
+++ b/Framework/Scene2D/Scene2D.h	Wed Dec 04 16:47:21 2019 +0100
@@ -40,7 +40,8 @@
       {
       }
 
-      virtual void Visit(const ISceneLayer& layer,
+      virtual void Visit(const Scene2D& scene,
+                         const ISceneLayer& layer,
                          uint64_t layerIdentifier,
                          int depth) = 0;
     };
--- a/Framework/Viewport/SdlViewport.cpp	Wed Dec 04 16:13:10 2019 +0100
+++ b/Framework/Viewport/SdlViewport.cpp	Wed Dec 04 16:47:21 2019 +0100
@@ -50,7 +50,7 @@
                                        bool allowDpiScaling) :
     context_(title, width, height, allowDpiScaling)
   {
-    compositor_.reset(new OpenGLCompositor(context_, GetScene()));
+    compositor_.reset(new OpenGLCompositor(context_));
   }
 
   void SdlOpenGLViewport::Invalidate()
@@ -61,7 +61,7 @@
   void SdlOpenGLViewport::Paint()
   {
     boost::mutex::scoped_lock lock(mutex_);
-    compositor_->Refresh();
+    compositor_->Refresh(GetScene());
   }
 
 
@@ -70,7 +70,7 @@
                                      unsigned int height,
                                      bool allowDpiScaling) :
     window_(title, width, height, false /* enable OpenGL */, allowDpiScaling),
-    compositor_(GetScene(), width, height),
+    compositor_(width, height),
     sdlSurface_(NULL)
   {
   }
@@ -85,7 +85,7 @@
   
   void SdlCairoViewport::InvalidateInternal()  // Assumes that the mutex is locked
   {
-    compositor_.Refresh();
+    compositor_.Refresh(GetScene());
     CreateSdlSurfaceFromCompositor();
   }