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

Generated by: LCOV version 1.11