OpenWalnut 1.3.1
WGraphicsEngine.cpp
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 }