OpenWalnut
1.4.0
|
00001 //--------------------------------------------------------------------------- 00002 // 00003 // Project: OpenWalnut ( http://www.openwalnut.org ) 00004 // 00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS 00006 // For more information see http://www.openwalnut.org/copying 00007 // 00008 // This file is part of OpenWalnut. 00009 // 00010 // OpenWalnut is free software: you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as published by 00012 // the Free Software Foundation, either version 3 of the License, or 00013 // (at your option) any later version. 00014 // 00015 // OpenWalnut is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 // GNU Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public License 00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>. 00022 // 00023 //--------------------------------------------------------------------------- 00024 00025 #include <stdlib.h> 00026 00027 #include <iostream> 00028 #include <list> 00029 #include <string> 00030 #include <vector> 00031 00032 #include <boost/shared_ptr.hpp> 00033 #include <boost/thread/locks.hpp> 00034 00035 #include <osg/Vec3> 00036 #include <osg/Vec4> 00037 #include <osg/ref_ptr> 00038 #include <osgViewer/CompositeViewer> 00039 #include <osgViewer/View> 00040 #include <osgViewer/Viewer> 00041 00042 #include "../common/WColor.h" 00043 #include "../common/WLogger.h" 00044 #include "../common/WPathHelper.h" 00045 #include "WGEViewer.h" 00046 #include "exceptions/WGEInitFailed.h" 00047 #include "exceptions/WGESignalSubscriptionFailed.h" 00048 #include "WGraphicsEngineMode.h" 00049 #include "postprocessing/WGEPostprocessor.h" 00050 00051 #include "WStaticOSGSetup.h" 00052 00053 #include "WGraphicsEngine.h" 00054 00055 // graphics engine instance as singleton 00056 boost::shared_ptr< WGraphicsEngine > WGraphicsEngine::m_instance = boost::shared_ptr< WGraphicsEngine >(); 00057 00058 WGraphicsEngine::WGraphicsEngine(): 00059 WThreadedRunner() 00060 { 00061 WLogger::getLogger()->addLogMessage( "Initializing Graphics Engine", "GE", LL_INFO ); 00062 00063 #ifdef WGEMODE_MULTITHREADED 00064 // initialize OSG render window 00065 m_viewer = osg::ref_ptr<osgViewer::CompositeViewer>( new osgViewer::CompositeViewer() ); 00066 m_viewer->setThreadingModel( osgViewer::ViewerBase::SingleThreaded ); 00067 #endif 00068 00069 // initialize members 00070 m_rootNode = new WGEScene(); 00071 00072 setThreadName( "WGE" ); 00073 } 00074 00075 WGraphicsEngine::~WGraphicsEngine() 00076 { 00077 // cleanup 00078 WLogger::getLogger()->addLogMessage( "Shutting down Graphics Engine", "GE", LL_INFO ); 00079 } 00080 00081 void WGraphicsEngine::setMultiThreadedViews( bool enable ) 00082 { 00083 #ifdef WGEMODE_SINGLETHREADED 00084 if( enable ) 00085 { 00086 WLogger::getLogger()->addLogMessage( "WGraphicsEngine::setMultiThreadedViews not implemented for single threaded mode", "GE", LL_INFO ); 00087 } 00088 #else 00089 // ThreadingModel: enum with the following possibilities 00090 // 00091 // SingleThreaded 00092 // CullDrawThreadPerContext 00093 // ThreadPerContext 00094 // DrawThreadPerContext 00095 // CullThreadPerCameraDrawThreadPerContext 00096 // ThreadPerCamera 00097 // AutomaticSelection 00098 if( !enable ) 00099 { 00100 m_viewer->setThreadingModel( osgViewer::Viewer::SingleThreaded ); 00101 } 00102 else 00103 { 00104 m_viewer->setThreadingModel( osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext ); 00105 } 00106 #endif 00107 } 00108 00109 bool WGraphicsEngine::isMultiThreadedViews() const 00110 { 00111 #ifdef WGEMODE_MULTITHREADED 00112 return ( osgViewer::Viewer::SingleThreaded != m_viewer->getThreadingModel() ); 00113 #endif 00114 // on mac, this always is false currently 00115 return false; 00116 } 00117 00118 boost::shared_ptr< WGraphicsEngine > WGraphicsEngine::getGraphicsEngine() 00119 { 00120 if( !m_instance ) 00121 { 00122 m_instance = boost::shared_ptr< WGraphicsEngine >( new WGraphicsEngine() ); 00123 } 00124 00125 return m_instance; 00126 } 00127 00128 osg::ref_ptr<WGEScene> WGraphicsEngine::getScene() 00129 { 00130 return m_rootNode; 00131 } 00132 00133 boost::shared_ptr<WGEViewer> WGraphicsEngine::createViewer( std::string name, osg::ref_ptr<osg::Referenced> wdata, int x, int y, 00134 int width, int height, WGECamera::ProjectionMode projectionMode, 00135 WColor bgColor ) 00136 { 00137 boost::shared_ptr<WGEViewer> viewer = boost::shared_ptr<WGEViewer>( 00138 new WGEViewer( name, wdata, x, y, width, height, projectionMode ) ); 00139 viewer->setBgColor( bgColor ); 00140 viewer->setScene( getScene() ); 00141 00142 #ifdef WGEMODE_MULTITHREADED 00143 // finally add view 00144 m_viewer->addView( viewer->getView() ); 00145 #endif 00146 00147 // store it in viewer list 00148 boost::mutex::scoped_lock lock( m_viewersLock ); 00149 bool insertSucceeded = m_viewers.insert( make_pair( name, viewer ) ).second; 00150 assert( insertSucceeded == true ); // if false, viewer with same name already exists 00151 00152 return viewer; 00153 } 00154 00155 void WGraphicsEngine::closeViewer( const std::string name ) 00156 { 00157 boost::mutex::scoped_lock lock( m_viewersLock ); 00158 if( m_viewers.count( name ) > 0 ) 00159 { 00160 m_viewers[name]->close(); 00161 00162 m_viewers.erase( name ); 00163 } 00164 } 00165 00166 boost::shared_ptr< WGEViewer > WGraphicsEngine::getViewerByName( std::string name ) 00167 { 00168 boost::mutex::scoped_lock lock( m_viewersLock ); 00169 boost::shared_ptr< WGEViewer > out = m_viewers.count( name ) > 0 ? 00170 m_viewers[name] : 00171 boost::shared_ptr< WGEViewer >(); 00172 return out; 00173 } 00174 00175 boost::shared_ptr< WGEViewer > WGraphicsEngine::getViewer() 00176 { 00177 boost::mutex::scoped_lock lock( m_viewersLock ); 00178 return m_viewers[ "Main View" ]; 00179 } 00180 00181 bool WGraphicsEngine::isRunning() 00182 { 00183 if( !m_instance ) 00184 { 00185 return false; 00186 } 00187 00188 return m_instance->m_running; 00189 } 00190 00191 bool WGraphicsEngine::waitForStartupComplete() 00192 { 00193 if( !m_instance ) 00194 { 00195 WLogger::getLogger()->addLogMessage( "Not Graphics Engine running", "GE", LL_INFO ); 00196 return false; 00197 } 00198 00199 WLogger::getLogger()->addLogMessage( "Blocking for graphics engine startup", "GE", LL_INFO ); 00200 // this ensures that the startup is completed if returning. 00201 m_instance->m_startThreadingCondition.wait(); 00202 00203 WLogger::getLogger()->addLogMessage( "Done blocking for graphics engine startup, maybe running now", "GE", LL_INFO ); 00204 // did something went wrong? Ensure by checking if really running. 00205 return isRunning(); 00206 } 00207 00208 void WGraphicsEngine::threadMain() 00209 { 00210 WLogger::getLogger()->addLogMessage( "Starting Graphics Engine", "GE", LL_INFO ); 00211 00212 // initialize all available postprocessors 00213 WGEPostprocessor::initPostprocessors(); 00214 00215 #ifdef WGEMODE_MULTITHREADED 00216 // NOTE: this is needed here since the viewer might start without any widgets being initialized properly. 00217 m_startThreadingCondition.wait(); 00218 m_running = true; 00219 m_viewer->startThreading(); 00220 m_viewer->run(); 00221 m_viewer->stopThreading(); 00222 m_running = false; 00223 #else 00224 //m_startThreadingCondition.wait(); 00225 m_running = true; // we have to make sure, that we are "running" 00226 #endif 00227 } 00228 00229 void WGraphicsEngine::notifyStop() 00230 { 00231 // when stopping the system while the GE is still waiting. 00232 m_startThreadingCondition.notify(); 00233 WLogger::getLogger()->addLogMessage( "Stopping Graphics Engine", "GE", LL_INFO ); 00234 #ifdef WGEMODE_MULTITHREADED 00235 m_viewer->setDone( true ); 00236 #endif 00237 } 00238 00239 void WGraphicsEngine::finalizeStartup() 00240 { 00241 m_startThreadingCondition.notify(); 00242 } 00243 00244 void WGraphicsEngine::waitForFinalize() 00245 { 00246 m_startThreadingCondition.wait(); 00247 } 00248 00249 void WGraphicsEngine::requestShaderReload() 00250 { 00251 m_reloadShadersSignal(); 00252 } 00253 00254 boost::signals2::connection WGraphicsEngine::subscribeSignal( GE_SIGNAL signal, t_GEGenericSignalHandlerType notifier ) 00255 { 00256 switch( signal ) 00257 { 00258 case GE_RELOADSHADERS: 00259 return m_reloadShadersSignal.connect( notifier ); 00260 case GE_STARTUPCOMPLETE: 00261 return m_startThreadingCondition.subscribeSignal( notifier ); 00262 default: 00263 std::ostringstream s; 00264 s << "Could not subscribe to unknown signal."; 00265 throw WGESignalSubscriptionFailed( s.str() ); 00266 break; 00267 } 00268 }