LCOV - code coverage report
Current view: top level - eq/server - channel.cpp (source / functions) Hit Total Coverage
Test: lcov2.info Lines: 208 271 76.8 %
Date: 2014-06-18 Functions: 37 47 78.7 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2005-2013, Stefan Eilemann <eile@equalizergraphics.com>
       3             :  *                    2011, Daniel Nachbaur <danielnachbaur@gmail.com>
       4             :  *                    2013, Julio Delgado Mangas <julio.delgadomangas@epfl.ch>
       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             : 
      21             : #include "channel.h"
      22             : 
      23             : #include "channelListener.h"
      24             : #include "channelUpdateVisitor.h"
      25             : #include "compound.h"
      26             : #include "compoundVisitor.h"
      27             : #include "configVisitor.h"
      28             : #include "config.h"
      29             : #include "global.h"
      30             : #include "log.h"
      31             : #include "node.h"
      32             : #include "segment.h"
      33             : #include "view.h"
      34             : #include "window.h"
      35             : 
      36             : #include <eq/client/log.h>
      37             : #include <eq/client/statistic.h>
      38             : 
      39             : #include <eq/fabric/commands.h>
      40             : #include <eq/fabric/paths.h>
      41             : 
      42             : #include <co/objectICommand.h>
      43             : 
      44             : #include <lunchbox/debug.h>
      45             : 
      46             : #include <set>
      47             : 
      48             : namespace eq
      49             : {
      50             : namespace server
      51             : {
      52             : typedef co::CommandFunc<Channel> CmdFunc;
      53             : typedef fabric::Channel< Window, Channel > Super;
      54             : 
      55             : namespace
      56             : {
      57             :     typedef std::set< View* > ViewSet;
      58             : 
      59             :     class ViewFinder : public ConfigVisitor
      60             :     {
      61             :     public:
      62           0 :         ViewFinder( const Channel* channel ) : _channel( channel ) {}
      63           0 :         virtual ~ViewFinder(){}
      64             : 
      65           0 :         virtual VisitorResult visit( Compound* compound )
      66             :         {
      67           0 :             Channel* channel = compound->getChannel();
      68           0 :             if( channel != _channel )
      69           0 :                 return TRAVERSE_CONTINUE;
      70             : 
      71           0 :             channel = compound->getInheritChannel();
      72           0 :             if ( channel->getView( ))
      73           0 :                 _viewSet.insert( channel->getView( ));
      74           0 :             return TRAVERSE_CONTINUE;
      75             :         }
      76             : 
      77           0 :         ViewSet& getViews() { return _viewSet; }
      78             : 
      79             :     private:
      80             :         const Channel*     _channel;
      81             :         ViewSet  _viewSet;
      82             :     };
      83             : }
      84             : 
      85         836 : Channel::Channel( Window* parent )
      86             :         : Super( parent )
      87             :         , _active( 0 )
      88             :         , _view( 0 )
      89             :         , _segment( 0 )
      90             :         , _state( STATE_STOPPED )
      91         836 :         , _lastDrawCompound( 0 )
      92             : {
      93         836 :     const Global* global = Global::instance();
      94        6688 :     for( unsigned i = 0; i < IATTR_ALL; ++i )
      95             :     {
      96        5852 :         const IAttribute attr = static_cast< IAttribute >( i );
      97        5852 :         setIAttribute( attr, global->getChannelIAttribute( attr ));
      98             :     }
      99        5852 :     for( unsigned i = 0; i < SATTR_ALL; ++i )
     100             :     {
     101        5016 :         const SAttribute attr = static_cast< SAttribute >( i );
     102        5016 :         setSAttribute( attr, global->getChannelSAttribute( attr ));
     103             :     }
     104         836 : }
     105             : 
     106         636 : Channel::Channel( const Channel& from )
     107             :         : Super( from )
     108             :         , _active( 0 )
     109             :         , _view( 0 )
     110             :         , _segment( 0 )
     111             :         , _state( STATE_STOPPED )
     112         636 :         , _lastDrawCompound( 0 )
     113             : {
     114             :     // Don't copy view and segment. Will be re-set by segment copy ctor
     115         636 : }
     116             : 
     117          86 : void Channel::attach( const uint128_t& id, const uint32_t instanceID )
     118             : {
     119          86 :     Super::attach( id, instanceID );
     120             : 
     121          86 :     co::CommandQueue* mainQ  = getMainThreadQueue();
     122          86 :     co::CommandQueue* cmdQ = getCommandThreadQueue();
     123             : 
     124             :     registerCommand( fabric::CMD_CHANNEL_CONFIG_INIT_REPLY,
     125          86 :                      CmdFunc( this, &Channel::_cmdConfigInitReply ), cmdQ );
     126             :     registerCommand( fabric::CMD_CHANNEL_CONFIG_EXIT_REPLY,
     127          86 :                      CmdFunc( this, &Channel::_cmdConfigExitReply ), cmdQ );
     128             :     registerCommand( fabric::CMD_CHANNEL_FRAME_FINISH_REPLY,
     129          86 :                      CmdFunc( this, &Channel::_cmdFrameFinishReply ), mainQ );
     130          86 : }
     131             : 
     132        2940 : Channel::~Channel()
     133             : {
     134        2940 : }
     135             : 
     136           0 : void Channel::postDelete()
     137             : {
     138             :     // Deregister server-queue command handler to avoid assertion in
     139             :     // command invokation after channel deletion
     140             :     registerCommand( fabric::CMD_CHANNEL_FRAME_FINISH_REPLY,
     141           0 :                      CmdFunc( this, &Channel::_cmdNop ), 0 );
     142           0 : }
     143             : 
     144         349 : Config* Channel::getConfig()
     145             : {
     146         349 :     Window* window = getWindow();
     147         349 :     LBASSERT( window );
     148         349 :     return window ? window->getConfig() : 0;
     149             : }
     150             : 
     151           7 : const Config* Channel::getConfig() const
     152             : {
     153           7 :     const Window* window = getWindow();
     154           7 :     LBASSERT( window );
     155           7 :     return window ? window->getConfig() : 0;
     156             : }
     157             : 
     158          97 : Node* Channel::getNode()
     159             : {
     160          97 :     Window* window = getWindow();
     161          97 :     LBASSERT( window );
     162          97 :     return window ? window->getNode() : 0;
     163             : }
     164             : 
     165           0 : const Node* Channel::getNode() const
     166             : {
     167           0 :     const Window* window = getWindow();
     168           0 :     LBASSERT( window );
     169           0 :     return window ? window->getNode() : 0;
     170             : }
     171             : 
     172           7 : Pipe* Channel::getPipe()
     173             : {
     174           7 :     Window* window = getWindow();
     175           7 :     LBASSERT( window );
     176           7 :     return window ? window->getPipe() : 0;
     177             : }
     178             : 
     179           0 : const Pipe* Channel::getPipe() const
     180             : {
     181           0 :     const Window* window = getWindow();
     182           0 :     LBASSERT( window );
     183           0 :     return window ? window->getPipe() : 0;
     184             : }
     185             : 
     186          86 : ServerPtr Channel::getServer()
     187             : {
     188          86 :     Window* window = getWindow();
     189          86 :     LBASSERT( window );
     190          86 :     return ( window ? window->getServer() : 0 );
     191             : }
     192             : 
     193         146 : const Canvas* Channel::getCanvas() const
     194             : {
     195         146 :     if( !_segment )
     196           0 :         return 0;
     197         146 :     return _segment->getCanvas();
     198             : }
     199             : 
     200           7 : const Compounds& Channel::getCompounds() const
     201             : {
     202           7 :     return getConfig()->getCompounds();
     203             : }
     204             : 
     205          86 : co::CommandQueue* Channel::getMainThreadQueue()
     206             : {
     207          86 :     Window* window = getWindow();
     208          86 :     LBASSERT( window );
     209          86 :     return window->getMainThreadQueue();
     210             : }
     211             : 
     212          86 : co::CommandQueue* Channel::getCommandThreadQueue()
     213             : {
     214          86 :     Window* window = getWindow();
     215          86 :     LBASSERT( window );
     216          86 :     return window->getCommandThreadQueue();
     217             : }
     218             : 
     219        1248 : bool Channel::supportsView( const View* view ) const
     220             : {
     221        1248 :     if( !view )
     222           0 :         return true;
     223             : 
     224        1248 :     const uint64_t minimum = view->getMinimumCapabilities();
     225        1248 :     const uint64_t supported = getCapabilities();
     226        1248 :     return( (supported & minimum) == minimum );
     227             : }
     228             : 
     229          22 : void Channel::activate()
     230             : {
     231          22 :     Window* window = getWindow();
     232          22 :     LBASSERT( window );
     233             : 
     234          22 :     ++_active;
     235          22 :     window->activate();
     236             : 
     237          22 :     LBLOG( LOG_VIEW ) << "activate: " << _active << " " << (void*)this
     238          22 :                       << std::endl;
     239          22 : }
     240             : 
     241          22 : void Channel::deactivate()
     242             : {
     243          22 :     Window* window = getWindow();
     244          22 :     LBASSERT( _active != 0 );
     245          22 :     LBASSERT( window );
     246             : 
     247          22 :     --_active;
     248          22 :     window->deactivate();
     249             : 
     250          22 :     LBLOG( LOG_VIEW ) << "deactivate: " << _active << " " << (void*)this
     251          22 :                       << std::endl;
     252          22 : }
     253             : 
     254         636 : void Channel::setOutput( View* view, Segment* segment )
     255             : {
     256         636 :     LBASSERT( !_view && !_segment );
     257         636 :     LBASSERT( view && segment );
     258             : 
     259         636 :     _view = view;
     260         636 :     _segment = segment;
     261             : 
     262         636 :     view->addChannel( this );
     263         636 :     segment->addDestinationChannel( this );
     264             : 
     265         636 :     co::ObjectVersion viewVersion( view );
     266         636 :     if( view && view->isDirty( ))
     267           0 :         ++viewVersion.version;
     268             : 
     269         636 :     setViewVersion( viewVersion );
     270         636 : }
     271             : 
     272         635 : void Channel::unsetOutput()
     273             : {
     274         635 :     LBASSERT( _view && _segment );
     275             : 
     276         635 :     LBCHECK( _view->removeChannel( this ));
     277         635 :     LBCHECK( _segment->removeDestinationChannel( this ));
     278             : 
     279         635 :     _view    = 0;
     280         635 :     _segment = 0;
     281         635 : }
     282             : 
     283         762 : const Layout* Channel::getLayout() const
     284             : {
     285         762 :     LBASSERT( _view );
     286         762 :     return _view ? _view->getLayout() : 0;
     287             : }
     288             : 
     289         348 : void Channel::addTasks( const uint32_t tasks )
     290             : {
     291         348 :     Window* window = getWindow();
     292         348 :     LBASSERT( window );
     293         348 :     setTasks( getTasks() | tasks );
     294         348 :     window->addTasks( tasks );
     295         348 : }
     296             : 
     297             : //===========================================================================
     298             : // Operations
     299             : //===========================================================================
     300             : 
     301             : //---------------------------------------------------------------------------
     302             : // init
     303             : //---------------------------------------------------------------------------
     304          15 : void Channel::configInit( const uint128_t& initID, const uint32_t /*frame*/ )
     305             : {
     306          15 :     LBASSERT( _state == STATE_STOPPED );
     307          15 :     _state = STATE_INITIALIZING;
     308             : 
     309          15 :     LBLOG( LOG_INIT ) << "Init channel" << std::endl;
     310          15 :     getWindow()->send( fabric::CMD_WINDOW_CREATE_CHANNEL ) << getID();
     311          15 :     send( fabric::CMD_CHANNEL_CONFIG_INIT ) << initID;
     312          15 : }
     313             : 
     314          15 : bool Channel::syncConfigInit()
     315             : {
     316          15 :     LBASSERT( _state == STATE_INITIALIZING || _state == STATE_INIT_SUCCESS ||
     317             :               _state == STATE_INIT_FAILED );
     318             : 
     319          15 :     _state.waitNE( STATE_INITIALIZING );
     320             : 
     321          15 :     if( _state == STATE_INIT_SUCCESS )
     322             :     {
     323          15 :         _state = STATE_RUNNING;
     324          15 :         return true;
     325             :     }
     326             : 
     327           0 :     configExit();
     328           0 :     return false;
     329             : }
     330             : 
     331             : //---------------------------------------------------------------------------
     332             : // exit
     333             : //---------------------------------------------------------------------------
     334          15 : void Channel::configExit()
     335             : {
     336          15 :     LBASSERT( _state == STATE_RUNNING || _state == STATE_INIT_FAILED );
     337          15 :     _state = STATE_EXITING;
     338             : 
     339          15 :     LBLOG( LOG_INIT ) << "Exit channel" << std::endl;
     340          15 :     send( fabric::CMD_CHANNEL_CONFIG_EXIT );
     341          15 : }
     342             : 
     343          15 : bool Channel::syncConfigExit()
     344             : {
     345          15 :     LBASSERT( _state == STATE_EXITING || _state == STATE_EXIT_SUCCESS ||
     346             :               _state == STATE_EXIT_FAILED );
     347             : 
     348          15 :     _state.waitNE( STATE_EXITING );
     349          15 :     const bool success = ( _state == STATE_EXIT_SUCCESS );
     350          15 :     LBASSERT( success || _state == STATE_EXIT_FAILED );
     351             : 
     352          15 :     _state = isActive() ? STATE_FAILED : STATE_STOPPED;
     353          15 :     return success;
     354             : }
     355             : 
     356             : //---------------------------------------------------------------------------
     357             : // update
     358             : //---------------------------------------------------------------------------
     359           7 : void Channel::_setupRenderContext( const uint128_t& frameID,
     360             :                                    RenderContext& context )
     361             : {
     362           7 :     context.frameID = frameID;
     363           7 :     context.pvp = getPixelViewport();
     364           7 :     context.view = _view;
     365           7 :     context.vp = getViewport();
     366           7 :     LBASSERTINFO( getNativeContext().view == context.view,
     367             :                   getNativeContext().view << " != " << context.view << " " <<
     368             :                   getName( ));
     369           7 : }
     370             : 
     371          24 : bool Channel::update( const uint128_t& frameID, const uint32_t frameNumber )
     372             : {
     373          24 :     if( !isRunning( ))
     374          17 :         return false; // not updated
     375             : 
     376           7 :     LBASSERT( isActive( ))
     377           7 :     LBASSERT( getWindow()->isActive( ));
     378             : 
     379           7 :     RenderContext context;
     380           7 :     _setupRenderContext( frameID, context );
     381             :     send( fabric::CMD_CHANNEL_FRAME_START )
     382           7 :             << context << getVersion() << frameNumber;
     383           7 :     LBLOG( LOG_TASKS ) << "TASK channel " << getName() << " start frame  "
     384           7 :                        << frameNumber << std::endl;
     385             : 
     386           7 :     bool updated = false;
     387           7 :     const Compounds& compounds = getCompounds();
     388         114 :     for( Compounds::const_iterator i = compounds.begin();
     389          76 :          i != compounds.end(); ++i )
     390             :     {
     391          31 :         const Compound* compound = *i;
     392          31 :         ChannelUpdateVisitor visitor( this, frameID, frameNumber );
     393             : 
     394          31 :         visitor.setEye( EYE_CYCLOP );
     395          31 :         compound->accept( visitor );
     396             : 
     397          31 :         visitor.setEye( EYE_LEFT );
     398          31 :         compound->accept( visitor );
     399             : 
     400          31 :         visitor.setEye( EYE_RIGHT );
     401          31 :         compound->accept( visitor );
     402             : 
     403          31 :         updated |= visitor.isUpdated();
     404          31 :     }
     405             : 
     406           7 :     send( fabric::CMD_CHANNEL_FRAME_FINISH ) << context << frameNumber;
     407           7 :     LBLOG( LOG_TASKS ) << "TASK channel " << getName() << " finish frame  "
     408           7 :                            << frameNumber << std::endl;
     409           7 :     _lastDrawCompound = 0;
     410             : 
     411           7 :     return updated;
     412             : }
     413             : 
     414          72 : co::ObjectOCommand Channel::send( const uint32_t cmd )
     415             : {
     416          72 :     return getNode()->send( cmd, getID( ));
     417             : }
     418             : 
     419             : //---------------------------------------------------------------------------
     420             : // Listener interface
     421             : //---------------------------------------------------------------------------
     422           8 : void Channel::addListener( ChannelListener* listener )
     423             : {
     424           8 :     LB_TS_SCOPED( _serverThread );
     425           8 :     LBASSERT( std::find( _listeners.begin(), _listeners.end(), listener ) ==
     426             :               _listeners.end( ));
     427             : 
     428           8 :     _listeners.push_back( listener );
     429           8 : }
     430             : 
     431           8 : void Channel::removeListener(  ChannelListener* listener )
     432             : {
     433             :     ChannelListeners::iterator i = find( _listeners.begin(), _listeners.end(),
     434           8 :                                           listener );
     435           8 :     if( i != _listeners.end( ))
     436           8 :         _listeners.erase( i );
     437           8 : }
     438             : 
     439           7 : void Channel::_fireLoadData( const uint32_t frameNumber,
     440             :                              const Statistics& statistics,
     441             :                              const Viewport& region )
     442             : {
     443           7 :     LB_TS_SCOPED( _serverThread );
     444             : 
     445          21 :     for( ChannelListeners::const_iterator i = _listeners.begin();
     446          14 :          i != _listeners.end(); ++i )
     447             :     {
     448           0 :         (*i)->notifyLoadData( this, frameNumber, statistics, region );
     449           7 :     }
     450           7 : }
     451             : 
     452             : //===========================================================================
     453             : // command handling
     454             : //===========================================================================
     455          15 : bool Channel::_cmdConfigInitReply( co::ICommand& cmd )
     456             : {
     457          15 :     co::ObjectICommand command( cmd );
     458          15 :     const bool result = command.read< bool >();
     459             : 
     460          15 :     LBLOG( LOG_INIT ) << "handle channel configInit reply " << command
     461          15 :                       << " result " << result << std::endl;
     462             : 
     463          15 :     _state = result ? STATE_INIT_SUCCESS : STATE_INIT_FAILED;
     464          15 :     return true;
     465             : }
     466             : 
     467          15 : bool Channel::_cmdConfigExitReply( co::ICommand& cmd )
     468             : {
     469          15 :     co::ObjectICommand command( cmd );
     470          15 :     LBLOG( LOG_INIT ) << "handle channel configExit reply " << command
     471          15 :                       << std::endl;
     472             : 
     473          15 :     _state = command.read< bool >() ? STATE_EXIT_SUCCESS : STATE_EXIT_FAILED;
     474          15 :     return true;
     475             : }
     476             : 
     477           7 : bool Channel::_cmdFrameFinishReply( co::ICommand& cmd )
     478             : {
     479           7 :     co::ObjectICommand command( cmd );
     480           7 :     const Viewport& region = command.read< Viewport >();
     481           7 :     const uint32_t frameNumber = command.read< uint32_t >();
     482          14 :     const Statistics& statistics = command.read< Statistics >();
     483             : 
     484           7 :     _fireLoadData( frameNumber, statistics, region );
     485          14 :     return true;
     486             : }
     487             : 
     488         860 : bool Channel::omitOutput() const
     489             : {
     490             :     // don't print generated channels for now
     491         860 :     return _view || _segment;
     492             : }
     493             : 
     494           0 : void Channel::output( std::ostream& os ) const
     495             : {
     496           0 :     bool attrPrinted   = false;
     497             : 
     498           0 :     for( IAttribute i = static_cast<IAttribute>( 0 );
     499           0 :          i < IATTR_LAST;
     500             :          i = static_cast<IAttribute>( static_cast<uint32_t>(i)+1 ))
     501             :     {
     502           0 :         const int value = getIAttribute( i );
     503           0 :         if( value == Global::instance()->getChannelIAttribute( i ))
     504           0 :             continue;
     505             : 
     506           0 :         if( !attrPrinted )
     507             :         {
     508           0 :             os << std::endl << "attributes" << std::endl
     509           0 :                << "{" << std::endl << lunchbox::indent;
     510           0 :             attrPrinted = true;
     511             :         }
     512             : 
     513             :         os << ( i==IATTR_HINT_STATISTICS ? "hint_statistics   " :
     514             :                 i==IATTR_HINT_SENDTOKEN ?  "hint_sendtoken    " :
     515           0 :                                            "ERROR " )
     516           0 :            << static_cast< fabric::IAttribute >( value ) << std::endl;
     517             :     }
     518           0 :     for( SAttribute i = static_cast<SAttribute>( 0 );
     519           0 :          i < SATTR_LAST;
     520             :          i = static_cast<SAttribute>( static_cast<uint32_t>(i)+1 ))
     521             :     {
     522           0 :         const std::string& value = getSAttribute( i );
     523           0 :         if( value == Global::instance()->getChannelSAttribute( i ))
     524           0 :             continue;
     525             : 
     526           0 :         if( !attrPrinted )
     527             :         {
     528           0 :             os << std::endl << "attributes" << std::endl
     529           0 :                << "{" << std::endl << lunchbox::indent;
     530           0 :             attrPrinted = true;
     531             :         }
     532             : 
     533           0 :         os << ( i == SATTR_DUMP_IMAGE ? "dump_image        " : "ERROR " )
     534           0 :            << "\"" << value << "\"" << std::endl;
     535           0 :     }
     536             : 
     537           0 :     if( attrPrinted )
     538           0 :         os << lunchbox::exdent << "}" << std::endl << std::endl;
     539           0 : }
     540             : 
     541           0 : void Channel::updateCapabilities()
     542             : {
     543           0 :     ViewFinder visitor( this );
     544           0 :     getConfig()->accept( visitor );
     545           0 :     ViewSet& views = visitor.getViews();
     546             : 
     547           0 :     for( ViewSet::const_iterator i = views.begin(); i != views.end(); ++i )
     548           0 :         (*i)->updateCapabilities();
     549           0 : }
     550             : 
     551             : }
     552             : }
     553             : 
     554             : #include "../fabric/channel.ipp"
     555             : template class eq::fabric::Channel< eq::server::Window, eq::server::Channel >;
     556             : /** @cond IGNORE */
     557             : template std::ostream& eq::fabric::operator << ( std::ostream&,
     558          27 :                                                  const eq::server::Super& );
     559             : /** @endcond */

Generated by: LCOV version 1.10