LCOV - code coverage report
Current view: top level - eq/fabric - canvas.ipp (source / functions) Hit Total Coverage
Test: lcov2.info Lines: 188 254 74.0 %
Date: 2014-06-18 Functions: 38 68 55.9 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2010-2013, Stefan Eilemann <eile@eyescale.ch>
       3             :  *                    2012, Daniel Nachbaur <danielnachbaur@gmail.com>
       4             :  *
       5             :  * This library is free software; you can redistribute it and/or modify it under
       6             :  * the terms of the GNU Lesser General Public License version 2.1 as published
       7             :  * by the Free Software Foundation.
       8             :  *
       9             :  * This library is distributed in the hope that it will be useful, but WITHOUT
      10             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      11             :  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
      12             :  * details.
      13             :  *
      14             :  * You should have received a copy of the GNU Lesser General Public License
      15             :  * along with this library; if not, write to the Free Software Foundation, Inc.,
      16             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      17             :  */
      18             : 
      19             : #include "canvas.h"
      20             : 
      21             : #include "commands.h"
      22             : #include "elementVisitor.h"
      23             : #include "leafVisitor.h"
      24             : #include "log.h"
      25             : #include "nameFinder.h"
      26             : #include "paths.h"
      27             : #include "segment.h"
      28             : 
      29             : #include <co/dataIStream.h>
      30             : #include <co/dataOStream.h>
      31             : #include <co/objectICommand.h>
      32             : 
      33             : namespace eq
      34             : {
      35             : namespace fabric
      36             : {
      37             : 
      38             : template< class CFG, class C, class S, class L >
      39         233 : Canvas< CFG, C, S, L >::Canvas( CFG* config )
      40         233 :         : _config( config )
      41             : {
      42         233 :     LBASSERT( config );
      43         233 :     setWall( Wall( )); // default frustum
      44         233 :     config->_addCanvas( static_cast< C* >( this ));
      45         233 :     LBLOG( LOG_INIT ) << "New " << lunchbox::className( this ) << std::endl;
      46         233 : }
      47             : 
      48             : template< class CFG, class C, class S, class L >
      49         232 : Canvas< CFG, C, S, L >::~Canvas()
      50             : {
      51         232 :     LBLOG( LOG_INIT ) << "Delete " << lunchbox::className( this ) << std::endl;
      52         838 :     while( !_segments.empty( ))
      53             :     {
      54         374 :         S* segment = _segments.back();
      55         374 :         _removeChild( segment );
      56         374 :         release( segment );
      57             :     }
      58             : 
      59         232 :     _data.activeLayout = 0;
      60         232 :     _layouts.clear();
      61         232 :     _config->_removeCanvas( static_cast< C* >( this ));
      62         464 : }
      63             : 
      64             : template< class CFG, class C, class S, class L >
      65          10 : void Canvas< CFG, C, S, L >::backup()
      66             : {
      67          10 :     _backup = _data;
      68          10 :     Object::backup();
      69          10 :     Frustum::backup();
      70          10 : }
      71             : 
      72             : template< class CFG, class C, class S, class L >
      73           2 : void Canvas< CFG, C, S, L >::restore()
      74             : {
      75           2 :     Frustum::restore();
      76           2 :     Object::restore();
      77           2 :     activateLayout( _backup.activeLayout );
      78           2 :     _data = _backup;
      79           2 :     setDirty( DIRTY_LAYOUT );
      80           2 : }
      81             : 
      82             : template< class CFG, class C, class S, class L >
      83          20 : void Canvas< CFG, C, S, L >::attach( const uint128_t& id,
      84             :                                      const uint32_t instanceID )
      85             : {
      86          20 :     Object::attach( id, instanceID );
      87             : 
      88          20 :     co::CommandQueue* queue = _config->getMainThreadQueue();
      89          20 :     LBASSERT( queue );
      90             : 
      91          20 :     registerCommand( CMD_CANVAS_NEW_SEGMENT,
      92             :                      CmdFunc( this, &Canvas< CFG, C, S, L >::_cmdNewSegment ),
      93             :                      queue );
      94          20 :     registerCommand( CMD_CANVAS_NEW_SEGMENT_REPLY,
      95             :                   CmdFunc( this, &Canvas< CFG, C, S, L >::_cmdNewSegmentReply ),
      96             :                      0 );
      97          20 : }
      98             : 
      99             : template< class CFG, class C, class S, class L >
     100        9219 : uint128_t Canvas< CFG, C, S, L >::commit( const uint32_t incarnation )
     101             : {
     102        9219 :     if( Serializable::isDirty( DIRTY_SEGMENTS ))
     103          19 :         commitChildren< S >( _segments, CMD_CANVAS_NEW_SEGMENT, incarnation );
     104        9219 :     return Object::commit( incarnation );
     105             : }
     106             : 
     107             : template< class CFG, class C, class S, class L >
     108          38 : void Canvas< CFG, C, S, L >::serialize( co::DataOStream& os,
     109             :                                         const uint64_t dirtyBits )
     110             : {
     111          38 :     Object::serialize( os, dirtyBits );
     112             : 
     113          38 :     if( dirtyBits & DIRTY_LAYOUT )
     114          21 :         os << _data.activeLayout;
     115          38 :     if( dirtyBits & DIRTY_SEGMENTS && isMaster( ))
     116          30 :         os.serializeChildren( _segments );
     117          38 :     if( dirtyBits & DIRTY_LAYOUTS )
     118          21 :         os.serializeChildren( _layouts );
     119          38 :     if( dirtyBits & DIRTY_FRUSTUM )
     120          37 :         Frustum::serialize( os );
     121          38 : }
     122             : 
     123             : template< class CFG, class C, class S, class L >
     124          27 : void Canvas< CFG, C, S, L >::deserialize( co::DataIStream& is,
     125             :                                           const uint64_t dirtyBits )
     126             : {
     127          27 :     Object::deserialize( is, dirtyBits );
     128             : 
     129          27 :     if( dirtyBits & DIRTY_LAYOUT )
     130             :     {
     131             :         uint32_t index;
     132          10 :         is >> index;
     133          10 :         activateLayout( index );
     134             :     }
     135             : 
     136          27 :     if( dirtyBits & DIRTY_SEGMENTS )
     137             :     {
     138          27 :         if( isMaster( ))
     139           8 :             syncChildren( _segments );
     140             :         else
     141             :         {
     142          19 :             Segments result;
     143          19 :             is.deserializeChildren( this, _segments, result );
     144          19 :             _segments.swap( result );
     145          19 :             LBASSERT( _segments.size() == result.size( ));
     146             :         }
     147             :     }
     148             : 
     149          27 :     if( dirtyBits & DIRTY_LAYOUTS )
     150             :     {
     151          10 :         _layouts.clear();
     152          10 :         co::ObjectVersions layouts;
     153          10 :         is >> layouts;
     154         219 :         for( co::ObjectVersions::const_iterator i = layouts.begin();
     155         146 :              i != layouts.end(); ++i )
     156             :         {
     157          63 :             const uint128_t& id = (*i).identifier;
     158             : 
     159          63 :             if( id == 0 )
     160           0 :                 _layouts.push_back( 0 );
     161             :             else
     162             :             {
     163          63 :                 L* layout = 0;
     164          63 :                 _config->find( id, &layout );
     165          63 :                 LBASSERT( layout );
     166          63 :                 _layouts.push_back( layout );
     167             :             }
     168             :         }
     169             : 
     170          10 :         _config->updateCanvas( static_cast< C* >( this ));
     171             :     }
     172          27 :     if( dirtyBits & DIRTY_FRUSTUM )
     173          26 :         Frustum::deserialize( is );
     174          27 : }
     175             : 
     176             : template< class CFG, class C, class S, class L >
     177        2397 : void Canvas< CFG, C, S, L >::setDirty( const uint64_t dirtyBits )
     178             : {
     179        2397 :     Object::setDirty( dirtyBits );
     180        2397 :     _config->setDirty( CFG::DIRTY_CANVASES );
     181        2397 : }
     182             : 
     183             : template< class CFG, class C, class S, class L >
     184          10 : void Canvas< CFG, C, S, L >::create( S** segment )
     185             : {
     186          10 :     *segment = _config->getServer()->getNodeFactory()->createSegment(
     187             :         static_cast< C* >( this ));
     188          10 : }
     189             : 
     190             : template< class CFG, class C, class S, class L >
     191         384 : void Canvas< CFG, C, S, L >::release( S* segment )
     192             : {
     193         384 :     _config->getServer()->getNodeFactory()->releaseSegment( segment );
     194         384 : }
     195             : 
     196             : template< class CFG, class C, class S, class L >
     197          20 : void Canvas< CFG, C, S, L >::notifyDetach()
     198             : {
     199          20 :     Object::notifyDetach();
     200          20 :     releaseChildren< C, S >( _segments );
     201          20 : }
     202             : 
     203             : template< class CFG, class C, class S, class L >
     204         385 : void Canvas< CFG, C, S, L >::_addChild( S* segment )
     205             : {
     206         385 :     LBASSERT( segment );
     207         385 :     LBASSERT( segment->getCanvas() == this );
     208         385 :     _segments.push_back( segment );
     209         385 :     setDirty( DIRTY_SEGMENTS );
     210         385 : }
     211             : 
     212             : template< class CFG, class C, class S, class L >
     213         768 : bool Canvas< CFG, C, S, L >::_removeChild( S* segment )
     214             : {
     215         768 :     typename Segments::iterator i = lunchbox::find( _segments, segment );
     216         768 :     if( i == _segments.end( ))
     217         384 :         return false;
     218             : 
     219         384 :     LBASSERT( segment->getCanvas() == this );
     220         384 :     _segments.erase( i );
     221         384 :     setDirty( DIRTY_SEGMENTS );
     222         384 :     if( isAttached() && !isMaster( ))
     223          10 :         postRemove( segment );
     224         384 :     return true;
     225             : }
     226             : 
     227             : template< class CFG, class C, class S, class L >
     228          10 : bool Canvas< CFG, C, S, L >::_mapViewObjects()
     229             : {
     230          10 :     return static_cast< typename CFG::Super* >( _config )->mapViewObjects();
     231             : }
     232             : 
     233             : template< class CFG, class C, class S, class L >
     234         819 : CanvasPath Canvas< CFG, C, S, L >::getPath() const
     235             : {
     236         819 :     const CFG* config = getConfig();
     237         819 :     LBASSERT( config );
     238             : 
     239         819 :     const Canvases& canvases = config->getCanvases();
     240             :     typename Canvases::const_iterator i = std::find( canvases.begin(),
     241             :                                                      canvases.end(),
     242         819 :                                                      this );
     243         819 :     LBASSERT( i != canvases.end( ));
     244             : 
     245         819 :     CanvasPath path;
     246         819 :     path.canvasIndex = std::distance( canvases.begin(), i );
     247         819 :     return path;
     248             : }
     249             : 
     250             : template< class CFG, class C, class S, class L >
     251           0 : S* Canvas< CFG, C, S, L >::findSegment( const std::string& name )
     252             : {
     253           0 :     NameFinder< S, Visitor > finder( name );
     254           0 :     accept( finder );
     255           0 :     return finder.getResult();
     256             : }
     257             : 
     258             : template< class CFG, class C, class S, class L >
     259           0 : const S* Canvas< CFG, C, S, L >::findSegment( const std::string& name ) const
     260             : {
     261           0 :     NameFinder< const S, Visitor > finder( name );
     262           0 :     accept( finder );
     263           0 :     return finder.getResult();
     264             : }
     265             : 
     266             : template< class CFG, class C, class S, class L >
     267         386 : void Canvas< CFG, C, S, L >::addLayout( L* layout )
     268             : {
     269         386 :     LBASSERT( lunchbox::find( _layouts, layout ) == _layouts.end( ));
     270             : 
     271             :     // dest channel creation is done be Config::addCanvas
     272         386 :     _layouts.push_back( layout );
     273         386 :     setDirty( DIRTY_LAYOUTS );
     274         386 : }
     275             : 
     276             : template< class CFG, class C, class S, class L >
     277           0 : bool Canvas< CFG, C, S, L >::removeLayout( L* layout )
     278             : {
     279           0 :     typename Layouts::iterator i = lunchbox::find( _layouts, layout );
     280           0 :     if( i == _layouts.end( ))
     281           0 :         return false;
     282             : 
     283           0 :     if( getActiveLayout() == layout )
     284             :     {
     285           0 :         _data.activeLayout = 0;
     286           0 :         setDirty( DIRTY_LAYOUT );
     287             :     }
     288             : 
     289           0 :     _layouts.erase( i );
     290           0 :     setDirty( DIRTY_LAYOUTS );
     291           0 :     return true;
     292             : }
     293             : 
     294             : template< class CFG, class C, class S, class L >
     295          39 : const L* Canvas< CFG, C, S, L >::getActiveLayout() const
     296             : {
     297          39 :     LBASSERTINFO( _data.activeLayout < _layouts.size(),
     298             :                   _data.activeLayout << " >= " << _layouts.size( ));
     299          39 :     return _layouts[ _data.activeLayout ];
     300             : }
     301             : 
     302             : template< class CFG, class C, class S, class L >
     303           0 : bool Canvas< CFG, C, S, L >::useLayout( const uint32_t index )
     304             : {
     305           0 :     LBASSERT( index < _layouts.size( ));
     306           0 :     if( _data.activeLayout == index )
     307           0 :         return false;
     308             : 
     309           0 :     _data.activeLayout = index;
     310           0 :     setDirty( DIRTY_LAYOUT );
     311           0 :     return true;
     312             : }
     313             : 
     314             : template< class CFG, class C, class S, class L >
     315           2 : void Canvas< CFG, C, S, L >::setSwapBarrier( SwapBarrierPtr barrier )
     316             : {
     317           2 :     if( barrier.isValid() && barrier->getName().empty( ))
     318             :     {
     319           1 :         const std::string& name = getName();
     320           1 :         std::stringstream out;
     321           1 :         out << "barrier.canvas.";
     322           1 :         if( name.empty( ))
     323           1 :             if( getConfig( ))
     324           1 :                 out << getPath().canvasIndex;
     325             :             else
     326           0 :                 out << (void*)this;
     327             :         else
     328           0 :             out << name;
     329             : 
     330           1 :         barrier->setName( out.str( ));
     331             :     }
     332             : 
     333           2 :     _swapBarrier = barrier;
     334           2 : }
     335             : 
     336             : namespace
     337             : {
     338             : template< class C, class V >
     339        1783 : VisitorResult _accept( C* canvas, V& visitor )
     340             : {
     341        1783 :     VisitorResult result = visitor.visitPre( canvas );
     342        1783 :     if( result != TRAVERSE_CONTINUE )
     343          16 :         return result;
     344             : 
     345        1767 :     const typename C::Segments& segments = canvas->getSegments();
     346       16881 :     for( typename C::Segments::const_iterator i = segments.begin();
     347       11254 :          i != segments.end(); ++i )
     348             :     {
     349        3860 :         switch( (*i)->accept( visitor ))
     350             :         {
     351             :             case TRAVERSE_TERMINATE:
     352           0 :                 return TRAVERSE_TERMINATE;
     353             : 
     354             :             case TRAVERSE_PRUNE:
     355           0 :                 result = TRAVERSE_PRUNE;
     356           0 :                 break;
     357             : 
     358             :             case TRAVERSE_CONTINUE:
     359             :             default:
     360        3860 :                 break;
     361             :         }
     362             :     }
     363             : 
     364        1767 :     switch( visitor.visitPost( canvas ))
     365             :     {
     366             :         case TRAVERSE_TERMINATE:
     367           0 :             return TRAVERSE_TERMINATE;
     368             : 
     369             :         case TRAVERSE_PRUNE:
     370           0 :             return TRAVERSE_PRUNE;
     371             : 
     372             :         case TRAVERSE_CONTINUE:
     373             :         default:
     374        1767 :             break;
     375             :     }
     376             : 
     377        1767 :     return result;
     378             : }
     379             : }
     380             : 
     381             : template< class CFG, class C, class S, class L >
     382        1783 : VisitorResult Canvas< CFG, C, S, L >::accept( Visitor& visitor )
     383             : {
     384        1783 :     return _accept( static_cast< C* >( this ), visitor );
     385             : }
     386             : 
     387             : template< class CFG, class C, class S, class L >
     388           0 : VisitorResult Canvas< CFG, C, S, L >::accept( Visitor& visitor ) const
     389             : {
     390           0 :     return _accept( static_cast< const C* >( this ), visitor );
     391             : }
     392             : 
     393             : template< class CFG, class C, class S, class L >
     394         444 : void Canvas< CFG, C, S, L >::setWall( const Wall& wall )
     395             : {
     396         444 :     if( getWall() == wall && getCurrentType() == TYPE_WALL )
     397         597 :         return;
     398             : 
     399         291 :     Frustum::setWall( wall );
     400         291 :     setDirty( DIRTY_FRUSTUM );
     401         873 :     for( typename Segments::const_iterator i = _segments.begin();
     402         582 :          i != _segments.end(); ++i )
     403             :     {
     404           0 :         (*i)->inheritFrustum();
     405             :     }
     406             : }
     407             : 
     408             : template< class CFG, class C, class S, class L >
     409           0 : void Canvas< CFG, C, S, L >::setProjection( const Projection& projection )
     410             : {
     411           0 :     if( getProjection() == projection && getCurrentType() == TYPE_PROJECTION )
     412           0 :         return;
     413             : 
     414           0 :     Frustum::setProjection( projection );
     415           0 :     setDirty( DIRTY_FRUSTUM );
     416           0 :     for( typename Segments::const_iterator i = _segments.begin();
     417           0 :          i != _segments.end(); ++i )
     418             :     {
     419           0 :         (*i)->inheritFrustum();
     420             :     }
     421             : }
     422             : 
     423             : template< class CFG, class C, class S, class L >
     424           0 : void Canvas< CFG, C, S, L >::unsetFrustum()
     425             : {
     426           0 :     if( getCurrentType() == TYPE_NONE )
     427           0 :         return;
     428             : 
     429           0 :     Frustum::unsetFrustum();
     430           0 :     setDirty( DIRTY_FRUSTUM );
     431             : }
     432             : 
     433             : //----------------------------------------------------------------------
     434             : // ICommand handlers
     435             : //----------------------------------------------------------------------
     436             : template< class CFG, class C, class S, class L > bool
     437           0 : Canvas< CFG, C, S, L >::_cmdNewSegment( co::ICommand& cmd )
     438             : {
     439           0 :     co::ObjectICommand command( cmd );
     440             : 
     441           0 :     S* segment = 0;
     442           0 :     create( &segment );
     443           0 :     LBASSERT( segment );
     444             : 
     445           0 :     getLocalNode()->registerObject( segment );
     446           0 :     segment->setAutoObsolete( _config->getLatency() + 1 );
     447           0 :     LBASSERT( segment->isAttached() );
     448             : 
     449           0 :     send( command.getRemoteNode(), CMD_CANVAS_NEW_SEGMENT_REPLY )
     450           0 :             << command.read< uint32_t >() << segment->getID();
     451             : 
     452           0 :     return true;
     453             : }
     454             : 
     455             : template< class CFG, class C, class S, class L > bool
     456           0 : Canvas< CFG, C, S, L >::_cmdNewSegmentReply( co::ICommand& cmd )
     457             : {
     458           0 :     co::ObjectICommand command( cmd );
     459             : 
     460           0 :     const uint32_t requestID = command.read< uint32_t >();
     461           0 :     const uint128_t& result = command.read< uint128_t >();
     462             : 
     463           0 :     getLocalNode()->serveRequest( requestID, result );
     464             : 
     465           0 :     return true;
     466             : }
     467             : 
     468             : template< class CFG, class C, class S, class L >
     469         124 : std::ostream& operator << ( std::ostream& os,
     470             :                             const Canvas< CFG, C, S, L >& canvas )
     471             : {
     472         124 :     os << lunchbox::disableFlush << lunchbox::disableHeader << "canvas"
     473             :        << std::endl;
     474         124 :     os << "{" << std::endl << lunchbox::indent;
     475             : 
     476         124 :     const std::string& name = canvas.getName();
     477         124 :     if( !name.empty( ))
     478           3 :         os << "name     \"" << name << "\"" << std::endl;
     479             : 
     480         124 :     const std::vector< L* >& layouts = canvas.getLayouts();
     481        1227 :     for( typename std::vector< L* >::const_iterator i = layouts.begin();
     482         818 :          i != layouts.end(); ++i )
     483             :     {
     484         285 :         L* layout = *i;
     485         285 :         if( layout )
     486             :         {
     487         284 :             const CFG* config = layout->getConfig();
     488         284 :             const std::string& layoutName = layout->getName();
     489         284 :             const L* foundLayout = 0;
     490         284 :             config->find( layoutName, &foundLayout );
     491         284 :             if( foundLayout == layout )
     492         283 :                 os << "layout   \"" << layoutName << "\"" << std::endl;
     493             :             else
     494           1 :                 os << layout->getPath() << std::endl;
     495             :         }
     496             :         else
     497           1 :             os << "layout   OFF" << std::endl;
     498             :     }
     499             : 
     500         124 :     if( canvas.getSwapBarrier().isValid( ))
     501           1 :         os << *canvas.getSwapBarrier();
     502         124 :     os << static_cast< const Frustum& >( canvas );
     503             : 
     504         124 :     const std::vector< S* >& segments = canvas.getSegments();
     505         972 :     for( typename std::vector< S* >::const_iterator i = segments.begin();
     506         648 :          i != segments.end(); ++i )
     507             :     {
     508         200 :         os << **i;
     509             :     }
     510         124 :     os << lunchbox::exdent << "}" << std::endl << lunchbox::enableHeader
     511             :        << lunchbox::enableFlush;
     512         124 :     return os;
     513             : }
     514             : 
     515             : }
     516             : }

Generated by: LCOV version 1.10