Mercurial > hg > orthanc-stone
comparison OrthancStone/Sources/Platforms/WebAssembly/WebAssemblyOpenGLContext.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 "WebAssemblyOpenGLContext.h" | |
25 | |
26 #include "../../../OrthancStone/Sources/StoneException.h" | |
27 | |
28 #include <Logging.h> | |
29 #include <OrthancException.h> | |
30 | |
31 #include <emscripten/html5.h> | |
32 #include <emscripten/em_asm.h> | |
33 | |
34 #include <boost/math/special_functions/round.hpp> | |
35 | |
36 namespace OrthancStone | |
37 { | |
38 namespace OpenGL | |
39 { | |
40 class WebAssemblyOpenGLContext::PImpl | |
41 { | |
42 private: | |
43 std::string canvasSelector_; | |
44 EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context_; | |
45 bool isContextLost_; | |
46 | |
47 public: | |
48 explicit PImpl(const std::string& canvasSelector) : | |
49 canvasSelector_(canvasSelector), | |
50 isContextLost_(false) | |
51 { | |
52 // Context configuration | |
53 EmscriptenWebGLContextAttributes attr; | |
54 emscripten_webgl_init_context_attributes(&attr); | |
55 | |
56 // The next line might be necessary to print using | |
57 // WebGL. Sometimes, if set to "false" (the default value), | |
58 // the canvas was rendered as a fully white or black | |
59 // area. UNCONFIRMED. | |
60 attr.preserveDrawingBuffer = true; | |
61 | |
62 context_ = emscripten_webgl_create_context(canvasSelector.c_str(), &attr); | |
63 if (context_ == 0) | |
64 { | |
65 std::string message("Cannot create an OpenGL context for the element with the following CSS selector: \""); | |
66 message += canvasSelector; | |
67 message += "\" Please make sure the -s DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR=1 flag has been passed to Emscripten when building."; | |
68 LOG(ERROR) << message; | |
69 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, message); | |
70 } | |
71 } | |
72 | |
73 void* DebugGetInternalContext() const | |
74 { | |
75 return reinterpret_cast<void*>(context_); | |
76 } | |
77 | |
78 bool IsContextLost() | |
79 { | |
80 //LOG(TRACE) << "IsContextLost() for context " << std::hex << context_ << std::dec; | |
81 bool apiFlag = (emscripten_is_webgl_context_lost(context_) != 0); | |
82 isContextLost_ = apiFlag; | |
83 return isContextLost_; | |
84 } | |
85 | |
86 void SetLostContext() | |
87 { | |
88 isContextLost_ = true; | |
89 } | |
90 | |
91 ~PImpl() | |
92 { | |
93 try | |
94 { | |
95 EMSCRIPTEN_RESULT result = emscripten_webgl_destroy_context(context_); | |
96 if (result != EMSCRIPTEN_RESULT_SUCCESS) | |
97 { | |
98 LOG(ERROR) << "emscripten_webgl_destroy_context returned code " << result; | |
99 } | |
100 } | |
101 catch (const Orthanc::OrthancException& e) | |
102 { | |
103 if (e.HasDetails()) | |
104 { | |
105 LOG(ERROR) << "OrthancException in WebAssemblyOpenGLContext::~PImpl: " << e.What() << " Details: " << e.GetDetails(); | |
106 } | |
107 else | |
108 { | |
109 LOG(ERROR) << "OrthancException in WebAssemblyOpenGLContext::~PImpl: " << e.What(); | |
110 } | |
111 } | |
112 catch (const std::exception& e) | |
113 { | |
114 LOG(ERROR) << "std::exception in WebAssemblyOpenGLContext::~PImpl: " << e.what(); | |
115 } | |
116 catch (...) | |
117 { | |
118 LOG(ERROR) << "Unknown exception in WebAssemblyOpenGLContext::~PImpl"; | |
119 } | |
120 } | |
121 | |
122 const std::string& GetCanvasSelector() const | |
123 { | |
124 return canvasSelector_; | |
125 } | |
126 | |
127 void MakeCurrent() | |
128 { | |
129 if (IsContextLost()) | |
130 { | |
131 LOG(ERROR) << "MakeCurrent() called on lost context " << context_; | |
132 throw StoneException(ErrorCode_WebGLContextLost); | |
133 } | |
134 | |
135 if (emscripten_is_webgl_context_lost(context_)) | |
136 { | |
137 LOG(ERROR) << "OpenGL context has been lost for canvas selector: " << canvasSelector_; | |
138 SetLostContext(); | |
139 throw StoneException(ErrorCode_WebGLContextLost); | |
140 } | |
141 | |
142 if (emscripten_webgl_make_context_current(context_) != EMSCRIPTEN_RESULT_SUCCESS) | |
143 { | |
144 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, | |
145 "Cannot set the OpenGL context"); | |
146 } | |
147 } | |
148 | |
149 void SwapBuffer() | |
150 { | |
151 /** | |
152 * "Rendered WebGL content is implicitly presented (displayed to | |
153 * the user) on the canvas when the event handler that renders with | |
154 * WebGL returns back to the browser event loop." | |
155 * https://emscripten.org/docs/api_reference/html5.h.html#webgl-context | |
156 * | |
157 * Could call "emscripten_webgl_commit_frame()" if | |
158 * "explicitSwapControl" option were set to "true". | |
159 **/ | |
160 } | |
161 }; | |
162 | |
163 | |
164 WebAssemblyOpenGLContext::WebAssemblyOpenGLContext(const std::string& canvasSelector) : | |
165 pimpl_(new PImpl(canvasSelector)) | |
166 { | |
167 } | |
168 | |
169 bool WebAssemblyOpenGLContext::IsContextLost() | |
170 { | |
171 return pimpl_->IsContextLost(); | |
172 } | |
173 | |
174 void WebAssemblyOpenGLContext::SetLostContext() | |
175 { | |
176 pimpl_->SetLostContext(); | |
177 } | |
178 | |
179 void* WebAssemblyOpenGLContext::DebugGetInternalContext() const | |
180 { | |
181 return pimpl_->DebugGetInternalContext(); | |
182 } | |
183 | |
184 void WebAssemblyOpenGLContext::MakeCurrent() | |
185 { | |
186 assert(pimpl_.get() != NULL); | |
187 pimpl_->MakeCurrent(); | |
188 } | |
189 | |
190 void WebAssemblyOpenGLContext::SwapBuffer() | |
191 { | |
192 assert(pimpl_.get() != NULL); | |
193 pimpl_->SwapBuffer(); | |
194 } | |
195 | |
196 const std::string& WebAssemblyOpenGLContext::GetCanvasSelector() const | |
197 { | |
198 assert(pimpl_.get() != NULL); | |
199 return pimpl_->GetCanvasSelector(); | |
200 } | |
201 } | |
202 } |