LCOV - code coverage report
Current view: top level - eq/server - channel.cpp (source / functions) Hit Total Coverage
Test: Equalizer Lines: 150 269 55.8 %
Date: 2016-07-30 05:04:55 Functions: 30 47 63.8 %

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

Generated by: LCOV version 1.11