OpenWalnut 1.3.1
|
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 "../common/math/linearAlgebra/WLinearAlgebra.h" 00046 #include "WGEViewer.h" 00047 #include "exceptions/WGEInitFailed.h" 00048 #include "exceptions/WGESignalSubscriptionFailed.h" 00049 #include "WGraphicsEngineMode.h" 00050 00051 #include "WGraphicsEngine.h" 00052 00053 // graphics engine instance as singleton 00054 boost::shared_ptr< WGraphicsEngine > WGraphicsEngine::m_instance = boost::shared_ptr< WGraphicsEngine >(); 00055 00056 WGraphicsEngine::WGraphicsEngine(): 00057 WThreadedRunner() 00058 { 00059 WLogger::getLogger()->addLogMessage( "Initializing Graphics Engine", "GE", LL_INFO ); 00060 00061 #ifdef WGEMODE_MULTITHREADED 00062 // initialize OSG render window 00063 m_viewer = osg::ref_ptr<osgViewer::CompositeViewer>( new osgViewer::CompositeViewer() ); 00064 m_viewer->setThreadingModel( osgViewer::ViewerBase::SingleThreaded ); 00065 #endif 00066 00067 // initialize members 00068 m_rootNode = new WGEScene(); 00069 00070 setThreadName( "WGE" ); 00071 } 00072 00073 WGraphicsEngine::~WGraphicsEngine() 00074 { 00075 // cleanup 00076 WLogger::getLogger()->addLogMessage( "Shutting down Graphics Engine", "GE", LL_INFO ); 00077 } 00078 00079 void WGraphicsEngine::setMultiThreadedViews( bool enable ) 00080 { 00081 #ifdef WGEMODE_SINGLETHREADED 00082 if( enable ) 00083 { 00084 WLogger::getLogger()->addLogMessage( "WGraphicsEngine::setMultiThreadedViews not implemented for single threaded mode", "GE", LL_INFO ); 00085 } 00086 #else 00087 // ThreadingModel: enum with the following possibilities 00088 // 00089 // SingleThreaded 00090 // CullDrawThreadPerContext 00091 // ThreadPerContext 00092 // DrawThreadPerContext 00093 // CullThreadPerCameraDrawThreadPerContext 00094 // ThreadPerCamera 00095 // AutomaticSelection 00096 if( !enable ) 00097 { 00098 m_viewer->setThreadingModel( osgViewer::Viewer::SingleThreaded ); 00099 } 00100 else 00101 { 00102 m_viewer->setThreadingModel( osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext ); 00103 } 00104 #endif 00105 } 00106 00107 bool WGraphicsEngine::isMultiThreadedViews() const 00108 { 00109 #ifdef WGEMODE_MULTITHREADED 00110 return ( osgViewer::Viewer::SingleThreaded != m_viewer->getThreadingModel() ); 00111 #endif 00112 // on mac, this always is false currently 00113 return false; 00114 } 00115 00116 boost::shared_ptr< WGraphicsEngine > WGraphicsEngine::getGraphicsEngine() 00117 { 00118 if( !m_instance ) 00119 { 00120 m_instance = boost::shared_ptr< WGraphicsEngine >( new WGraphicsEngine() ); 00121 } 00122 00123 return m_instance; 00124 } 00125 00126 osg::ref_ptr<WGEScene> WGraphicsEngine::getScene() 00127 { 00128 return m_rootNode; 00129 } 00130 00131 boost::shared_ptr<WGEViewer> WGraphicsEngine::createViewer( std::string name, osg::ref_ptr<osg::Referenced> wdata, int x, int y, 00132 int width, int height, WGECamera::ProjectionMode projectionMode, 00133 WColor bgColor ) 00134 { 00135 boost::shared_ptr<WGEViewer> viewer = boost::shared_ptr<WGEViewer>( 00136 new WGEViewer( name, wdata, x, y, width, height, projectionMode ) ); 00137 viewer->setBgColor( bgColor ); 00138 viewer->setScene( getScene() ); 00139 00140 #ifdef WGEMODE_MULTITHREADED 00141 // finally add view 00142 m_viewer->addView( viewer->getView() ); 00143 #endif 00144 00145 // store it in viewer list 00146 boost::mutex::scoped_lock lock( m_viewersLock ); 00147 bool insertSucceeded = m_viewers.insert( make_pair( name, viewer ) ).second; 00148 assert( insertSucceeded == true ); // if false, viewer with same name already exists 00149 00150 return viewer; 00151 } 00152 00153 void WGraphicsEngine::closeViewer( const std::string name ) 00154 { 00155 boost::mutex::scoped_lock lock( m_viewersLock ); 00156 if( m_viewers.count( name ) > 0 ) 00157 { 00158 m_viewers[name]->close(); 00159 00160 m_viewers.erase( name ); 00161 } 00162 } 00163 00164 boost::shared_ptr< WGEViewer > WGraphicsEngine::getViewerByName( std::string name ) 00165 { 00166 boost::mutex::scoped_lock lock( m_viewersLock ); 00167 boost::shared_ptr< WGEViewer > out = m_viewers.count( name ) > 0 ? 00168 m_viewers[name] : 00169 boost::shared_ptr< WGEViewer >(); 00170 return out; 00171 } 00172 00173 boost::shared_ptr< WGEViewer > WGraphicsEngine::getViewer() 00174 { 00175 boost::mutex::scoped_lock lock( m_viewersLock ); 00176 return m_viewers[ "Main View" ]; 00177 } 00178 00179 bool WGraphicsEngine::isRunning() 00180 { 00181 if( !m_instance ) 00182 { 00183 return false; 00184 } 00185 00186 return m_instance->m_running; 00187 } 00188 00189 bool WGraphicsEngine::waitForStartupComplete() 00190 { 00191 if( !m_instance ) 00192 { 00193 WLogger::getLogger()->addLogMessage( "Not Graphics Engine running", "GE", LL_INFO ); 00194 return false; 00195 } 00196 00197 WLogger::getLogger()->addLogMessage( "Blocking for graphics engine startup", "GE", LL_INFO ); 00198 // this ensures that the startup is completed if returning. 00199 m_instance->m_startThreadingCondition.wait(); 00200 00201 WLogger::getLogger()->addLogMessage( "Done blocking for graphics engine startup, maybe running now", "GE", LL_INFO ); 00202 // did something went wrong? Ensure by checking if really running. 00203 return isRunning(); 00204 } 00205 00206 void WGraphicsEngine::threadMain() 00207 { 00208 WLogger::getLogger()->addLogMessage( "Starting Graphics Engine", "GE", LL_INFO ); 00209 00210 #ifdef WGEMODE_MULTITHREADED 00211 // NOTE: this is needed here since the viewer might start without any widgets being initialized properly. 00212 m_startThreadingCondition.wait(); 00213 m_running = true; 00214 m_viewer->startThreading(); 00215 m_viewer->run(); 00216 m_viewer->stopThreading(); 00217 m_running = false; 00218 #else 00219 //m_startThreadingCondition.wait(); 00220 m_running = true; // we have to make sure, that we are "running" 00221 #endif 00222 } 00223 00224 void WGraphicsEngine::notifyStop() 00225 { 00226 WLogger::getLogger()->addLogMessage( "Stopping Graphics Engine", "GE", LL_INFO ); 00227 #ifdef WGEMODE_MULTITHREADED 00228 m_viewer->setDone( true ); 00229 #endif 00230 } 00231 00232 void WGraphicsEngine::finalizeStartup() 00233 { 00234 m_startThreadingCondition.notify(); 00235 } 00236 00237 void WGraphicsEngine::requestShaderReload() 00238 { 00239 m_reloadShadersSignal(); 00240 } 00241 00242 boost::signals2::connection WGraphicsEngine::subscribeSignal( GE_SIGNAL signal, t_GEGenericSignalHandlerType notifier ) 00243 { 00244 switch( signal ) 00245 { 00246 case GE_RELOADSHADERS: 00247 return m_reloadShadersSignal.connect( notifier ); 00248 case GE_STARTUPCOMPLETE: 00249 return m_startThreadingCondition.subscribeSignal( notifier ); 00250 default: 00251 std::ostringstream s; 00252 s << "Could not subscribe to unknown signal."; 00253 throw WGESignalSubscriptionFailed( s.str() ); 00254 break; 00255 } 00256 }