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 }