LCOV - code coverage report
Current view: top level - eq/fabric - pipe.ipp (source / functions) Hit Total Coverage
Test: Equalizer Lines: 164 209 78.5 %
Date: 2016-09-29 05:02:09 Functions: 32 91 35.2 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2010-2016, Stefan Eilemann <eile@equalizergraphics.com>
       3             :  *                          Daniel Nachbaur <danielnachbaur@gmail.com>
       4             :  *                          Cedric Stalder <cedric.stalder@gmail.com>
       5             :  *
       6             :  * This library is free software; you can redistribute it and/or modify it under
       7             :  * the terms of the GNU Lesser General Public License version 2.1 as published
       8             :  * by the Free Software Foundation.
       9             :  *
      10             :  * This library is distributed in the hope that it will be useful, but WITHOUT
      11             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      12             :  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
      13             :  * details.
      14             :  *
      15             :  * You should have received a copy of the GNU Lesser General Public License
      16             :  * along with this library; if not, write to the Free Software Foundation, Inc.,
      17             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      18             :  */
      19             : 
      20             : #include "pipe.h"
      21             : 
      22             : #include "commands.h"
      23             : #include "elementVisitor.h"
      24             : #include "leafVisitor.h"
      25             : #include "log.h"
      26             : #include "task.h"
      27             : 
      28             : #include <co/dataIStream.h>
      29             : #include <co/dataOStream.h>
      30             : #include <co/objectICommand.h>
      31             : 
      32             : namespace eq
      33             : {
      34             : namespace fabric
      35             : {
      36             : namespace
      37             : {
      38             : 
      39             : #define MAKE_PIPE_ATTR_STRING( attr ) ( std::string("EQ_PIPE_") + #attr )
      40         140 : std::string _iPipeAttributeStrings[] = {
      41             :     MAKE_PIPE_ATTR_STRING( IATTR_HINT_THREAD ),
      42             :     MAKE_PIPE_ATTR_STRING( IATTR_HINT_AFFINITY ),
      43          70 : };
      44             : 
      45             : }
      46             : 
      47             : template< class N, class P, class W, class V >
      48        1237 : Pipe< N, P, W, V >::Pipe( N* parent )
      49             :         : _node( parent )
      50             :         , _port( LB_UNDEFINED_UINT32 )
      51        1237 :         , _device( LB_UNDEFINED_UINT32 )
      52             : {
      53        1237 :     memset( _iAttributes, 0xff, IATTR_ALL * sizeof( int32_t ));
      54        1237 :     parent->_addPipe( static_cast< P* >( this ) );
      55        1237 :     LBLOG( LOG_INIT ) << "New " << lunchbox::className( this ) << std::endl;
      56        1237 : }
      57             : 
      58             : template< class N, class P, class W, class V >
      59        1145 : Pipe< N, P, W, V >::~Pipe()
      60             : {
      61        1145 :     LBLOG( LOG_INIT ) << "Delete " << lunchbox::className( this ) << std::endl;
      62        3782 :     while( !_windows.empty() )
      63             :     {
      64        1492 :         W* window = _windows.back();
      65        1492 :         _removeWindow( window );
      66        1492 :         delete window;
      67             :     }
      68        1145 :     _node->_removePipe( static_cast< P* >( this ) );
      69        2290 : }
      70             : 
      71             : template< class N, class P, class W, class V >
      72           4 : void Pipe< N, P, W, V >::backup()
      73             : {
      74           4 :     Object::backup();
      75           4 :     _backup = _data;
      76           4 : }
      77             : 
      78             : 
      79             : template< class N, class P, class W, class V >
      80           4 : void Pipe< N, P, W, V >::restore()
      81             : {
      82           4 :     _data = _backup;
      83           4 :     Object::restore();
      84           4 :     notifyPixelViewportChanged();
      85           4 :     setDirty( DIRTY_PIXELVIEWPORT );
      86           4 : }
      87             : 
      88             : template< class N, class P, class W, class V >
      89           5 : void Pipe< N, P, W, V >::attach( const uint128_t& id,
      90             :                                  const uint32_t instanceID )
      91             : {
      92           5 :     Object::attach( id, instanceID );
      93             : 
      94           5 :     co::CommandQueue* queue = _node->getConfig()->getMainThreadQueue();
      95           5 :     LBASSERT( queue );
      96             : 
      97           5 :     registerCommand( CMD_PIPE_NEW_WINDOW,
      98             :                      CmdFunc( this, &Pipe< N, P, W, V >::_cmdNewWindow ),
      99             :                      queue );
     100           5 :     registerCommand( CMD_PIPE_NEW_WINDOW_REPLY,
     101             :                      CmdFunc( this, &Pipe< N, P, W, V >::_cmdNewWindowReply ),
     102             :                      0 );
     103           5 : }
     104             : 
     105             : template< class N, class P, class W, class V >
     106           9 : uint128_t Pipe< N, P, W, V >::commit( const uint32_t incarnation )
     107             : {
     108           9 :     if( Serializable::isDirty( DIRTY_WINDOWS ))
     109           6 :         commitChildren< W >( _windows, CMD_PIPE_NEW_WINDOW, incarnation );
     110           9 :     return Object::commit( incarnation );
     111             : }
     112             : 
     113             : template< class N, class P, class W, class V >
     114           2 : void Pipe< N, P, W, V >::serialize( co::DataOStream& os,
     115             :                                     const uint64_t dirtyBits )
     116             : {
     117           2 :     Object::serialize( os, dirtyBits );
     118           2 :     if( dirtyBits & DIRTY_ATTRIBUTES )
     119           2 :         os << co::Array< int32_t >( _iAttributes, IATTR_ALL );
     120           2 :     if( dirtyBits & DIRTY_WINDOWS && isMaster( ))
     121             :     {
     122           2 :         os << _mapNodeObjects();
     123           2 :         os.serializeChildren( _windows );
     124             :     }
     125           2 :     if( dirtyBits & DIRTY_PIXELVIEWPORT )
     126           2 :         os << _data.pvp;
     127           2 :     if( dirtyBits & DIRTY_MEMBER )
     128           2 :         os << _port << _device;
     129           2 : }
     130             : 
     131             : template< class N, class P, class W, class V >
     132           1 : void Pipe< N, P, W, V >::deserialize( co::DataIStream& is,
     133             :                                       const uint64_t dirtyBits )
     134             : {
     135           1 :     Object::deserialize( is, dirtyBits );
     136           1 :     if( dirtyBits & DIRTY_ATTRIBUTES )
     137           1 :         is >> co::Array< int32_t >( _iAttributes, IATTR_ALL );
     138           1 :     if( dirtyBits & DIRTY_WINDOWS )
     139             :     {
     140           1 :         if( isMaster( ))
     141           0 :             syncChildren( _windows );
     142             :         else
     143             :         {
     144           1 :             const bool useChildren = is.read< bool >();
     145           1 :             if( useChildren && _mapNodeObjects( ))
     146             :             {
     147           0 :                 Windows result;
     148           0 :                 is.deserializeChildren( this, _windows, result );
     149           0 :                 _windows.swap( result );
     150           0 :                 LBASSERT( _windows.size() == result.size( ));
     151             :             }
     152             :             else // consume unused ObjectVersions
     153           1 :                 is.read< co::ObjectVersions >();
     154             :         }
     155             :     }
     156           1 :     if( dirtyBits & DIRTY_PIXELVIEWPORT )
     157             :     {
     158           1 :         PixelViewport pvp;
     159           1 :         is >> pvp;
     160           1 :         setPixelViewport( pvp );
     161             :     }
     162           1 :     if( dirtyBits & DIRTY_MEMBER )
     163           1 :         is >> _port >> _device;
     164           1 : }
     165             : 
     166             : template< class N, class P, class W, class V >
     167       59064 : void Pipe< N, P, W, V >::setDirty( const uint64_t dirtyBits )
     168             : {
     169       59064 :     Object::setDirty( dirtyBits );
     170       59064 :     _node->setDirty( N::DIRTY_PIPES );
     171       59064 : }
     172             : 
     173             : template< class N, class P, class W, class V >
     174           5 : void Pipe< N, P, W, V >::notifyDetach()
     175             : {
     176           5 :     Object::notifyDetach();
     177          10 :     while( !_windows.empty( ))
     178             :     {
     179           4 :         W* window = _windows.back();
     180           4 :         if( !window->isAttached()  )
     181             :         {
     182           4 :             LBASSERT( isMaster( ));
     183           9 :             return;
     184             :         }
     185             : 
     186           0 :         LBASSERT( !isMaster( ));
     187             : 
     188           0 :         getLocalNode()->unmapObject( window );
     189           0 :         _removeWindow( window );
     190           0 :         _node->getServer()->getNodeFactory()->releaseWindow( window );
     191             :     }
     192             : }
     193             : 
     194             : template< class N, class P, class W, class V >
     195           0 : void Pipe< N, P, W, V >::create( W** window )
     196             : {
     197           0 :     *window = _node->getServer()->getNodeFactory()->createWindow(
     198             :         static_cast< P* >( this ));
     199           0 :     (*window)->init(); // not in ctor, virtual method
     200           0 : }
     201             : 
     202             : template< class N, class P, class W, class V >
     203           0 : void Pipe< N, P, W, V >::release( W* window )
     204             : {
     205           0 :     _node->getServer()->getNodeFactory()->releaseWindow( window );
     206           0 : }
     207             : 
     208             : namespace
     209             : {
     210             : template< class P, class V >
     211       28314 : VisitorResult _accept( P* pipe, V& visitor )
     212             : {
     213       28314 :     VisitorResult result = visitor.visitPre( pipe );
     214       28314 :     if( result != TRAVERSE_CONTINUE )
     215          12 :         return result;
     216             : 
     217       28302 :     const typename P::Windows& windows = pipe->getWindows();
     218      168900 :     for( typename P::Windows::const_iterator i = windows.begin();
     219      112600 :          i != windows.end(); ++i )
     220             :     {
     221       33314 :         switch( (*i)->accept( visitor ))
     222             :         {
     223             :             case TRAVERSE_TERMINATE:
     224        5316 :                 return TRAVERSE_TERMINATE;
     225             : 
     226             :             case TRAVERSE_PRUNE:
     227         122 :                 result = TRAVERSE_PRUNE;
     228         122 :                 break;
     229             : 
     230             :             case TRAVERSE_CONTINUE:
     231             :             default:
     232       27876 :                 break;
     233             :         }
     234             :     }
     235             : 
     236       22986 :     switch( visitor.visitPost( pipe ))
     237             :     {
     238             :         case TRAVERSE_TERMINATE:
     239           0 :             return TRAVERSE_TERMINATE;
     240             : 
     241             :         case TRAVERSE_PRUNE:
     242           2 :             return TRAVERSE_PRUNE;
     243             : 
     244             :         case TRAVERSE_CONTINUE:
     245             :         default:
     246       22984 :             break;
     247             :     }
     248             : 
     249       22984 :     return result;
     250             : }
     251             : }
     252             : 
     253             : template< class N, class P, class W, class V >
     254       28314 : VisitorResult Pipe< N, P, W, V >::accept( V& visitor )
     255             : {
     256       28314 :     return _accept( static_cast< P* >( this ), visitor );
     257             : }
     258             : 
     259             : template< class N, class P, class W, class V >
     260           0 : VisitorResult Pipe< N, P, W, V >::accept( V& visitor ) const
     261             : {
     262           0 :     return _accept( static_cast< const P* >( this ), visitor );
     263             : }
     264             : 
     265             : template< class N, class P, class W, class V >
     266          92 : PipePath Pipe< N, P, W, V >::getPath() const
     267             : {
     268          92 :     const N* node = getNode();
     269          92 :     LBASSERT( node );
     270          92 :     PipePath path( node->getPath( ));
     271             : 
     272          92 :     const typename std::vector< P* >& pipes = node->getPipes();
     273             :     typename std::vector< P* >::const_iterator i = std::find( pipes.begin(),
     274             :                                                               pipes.end(),
     275          92 :                                                               this );
     276          92 :     LBASSERT( i != pipes.end( ));
     277          92 :     path.pipeIndex = std::distance( pipes.begin(), i );
     278          92 :     return path;
     279             : }
     280             : 
     281             : template< class N, class P, class W, class V >
     282        2312 : void Pipe< N, P, W, V >::setIAttribute( const IAttribute attr,
     283             :                                      const int32_t value )
     284             : {
     285        2312 :     if( _iAttributes[attr] == value )
     286        3458 :         return;
     287             : 
     288        1166 :     _iAttributes[attr] = value;
     289        1166 :     setDirty( DIRTY_ATTRIBUTES );
     290             :  }
     291             : 
     292             : template< class N, class P, class W, class V >
     293         150 : void Pipe< N, P, W, V >::setDevice( const uint32_t device )
     294             : {
     295         150 :     _device = device;
     296         150 :     setDirty( DIRTY_MEMBER );
     297         150 : }
     298             : 
     299             : template< class N, class P, class W, class V >
     300           0 : void Pipe< N, P, W, V >::setPort( const uint32_t port )
     301             : {
     302           0 :     _port = port;
     303           0 :     setDirty( DIRTY_MEMBER );
     304           0 : }
     305             : 
     306             : template< class N, class P, class W, class V >
     307        1765 : void Pipe< N, P, W, V >::_addWindow( W* window )
     308             : {
     309        1765 :     LBASSERT( window->getPipe() == this );
     310        1765 :     _windows.push_back( window );
     311        1765 :     setDirty( DIRTY_WINDOWS );
     312        1765 : }
     313             : 
     314             : template< class N, class P, class W, class V >
     315        2985 : bool Pipe< N, P, W, V >::_removeWindow( W* window )
     316             : {
     317             :     typename Windows::iterator i = find( _windows.begin(), _windows.end(),
     318        2985 :                                          window );
     319        2985 :     if ( i == _windows.end( ) )
     320        1492 :         return false;
     321             : 
     322        1493 :     _windows.erase( i );
     323        1493 :     setDirty( DIRTY_WINDOWS );
     324        1493 :     if( !isMaster( ))
     325        1493 :         postRemove( window );
     326        1493 :     return true;
     327             : }
     328             : 
     329             : template< class N, class P, class W, class V >
     330           1 : W* Pipe< N, P, W, V >::_findWindow( const uint128_t& id )
     331             : {
     332           3 :     for( typename Windows::const_iterator i = _windows.begin();
     333           2 :          i != _windows.end(); ++i )
     334             :     {
     335           1 :         W* window = *i;
     336           1 :         if( window->getID() == id )
     337           1 :             return window;
     338             :     }
     339           0 :     return 0;
     340             : }
     341             : 
     342             : template< class N, class P, class W, class V >
     343        1362 : const std::string& Pipe< N, P, W, V >::getIAttributeString( const IAttribute attr )
     344             : {
     345        1362 :     return _iPipeAttributeStrings[attr];
     346             : }
     347             : 
     348             : //----------------------------------------------------------------------
     349             : // viewport
     350             : //----------------------------------------------------------------------
     351             : template< class N, class P, class W, class V >
     352           1 : void Pipe< N, P, W, V >::setPixelViewport( const PixelViewport& pvp )
     353             : {
     354           1 :     if( pvp == _data.pvp || !pvp.hasArea( ))
     355           2 :         return;
     356             : 
     357           0 :     _data.pvp = pvp;
     358           0 :     notifyPixelViewportChanged();
     359           0 :     LBVERB << "Pipe pvp set: " << _data.pvp << std::endl;
     360             : }
     361             : 
     362             : template< class N, class P, class W, class V >
     363           4 : void Pipe< N, P, W, V >::notifyPixelViewportChanged()
     364             : {
     365           4 :     const Windows& windows = getWindows();
     366          24 :     for( typename Windows::const_iterator i = windows.begin();
     367          16 :          i != windows.end(); ++i )
     368             :     {
     369           4 :         (*i)->notifyViewportChanged();
     370             :     }
     371           4 :     setDirty( DIRTY_PIXELVIEWPORT );
     372           4 :     LBVERB << getName() << " pvp update: " << _data.pvp << std::endl;
     373           4 : }
     374             : 
     375             : //----------------------------------------------------------------------
     376             : // ICommand handlers
     377             : //----------------------------------------------------------------------
     378             : template< class N, class P, class W, class V > bool
     379           0 : Pipe< N, P, W, V >::_cmdNewWindow( co::ICommand& cmd )
     380             : {
     381           0 :     co::ObjectICommand command( cmd );
     382             : 
     383           0 :     W* window = 0;
     384           0 :     create( &window );
     385           0 :     LBASSERT( window );
     386             : 
     387           0 :     getLocalNode()->registerObject( window );
     388           0 :     LBASSERT( window->isAttached() );
     389             : 
     390           0 :     send( command.getRemoteNode(), CMD_PIPE_NEW_WINDOW_REPLY )
     391           0 :             << command.read< uint32_t >() << window->getID();
     392             : 
     393           0 :     return true;
     394             : }
     395             : 
     396             : template< class N, class P, class W, class V > bool
     397           0 : Pipe< N, P, W, V >::_cmdNewWindowReply( co::ICommand& cmd )
     398             : {
     399           0 :     co::ObjectICommand command( cmd );
     400             : 
     401           0 :     const uint32_t requestID = command.read< uint32_t >();
     402           0 :     const uint128_t& result = command.read< uint128_t >();
     403             : 
     404           0 :     getLocalNode()->serveRequest( requestID, result );
     405             : 
     406           0 :     return true;
     407             : }
     408             : 
     409             : template< class N, class P, class W, class V >
     410         574 : std::ostream& operator << ( std::ostream& os, const Pipe< N, P, W, V >& pipe )
     411             : {
     412         574 :     os << lunchbox::disableFlush << lunchbox::disableHeader << "pipe"
     413             :        << std::endl;
     414         574 :     os << "{" << std::endl << lunchbox::indent;
     415             : 
     416         574 :     const std::string& name = pipe.getName();
     417         574 :     if( !name.empty( ))
     418          82 :         os << "name     \"" << name << "\"" << std::endl;
     419             : 
     420         574 :     if( pipe.getPort() != LB_UNDEFINED_UINT32 )
     421           0 :         os << "port     " << pipe.getPort() << std::endl;
     422             : 
     423         574 :     if( pipe.getDevice() != LB_UNDEFINED_UINT32 )
     424          76 :         os << "device   " << pipe.getDevice() << std::endl;
     425             : 
     426         574 :     const PixelViewport& pvp = pipe.getPixelViewport();
     427         574 :     if( pvp.hasArea( ))
     428           0 :         os << "viewport " << pvp << std::endl;
     429             : 
     430         574 :     pipe.output( os );
     431         574 :     os << std::endl;
     432             : 
     433         574 :     const typename P::Windows& windows = pipe.getWindows();
     434        3966 :     for( typename P::Windows::const_iterator i = windows.begin();
     435        2644 :          i != windows.end(); ++i )
     436             :     {
     437         748 :         os << **i;
     438             :     }
     439             : 
     440         574 :     os << lunchbox::exdent << "}" << std::endl << lunchbox::enableHeader
     441             :        << lunchbox::enableFlush;
     442         574 :     return os;
     443             : }
     444             : 
     445             : }
     446             : }

Generated by: LCOV version 1.11