OpenWalnut  1.5.0dev
WGraphicsEngine.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <iostream>
26 #include <list>
27 #include <memory>
28 #include <stdlib.h>
29 #include <string>
30 #include <vector>
31 
32 #include <boost/thread/locks.hpp>
33 #include <osg/Vec3>
34 #include <osg/Vec4>
35 #include <osg/ref_ptr>
36 #include <osgViewer/CompositeViewer>
37 #include <osgViewer/View>
38 #include <osgViewer/Viewer>
39 
40 #include "../common/WColor.h"
41 #include "../common/WLogger.h"
42 #include "../common/WPathHelper.h"
43 #include "../common/exceptions/WNameNotUnique.h"
44 #include "WGEViewer.h"
45 #include "WGraphicsEngine.h"
46 #include "WStaticOSGSetup.h"
47 #include "exceptions/WGEInitFailed.h"
48 #include "exceptions/WGESignalSubscriptionFailed.h"
49 #include "postprocessing/WGEPostprocessor.h"
50 
51 // graphics engine instance as singleton
52 std::shared_ptr< WGraphicsEngine > WGraphicsEngine::m_instance = std::shared_ptr< WGraphicsEngine >();
53 
56 {
57  WLogger::getLogger()->addLogMessage( "Initializing Graphics Engine", "GE", LL_INFO );
58 
59  // initialize OSG render window
60  m_viewer = osg::ref_ptr<osgViewer::CompositeViewer>( new osgViewer::CompositeViewer() );
61  m_viewer->setThreadingModel( osgViewer::ViewerBase::SingleThreaded );
62  m_viewer->setRunMaxFrameRate( 60.0 );
63 
64  // initialize members
65  m_rootNode = new WGEScene();
66 
67  m_viewersUpdate = false;
68 
69  setThreadName( "WGE" );
70 }
71 
73 {
74  // cleanup
75  WLogger::getLogger()->addLogMessage( "Shutting down Graphics Engine", "GE", LL_INFO );
76 }
77 
79 {
80  if( enable )
81  {
82  WLogger::getLogger()->addLogMessage( "WGraphicsEngine::setMultiThreadedViews not implemented for single threaded mode", "GE", LL_INFO );
83  }
84 }
85 
87 {
88  // on mac, this always is false currently
89  return false;
90 }
91 
92 std::shared_ptr< WGraphicsEngine > WGraphicsEngine::getGraphicsEngine()
93 {
94  if( !m_instance )
95  {
96  m_instance = std::shared_ptr< WGraphicsEngine >( new WGraphicsEngine() );
97  }
98 
99  return m_instance;
100 }
101 
102 osg::ref_ptr<WGEScene> WGraphicsEngine::getScene()
103 {
104  return m_rootNode;
105 }
106 
107 std::shared_ptr<WGEViewer> WGraphicsEngine::createViewer( std::string name, osg::ref_ptr<osg::Referenced> wdata, int x, int y,
108  int width, int height, WGECamera::ProjectionMode projectionMode,
109  WColor bgColor )
110 {
111  std::shared_ptr<WGEViewer> viewer = std::shared_ptr<WGEViewer>(
112  new WGEViewer( name, wdata, x, y, width, height, projectionMode ) );
113  viewer->setBgColor( bgColor );
114  viewer->setScene( getScene() );
115 
116  // store it in viewer list
117  std::unique_lock< std::shared_mutex > lock( m_viewersLock );
118  bool insertSucceeded = m_viewers.insert( make_pair( name, viewer ) ).second;
119  if( !insertSucceeded ) // if false, viewer with same name already exists
120  {
121  throw WNameNotUnique( "Viewer names need to be unique." );
122  }
123 
124  m_viewer->addView( viewer->getView() );
125  lock.unlock();
126 
127  return viewer;
128 }
129 
130 void WGraphicsEngine::closeViewer( std::shared_ptr< WGEViewer > viewer )
131 {
132  std::unique_lock< std::shared_mutex > lock( m_viewersLock );
133 
134  // close and erase
135  viewer->close();
136  if( m_viewers.count( viewer->getName() ) > 0 )
137  {
138  m_viewers.erase( viewer->getName() );
139  }
140 
141  m_viewer->removeView( viewer->getView() );
142 
143  lock.unlock();
144 }
145 
146 void WGraphicsEngine::closeViewer( const std::string name )
147 {
148  std::unique_lock< std::shared_mutex > lock( m_viewersLock );
149  if( m_viewers.count( name ) > 0 )
150  {
151  m_viewers[name]->close();
152  m_viewers.erase( name );
153 
154  m_viewer->removeView( m_viewers[name]->getView() );
155  lock.unlock();
156  }
157  else
158  {
159  lock.unlock();
160  }
161 }
162 
163 std::shared_ptr< WGEViewer > WGraphicsEngine::getViewerByName( std::string name )
164 {
165  boost::shared_lock< std::shared_mutex > lock( m_viewersLock );
166  std::shared_ptr< WGEViewer > out = m_viewers.count( name ) > 0 ?
167  m_viewers[name] :
168  std::shared_ptr< WGEViewer >();
169  lock.unlock();
170  return out;
171 }
172 
173 std::shared_ptr< WGEViewer > WGraphicsEngine::getViewer()
174 {
175  boost::shared_lock< std::shared_mutex > lock( m_viewersLock );
176  std::shared_ptr< WGEViewer > result = m_viewers[ "Main View" ];
177  lock.unlock();
178  return result;
179 }
180 
182 {
183  if( !m_instance )
184  {
185  return false;
186  }
187 
188  return m_instance->m_running;
189 }
190 
192 {
193  if( !m_instance )
194  {
195  WLogger::getLogger()->addLogMessage( "Not Graphics Engine running", "GE", LL_INFO );
196  return false;
197  }
198 
199  WLogger::getLogger()->addLogMessage( "Blocking for graphics engine startup", "GE", LL_INFO );
200  // this ensures that the startup is completed if returning.
201  m_instance->m_startThreadingCondition.wait();
202 
203  WLogger::getLogger()->addLogMessage( "Done blocking for graphics engine startup, maybe running now", "GE", LL_INFO );
204  // did something went wrong? Ensure by checking if really running.
205  return isRunning();
206 }
207 
209 {
210  // any new or removed views?
211  if( m_viewersUpdate )
212  {
213  std::unique_lock< std::shared_mutex > lock( m_viewersLock );
214 
215  // add all views
216  for( std::vector< WGEViewer::SPtr >::iterator it = m_addViewers.begin(); it != m_addViewers.end(); ++it )
217  {
218  m_viewer->addView( ( *it )->getView() );
219  }
220  m_addViewers.clear();
221  for( std::vector< WGEViewer::SPtr >::iterator it = m_removeViewers.begin(); it != m_removeViewers.end(); ++it )
222  {
223  m_viewer->removeView( ( *it )->getView() );
224  }
225  m_removeViewers.clear();
226  m_viewersUpdate = false;
227 
228  // notify all of them
229  for( std::vector< WCondition::SPtr >::iterator it = m_viewerUpdateNotifiers.begin(); it != m_viewerUpdateNotifiers.end(); ++it )
230  {
231  ( *it )->notify();
232  }
233  m_viewerUpdateNotifiers.clear();
234  lock.unlock();
235  }
236 }
237 
239 {
240  WLogger::getLogger()->addLogMessage( "Starting Graphics Engine", "GE", LL_INFO );
241 
242  // initialize all available postprocessors
244 
245  m_running = true; // we have to make sure, that we are "running"
246 }
247 
249 {
250  // when stopping the system while the GE is still waiting.
252  WLogger::getLogger()->addLogMessage( "Stopping Graphics Engine", "GE", LL_INFO );
253 }
254 
256 {
258 }
259 
261 {
263 }
264 
266 {
268 }
269 
270 boost::signals2::connection WGraphicsEngine::subscribeSignal( GE_SIGNAL signal, t_GEGenericSignalHandlerType notifier )
271 {
272  switch( signal )
273  {
274  case GE_RELOADSHADERS:
275  return m_reloadShadersSignal.connect( notifier );
276  case GE_STARTUPCOMPLETE:
277  return m_startThreadingCondition.subscribeSignal( notifier );
278  default:
279  std::ostringstream s;
280  s << "Could not subscribe to unknown signal.";
281  throw WGESignalSubscriptionFailed( s.str() );
282  break;
283  }
284 }
virtual void notify()
Notifies all waiting threads.
virtual void wait() const
Wait for the condition.
boost::signals2::connection subscribeSignal(t_ConditionNotifierType notifier) const
Subscribes a specified function to be notified on condition change.
Definition: WCondition.cpp:50
ProjectionMode
List of possible camera modes.
Definition: WGECamera.h:44
static void initPostprocessors()
Needs to be called prior to any "getPostprocessors" call.
Class for managing the OpenSceneGraph root node.
Definition: WGEScene.h:36
Exception thrown if a notifier could not be subscribed to a signal.
Class for managing one view to the scene.
Definition: WGEViewer.h:71
virtual boost::signals2::connection subscribeSignal(THREAD_SIGNAL signal, t_ThreadErrorSignalHandlerType notifier)
Connects a specified notify function with a signal this thread instance is offering.
static std::shared_ptr< WGraphicsEngine > getGraphicsEngine()
Returns instance of the graphics engine.
virtual void threadMain()
Handler for repainting and event handling.
std::vector< WGEViewer::SPtr > m_addViewers
List of viewers to add to m_viewer via addView.
static bool waitForStartupComplete()
Waits for the GE to come up.
std::shared_mutex m_viewersLock
Mutex used to lock the map of viewers.
virtual void notifyStop()
Gets called when the thread should be stopped.
std::shared_ptr< WGEViewer > getViewer()
Returns the unnamed view, which is the view for the default scene which can be acquired using getScen...
void waitForFinalize()
Wait until someone called finalizeStartup().
std::shared_ptr< WGEViewer > getViewerByName(std::string name)
Searches for a viewer with a given name and returns it, if found.
static std::shared_ptr< WGraphicsEngine > m_instance
Singleton instance of WGraphicsEngine.
std::shared_ptr< WGEViewer > createViewer(std::string name, osg::ref_ptr< osg::Referenced > wdata, int x, int y, int width, int height, WGECamera::ProjectionMode projectionMode=WGECamera::ORTHOGRAPHIC, WColor bgColor=WColor(1.0, 1.0, 1.0, 1.0))
Creates a new viewer.
bool m_viewersUpdate
If true, the view thread checks for updates in the m_viewers list.
ViewerMap m_viewers
All registered viewers.
std::vector< WGEViewer::SPtr > m_removeViewers
List of viewers to remove from m_viewer via addView.
osg::ref_ptr< WGEScene > getScene()
Returns the root node of the WGraphicsEngine (this is not the root node of the OSG).
osg::ref_ptr< WGEScene > m_rootNode
OpenSceneGraph root node.
bool isMultiThreadedViews() const
Checks whether the viewers work multithreaded.
std::vector< WCondition::SPtr > m_viewerUpdateNotifiers
A list of conditions to notify when the GE thread processed the m_addViewers and m_removeViewers list...
void closeViewer(const std::string name)
Closes a viewer and deletes it from the list of viewers.
t_GEGenericSignalType m_reloadShadersSignal
Signal getting emitted whenever a reload shader request is waiting.
osg::ref_ptr< osgViewer::CompositeViewer > m_viewer
OpenSceneGraph composite viewer.
virtual ~WGraphicsEngine()
Destructor.
static bool isRunning()
Checks whether the graphics engine is currently running or not.
void finalizeStartup()
Function notifies the viewer threads (if any) to start.
WGraphicsEngine()
Constructors are protected because this is a Singleton.
void setMultiThreadedViews(bool enable=true)
Enables multithreaded view.
void applyViewerListUpdates()
Apply updates in m_addViewers and m_removeViewers.
void requestShaderReload()
This requests all shaders to reload during the next update cycle.
bool m_running
True if graphics engine is running.
WConditionOneShot m_startThreadingCondition
This condition is fired externally if all the GUI startup is done to ensure all OGL stuff is initiali...
void addLogMessage(std::string message, std::string source="", LogLevel level=LL_DEBUG)
Appends a log message to the logging queue.
Definition: WLogger.cpp:84
static WLogger * getLogger()
Returns pointer to the currently running logger instance.
Definition: WLogger.cpp:64
Indicates that a given name is not unique in a group of names.
Base class for all classes needing to be executed in a separate thread.
void setThreadName(std::string name)
Set the name of the thread.