Mercurial > hg > orthanc-stone
comparison Applications/Platforms/WebAssembly/WebAssemblyOpenGLContext.cpp @ 1591:5887a4f8594b
moving platform-specific files out of the "OrthancStone" folder
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 23 Oct 2020 13:15:03 +0200 |
parents | OrthancStone/Sources/OpenGL/WebAssemblyOpenGLContext.cpp@1f812f4c95be |
children | 4fb8fdf03314 |
comparison
equal
deleted
inserted
replaced
1590:7b963bccafef | 1591:5887a4f8594b |
---|---|
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-2020 Osimis S.A., Belgium | |
6 * | |
7 * This program is free software: you can redistribute it and/or | |
8 * modify it under the terms of the GNU Affero General Public License | |
9 * as published by the Free Software Foundation, either version 3 of | |
10 * the License, or (at your option) any later version. | |
11 * | |
12 * This program is distributed in the hope that it will be useful, but | |
13 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Affero General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Affero General Public License | |
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 **/ | |
20 | |
21 | |
22 #include "WebAssemblyOpenGLContext.h" | |
23 | |
24 #include "../../../OrthancStone/Sources/StoneException.h" | |
25 | |
26 #include <OrthancException.h> | |
27 | |
28 #include <emscripten/html5.h> | |
29 #include <emscripten/em_asm.h> | |
30 | |
31 #include <boost/math/special_functions/round.hpp> | |
32 | |
33 namespace OrthancStone | |
34 { | |
35 namespace OpenGL | |
36 { | |
37 class WebAssemblyOpenGLContext::PImpl | |
38 { | |
39 private: | |
40 std::string canvasSelector_; | |
41 EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context_; | |
42 bool isContextLost_; | |
43 | |
44 public: | |
45 explicit PImpl(const std::string& canvasSelector) : | |
46 canvasSelector_(canvasSelector), | |
47 isContextLost_(false) | |
48 { | |
49 // Context configuration | |
50 EmscriptenWebGLContextAttributes attr; | |
51 emscripten_webgl_init_context_attributes(&attr); | |
52 | |
53 // The next line might be necessary to print using | |
54 // WebGL. Sometimes, if set to "false" (the default value), | |
55 // the canvas was rendered as a fully white or black | |
56 // area. UNCONFIRMED. | |
57 attr.preserveDrawingBuffer = true; | |
58 | |
59 context_ = emscripten_webgl_create_context(canvasSelector.c_str(), &attr); | |
60 if (context_ == 0) | |
61 { | |
62 std::string message("Cannot create an OpenGL context for the element with the following CSS selector: \""); | |
63 message += canvasSelector; | |
64 message += "\" Please make sure the -s DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR=1 flag has been passed to Emscripten when building."; | |
65 LOG(ERROR) << message; | |
66 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, message); | |
67 } | |
68 } | |
69 | |
70 void* DebugGetInternalContext() const | |
71 { | |
72 return reinterpret_cast<void*>(context_); | |
73 } | |
74 | |
75 bool IsContextLost() | |
76 { | |
77 //LOG(TRACE) << "IsContextLost() for context " << std::hex << context_ << std::dec; | |
78 bool apiFlag = (emscripten_is_webgl_context_lost(context_) != 0); | |
79 isContextLost_ = apiFlag; | |
80 return isContextLost_; | |
81 } | |
82 | |
83 void SetLostContext() | |
84 { | |
85 isContextLost_ = true; | |
86 } | |
87 | |
88 ~PImpl() | |
89 { | |
90 try | |
91 { | |
92 EMSCRIPTEN_RESULT result = emscripten_webgl_destroy_context(context_); | |
93 if (result != EMSCRIPTEN_RESULT_SUCCESS) | |
94 { | |
95 LOG(ERROR) << "emscripten_webgl_destroy_context returned code " << result; | |
96 } | |
97 } | |
98 catch (const Orthanc::OrthancException& e) | |
99 { | |
100 if (e.HasDetails()) | |
101 { | |
102 LOG(ERROR) << "OrthancException in WebAssemblyOpenGLContext::~PImpl: " << e.What() << " Details: " << e.GetDetails(); | |
103 } | |
104 else | |
105 { | |
106 LOG(ERROR) << "OrthancException in WebAssemblyOpenGLContext::~PImpl: " << e.What(); | |
107 } | |
108 } | |
109 catch (const std::exception& e) | |
110 { | |
111 LOG(ERROR) << "std::exception in WebAssemblyOpenGLContext::~PImpl: " << e.what(); | |
112 } | |
113 catch (...) | |
114 { | |
115 LOG(ERROR) << "Unknown exception in WebAssemblyOpenGLContext::~PImpl"; | |
116 } | |
117 } | |
118 | |
119 const std::string& GetCanvasSelector() const | |
120 { | |
121 return canvasSelector_; | |
122 } | |
123 | |
124 void MakeCurrent() | |
125 { | |
126 if (IsContextLost()) | |
127 { | |
128 LOG(ERROR) << "MakeCurrent() called on lost context " << context_; | |
129 throw StoneException(ErrorCode_WebGLContextLost); | |
130 } | |
131 | |
132 if (emscripten_is_webgl_context_lost(context_)) | |
133 { | |
134 LOG(ERROR) << "OpenGL context has been lost for canvas selector: " << canvasSelector_; | |
135 SetLostContext(); | |
136 throw StoneException(ErrorCode_WebGLContextLost); | |
137 } | |
138 | |
139 if (emscripten_webgl_make_context_current(context_) != EMSCRIPTEN_RESULT_SUCCESS) | |
140 { | |
141 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, | |
142 "Cannot set the OpenGL context"); | |
143 } | |
144 } | |
145 | |
146 void SwapBuffer() | |
147 { | |
148 /** | |
149 * "Rendered WebGL content is implicitly presented (displayed to | |
150 * the user) on the canvas when the event handler that renders with | |
151 * WebGL returns back to the browser event loop." | |
152 * https://emscripten.org/docs/api_reference/html5.h.html#webgl-context | |
153 * | |
154 * Could call "emscripten_webgl_commit_frame()" if | |
155 * "explicitSwapControl" option were set to "true". | |
156 **/ | |
157 } | |
158 }; | |
159 | |
160 | |
161 WebAssemblyOpenGLContext::WebAssemblyOpenGLContext(const std::string& canvasSelector) : | |
162 pimpl_(new PImpl(canvasSelector)) | |
163 { | |
164 } | |
165 | |
166 bool WebAssemblyOpenGLContext::IsContextLost() | |
167 { | |
168 return pimpl_->IsContextLost(); | |
169 } | |
170 | |
171 void WebAssemblyOpenGLContext::SetLostContext() | |
172 { | |
173 pimpl_->SetLostContext(); | |
174 } | |
175 | |
176 void* WebAssemblyOpenGLContext::DebugGetInternalContext() const | |
177 { | |
178 return pimpl_->DebugGetInternalContext(); | |
179 } | |
180 | |
181 void WebAssemblyOpenGLContext::MakeCurrent() | |
182 { | |
183 assert(pimpl_.get() != NULL); | |
184 pimpl_->MakeCurrent(); | |
185 } | |
186 | |
187 void WebAssemblyOpenGLContext::SwapBuffer() | |
188 { | |
189 assert(pimpl_.get() != NULL); | |
190 pimpl_->SwapBuffer(); | |
191 } | |
192 | |
193 const std::string& WebAssemblyOpenGLContext::GetCanvasSelector() const | |
194 { | |
195 assert(pimpl_.get() != NULL); | |
196 return pimpl_->GetCanvasSelector(); | |
197 } | |
198 } | |
199 } |