changeset 942:685c9a2d115f

Added missing ORTHANC_OVERRIDE + preparation for lost GL context handling + stubs for GL context event handlers
author Benjamin Golinvaux <bgo@osimis.io>
date Mon, 05 Aug 2019 12:27:27 +0200
parents ab90628e70d9
children 8b2d0d2c17a6
files Framework/OpenGL/WebAssemblyOpenGLContext.cpp Framework/Scene2D/CairoCompositor.h Framework/Scene2D/OpenGLCompositor.cpp Framework/Scene2D/OpenGLCompositor.h Framework/Scene2D/Scene2D.cpp Framework/Scene2DViewport/ViewportController.h Framework/Viewport/IViewport.h Framework/Viewport/SdlViewport.h Framework/Viewport/ViewportBase.h Framework/Viewport/WebAssemblyViewport.cpp Framework/Viewport/WebAssemblyViewport.h
diffstat 11 files changed, 148 insertions(+), 68 deletions(-) [+]
line wrap: on
line diff
--- a/Framework/OpenGL/WebAssemblyOpenGLContext.cpp	Wed Jul 31 11:29:08 2019 +0200
+++ b/Framework/OpenGL/WebAssemblyOpenGLContext.cpp	Mon Aug 05 12:27:27 2019 +0200
@@ -24,6 +24,8 @@
 #include <Core/OrthancException.h>
 
 #include <emscripten/html5.h>
+#include <emscripten/em_asm.h>
+
 #include <boost/math/special_functions/round.hpp>
 
 namespace OrthancStone
@@ -70,6 +72,13 @@
 
       void MakeCurrent()
       {
+        if (emscripten_is_webgl_context_lost(context_))
+        {
+          LOG(ERROR) << "OpenGL context has been lost! for canvas: " << canvas_;
+          throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError,
+            "OpenGL context has been lost!");
+        }
+
         if (emscripten_webgl_make_context_current(context_) != EMSCRIPTEN_RESULT_SUCCESS)
         {
           throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError,
--- a/Framework/Scene2D/CairoCompositor.h	Wed Jul 31 11:29:08 2019 +0200
+++ b/Framework/Scene2D/CairoCompositor.h	Mon Aug 05 12:27:27 2019 +0200
@@ -44,9 +44,9 @@
     // Only valid during a call to "Refresh()"
     std::auto_ptr<CairoContext>  context_;
 
-    virtual cairo_t* GetCairoContext();
+    virtual cairo_t* GetCairoContext() ORTHANC_OVERRIDE;
 
-    virtual Internals::CompositorHelper::ILayerRenderer* Create(const ISceneLayer& layer);
+    virtual Internals::CompositorHelper::ILayerRenderer* Create(const ISceneLayer& layer) ORTHANC_OVERRIDE;
 
   public:
     CairoCompositor(const Scene2D& scene,
@@ -60,27 +60,27 @@
       return canvas_;
     }
 
-    virtual unsigned int GetCanvasWidth() const
+    virtual unsigned int GetCanvasWidth() const ORTHANC_OVERRIDE
     {
       return canvas_.GetWidth();
     }
 
-    virtual unsigned int GetCanvasHeight() const
+    virtual unsigned int GetCanvasHeight() const ORTHANC_OVERRIDE
     {
       return canvas_.GetHeight();
     }
     
     void SetFont(size_t index,
-                 GlyphBitmapAlphabet* dict);  // Takes ownership
+                 GlyphBitmapAlphabet* dict); // Takes ownership
 
 #if ORTHANC_ENABLE_LOCALE == 1
     virtual void SetFont(size_t index,
                          Orthanc::EmbeddedResources::FileResourceId resource,
                          unsigned int fontSize,
-                         Orthanc::Encoding codepage);
+                         Orthanc::Encoding codepage) ORTHANC_OVERRIDE;
 #endif
 
-    virtual void Refresh();
+    virtual void Refresh() ORTHANC_OVERRIDE;
 
     void UpdateSize(unsigned int canvasWidth,
                     unsigned int canvasHeight);
--- a/Framework/Scene2D/OpenGLCompositor.cpp	Wed Jul 31 11:29:08 2019 +0200
+++ b/Framework/Scene2D/OpenGLCompositor.cpp	Mon Aug 05 12:27:27 2019 +0200
@@ -18,7 +18,6 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  **/
 
-
 #include "OpenGLCompositor.h"
 
 #include "Internals/OpenGLAdvancedPolylineRenderer.h"
@@ -60,7 +59,6 @@
     }
   };
 
-
   const OpenGLCompositor::Font* OpenGLCompositor::GetFont(size_t fontIndex) const
   {
     Fonts::const_iterator found = fonts_.find(fontIndex);
@@ -76,7 +74,6 @@
     }
   }
 
-
   Internals::CompositorHelper::ILayerRenderer* OpenGLCompositor::Create(const ISceneLayer& layer)
   {
     switch (layer.GetType())
@@ -122,7 +119,6 @@
     }
   }
 
-
   OpenGLCompositor::OpenGLCompositor(OpenGL::IOpenGLContext& context,
                                      const Scene2D& scene) :
     context_(context),
@@ -136,7 +132,6 @@
   {
   }
 
-  
   OpenGLCompositor::~OpenGLCompositor()
   {
     for (Fonts::iterator it = fonts_.begin(); it != fonts_.end(); ++it)
@@ -146,7 +141,6 @@
     }
   }
 
-  
   void OpenGLCompositor::Refresh()
   {
     context_.MakeCurrent();
@@ -163,7 +157,6 @@
     context_.SwapBuffer();
   }
 
-  
   void OpenGLCompositor::SetFont(size_t index,
                                  const GlyphBitmapAlphabet& dict)
   {
@@ -185,7 +178,6 @@
       found->second = font.release();
     }
   }
-  
 
 #if ORTHANC_ENABLE_LOCALE == 1
   void OpenGLCompositor::SetFont(size_t index,
--- a/Framework/Scene2D/OpenGLCompositor.h	Wed Jul 31 11:29:08 2019 +0200
+++ b/Framework/Scene2D/OpenGLCompositor.h	Mon Aug 05 12:27:27 2019 +0200
@@ -30,9 +30,7 @@
 
 namespace OrthancStone
 {
-  class OpenGLCompositor :
-      public ICompositor,
-      private Internals::CompositorHelper::IRendererFactory
+  class OpenGLCompositor : public ICompositor, private Internals::CompositorHelper::IRendererFactory
   {
   private:
     class Font;
@@ -51,7 +49,7 @@
     
     const Font* GetFont(size_t fontIndex) const;
 
-    virtual Internals::CompositorHelper::ILayerRenderer* Create(const ISceneLayer& layer);
+    virtual Internals::CompositorHelper::ILayerRenderer* Create(const ISceneLayer& layer) ORTHANC_OVERRIDE;
 
   public:
     OpenGLCompositor(OpenGL::IOpenGLContext& context,
@@ -59,7 +57,7 @@
 
     virtual ~OpenGLCompositor();
 
-    virtual void Refresh();
+    virtual void Refresh() ORTHANC_OVERRIDE;
 
     void SetFont(size_t index,
                  const GlyphBitmapAlphabet& dict);
@@ -68,15 +66,15 @@
     void SetFont(size_t index,
                  Orthanc::EmbeddedResources::FileResourceId resource,
                  unsigned int fontSize,
-                 Orthanc::Encoding codepage);
+                 Orthanc::Encoding codepage) ORTHANC_OVERRIDE;
 #endif
 
-    virtual unsigned int GetCanvasWidth() const
+    virtual unsigned int GetCanvasWidth() const ORTHANC_OVERRIDE
     {
       return canvasWidth_;
     }
 
-    virtual unsigned int GetCanvasHeight() const
+    virtual unsigned int GetCanvasHeight() const ORTHANC_OVERRIDE
     {
       return canvasHeight_;
     }
--- a/Framework/Scene2D/Scene2D.cpp	Wed Jul 31 11:29:08 2019 +0200
+++ b/Framework/Scene2D/Scene2D.cpp	Mon Aug 05 12:27:27 2019 +0200
@@ -199,8 +199,7 @@
       return layer.release();
     }    
   }
-  
-  
+
   void Scene2D::Apply(IVisitor& visitor) const
   {
     for (Content::const_iterator it = content_.begin(); 
--- a/Framework/Scene2DViewport/ViewportController.h	Wed Jul 31 11:29:08 2019 +0200
+++ b/Framework/Scene2DViewport/ViewportController.h	Mon Aug 05 12:27:27 2019 +0200
@@ -170,11 +170,6 @@
     /** forwarded to the UndoStack */
     bool CanRedo() const;
 
-    IViewport& GetViewport()
-    {
-      return viewport_;
-    }
-
     Scene2D& GetScene()
     {
       return viewport_.GetScene();
--- a/Framework/Viewport/IViewport.h	Wed Jul 31 11:29:08 2019 +0200
+++ b/Framework/Viewport/IViewport.h	Mon Aug 05 12:27:27 2019 +0200
@@ -50,6 +50,14 @@
 
     virtual ScenePoint2D GetPixelCenterCoordinates(int x, int y) const = 0;
 
+#if ORTHANC_ENABLE_LOCALE == 1
+    virtual void SetFont(size_t index,
+      Orthanc::EmbeddedResources::FileResourceId resource,
+      unsigned int fontSize,
+      Orthanc::Encoding codepage) = 0;
+#endif
+
+  protected:
     virtual ICompositor& GetCompositor() = 0;
 
     virtual const ICompositor& GetCompositor() const
--- a/Framework/Viewport/SdlViewport.h	Wed Jul 31 11:29:08 2019 +0200
+++ b/Framework/Viewport/SdlViewport.h	Mon Aug 05 12:27:27 2019 +0200
@@ -81,22 +81,21 @@
                       boost::shared_ptr<Scene2D>& scene,
                       bool allowDpiScaling = true);
 
-
-    virtual ICompositor& GetCompositor()
-    {
-      return compositor_;
-    }
-
-    virtual SdlWindow& GetWindow()
+    virtual SdlWindow& GetWindow() ORTHANC_OVERRIDE
     {
       return context_.GetWindow();
     }
 
-    virtual void UpdateSize(unsigned int width,
-                            unsigned int height)
+    virtual void UpdateSize(unsigned int width, unsigned int height) ORTHANC_OVERRIDE
     {
       // nothing to do in OpenGL, the OpenGLCompositor::UpdateSize will be called automatically
     }
+
+  protected:
+    virtual ICompositor& GetCompositor() ORTHANC_OVERRIDE
+    {
+      return compositor_;
+    }
   };
 
 
@@ -121,20 +120,20 @@
 
     ~SdlCairoViewport();
 
-    virtual ICompositor& GetCompositor()
-    {
-      return compositor_;
-    }
-
-    virtual SdlWindow& GetWindow()
+    virtual SdlWindow& GetWindow() ORTHANC_OVERRIDE
     {
       return window_;
     }
 
-    virtual void Refresh();
+    virtual void Refresh() ORTHANC_OVERRIDE;
 
     virtual void UpdateSize(unsigned int width,
-                            unsigned int height);
+                            unsigned int height) ORTHANC_OVERRIDE;
+  protected:
+    virtual ICompositor& GetCompositor() ORTHANC_OVERRIDE
+    {
+      return compositor_;
+    }
 
   private:
     void UpdateSdlSurfaceSize(unsigned int width,
--- a/Framework/Viewport/ViewportBase.h	Wed Jul 31 11:29:08 2019 +0200
+++ b/Framework/Viewport/ViewportBase.h	Mon Aug 05 12:27:27 2019 +0200
@@ -38,32 +38,41 @@
     ViewportBase(const std::string& identifier,
                  boost::shared_ptr<Scene2D>& scene);
 
-    virtual Scene2D& GetScene()
+    virtual Scene2D& GetScene() ORTHANC_OVERRIDE
     {
       return *scene_;
     }
 
-    virtual const std::string& GetCanvasIdentifier() const
+    virtual const std::string& GetCanvasIdentifier() const ORTHANC_OVERRIDE
     {
       return identifier_;
     }
 
-    virtual ScenePoint2D GetPixelCenterCoordinates(int x, int y) const;
+    virtual ScenePoint2D GetPixelCenterCoordinates(int x, int y) const ORTHANC_OVERRIDE;
 
-    virtual void Refresh()
+    virtual void Refresh() ORTHANC_OVERRIDE
     {
       GetCompositor().Refresh();
     }
 
-    virtual unsigned int GetCanvasWidth() const
+    virtual unsigned int GetCanvasWidth() const ORTHANC_OVERRIDE
     {
       return GetCompositor().GetCanvasWidth();
     }
 
-    virtual unsigned int GetCanvasHeight() const
+    virtual unsigned int GetCanvasHeight() const ORTHANC_OVERRIDE
     {
       return GetCompositor().GetCanvasHeight();
     }
 
+#if ORTHANC_ENABLE_LOCALE == 1
+    virtual void SetFont(size_t index,
+      Orthanc::EmbeddedResources::FileResourceId resource,
+      unsigned int fontSize,
+      Orthanc::Encoding codepage) ORTHANC_OVERRIDE
+    {
+      return GetCompositor().SetFont(index, resource, fontSize, codepage);
+    }
+#endif
   };
 }
--- a/Framework/Viewport/WebAssemblyViewport.cpp	Wed Jul 31 11:29:08 2019 +0200
+++ b/Framework/Viewport/WebAssemblyViewport.cpp	Mon Aug 05 12:27:27 2019 +0200
@@ -13,7 +13,7 @@
  * 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/>.
  **/
@@ -26,27 +26,94 @@
 {
   WebAssemblyOpenGLViewport::WebAssemblyOpenGLViewport(const std::string& canvas) :
     WebAssemblyViewport(canvas),
-    context_(canvas),
-    compositor_(context_, GetScene())
+    context_(canvas)
   {
+    compositor_.reset(new OpenGLCompositor(context_, GetScene()));
+    RegisterContextCallbacks();
   }
 
-    
   WebAssemblyOpenGLViewport::WebAssemblyOpenGLViewport(const std::string& canvas,
-                                                       boost::shared_ptr<Scene2D>& scene) :
+    boost::shared_ptr<Scene2D>& scene) :
     WebAssemblyViewport(canvas, scene),
-    context_(canvas),
-    compositor_(context_, GetScene())
+    context_(canvas)
   {
+    compositor_.reset(new OpenGLCompositor(context_, GetScene()));
+    RegisterContextCallbacks();
   }
-    
 
   void WebAssemblyOpenGLViewport::UpdateSize()
   {
     context_.UpdateSize();  // First read the size of the canvas
-    compositor_.Refresh();  // Then refresh the content of the canvas
+    compositor_->Refresh();  // Then refresh the content of the canvas
+  }
+
+  /*
+  typedef EM_BOOL (*em_webgl_context_callback)(int eventType, const void *reserved, void *userData);
+
+  EMSCRIPTEN_EVENT_WEBGLCONTEXTLOST EMSCRIPTEN_EVENT_WEBGLCONTEXTRESTORED
+
+  EMSCRIPTEN_RESULT emscripten_set_webglcontextlost_callback(
+    const char *target, void *userData, EM_BOOL useCapture, em_webgl_context_callback callback)
+
+  EMSCRIPTEN_RESULT emscripten_set_webglcontextrestored_callback(
+    const char *target, void *userData, EM_BOOL useCapture, em_webgl_context_callback callback)
+
+  */
+
+  EM_BOOL WebAssemblyOpenGLViewport_OpenGLContextLost_callback(
+    int eventType, const void* reserved, void* userData)
+  {
+    ORTHANC_ASSERT(eventType == EMSCRIPTEN_EVENT_WEBGLCONTEXTLOST);
+    WebAssemblyOpenGLViewport* viewport = reinterpret_cast<WebAssemblyOpenGLViewport*>(userData);
+    return viewport->OpenGLContextLost();
+  }
+
+  EM_BOOL WebAssemblyOpenGLViewport_OpenGLContextRestored_callback(
+    int eventType, const void* reserved, void* userData)
+  {
+    ORTHANC_ASSERT(eventType == EMSCRIPTEN_EVENT_WEBGLCONTEXTRESTORED);
+    WebAssemblyOpenGLViewport* viewport = reinterpret_cast<WebAssemblyOpenGLViewport*>(userData);
+    return viewport->OpenGLContextRestored();
   }
 
+  void WebAssemblyOpenGLViewport::RegisterContextCallbacks()
+  {
+    // TODO: what's the impact of userCapture=true ?
+    const char* canvasId = GetCanvasIdentifier().c_str();
+    void* that = reinterpret_cast<void*>(this);
+    EMSCRIPTEN_RESULT status = EMSCRIPTEN_RESULT_SUCCESS;
+
+    status = emscripten_set_webglcontextlost_callback(canvasId, that, true, WebAssemblyOpenGLViewport_OpenGLContextLost_callback);
+    if (status != EMSCRIPTEN_RESULT_SUCCESS)
+    {
+      std::stringstream ss;
+      ss << "Error while calling emscripten_set_webglcontextlost_callback for: \"" << GetCanvasIdentifier() << "\"";
+      std::string msg = ss.str();
+      LOG(ERROR) << msg;
+      ORTHANC_ASSERT(false, msg.c_str());
+    }
+    status = emscripten_set_webglcontextrestored_callback(canvasId, that, true, WebAssemblyOpenGLViewport_OpenGLContextRestored_callback);
+    if (status != EMSCRIPTEN_RESULT_SUCCESS)
+    {
+      std::stringstream ss;
+      ss << "Error while calling emscripten_set_webglcontextrestored_callback for: \"" << GetCanvasIdentifier() << "\"";
+      std::string msg = ss.str();
+      LOG(ERROR) << msg;
+      ORTHANC_ASSERT(false, msg.c_str());
+    }
+  }
+
+  bool WebAssemblyOpenGLViewport::OpenGLContextLost()
+  {
+    LOG(ERROR) << "WebAssemblyOpenGLViewport::OpenGLContextLost() for canvas: " << GetCanvasIdentifier();
+    return false;
+  }
+
+  bool WebAssemblyOpenGLViewport::OpenGLContextRestored()
+  {
+    LOG(ERROR) << "WebAssemblyOpenGLViewport::OpenGLContextRestored() for canvas: " << GetCanvasIdentifier();
+    return false;
+  }
 
   WebAssemblyCairoViewport::WebAssemblyCairoViewport(const std::string& canvas) :
     WebAssemblyViewport(canvas),
@@ -55,16 +122,14 @@
   {
   }
 
-    
   WebAssemblyCairoViewport::WebAssemblyCairoViewport(const std::string& canvas,
-                                                     boost::shared_ptr<Scene2D>& scene) :
+    boost::shared_ptr<Scene2D>& scene) :
     WebAssemblyViewport(canvas, scene),
     canvas_(canvas),
     compositor_(GetScene(), 1024, 768)
   {
   }
 
-
   void WebAssemblyCairoViewport::UpdateSize()
   {
     LOG(INFO) << "updating cairo viewport size";
@@ -84,7 +149,7 @@
     unsigned int canvasHeight = 0;
 
     if (w > 0 ||
-        h > 0)
+      h > 0)
     {
       canvasWidth = static_cast<unsigned int>(boost::math::iround(w));
       canvasHeight = static_cast<unsigned int>(boost::math::iround(h));
--- a/Framework/Viewport/WebAssemblyViewport.h	Wed Jul 31 11:29:08 2019 +0200
+++ b/Framework/Viewport/WebAssemblyViewport.h	Mon Aug 05 12:27:27 2019 +0200
@@ -47,7 +47,7 @@
   {
   private:
     OpenGL::WebAssemblyOpenGLContext  context_;
-    OpenGLCompositor                  compositor_;
+    std::auto_ptr<OpenGLCompositor>   compositor_;
 
   public:
     WebAssemblyOpenGLViewport(const std::string& canvas);
@@ -60,8 +60,14 @@
 
     virtual ICompositor& GetCompositor()
     {
-      return compositor_;
+      return *compositor_;
     }
+
+    bool OpenGLContextLost();
+    bool OpenGLContextRestored();
+
+  private:
+    void RegisterContextCallbacks();
   };
 
   class WebAssemblyCairoViewport : public WebAssemblyViewport