LCOV - code coverage report
Current view: top level - eq/server - window.cpp (source / functions) Hit Total Coverage
Test: lcov2.info Lines: 171 273 62.6 %
Date: 2014-06-18 Functions: 27 33 81.8 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2005-2013, Stefan Eilemann <eile@equalizergraphics.com>
       3             :  *                    2010, Cedric Stalder <cedric.stalder@gmail.com>
       4             :  *
       5             :  * This library is free software; you can redistribute it and/or modify it under
       6             :  * the terms of the GNU Lesser General Public License version 2.1 as published
       7             :  * by the Free Software Foundation.
       8             :  *
       9             :  * This library is distributed in the hope that it will be useful, but WITHOUT
      10             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      11             :  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
      12             :  * details.
      13             :  *
      14             :  * You should have received a copy of the GNU Lesser General Public License
      15             :  * along with this library; if not, write to the Free Software Foundation, Inc.,
      16             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      17             :  */
      18             : 
      19             : #include "window.h"
      20             : 
      21             : #include "global.h"
      22             : #include "channel.h"
      23             : #include "config.h"
      24             : #include "compound.h"
      25             : #include "log.h"
      26             : #include "node.h"
      27             : #include "nodeFactory.h"
      28             : #include "pipe.h"
      29             : 
      30             : #include <eq/fabric/commands.h>
      31             : #include <eq/fabric/elementVisitor.h>
      32             : #include <eq/fabric/leafVisitor.h>
      33             : #include <eq/fabric/paths.h>
      34             : #include <co/objectICommand.h>
      35             : 
      36             : #include <boost/foreach.hpp>
      37             : 
      38             : namespace eq
      39             : {
      40             : namespace server
      41             : {
      42             : typedef fabric::Window< Pipe, Window, Channel > Super;
      43             : typedef co::CommandFunc<Window> WindowFunc;
      44             : 
      45         754 : Window::Window( Pipe* parent )
      46             :         : Super( parent )
      47             :         , _active( 0 )
      48             :         , _state( STATE_STOPPED )
      49         754 :         , _maxFPS( std::numeric_limits< float >::max( ))
      50             :         , _nvSwapBarrier( 0 )
      51             :         , _nvNetBarrier( 0 )
      52             :         , _lastDrawChannel( 0 )
      53             :         , _swapFinish( false )
      54        1508 :         , _swap( false )
      55             : {
      56         754 :     const Global* global = Global::instance();
      57       14326 :     for( unsigned i = 0; i < WindowSettings::IATTR_ALL; ++i )
      58             :     {
      59       13572 :         const WindowSettings::IAttribute attr = static_cast< WindowSettings::IAttribute >( i );
      60       13572 :         setIAttribute( attr, global->getWindowIAttribute( attr ));
      61             :     }
      62         754 : }
      63             : 
      64        1506 : Window::~Window()
      65             : {
      66        1506 : }
      67             : 
      68          23 : void Window::attach( const uint128_t& id, const uint32_t instanceID )
      69             : {
      70          23 :     Super::attach( id, instanceID );
      71             : 
      72          23 :     co::CommandQueue* cmdQ = getCommandThreadQueue();
      73             :     registerCommand( fabric::CMD_OBJECT_SYNC,
      74          23 :                      WindowFunc( this, &Window::_cmdSync ), cmdQ );
      75             :     registerCommand( fabric::CMD_WINDOW_CONFIG_INIT_REPLY,
      76          23 :                      WindowFunc( this, &Window::_cmdConfigInitReply ), cmdQ );
      77             :     registerCommand( fabric::CMD_WINDOW_CONFIG_EXIT_REPLY,
      78          23 :                      WindowFunc( this, &Window::_cmdConfigExitReply ), cmdQ );
      79          23 : }
      80             : 
      81           0 : void Window::removeChild( const uint128_t& id )
      82             : {
      83           0 :     LBASSERT( getConfig()->isRunning( ));
      84             : 
      85           0 :     Channel* channel = _findChannel( id );
      86           0 :     LBASSERT( channel );
      87           0 :     if( channel )
      88           0 :         channel->postDelete();
      89           0 : }
      90             : 
      91           0 : void Window::postDelete()
      92             : {
      93           0 :     _state = State( _state.get() | STATE_DELETE );
      94           0 :     getConfig()->postNeedsFinish();
      95             : 
      96           0 :     const Channels& channels = getChannels();
      97           0 :     for( Channels::const_iterator i = channels.begin(); i!=channels.end(); ++i )
      98             :     {
      99           0 :         (*i)->postDelete();
     100             :     }
     101           0 : }
     102             : 
     103           0 : const Node* Window::getNode() const
     104             : {
     105           0 :     const Pipe* pipe = getPipe();
     106           0 :     LBASSERT( pipe );
     107           0 :     return ( pipe ? pipe->getNode() : 0 );
     108             : }
     109             : 
     110         170 : Node* Window::getNode()
     111             : {
     112         170 :     Pipe* pipe = getPipe();
     113         170 :     LBASSERT( pipe );
     114         170 :     return ( pipe ? pipe->getNode() : 0 );
     115             : }
     116             : 
     117           7 : const Config* Window::getConfig() const
     118             : {
     119           7 :     const Pipe* pipe = getPipe();
     120           7 :     LBASSERT( pipe );
     121           7 :     return ( pipe ? pipe->getConfig() : 0);
     122             : }
     123             : 
     124         349 : Config* Window::getConfig()
     125             : {
     126         349 :     Pipe* pipe = getPipe();
     127         349 :     LBASSERT( pipe );
     128         349 :     return ( pipe ? pipe->getConfig() : 0);
     129             : }
     130             : 
     131         109 : ServerPtr Window::getServer()
     132             : {
     133         109 :     Pipe* pipe = getPipe();
     134         109 :     LBASSERT( pipe );
     135         109 :     return ( pipe ? pipe->getServer() : 0 );
     136             : }
     137             : 
     138          86 : co::CommandQueue* Window::getMainThreadQueue()
     139             : {
     140          86 :     Pipe* pipe = getPipe();
     141          86 :     LBASSERT( pipe );
     142          86 :     return pipe->getMainThreadQueue();
     143             : }
     144             : 
     145         109 : co::CommandQueue* Window::getCommandThreadQueue()
     146             : {
     147         109 :     Pipe* pipe = getPipe();
     148         109 :     LBASSERT( pipe );
     149         109 :     return pipe->getCommandThreadQueue();
     150             : }
     151             : 
     152           0 : Channel* Window::getChannel( const ChannelPath& path )
     153             : {
     154           0 :     const Channels& channels = getChannels();
     155           0 :     LBASSERT( channels.size() > path.channelIndex );
     156             : 
     157           0 :     if( channels.size() <= path.channelIndex )
     158           0 :         return 0;
     159             : 
     160           0 :     return channels[ path.channelIndex ];
     161             : }
     162             : 
     163          22 : void Window::activate()
     164             : {
     165          22 :     Pipe* pipe = getPipe();
     166          22 :     LBASSERT( pipe );
     167             : 
     168          22 :     ++_active;
     169          22 :     pipe->activate();
     170             : 
     171          22 :     LBLOG( LOG_VIEW ) << "activate: " << _active << std::endl;
     172          22 : }
     173             : 
     174          22 : void Window::deactivate()
     175             : {
     176          22 :     LBASSERT( _active != 0 );
     177          22 :     Pipe* pipe = getPipe();
     178          22 :     LBASSERT( pipe );
     179             : 
     180          22 :     --_active;
     181          22 :     pipe->deactivate();
     182             : 
     183          22 :     LBLOG( LOG_VIEW ) << "deactivate: " << _active << std::endl;
     184          22 : }
     185             : 
     186         348 : void Window::addTasks( const uint32_t tasks )
     187             : {
     188         348 :     Pipe* pipe = getPipe();
     189         348 :     LBASSERT( pipe );
     190         348 :     setTasks( getTasks() | tasks );
     191         348 :     pipe->addTasks( tasks );
     192         348 : }
     193             : 
     194             : //---------------------------------------------------------------------------
     195             : // swap barrier operations
     196             : //---------------------------------------------------------------------------
     197           7 : void Window::_resetSwapBarriers()
     198             : {
     199           7 :     Node* node = getNode();
     200           7 :     LBASSERT( node );
     201             : 
     202           7 :     BOOST_FOREACH( co::Barrier* barrier, _masterBarriers )
     203             :     {
     204           0 :         node->releaseBarrier( barrier );
     205             :     }
     206             : 
     207           7 :     _nvNetBarrier = 0;
     208           7 :     _masterBarriers.clear();
     209           7 :     _barriers.clear();
     210           7 : }
     211             : 
     212           0 : co::Barrier* Window::joinSwapBarrier( co::Barrier* barrier )
     213             : {
     214           0 :     _swapFinish = true;
     215             : 
     216           0 :     if( !barrier )
     217             :     {
     218           0 :         Node* node = getNode();
     219           0 :         barrier = node->getBarrier();
     220           0 :         barrier->increase();
     221             : 
     222           0 :         _masterBarriers.push_back( barrier );
     223           0 :         _barriers.push_back( barrier );
     224           0 :         return barrier;
     225             :     }
     226             : 
     227           0 :     co::BarriersCIter i = lunchbox::find( _barriers, barrier );
     228           0 :     if( i != _barriers.end( )) // Issue #39: window already has this barrier
     229           0 :         return barrier;
     230             : 
     231           0 :     LBASSERT( getPipe() );
     232           0 :     const Windows& windows = getPipe()->getWindows();
     233           0 :     bool beforeSelf = true;
     234             : 
     235             :     // Check if another window in the same thread is using the swap barrier
     236           0 :     for( WindowsCIter j = windows.begin(); j != windows.end(); ++j )
     237             :     {
     238           0 :         Window* window = *j;
     239           0 :         if( window == this ) // skip self
     240             :         {
     241           0 :             beforeSelf = false;
     242           0 :             continue;
     243             :         }
     244             : 
     245           0 :         co::Barriers& barriers = window->_barriers;
     246           0 :         co::BarriersIter k = lunchbox::find( barriers, barrier );
     247           0 :         if( k == barriers.end( ))
     248           0 :             continue;
     249             : 
     250           0 :         if( beforeSelf ) // some earlier window will do the barrier for us
     251           0 :             return barrier;
     252             : 
     253             :         // else we will do the barrier, remove from later window
     254           0 :         barriers.erase( k );
     255           0 :         _barriers.push_back( barrier );
     256           0 :         return barrier;
     257             :     }
     258             : 
     259             :     // No other window on this pipe does the barrier yet
     260           0 :     barrier->increase();
     261           0 :     _barriers.push_back( barrier );
     262           0 :     return barrier;
     263             : }
     264             : 
     265           0 : co::Barrier* Window::joinNVSwapBarrier( SwapBarrierConstPtr swapBarrier,
     266             :                                         co::Barrier* netBarrier )
     267             : {
     268           0 :     LBASSERTINFO( !_nvSwapBarrier,
     269             :                   "Only one NV_swap_group barrier per window allowed" );
     270             : 
     271           0 :     _nvSwapBarrier = swapBarrier;
     272           0 :     _nvNetBarrier = netBarrier;
     273             :     // no _swapFinish = true since NV_swap_group takes care of this
     274             : 
     275           0 :     if( !_nvNetBarrier )
     276             :     {
     277           0 :         Node* node = getNode();
     278           0 :         _nvNetBarrier = node->getBarrier();
     279           0 :         _masterBarriers.push_back( _nvNetBarrier );
     280             :     }
     281             : 
     282           0 :     _nvNetBarrier->increase();
     283           0 :     _barriers.push_back( _nvNetBarrier );
     284           0 :     return _nvNetBarrier;
     285             : }
     286             : 
     287             : 
     288          66 : co::ObjectOCommand Window::send( const uint32_t cmd )
     289             : {
     290          66 :     return getNode()->send( cmd, getID( ));
     291             : }
     292             : 
     293             : //===========================================================================
     294             : // Operations
     295             : //===========================================================================
     296             : //---------------------------------------------------------------------------
     297             : // init
     298             : //---------------------------------------------------------------------------
     299          15 : void Window::configInit( const uint128_t& initID, const uint32_t /*frame*/ )
     300             : {
     301          15 :     LBASSERT( !needsDelete( ));
     302          15 :     LBASSERT( _state == STATE_STOPPED );
     303          15 :     _state = STATE_INITIALIZING;
     304             : 
     305          15 :     LBLOG( LOG_INIT ) << "Create Window" << std::endl;
     306          15 :     getPipe()->send( fabric::CMD_PIPE_CREATE_WINDOW ) << getID();
     307             : 
     308          15 :     LBLOG( LOG_INIT ) << "Init Window" << std::endl;
     309          15 :     send( fabric::CMD_WINDOW_CONFIG_INIT ) << initID;
     310          15 :     LBLOG( LOG_TASKS ) << "TASK window configInit  " << " id " << getID()
     311          15 :                        << std::endl;
     312          15 : }
     313             : 
     314          15 : bool Window::syncConfigInit()
     315             : {
     316          15 :     LBASSERT( !needsDelete( ));
     317          15 :     LBASSERT( _state == STATE_INITIALIZING || _state == STATE_INIT_SUCCESS ||
     318             :               _state == STATE_INIT_FAILED );
     319             : 
     320          15 :     _state.waitNE( STATE_INITIALIZING );
     321             : 
     322          15 :     if( _state == STATE_INIT_SUCCESS )
     323             :     {
     324          15 :         _state = STATE_RUNNING;
     325          15 :         return true;
     326             :     }
     327             : 
     328           0 :     configExit();
     329           0 :     return false;
     330             : }
     331             : 
     332             : //---------------------------------------------------------------------------
     333             : // exit
     334             : //---------------------------------------------------------------------------
     335          15 : void Window::configExit()
     336             : {
     337          15 :     if( _state & STATE_EXITING )
     338          15 :         return;
     339             : 
     340          15 :     LBASSERT( isRunning() || _state == STATE_INIT_FAILED );
     341          30 :     _state =
     342          30 :         State( needsDelete() ? STATE_EXITING | STATE_DELETE : STATE_EXITING );
     343             : 
     344          15 :     LBLOG( LOG_INIT ) << "Exit Window" << std::endl;
     345          15 :     send( fabric::CMD_WINDOW_CONFIG_EXIT );
     346             : }
     347             : 
     348          15 : bool Window::syncConfigExit()
     349             : {
     350          15 :     _state.waitNE( STATE_EXITING, State( STATE_EXITING | STATE_DELETE ));
     351          15 :     const bool success = ( _state & STATE_EXIT_SUCCESS );
     352          15 :     LBASSERT( success || _state & STATE_EXIT_FAILED );
     353             : 
     354             :     // EXIT_FAILED -> STOPPED transition
     355          15 :     uint32_t state = needsDelete() ? STATE_DELETE : 0;
     356          15 :     state |= ( isActive() ? STATE_FAILED : STATE_STOPPED );
     357          15 :     _state = State( state );
     358          15 :     _nvSwapBarrier = 0;
     359          15 :     return success;
     360             : }
     361             : 
     362             : //---------------------------------------------------------------------------
     363             : // update
     364             : //---------------------------------------------------------------------------
     365           7 : void Window::updateDraw( const uint128_t& frameID, const uint32_t frameNumber )
     366             : {
     367           7 :     if( !isRunning( ))
     368           7 :         return;
     369             : 
     370           7 :     LBASSERT( isActive( ))
     371             : 
     372             :     send( fabric::CMD_WINDOW_FRAME_START )
     373           7 :             << getVersion() << frameID << frameNumber;
     374           7 :     LBLOG( LOG_TASKS ) << "TASK window start frame " << frameNumber
     375           7 :                        << " id " << frameID << std::endl;
     376             : 
     377           7 :     const Channels& channels = getChannels();
     378           7 :     _swap = false;
     379             : 
     380          31 :     for( ChannelsCIter i = channels.begin(); i != channels.end(); ++i )
     381             :     {
     382          24 :         Channel* channel = *i;
     383          24 :         if( channel->update( frameID, frameNumber ))
     384           7 :             _swap = true;
     385             :     }
     386             : 
     387           7 :     if( _lastDrawChannel )
     388           7 :         _lastDrawChannel = 0;
     389             :     else // no FrameDrawFinish sent
     390             :     {
     391           0 :         send( fabric::CMD_WINDOW_FRAME_DRAW_FINISH ) << frameID << frameNumber;
     392           0 :         LBLOG( LOG_TASKS ) << "TASK window draw finish " << getName()
     393           0 :                            << " frame " << frameNumber
     394           0 :                            << " id " << frameID << std::endl;
     395             :     }
     396             : 
     397           7 :     if( _swapFinish )
     398             :     {
     399           0 :         send( fabric::CMD_WINDOW_FLUSH );
     400           0 :         LBLOG( LOG_TASKS ) << "TASK flush " << std::endl;
     401             :     }
     402             : }
     403             : 
     404           7 : void Window::updatePost( const uint128_t& frameID,
     405             :                          const uint32_t frameNumber )
     406             : {
     407           7 :     if( !isRunning( ))
     408           7 :         return;
     409             : 
     410           7 :     LBASSERT( isActive( ))
     411           7 :     _updateSwap( frameNumber );
     412             : 
     413           7 :     send( fabric::CMD_WINDOW_FRAME_FINISH ) << frameID << frameNumber;
     414           7 :     LBLOG( LOG_TASKS ) << "TASK window finish frame " << frameNumber
     415           7 :                        << " id " << frameID << std::endl;
     416             : }
     417             : 
     418           7 : void Window::_updateSwap( const uint32_t frameNumber )
     419             : {
     420           7 :     if( _swapFinish )
     421             :     {
     422           0 :         send( fabric::CMD_WINDOW_FINISH );
     423           0 :         LBLOG( LOG_TASKS ) << "TASK finish " << frameNumber << std::endl;
     424           0 :         _swapFinish = false;
     425             :     }
     426             : 
     427           7 :     if( _maxFPS < std::numeric_limits< float >::max( ))
     428             :     {
     429           0 :         const float minFrameTime = 1000.0f / _maxFPS;
     430           0 :         send( fabric::CMD_WINDOW_THROTTLE_FRAMERATE ) << minFrameTime;
     431           0 :         LBLOG( LOG_TASKS ) << "TASK Throttle framerate  "
     432           0 :                                << minFrameTime << std::endl;
     433             : 
     434           0 :         _maxFPS = std::numeric_limits< float >::max();
     435             :     }
     436             : 
     437           7 :     for( co::BarriersCIter i = _barriers.begin(); i != _barriers.end(); ++i )
     438             :     {
     439           0 :         const co::Barrier* barrier = *i;
     440           0 :         if( barrier->getHeight() <= 1 )
     441             :         {
     442           0 :             LBVERB << "Ignoring swap barrier of height " << barrier->getHeight()
     443           0 :                    << std::endl;
     444           0 :             continue;
     445             :         }
     446             : 
     447           0 :         send( fabric::CMD_WINDOW_BARRIER ) << co::ObjectVersion( barrier );
     448           0 :         LBLOG( LOG_TASKS ) << "TASK barrier  barrier "
     449           0 :                            << co::ObjectVersion( barrier ) << std::endl;
     450             :     }
     451             : 
     452           7 :     if( _nvNetBarrier )
     453             :     {
     454           0 :         if( _nvNetBarrier->getHeight() <= 1 )
     455             :         {
     456           0 :             LBWARN << "Ignoring NV swap barrier of height "
     457           0 :                    << _nvNetBarrier->getHeight() << std::endl;
     458             :         }
     459             :         else
     460             :         {
     461           0 :             LBASSERT( _nvSwapBarrier );
     462           0 :             LBASSERT( _nvSwapBarrier->isNvSwapBarrier( ));
     463             :             // Entering the NV_swap_group. The _nvNetBarrier is also part of
     464             :             // _barriers, which means that the pre-join was already sync'ed
     465             :             // with a barrier.
     466             : 
     467             :             // Now enter the swap group and post-sync with the barrier again.
     468             :             send( fabric::CMD_WINDOW_NV_BARRIER )
     469           0 :                     << co::ObjectVersion( _nvNetBarrier )
     470           0 :                     << _nvSwapBarrier->getNVSwapGroup()
     471           0 :                     << _nvSwapBarrier->getNVSwapBarrier();
     472             :         }
     473             :     }
     474             : 
     475           7 :     _resetSwapBarriers();
     476             : 
     477           7 :     if( _swap )
     478             :     {
     479           7 :         send( fabric::CMD_WINDOW_SWAP );
     480           7 :         LBLOG( LOG_TASKS ) << "TASK swap  " << frameNumber << std::endl;
     481             :     }
     482           7 : }
     483             : 
     484             : //===========================================================================
     485             : // command handling
     486             : //===========================================================================
     487          15 : bool Window::_cmdConfigInitReply( co::ICommand& cmd )
     488             : {
     489          15 :     co::ObjectICommand command( cmd );
     490          15 :     LBVERB << "handle window configInit reply " << command << std::endl;
     491             : 
     492          15 :     LBASSERT( !needsDelete( ));
     493          15 :     _state = command.read< bool >() ? STATE_INIT_SUCCESS : STATE_INIT_FAILED;
     494          15 :     return true;
     495             : }
     496             : 
     497          15 : bool Window::_cmdConfigExitReply( co::ICommand& cmd )
     498             : {
     499          15 :     co::ObjectICommand command( cmd );
     500          15 :     LBVERB << "handle window configExit reply " << command << std::endl;
     501             : 
     502          15 :     if( command.read< bool >( ))
     503          30 :         _state = State( needsDelete() ?
     504          15 :                         STATE_EXIT_SUCCESS|STATE_DELETE : STATE_EXIT_SUCCESS );
     505             :     else
     506           0 :         _state = State( needsDelete() ?
     507           0 :                         STATE_EXIT_FAILED | STATE_DELETE : STATE_EXIT_FAILED );
     508          15 :     return true;
     509             : }
     510             : 
     511         409 : void Window::output( std::ostream& os ) const
     512             : {
     513         409 :     bool attrPrinted   = false;
     514             : 
     515       15542 :     for( WindowSettings::IAttribute i = static_cast<WindowSettings::IAttribute>( 0 );
     516        7771 :          i < WindowSettings::IATTR_LAST;
     517             :          i = static_cast<WindowSettings::IAttribute>( static_cast<uint32_t>( i )+1))
     518             :     {
     519        7362 :         const int value = getIAttribute( i );
     520        7362 :         if( value == Global::instance()->getWindowIAttribute( i ))
     521        7255 :             continue;
     522             : 
     523         107 :         if( !attrPrinted )
     524             :         {
     525          84 :             os << std::endl << "attributes" << std::endl;
     526          84 :             os << "{" << std::endl << lunchbox::indent;
     527          84 :             attrPrinted = true;
     528             :         }
     529             : 
     530             :         os << ( i== WindowSettings::IATTR_HINT_STEREO ?
     531             :                     "hint_stereo        " :
     532             :                 i== WindowSettings::IATTR_HINT_DOUBLEBUFFER ?
     533             :                     "hint_doublebuffer  " :
     534             :                 i== WindowSettings::IATTR_HINT_FULLSCREEN ?
     535             :                     "hint_fullscreen    " :
     536             :                 i== WindowSettings::IATTR_HINT_DECORATION ?
     537             :                     "hint_decoration    " :
     538             :                 i== WindowSettings::IATTR_HINT_SWAPSYNC ?
     539             :                     "hint_swapsync      " :
     540             :                 i== WindowSettings::IATTR_HINT_DRAWABLE ?
     541             :                     "hint_drawable      " :
     542             :                 i== WindowSettings::IATTR_HINT_STATISTICS ?
     543             :                     "hint_statistics    " :
     544             :                 i== WindowSettings::IATTR_HINT_SCREENSAVER ?
     545             :                     "hint_screensaver   " :
     546             :                 i== WindowSettings::IATTR_HINT_GRAB_POINTER ?
     547             :                     "hint_grab_pointer  " :
     548             :                 i== WindowSettings::IATTR_PLANES_COLOR ?
     549             :                     "planes_color       " :
     550             :                 i== WindowSettings::IATTR_PLANES_ALPHA ?
     551             :                     "planes_alpha       " :
     552             :                 i== WindowSettings::IATTR_PLANES_DEPTH ?
     553             :                     "planes_depth       " :
     554             :                 i== WindowSettings::IATTR_PLANES_STENCIL ?
     555             :                     "planes_stencil     " :
     556             :                 i== WindowSettings::IATTR_PLANES_ACCUM ?
     557             :                     "planes_accum       " :
     558             :                 i== WindowSettings::IATTR_PLANES_ACCUM_ALPHA ?
     559             :                     "planes_accum_alpha " :
     560             :                 i== WindowSettings::IATTR_PLANES_SAMPLES ?
     561         107 :                     "planes_samples     " : "ERROR" )
     562         107 :            << static_cast< fabric::IAttribute >( value ) << std::endl;
     563             :     }
     564             : 
     565         409 :     if( attrPrinted )
     566          84 :         os << lunchbox::exdent << "}" << std::endl << std::endl;
     567         409 : }
     568             : 
     569             : }
     570             : }
     571             : 
     572             : #include "../fabric/window.ipp"
     573             : template class eq::fabric::Window< eq::server::Pipe, eq::server::Window,
     574             :                                    eq::server::Channel >;
     575             : 
     576             : /** @cond IGNORE */
     577             : template std::ostream& eq::fabric::operator << ( std::ostream&,
     578          27 :                                                  const eq::server::Super& );
     579             : /** @endcond */

Generated by: LCOV version 1.10