diff Framework/OpenGL/WebAssemblyOpenGLContext.cpp @ 947:1091b2adeb5a toa2019081001

Fixed animation frame stopping when returning false + big work on the OpenGL objects to make them lost context-safe + debug code to forcefully tag a context as lost + debug macros
author Benjamin Golinvaux <bgo@osimis.io>
date Sat, 10 Aug 2019 13:07:31 +0200
parents 2db3ef713664
children a7351ad54960
line wrap: on
line diff
--- a/Framework/OpenGL/WebAssemblyOpenGLContext.cpp	Tue Aug 06 15:07:23 2019 +0200
+++ b/Framework/OpenGL/WebAssemblyOpenGLContext.cpp	Sat Aug 10 13:07:31 2019 +0200
@@ -21,6 +21,8 @@
 
 #include "WebAssemblyOpenGLContext.h"
 
+#include "../StoneException.h"
+
 #include <Core/OrthancException.h>
 
 #include <emscripten/html5.h>
@@ -35,14 +37,16 @@
     class WebAssemblyOpenGLContext::PImpl
     {
     private:
-      std::string                      canvas_;
-      EMSCRIPTEN_WEBGL_CONTEXT_HANDLE  context_;
-      unsigned int                     canvasWidth_;
-      unsigned int                     canvasHeight_;
+      std::string                     canvas_;
+      EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context_;
+      unsigned int                    canvasWidth_;
+      unsigned int                    canvasHeight_;
+      bool                            isContextLost_;
 
     public:
-      PImpl(const std::string& canvas) :
-        canvas_(canvas)
+      PImpl(const std::string& canvas)
+        : canvas_(canvas)
+        , isContextLost_(false)
       {
         // Context configuration
         EmscriptenWebGLContextAttributes attr; 
@@ -60,6 +64,27 @@
         UpdateSize();
       }
 
+      void* DebugGetInternalContext() const
+      {
+        return reinterpret_cast<void*>(context_);
+      }
+
+      bool IsContextLost() const
+      {
+        bool apiFlag = (emscripten_is_webgl_context_lost(context_) != 0);
+        bool ownFlag = isContextLost_;
+        if (ownFlag != apiFlag)
+        {
+          LOG(WARNING) << "Context loss, according to emscripten, is: " << apiFlag << " | while, according to internal state, is: " << ownFlag;
+        }
+        return ownFlag | apiFlag;
+      }
+
+      void SetLostContext()
+      {
+        isContextLost_ = true;
+      }
+
       ~PImpl()
       {
         emscripten_webgl_destroy_context(context_);
@@ -72,11 +97,17 @@
 
       void MakeCurrent()
       {
+        if (IsContextLost())
+        {
+          LOG(ERROR) << "MakeCurrent() called on lost context " << context_;
+          throw OpenGLContextLostException(reinterpret_cast<void*>(context_));
+        }
+
         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!");
+          LOG(ERROR) << "OpenGL context has been lost for canvas: " << canvas_;
+          SetLostContext();
+          throw OpenGLContextLostException(reinterpret_cast<void*>(context_));
         }
 
         if (emscripten_webgl_make_context_current(context_) != EMSCRIPTEN_RESULT_SUCCESS)
@@ -146,13 +177,32 @@
     {
     }
 
+    bool WebAssemblyOpenGLContext::IsContextLost() const
+    {
+      return pimpl_->IsContextLost();
+    }
+
+    void WebAssemblyOpenGLContext::RestoreLostContext()
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
+    }
+
+    void WebAssemblyOpenGLContext::SetLostContext()
+    {
+      pimpl_->SetLostContext();
+    }
+
+    void* WebAssemblyOpenGLContext::DebugGetInternalContext() const
+    {
+      return pimpl_->DebugGetInternalContext();
+    }
+    
     void WebAssemblyOpenGLContext::MakeCurrent()
     {
       assert(pimpl_.get() != NULL);
       pimpl_->MakeCurrent();
     }
 
-
     void WebAssemblyOpenGLContext::SwapBuffer() 
     {
       assert(pimpl_.get() != NULL);