comparison OrthancStone/Sources/Platforms/WebAssembly/WebGLViewportsRegistry.cpp @ 1899:917500c46fe0

moved the Platform folder from the Applications folder to the Stone library itself
author Alain Mazy <am@osimis.io>
date Sat, 29 Jan 2022 12:47:32 +0100
parents
children 184b0aeae1af
comparison
equal deleted inserted replaced
1898:a5e54bd87b25 1899:917500c46fe0
1 /**
2 * Stone of Orthanc
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017-2022 Osimis S.A., Belgium
6 * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
7 *
8 * This program is free software: you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation, either version 3 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this program. If not, see
20 * <http://www.gnu.org/licenses/>.
21 **/
22
23
24 #include "WebGLViewportsRegistry.h"
25
26 #include "../../../OrthancStone/Sources/Scene2DViewport/ViewportController.h"
27 #include "../../../OrthancStone/Sources/Toolbox/GenericToolbox.h"
28
29 #include <OrthancException.h>
30
31 #include <boost/make_shared.hpp>
32
33
34 static double viewportsTimeout_ = 1000;
35 static std::unique_ptr<OrthancStone::WebGLViewportsRegistry> globalRegistry_;
36
37
38 namespace OrthancStone
39 {
40 void WebGLViewportsRegistry::LaunchTimer()
41 {
42 timeOutID_ = emscripten_set_timeout(
43 OnTimeoutCallback,
44 timeoutMS_,
45 reinterpret_cast<void*>(this));
46 }
47
48 void WebGLViewportsRegistry::OnTimeout()
49 {
50 for (Viewports::iterator it = viewports_.begin();
51 it != viewports_.end();
52 ++it)
53 {
54 if (it->second == NULL ||
55 it->second->IsContextLost())
56 {
57 LOG(INFO) << "WebGL context lost for canvas: " << it->first;
58
59 // Try and duplicate the HTML5 canvas in the DOM
60 EM_ASM({
61 var canvas = document.getElementById(UTF8ToString($0));
62 if (canvas) {
63 var parent = canvas.parentElement;
64 if (parent) {
65 var cloned = canvas.cloneNode(true /* deep copy */);
66 parent.insertBefore(cloned, canvas);
67 parent.removeChild(canvas);
68 }
69 }
70 },
71 it->first.c_str() // $0 = ID of the canvas
72 );
73
74 // At this point, the old canvas is removed from the DOM and
75 // replaced by a fresh one with the same ID: Recreate the
76 // WebGL context on the new canvas
77 boost::shared_ptr<WebGLViewport> viewport;
78
79 // we need to steal the properties from the old viewport
80 // and set them to the new viewport
81 {
82 std::unique_ptr<IViewport::ILock> lock(it->second->Lock());
83
84 // TODO: remove ViewportController
85 Scene2D* scene = lock->GetController().ReleaseScene();
86 viewport = WebGLViewport::Create(it->first);
87
88 {
89 std::unique_ptr<IViewport::ILock> newLock(viewport->Lock());
90 newLock->GetController().AcquireScene(scene);
91 }
92 }
93
94 // Replace the old WebGL viewport by the new one
95 it->second = viewport;
96
97 // Tag the fresh canvas as needing a repaint
98 {
99 std::unique_ptr<IViewport::ILock> lock(it->second->Lock());
100 lock->Invalidate();
101 }
102 }
103 }
104
105 LaunchTimer();
106 }
107
108 void WebGLViewportsRegistry::OnTimeoutCallback(void *userData)
109 {
110 // This object dies with the process or tab.
111 WebGLViewportsRegistry* that =
112 reinterpret_cast<WebGLViewportsRegistry*>(userData);
113 that->OnTimeout();
114 }
115
116 WebGLViewportsRegistry::WebGLViewportsRegistry(double timeoutMS) :
117 timeoutMS_(timeoutMS),
118 timeOutID_(0)
119 {
120 if (timeoutMS <= 0)
121 {
122 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
123 }
124
125 LaunchTimer();
126 }
127
128 WebGLViewportsRegistry::~WebGLViewportsRegistry()
129 {
130 emscripten_clear_timeout(timeOutID_);
131 Clear();
132 }
133
134 boost::shared_ptr<WebGLViewport> WebGLViewportsRegistry::Add(
135 const std::string& canvasId)
136 {
137 if (viewports_.find(canvasId) != viewports_.end())
138 {
139 LOG(ERROR) << "Canvas was already registered: " << canvasId;
140 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
141 }
142 else
143 {
144 boost::shared_ptr<WebGLViewport> viewport =
145 WebGLViewport::Create(canvasId);
146 viewports_[canvasId] = viewport;
147 return viewport;
148 }
149 }
150
151 void WebGLViewportsRegistry::Remove(const std::string& canvasId)
152 {
153 Viewports::iterator found = viewports_.find(canvasId);
154
155 if (found == viewports_.end())
156 {
157 LOG(ERROR) << "Cannot remove unregistered canvas: " << canvasId;
158 }
159 else
160 {
161 viewports_.erase(found);
162 }
163 }
164
165 void WebGLViewportsRegistry::Clear()
166 {
167 viewports_.clear();
168 }
169
170 WebGLViewportsRegistry::Accessor::Accessor(WebGLViewportsRegistry& that,
171 const std::string& canvasId) :
172 that_(that)
173 {
174 Viewports::iterator viewport = that.viewports_.find(canvasId);
175 if (viewport != that.viewports_.end() &&
176 viewport->second != NULL)
177 {
178 lock_.reset(viewport->second->Lock());
179 }
180 }
181
182 IViewport::ILock& WebGLViewportsRegistry::Accessor::GetViewport() const
183 {
184 if (IsValid())
185 {
186 return *lock_;
187 }
188 else
189 {
190 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
191 }
192 }
193
194
195 void WebGLViewportsRegistry::FinalizeGlobalRegistry()
196 {
197 globalRegistry_.reset();
198 }
199
200
201 void WebGLViewportsRegistry::SetGlobalRegistryTimeout(double timeout)
202 {
203 if (globalRegistry_.get())
204 {
205 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
206 }
207 else
208 {
209 viewportsTimeout_ = timeout;
210 }
211 }
212
213
214 WebGLViewportsRegistry& WebGLViewportsRegistry::GetGlobalRegistry()
215 {
216 if (globalRegistry_.get() == NULL)
217 {
218 globalRegistry_.reset(new WebGLViewportsRegistry(viewportsTimeout_));
219 }
220
221 return *globalRegistry_;
222 }
223 }