LCOV - code coverage report
Current view: top level - eq/fabric - pipe.ipp (source / functions) Hit Total Coverage
Test: lcov2.info Lines: 175 209 83.7 %
Date: 2014-06-18 Functions: 39 61 63.9 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2010-2014, Stefan Eilemann <eile@equalizergraphics.com>
       3             :  *                    2012, Daniel Nachbaur <danielnachbaur@gmail.com>
       4             :  *                    2010, 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          42 : 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          21 : };
      45             : 
      46             : }
      47             : 
      48             : template< class N, class P, class W, class V >
      49         693 : Pipe< N, P, W, V >::Pipe( N* parent )
      50             :         : _node( parent )
      51             :         , _port( LB_UNDEFINED_UINT32 )
      52         693 :         , _device( LB_UNDEFINED_UINT32 )
      53             : {
      54         693 :     memset( _iAttributes, 0xff, IATTR_ALL * sizeof( int32_t ));
      55         693 :     parent->_addPipe( static_cast< P* >( this ) );
      56         693 :     LBLOG( LOG_INIT ) << "New " << lunchbox::className( this ) << std::endl;
      57         693 : }
      58             : 
      59             : template< class N, class P, class W, class V >
      60         602 : Pipe< N, P, W, V >::~Pipe()
      61             : {
      62         602 :     LBLOG( LOG_INIT ) << "Delete " << lunchbox::className( this ) << std::endl;
      63        1957 :     while( !_windows.empty() )
      64             :     {
      65         753 :         W* window = _windows.back();
      66         753 :         _removeWindow( window );
      67         753 :         delete window;
      68             :     }
      69         602 :     _node->_removePipe( static_cast< P* >( this ) );
      70        1204 : }
      71             : 
      72             : template< class N, class P, class W, class V >
      73          23 : void Pipe< N, P, W, V >::backup()
      74             : {
      75          23 :     Object::backup();
      76          23 :     _backup = _data;
      77          23 : }
      78             : 
      79             : 
      80             : template< class N, class P, class W, class V >
      81           2 : void Pipe< N, P, W, V >::restore()
      82             : {
      83           2 :     _data = _backup;
      84           2 :     Object::restore();
      85           2 :     notifyPixelViewportChanged();
      86           2 :     setDirty( DIRTY_PIXELVIEWPORT );
      87           2 : }
      88             : 
      89             : template< class N, class P, class W, class V >
      90          38 : void Pipe< N, P, W, V >::attach( const uint128_t& id,
      91             :                                  const uint32_t instanceID )
      92             : {
      93          38 :     Object::attach( id, instanceID );
      94             : 
      95          38 :     co::CommandQueue* queue = _node->getConfig()->getMainThreadQueue();
      96          38 :     LBASSERT( queue );
      97             : 
      98          38 :     registerCommand( CMD_PIPE_NEW_WINDOW,
      99             :                      CmdFunc( this, &Pipe< N, P, W, V >::_cmdNewWindow ),
     100             :                      queue );
     101          38 :     registerCommand( CMD_PIPE_NEW_WINDOW_REPLY,
     102             :                      CmdFunc( this, &Pipe< N, P, W, V >::_cmdNewWindowReply ),
     103             :                      0 );
     104          38 : }
     105             : 
     106             : template< class N, class P, class W, class V >
     107          64 : uint128_t Pipe< N, P, W, V >::commit( const uint32_t incarnation )
     108             : {
     109          64 :     if( Serializable::isDirty( DIRTY_WINDOWS ))
     110          40 :         commitChildren< W >( _windows, CMD_PIPE_NEW_WINDOW, incarnation );
     111          64 :     return Object::commit( incarnation );
     112             : }
     113             : 
     114             : template< class N, class P, class W, class V >
     115          63 : void Pipe< N, P, W, V >::serialize( co::DataOStream& os,
     116             :                                     const uint64_t dirtyBits )
     117             : {
     118          63 :     Object::serialize( os, dirtyBits );
     119          63 :     if( dirtyBits & DIRTY_ATTRIBUTES )
     120          15 :         os << co::Array< int32_t >( _iAttributes, IATTR_ALL );
     121          63 :     if( dirtyBits & DIRTY_WINDOWS && isMaster( ))
     122             :     {
     123          43 :         os << _mapNodeObjects();
     124          43 :         os.serializeChildren( _windows );
     125             :     }
     126          63 :     if( dirtyBits & DIRTY_PIXELVIEWPORT )
     127          45 :         os << _data.pvp;
     128          63 :     if( dirtyBits & DIRTY_MEMBER )
     129          15 :         os << _port << _device;
     130          63 : }
     131             : 
     132             : template< class N, class P, class W, class V >
     133          44 : void Pipe< N, P, W, V >::deserialize( co::DataIStream& is,
     134             :                                       const uint64_t dirtyBits )
     135             : {
     136          44 :     Object::deserialize( is, dirtyBits );
     137          44 :     if( dirtyBits & DIRTY_ATTRIBUTES )
     138          15 :         is >> co::Array< int32_t >( _iAttributes, IATTR_ALL );
     139          44 :     if( dirtyBits & DIRTY_WINDOWS )
     140             :     {
     141          29 :         if( isMaster( ))
     142           5 :             syncChildren( _windows );
     143             :         else
     144             :         {
     145          24 :             const bool useChildren = is.read< bool >();
     146          24 :             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          24 :                 is.read< co::ObjectVersions >();
     155             :         }
     156             :     }
     157          44 :     if( dirtyBits & DIRTY_PIXELVIEWPORT )
     158             :     {
     159          35 :         PixelViewport pvp;
     160          35 :         is >> pvp;
     161          35 :         setPixelViewport( pvp );
     162             :     }
     163          44 :     if( dirtyBits & DIRTY_MEMBER )
     164          15 :         is >> _port >> _device;
     165          44 : }
     166             : 
     167             : template< class N, class P, class W, class V >
     168       31102 : void Pipe< N, P, W, V >::setDirty( const uint64_t dirtyBits )
     169             : {
     170       31102 :     Object::setDirty( dirtyBits );
     171       31102 :     _node->setDirty( N::DIRTY_PIPES );
     172       31102 : }
     173             : 
     174             : template< class N, class P, class W, class V >
     175          38 : void Pipe< N, P, W, V >::notifyDetach()
     176             : {
     177          38 :     Object::notifyDetach();
     178          76 :     while( !_windows.empty( ))
     179             :     {
     180          23 :         W* window = _windows.back();
     181          23 :         if( !window->isAttached()  )
     182             :         {
     183          23 :             LBASSERT( isMaster( ));
     184          61 :             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       17132 : VisitorResult _accept( P* pipe, V& visitor )
     213             : {
     214       17132 :     VisitorResult result = visitor.visitPre( pipe );
     215       17132 :     if( result != TRAVERSE_CONTINUE )
     216          10 :         return result;
     217             : 
     218       17122 :     const typename P::Windows& windows = pipe->getWindows();
     219      100971 :     for( typename P::Windows::const_iterator i = windows.begin();
     220       67314 :          i != windows.end(); ++i )
     221             :     {
     222       19453 :         switch( (*i)->accept( visitor ))
     223             :         {
     224             :             case TRAVERSE_TERMINATE:
     225        2918 :                 return TRAVERSE_TERMINATE;
     226             : 
     227             :             case TRAVERSE_PRUNE:
     228         120 :                 result = TRAVERSE_PRUNE;
     229         120 :                 break;
     230             : 
     231             :             case TRAVERSE_CONTINUE:
     232             :             default:
     233       16415 :                 break;
     234             :         }
     235             :     }
     236             : 
     237       14204 :     switch( visitor.visitPost( pipe ))
     238             :     {
     239             :         case TRAVERSE_TERMINATE:
     240           0 :             return TRAVERSE_TERMINATE;
     241             : 
     242             :         case TRAVERSE_PRUNE:
     243           0 :             return TRAVERSE_PRUNE;
     244             : 
     245             :         case TRAVERSE_CONTINUE:
     246             :         default:
     247       14204 :             break;
     248             :     }
     249             : 
     250       14204 :     return result;
     251             : }
     252             : }
     253             : 
     254             : template< class N, class P, class W, class V >
     255       17125 : VisitorResult Pipe< N, P, W, V >::accept( V& visitor )
     256             : {
     257       17125 :     return _accept( static_cast< P* >( this ), visitor );
     258             : }
     259             : 
     260             : template< class N, class P, class W, class V >
     261           7 : VisitorResult Pipe< N, P, W, V >::accept( V& visitor ) const
     262             : {
     263           7 :     return _accept( static_cast< const P* >( this ), visitor );
     264             : }
     265             : 
     266             : template< class N, class P, class W, class V >
     267         120 : PipePath Pipe< N, P, W, V >::getPath() const
     268             : {
     269         120 :     const N* node = getNode();
     270         120 :     LBASSERT( node );
     271         120 :     PipePath path( node->getPath( ));
     272             : 
     273         120 :     const typename std::vector< P* >& pipes = node->getPipes();
     274             :     typename std::vector< P* >::const_iterator i = std::find( pipes.begin(),
     275             :                                                               pipes.end(),
     276         120 :                                                               this );
     277         120 :     LBASSERT( i != pipes.end( ));
     278         120 :     path.pipeIndex = std::distance( pipes.begin(), i );
     279         120 :     return path;
     280             : }
     281             : 
     282             : template< class N, class P, class W, class V >
     283        1774 : void Pipe< N, P, W, V >::setIAttribute( const IAttribute attr,
     284             :                                      const int32_t value )
     285             : {
     286        1774 :     if( _iAttributes[attr] == value )
     287        2362 :         return;
     288             : 
     289        1186 :     _iAttributes[attr] = value;
     290        1186 :     setDirty( DIRTY_ATTRIBUTES );
     291             :  }
     292             : 
     293             : template< class N, class P, class W, class V >
     294          93 : void Pipe< N, P, W, V >::setDevice( const uint32_t device )
     295             : {
     296          93 :     _device = device;
     297          93 :     setDirty( DIRTY_MEMBER );
     298          93 : }
     299             : 
     300             : template< class N, class P, class W, class V >
     301          21 : void Pipe< N, P, W, V >::setPort( const uint32_t port )
     302             : {
     303          21 :     _port = port;
     304          21 :     setDirty( DIRTY_MEMBER );
     305          21 : }
     306             : 
     307             : template< class N, class P, class W, class V >
     308        1039 : void Pipe< N, P, W, V >::_addWindow( W* window )
     309             : {
     310        1039 :     LBASSERT( window->getPipe() == this );
     311        1039 :     _windows.push_back( window );
     312        1039 :     setDirty( DIRTY_WINDOWS );
     313        1039 : }
     314             : 
     315             : template< class N, class P, class W, class V >
     316        1521 : bool Pipe< N, P, W, V >::_removeWindow( W* window )
     317             : {
     318             :     typename Windows::iterator i = find( _windows.begin(), _windows.end(),
     319        1521 :                                          window );
     320        1521 :     if ( i == _windows.end( ) )
     321         753 :         return false;
     322             : 
     323         768 :     _windows.erase( i );
     324         768 :     setDirty( DIRTY_WINDOWS );
     325         768 :     if( !isMaster( ))
     326         768 :         postRemove( window );
     327         768 :     return true;
     328             : }
     329             : 
     330             : template< class N, class P, class W, class V >
     331          15 : W* Pipe< N, P, W, V >::_findWindow( const uint128_t& id )
     332             : {
     333          45 :     for( typename Windows::const_iterator i = _windows.begin();
     334          30 :          i != _windows.end(); ++i )
     335             :     {
     336          15 :         W* window = *i;
     337          15 :         if( window->getID() == id )
     338          15 :             return window;
     339             :     }
     340           0 :     return 0;
     341             : }
     342             : 
     343             : template< class N, class P, class W, class V >
     344        1066 : const std::string& Pipe< N, P, W, V >::getIAttributeString( const IAttribute attr )
     345             : {
     346        1066 :     return _iPipeAttributeStrings[attr];
     347             : }
     348             : 
     349             : //----------------------------------------------------------------------
     350             : // viewport
     351             : //----------------------------------------------------------------------
     352             : template< class N, class P, class W, class V >
     353          59 : void Pipe< N, P, W, V >::setPixelViewport( const PixelViewport& pvp )
     354             : {
     355          59 :     if( pvp == _data.pvp || !pvp.hasArea( ))
     356          77 :         return;
     357             : 
     358          41 :     _data.pvp = pvp;
     359          41 :     notifyPixelViewportChanged();
     360          41 :     LBVERB << "Pipe pvp set: " << _data.pvp << std::endl;
     361             : }
     362             : 
     363             : template< class N, class P, class W, class V >
     364          43 : void Pipe< N, P, W, V >::notifyPixelViewportChanged()
     365             : {
     366          43 :     const Windows& windows = getWindows();
     367         144 :     for( typename Windows::const_iterator i = windows.begin();
     368          96 :          i != windows.end(); ++i )
     369             :     {
     370           5 :         (*i)->notifyViewportChanged();
     371             :     }
     372          43 :     setDirty( DIRTY_PIXELVIEWPORT );
     373          43 :     LBVERB << getName() << " pvp update: " << _data.pvp << std::endl;
     374          43 : }
     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         326 : std::ostream& operator << ( std::ostream& os, const Pipe< N, P, W, V >& pipe )
     412             : {
     413         326 :     os << lunchbox::disableFlush << lunchbox::disableHeader << "pipe"
     414             :        << std::endl;
     415         326 :     os << "{" << std::endl << lunchbox::indent;
     416             : 
     417         326 :     const std::string& name = pipe.getName();
     418         326 :     if( !name.empty( ))
     419          83 :         os << "name     \"" << name << "\"" << std::endl;
     420             : 
     421         326 :     if( pipe.getPort() != LB_UNDEFINED_UINT32 )
     422          26 :         os << "port     " << pipe.getPort() << std::endl;
     423             : 
     424         326 :     if( pipe.getDevice() != LB_UNDEFINED_UINT32 )
     425          62 :         os << "device   " << pipe.getDevice() << std::endl;
     426             : 
     427         326 :     const PixelViewport& pvp = pipe.getPixelViewport();
     428         326 :     if( pvp.isValid( ))
     429          42 :         os << "viewport " << pvp << std::endl;
     430             : 
     431         326 :     pipe.output( os );
     432         326 :     os << std::endl;
     433             : 
     434         326 :     const typename P::Windows& windows = pipe.getWindows();
     435        2205 :     for( typename P::Windows::const_iterator i = windows.begin();
     436        1470 :          i != windows.end(); ++i )
     437             :     {
     438         409 :         os << **i;
     439             :     }
     440             : 
     441         326 :     os << lunchbox::exdent << "}" << std::endl << lunchbox::enableHeader
     442             :        << lunchbox::enableFlush;
     443         326 :     return os;
     444             : }
     445             : 
     446             : }
     447             : }

Generated by: LCOV version 1.10