comparison OrthancStone/Sources/Platforms/Sdl/SdlViewport.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 #include "SdlViewport.h"
24
25 #include "../../../OrthancStone/Sources/Scene2DViewport/ViewportController.h"
26
27 #include <OrthancException.h>
28
29 #include <boost/make_shared.hpp>
30
31 namespace OrthancStone
32 {
33 ICompositor& SdlViewport::SdlLock::GetCompositor()
34 {
35 if (that_.compositor_.get() == NULL)
36 {
37 // The derived class should have called "AcquireCompositor()"
38 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
39 }
40 else
41 {
42 return *that_.compositor_;
43 }
44 }
45
46
47 void SdlViewport::AcquireCompositor(ICompositor* compositor /* takes ownership */)
48 {
49 if (compositor == NULL)
50 {
51 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
52 }
53
54 compositor_.reset(compositor);
55 }
56
57
58 SdlViewport::SdlViewport()
59 {
60 refreshEvent_ = SDL_RegisterEvents(1);
61
62 if (refreshEvent_ == static_cast<uint32_t>(-1))
63 {
64 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
65 }
66 }
67
68 void SdlViewport::PostConstructor()
69 {
70 controller_ = boost::make_shared<ViewportController>(shared_from_this());
71 }
72
73 void SdlViewport::SendRefreshEvent()
74 {
75 SDL_Event event;
76 SDL_memset(&event, 0, sizeof(event));
77 event.type = refreshEvent_;
78 SDL_PushEvent(&event); // This function is thread-safe, and can be called from other threads safely.
79 }
80
81
82 void SdlViewport::UpdateSize(unsigned int width, unsigned int height)
83 {
84 SdlLock lock(*this);
85 lock.GetCompositor().SetCanvasSize(width, height);
86 lock.Invalidate();
87 }
88
89
90 #if ORTHANC_ENABLE_OPENGL == 1
91 SdlOpenGLViewport::SdlOpenGLViewport(const std::string& title,
92 unsigned int width,
93 unsigned int height,
94 bool allowDpiScaling) :
95 context_(title.c_str(), width, height, allowDpiScaling)
96 {
97 AcquireCompositor(new OpenGLCompositor(context_)); // (*)
98 }
99 #endif
100
101
102 #if ORTHANC_ENABLE_OPENGL == 1
103 void SdlOpenGLViewport::RefreshCanvasSize()
104 {
105 UpdateSize(context_.GetCanvasWidth(), context_.GetCanvasHeight());
106 }
107 #endif
108
109
110 #if ORTHANC_ENABLE_OPENGL == 1
111 boost::shared_ptr<SdlOpenGLViewport> SdlOpenGLViewport::Create(const std::string& title,
112 unsigned int width,
113 unsigned int height,
114 bool allowDpiScaling)
115 {
116 boost::shared_ptr<SdlOpenGLViewport> that =
117 boost::shared_ptr<SdlOpenGLViewport>(new SdlOpenGLViewport(title, width, height, allowDpiScaling));
118 that->SdlViewport::PostConstructor();
119 return that;
120 }
121 #endif
122
123
124 #if ORTHANC_ENABLE_OPENGL == 1
125 uint32_t SdlOpenGLViewport::GetSdlWindowId()
126 {
127 const SdlWindow& sdlWindowWrapper = context_.GetWindow();
128 SDL_Window* sdlWindow = sdlWindowWrapper.GetObject();
129 Uint32 sdlWindowId = SDL_GetWindowID(sdlWindow);
130 return sdlWindowId;
131 }
132 #endif
133
134
135 #if ORTHANC_ENABLE_OPENGL == 1
136 SdlOpenGLViewport::~SdlOpenGLViewport()
137 {
138 // Make sure that the "OpenGLCompositor" is destroyed BEFORE the
139 // "OpenGLContext" it references (*)
140 ClearCompositor();
141 }
142 #endif
143
144
145 #if ORTHANC_ENABLE_OPENGL == 1
146 void SdlOpenGLViewport::Paint()
147 {
148 SdlLock lock(*this);
149 lock.GetCompositor().Refresh(lock.GetController().GetScene());
150 }
151 #endif
152
153
154 #if ORTHANC_ENABLE_OPENGL == 1
155 void SdlOpenGLViewport::ToggleMaximize()
156 {
157 // No need to call "Invalidate()" here, as "UpdateSize()" will
158 // be invoked after event "SDL_WINDOWEVENT_SIZE_CHANGED"
159 SdlLock lock(*this);
160 context_.ToggleMaximize();
161 }
162 #endif
163
164
165 void SdlCairoViewport::RefreshCanvasSize()
166 {
167 UpdateSize(window_.GetWidth(), window_.GetHeight());
168 }
169
170 SdlCairoViewport::SdlCairoViewport(const std::string& title,
171 unsigned int width,
172 unsigned int height,
173 bool allowDpiScaling) :
174 window_(title, width, height, false /* enable OpenGL */, allowDpiScaling),
175 sdlSurface_(NULL)
176 {
177 AcquireCompositor(new CairoCompositor(width, height));
178 }
179
180 SdlCairoViewport::~SdlCairoViewport()
181 {
182 if (sdlSurface_)
183 {
184 SDL_FreeSurface(sdlSurface_);
185 }
186 }
187
188 uint32_t SdlCairoViewport::GetSdlWindowId()
189 {
190 SDL_Window* sdlWindow = window_.GetObject();
191 Uint32 sdlWindowId = SDL_GetWindowID(sdlWindow);
192 return sdlWindowId;
193 }
194
195 void SdlCairoViewport::Paint()
196 {
197 SdlLock lock(*this);
198
199 lock.GetCompositor().Refresh(lock.GetController().GetScene());
200 CreateSdlSurfaceFromCompositor(dynamic_cast<CairoCompositor&>(lock.GetCompositor()));
201
202 if (sdlSurface_ != NULL)
203 {
204 window_.Render(sdlSurface_);
205 }
206 }
207
208
209 void SdlCairoViewport::ToggleMaximize()
210 {
211 // No need to call "Invalidate()" here, as "UpdateSize()" will
212 // be invoked after event "SDL_WINDOWEVENT_SIZE_CHANGED"
213 SdlLock lock(*this);
214 window_.ToggleMaximize();
215 }
216
217
218 // Assumes that the mutex is locked
219 void SdlCairoViewport::CreateSdlSurfaceFromCompositor(const CairoCompositor& compositor)
220 {
221 static const uint32_t rmask = 0x00ff0000;
222 static const uint32_t gmask = 0x0000ff00;
223 static const uint32_t bmask = 0x000000ff;
224
225 const unsigned int width = compositor.GetCanvas().GetWidth();
226 const unsigned int height = compositor.GetCanvas().GetHeight();
227
228 if (sdlSurface_ != NULL)
229 {
230 if (sdlSurface_->pixels == compositor.GetCanvas().GetBuffer() &&
231 sdlSurface_->w == static_cast<int>(width) &&
232 sdlSurface_->h == static_cast<int>(height) &&
233 sdlSurface_->pitch == static_cast<int>(compositor.GetCanvas().GetPitch()))
234 {
235 // The image from the compositor has not changed, no need to update the surface
236 return;
237 }
238 else
239 {
240 SDL_FreeSurface(sdlSurface_);
241 }
242 }
243
244 sdlSurface_ = SDL_CreateRGBSurfaceFrom((void*)(compositor.GetCanvas().GetBuffer()), width, height, 32,
245 compositor.GetCanvas().GetPitch(), rmask, gmask, bmask, 0);
246 if (!sdlSurface_)
247 {
248 LOG(ERROR) << "Cannot create a SDL surface from a Cairo surface";
249 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
250 }
251 }
252
253
254 boost::shared_ptr<SdlCairoViewport> SdlCairoViewport::Create(const std::string& title,
255 unsigned int width,
256 unsigned int height,
257 bool allowDpiScaling)
258 {
259 boost::shared_ptr<SdlCairoViewport> that =
260 boost::shared_ptr<SdlCairoViewport>(new SdlCairoViewport(title, width, height, allowDpiScaling));
261 that->SdlViewport::PostConstructor();
262 return that;
263 }
264 }