server/window.cpp

00001 
00002 /* Copyright (c) 2005-2009, Stefan Eilemann <eile@equalizergraphics.com> 
00003  *
00004  * This library is free software; you can redistribute it and/or modify it under
00005  * the terms of the GNU Lesser General Public License version 2.1 as published
00006  * by the Free Software Foundation.
00007  *  
00008  * This library is distributed in the hope that it will be useful, but WITHOUT
00009  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00010  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00011  * details.
00012  * 
00013  * You should have received a copy of the GNU Lesser General Public License
00014  * along with this library; if not, write to the Free Software Foundation, Inc.,
00015  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00016  */
00017 
00018 #include <pthread.h>
00019 
00020 #include "window.h"
00021 
00022 #include "global.h"
00023 #include "channel.h"
00024 #include "config.h"
00025 #include "compound.h"
00026 #include "log.h"
00027 #include "node.h"
00028 #include "paths.h"
00029 #include "pipe.h"
00030 #include "windowVisitor.h"
00031 
00032 #include <eq/client/packets.h>
00033 #include <eq/net/command.h>
00034 
00035 using namespace eq::base;
00036 using namespace std;
00037 
00038 namespace eq
00039 {
00040 namespace server
00041 {
00042 typedef net::CommandFunc<Window> WindowFunc;
00043 
00044 void Window::_construct()
00045 {
00046     _active          = 0;
00047     _pipe            = 0;
00048     _tasks           = eq::TASK_NONE;
00049     _fixedPVP        = false;
00050     _lastDrawChannel = 0;
00051     _maxFPS          = numeric_limits< float >::max();
00052     _swapFinish      = false;
00053     _swap            = false;
00054     _nvSwapBarrier   = 0;
00055     _nvNetBarrier    = 0;
00056     EQINFO << "New window @" << (void*)this << endl;
00057 }
00058 
00059 Window::Window()
00060 {
00061     _construct();
00062     
00063     const Global* global = Global::instance();
00064     for( int i=0; i<eq::Window::IATTR_ALL; ++i )
00065         _iAttributes[i] = global->getWindowIAttribute(
00066             static_cast<eq::Window::IAttribute>( i ));
00067 }
00068 
00069 Window::Window( const Window& from, Pipe* pipe )
00070         : net::Object()
00071 {
00072     _construct();
00073 
00074     _name     = from._name;
00075     _pvp      = from._pvp;
00076     _vp       = from._vp;
00077     _fixedPVP = from._fixedPVP;
00078 
00079     pipe->addWindow( this );
00080 
00081     for( int i=0; i<eq::Window::IATTR_ALL; ++i )
00082         _iAttributes[i] = from._iAttributes[i];
00083 
00084     const ChannelVector& channels = from.getChannels();
00085     for( ChannelVector::const_iterator i = channels.begin();
00086          i != channels.end(); ++i )
00087     {
00088         new Channel( **i, this );
00089     }            
00090 }
00091 
00092 Window::~Window()
00093 {
00094     EQINFO << "Delete window @" << (void*)this << endl;
00095 
00096     if( _pipe )
00097         _pipe->removeWindow( this );
00098     
00099     for( ChannelVector::const_iterator i = _channels.begin(); 
00100          i != _channels.end(); ++i )
00101     {
00102         Channel* channel = *i;
00103 
00104         channel->_window = 0;
00105         delete channel;
00106     }
00107     _channels.clear();
00108 }
00109 
00110 void Window::attachToSession( const uint32_t id, const uint32_t instanceID, 
00111                                net::Session* session )
00112 {
00113     net::Object::attachToSession( id, instanceID, session );
00114     
00115     net::CommandQueue* commandQueue = getCommandThreadQueue();
00116 
00117     registerCommand( eq::CMD_WINDOW_CONFIG_INIT_REPLY, 
00118                      WindowFunc( this, &Window::_cmdConfigInitReply),
00119                      commandQueue );
00120     registerCommand( eq::CMD_WINDOW_CONFIG_EXIT_REPLY, 
00121                      WindowFunc( this, &Window::_cmdConfigExitReply),
00122                      commandQueue );
00123     registerCommand( eq::CMD_WINDOW_SET_PVP, 
00124                      WindowFunc( this, &Window::_cmdSetPixelViewport ),
00125                      commandQueue );
00126                          
00127 }
00128 
00129 void Window::addChannel( Channel* channel )
00130 {
00131     EQASSERT( find( _channels.begin(), _channels.end(), channel ) == 
00132               _channels.end( ));
00133 
00134     _channels.push_back( channel ); 
00135     channel->_window = this;
00136     channel->notifyViewportChanged();
00137 }
00138 
00139 void Window::insertChannel( const Channel* position, Channel* channel )
00140 {
00141     ChannelVector::iterator i = std::find( _channels.begin(), _channels.end(),
00142                                            position );
00143     if( i != _channels.end( ))
00144         ++i;
00145 
00146     _channels.insert( i, channel );
00147     channel->_window = this;
00148     channel->notifyViewportChanged();    
00149 }
00150 
00151 bool Window::removeChannel( Channel* channel )
00152 {
00153     ChannelVector::iterator i = find( _channels.begin(), _channels.end(),
00154                                         channel );
00155     if( i == _channels.end( ))
00156         return false;
00157 
00158     _channels.erase( i );
00159     channel->_window = 0;
00160     return true;
00161 }
00162 
00163 Node* Window::getNode()
00164 {
00165     EQASSERT( _pipe );
00166     return (_pipe ? _pipe->getNode() : 0); 
00167 }
00168 const Node* Window::getNode() const
00169 {
00170     EQASSERT( _pipe );
00171     return (_pipe ? _pipe->getNode() : 0); 
00172 }
00173 
00174 Config* Window::getConfig()
00175 {
00176     EQASSERT( _pipe );
00177     return (_pipe ? _pipe->getConfig() : 0); 
00178 }
00179 const Config* Window::getConfig() const 
00180 {
00181     EQASSERT( _pipe );
00182     return (_pipe ? _pipe->getConfig() : 0); 
00183 }
00184         
00185 net::CommandQueue* Window::getServerThreadQueue()
00186 {
00187     EQASSERT( _pipe );
00188     return _pipe->getServerThreadQueue(); 
00189 }
00190 
00191 net::CommandQueue* Window::getCommandThreadQueue()
00192 { 
00193     EQASSERT( _pipe );
00194     return _pipe->getCommandThreadQueue(); 
00195 }
00196 
00197 WindowPath Window::getPath() const
00198 {
00199     EQASSERT( _pipe );
00200     WindowPath path( _pipe->getPath( ));
00201     
00202     const WindowVector&    windows = _pipe->getWindows();
00203     WindowVector::const_iterator i = std::find( windows.begin(), windows.end(),
00204                                                 this );
00205     EQASSERT( i != windows.end( ));
00206     path.windowIndex = std::distance( windows.begin(), i );
00207     return path;
00208 }
00209 
00210 Channel* Window::getChannel( const ChannelPath& path )
00211 {
00212     EQASSERT( _channels.size() > path.channelIndex );
00213 
00214     if( _channels.size() <= path.channelIndex )
00215         return 0;
00216 
00217     return _channels[ path.channelIndex ];
00218 }
00219 
00220 namespace
00221 {
00222 template< class C, class V >
00223 VisitorResult _accept( C* window, V& visitor )
00224 { 
00225     VisitorResult result = visitor.visitPre( window );
00226     if( result != TRAVERSE_CONTINUE )
00227         return result;
00228 
00229     const ChannelVector& channels = window->getChannels();
00230     for( ChannelVector::const_iterator i = channels.begin(); 
00231          i != channels.end(); ++i )
00232     {
00233         switch( (*i)->accept( visitor ))
00234         {
00235             case TRAVERSE_TERMINATE:
00236                 return TRAVERSE_TERMINATE;
00237 
00238             case TRAVERSE_PRUNE:
00239                 result = TRAVERSE_PRUNE;
00240                 break;
00241                 
00242             case TRAVERSE_CONTINUE:
00243             default:
00244                 break;
00245         }
00246     }
00247 
00248     switch( visitor.visitPost( window ))
00249     {
00250         case TRAVERSE_TERMINATE:
00251             return TRAVERSE_TERMINATE;
00252 
00253         case TRAVERSE_PRUNE:
00254             return TRAVERSE_PRUNE;
00255                 
00256         case TRAVERSE_CONTINUE:
00257         default:
00258             break;
00259     }
00260 
00261     return result;
00262 }
00263 }
00264 
00265 VisitorResult Window::accept( WindowVisitor& visitor )
00266 {
00267     return _accept( this, visitor );
00268 }
00269 
00270 VisitorResult Window::accept( ConstWindowVisitor& visitor ) const
00271 {
00272     return _accept( this, visitor );
00273 }
00274 
00275 void Window::activate()
00276 {   
00277     EQASSERT( _pipe );
00278 
00279     ++_active;
00280     if( _pipe ) 
00281         _pipe->activate();
00282 
00283     EQLOG( LOG_VIEW ) << "activate: " << _active << std::endl;
00284 }
00285 
00286 void Window::deactivate()
00287 { 
00288     EQASSERT( _active != 0 );
00289     EQASSERT( _pipe );
00290 
00291     --_active; 
00292     if( _pipe ) 
00293         _pipe->deactivate(); 
00294 
00295     EQLOG( LOG_VIEW ) << "deactivate: " << _active << std::endl;
00296 };
00297 
00298 void Window::addTasks( const uint32_t tasks )
00299 {
00300     EQASSERT( _pipe );
00301     _tasks |= tasks;
00302     _pipe->addTasks( tasks );
00303 }
00304 
00305 //----------------------------------------------------------------------
00306 // viewport
00307 //----------------------------------------------------------------------
00308 void Window::setPixelViewport( const eq::PixelViewport& pvp )
00309 {
00310     if( !pvp.isValid( ))
00311         return;
00312 
00313     _fixedPVP = true;
00314 
00315     if( pvp == _pvp )
00316         return;
00317 
00318     _pvp      = pvp;
00319     _vp.invalidate();
00320     notifyViewportChanged();
00321 }
00322 
00323 void Window::setViewport( const eq::Viewport& vp )
00324 {
00325     if( !vp.hasArea( ))
00326         return;
00327 
00328     _fixedPVP = false;
00329 
00330     if( vp == _vp )
00331         return;
00332     
00333     _vp = vp;
00334     _pvp.invalidate();
00335     notifyViewportChanged();
00336 }
00337 
00338 void Window::notifyViewportChanged()
00339 {
00340     if( _pipe )
00341     {
00342         eq::PixelViewport pipePVP = _pipe->getPixelViewport();
00343         if( pipePVP.hasArea( ))
00344         {
00345             if( _fixedPVP ) // update viewport
00346                 _vp = _pvp.getSubVP( pipePVP );
00347             else            // update pixel viewport
00348                 _pvp = pipePVP.getSubPVP( _vp );
00349         }
00350     }
00351     EQINFO << "Window viewport update: " << _pvp << ":" << _vp << endl;
00352 
00353     for( ChannelVector::iterator i = _channels.begin();
00354          i != _channels.end(); ++i )
00355 
00356         (*i)->notifyViewportChanged();
00357 }
00358 
00359 //---------------------------------------------------------------------------
00360 // swap barrier operations
00361 //---------------------------------------------------------------------------
00362 void Window::_resetSwapBarriers()
00363 { 
00364     Node* node = getNode();
00365     EQASSERT( node );
00366 
00367     for( vector<net::Barrier*>::iterator i = _masterSwapBarriers.begin();
00368          i != _masterSwapBarriers.end(); ++i )
00369             
00370         node->releaseBarrier( *i );
00371 
00372     _nvNetBarrier = 0;
00373     _masterSwapBarriers.clear();
00374     _swapBarriers.clear();
00375 }
00376 
00377 net::Barrier* Window::joinSwapBarrier( net::Barrier* barrier )
00378 {
00379     _swapFinish = true;
00380 
00381     if( !barrier )
00382     {
00383         Node* node = getNode();
00384         barrier = node->getBarrier();
00385         barrier->increase();
00386 
00387         _masterSwapBarriers.push_back( barrier );
00388         _swapBarriers.push_back( barrier );
00389         return barrier;
00390     }
00391 
00392     EQASSERT( _pipe );
00393     const WindowVector& windows = _pipe->getWindows();
00394     bool beforeSelf = true;
00395 
00396     // Check if another window in the same thread is using the swap barrier
00397     for( WindowVector::const_iterator i = windows.begin(); 
00398          i != windows.end(); ++i )
00399     {
00400         Window* window = *i;
00401 
00402         if( window == this ) // skip self
00403         {
00404             beforeSelf = false;
00405             continue;
00406         }
00407 
00408         net::BarrierVector& barriers = window->_swapBarriers;
00409         net::BarrierVector::iterator j =
00410             std::find( barriers.begin(), barriers.end(), barrier );
00411         if( j == barriers.end( ))
00412             continue;
00413 
00414         if( beforeSelf ) // some earlier window will do the barrier for us
00415             return barrier;
00416             
00417         // else we will do the barrier, remove from later window
00418         barriers.erase( j );
00419         _swapBarriers.push_back( barrier );
00420         return barrier;
00421     }
00422 
00423     // No other window on this pipe does the barrier yet
00424     barrier->increase();
00425     _swapBarriers.push_back( barrier );
00426     return barrier;
00427 }
00428 
00429 net::Barrier* Window::joinNVSwapBarrier( const SwapBarrier* swapBarrier,
00430                                          net::Barrier* netBarrier )
00431 { 
00432     EQASSERTINFO( !_nvSwapBarrier, 
00433                   "Only one NV_swap_group barrier per window allowed" );
00434 
00435     _nvSwapBarrier = swapBarrier;
00436     _nvNetBarrier = netBarrier;
00437     // no _swapFinish = true since NV_swap_group takes care of this
00438 
00439     if( !_nvNetBarrier )
00440     {
00441         Node* node = getNode();
00442         _nvNetBarrier = node->getBarrier();
00443         _masterSwapBarriers.push_back( _nvNetBarrier );
00444     }
00445 
00446     _nvNetBarrier->increase();
00447     _swapBarriers.push_back( _nvNetBarrier );
00448     return _nvNetBarrier;
00449 }
00450 
00451 
00452 void Window::send( net::ObjectPacket& packet ) 
00453 {
00454     packet.objectID = getID(); 
00455     getNode()->send( packet ); 
00456 }
00457 
00458 void Window::_send( net::ObjectPacket& packet, const std::string& string ) 
00459 {
00460     packet.objectID = getID(); 
00461     getNode()->send( packet, string ); 
00462 }
00463 
00464 //===========================================================================
00465 // Operations
00466 //===========================================================================
00467 
00468 //---------------------------------------------------------------------------
00469 // update running entities (init/exit)
00470 //---------------------------------------------------------------------------
00471 
00472 void Window::updateRunning( const uint32_t initID )
00473 {
00474     if( !isActive() && _state == STATE_STOPPED ) // inactive
00475         return;
00476 
00477     if( isActive() && _state != STATE_RUNNING ) // becoming active
00478         _configInit( initID );
00479 
00480     // Let all running channels update their running state (incl. children)
00481     for( ChannelVector::const_iterator i = _channels.begin(); 
00482          i != _channels.end(); ++i )
00483     {
00484         (*i)->updateRunning( initID );
00485     }
00486 
00487     if( !isActive( )) // becoming inactive
00488         _configExit();
00489 }
00490 
00491 bool Window::syncRunning()
00492 {
00493     if( !isActive() && _state == STATE_STOPPED ) // inactive
00494         return true;
00495 
00496     // Sync state updates
00497     bool success = true;
00498     for( ChannelVector::const_iterator i = _channels.begin(); 
00499          i != _channels.end(); ++i )
00500     {
00501         Channel* channel = *i;
00502         if( !channel->syncRunning( ))
00503         {
00504             _error += "channel " + channel->getName() + ": '" + 
00505                       channel->getErrorMessage() + '\'';
00506             success = false;
00507         }
00508     }
00509 
00510     if( isActive() && _state != STATE_RUNNING && !_syncConfigInit( ))
00511         // becoming active
00512         success = false;
00513 
00514     if( !isActive() && !_syncConfigExit( ))
00515         // becoming inactive
00516         success = false;
00517 
00518     EQASSERT( _state == STATE_STOPPED || _state == STATE_RUNNING || 
00519               _state == STATE_INIT_FAILED );
00520     return success;
00521 }
00522 
00523 //---------------------------------------------------------------------------
00524 // init
00525 //---------------------------------------------------------------------------
00526 void Window::_configInit( const uint32_t initID )
00527 {
00528     EQASSERT( _state == STATE_STOPPED );
00529     _state         = STATE_INITIALIZING;
00530 
00531     getConfig()->registerObject( this );
00532 
00533     EQLOG( LOG_INIT ) << "Create Window" << std::endl;
00534     eq::PipeCreateWindowPacket createWindowPacket;
00535     createWindowPacket.windowID = getID();
00536     _pipe->send( createWindowPacket );
00537 
00538     eq::WindowConfigInitPacket packet;
00539     packet.initID = initID;
00540     packet.tasks  = _tasks;
00541 
00542     if( _fixedPVP )
00543         packet.pvp    = _pvp; 
00544     else
00545         packet.vp     = _vp;
00546 
00547     memcpy( packet.iAttributes, _iAttributes, 
00548             eq::Window::IATTR_ALL * sizeof( int32_t ));
00549     
00550     EQLOG( LOG_INIT ) << "Init Window" << std::endl;
00551     _send( packet, _name );
00552     EQLOG( eq::LOG_TASKS ) << "TASK window configInit  " << &packet << endl;
00553 }
00554 
00555 bool Window::_syncConfigInit()
00556 {
00557     EQASSERT( _state == STATE_INITIALIZING || _state == STATE_INIT_SUCCESS ||
00558               _state == STATE_INIT_FAILED );
00559 
00560     _state.waitNE( STATE_INITIALIZING );
00561 
00562     const bool success = ( _state == STATE_INIT_SUCCESS );
00563     if( success )
00564         _state = STATE_RUNNING;
00565     else
00566         EQWARN << "Window initialization failed: " << _error << endl;
00567 
00568     return success;
00569 }
00570 
00571 //---------------------------------------------------------------------------
00572 // exit
00573 //---------------------------------------------------------------------------
00574 void Window::_configExit()
00575 {
00576     EQASSERT( _state == STATE_RUNNING || _state == STATE_INIT_FAILED );
00577     _state = STATE_EXITING;
00578 
00579     EQLOG( LOG_INIT ) << "Exit Window" << std::endl;
00580     eq::WindowConfigExitPacket packet;
00581     send( packet );
00582 
00583     EQLOG( LOG_INIT ) << "Destroy Window" << std::endl;
00584     eq::PipeDestroyWindowPacket destroyWindowPacket;
00585     destroyWindowPacket.windowID = getID();
00586     _pipe->send( destroyWindowPacket );
00587 }
00588 
00589 bool Window::_syncConfigExit()
00590 {
00591     EQASSERT( _state == STATE_EXITING || _state == STATE_EXIT_SUCCESS || 
00592               _state == STATE_EXIT_FAILED );
00593     
00594     _state.waitNE( STATE_EXITING );
00595     const bool success = ( _state == STATE_EXIT_SUCCESS );
00596     EQASSERT( success || _state == STATE_EXIT_FAILED );
00597 
00598     getConfig()->deregisterObject( this );
00599 
00600     _state = STATE_STOPPED; // EXIT_FAILED -> STOPPED transition
00601     _nvSwapBarrier = 0;
00602     _tasks = eq::TASK_NONE;
00603     return success;
00604 }
00605 
00606 //---------------------------------------------------------------------------
00607 // update
00608 //---------------------------------------------------------------------------
00609 void Window::updateDraw( const uint32_t frameID, const uint32_t frameNumber )
00610 {
00611     EQASSERT( _state == STATE_RUNNING );
00612     EQASSERT( _active > 0 );
00613 
00614     _swap = false;
00615 
00616     eq::WindowFrameStartPacket startPacket;
00617     startPacket.frameID     = frameID;
00618     startPacket.frameNumber = frameNumber;
00619     send( startPacket );
00620     EQLOG( eq::LOG_TASKS ) << "TASK window start frame  " << &startPacket 
00621                            << endl;
00622 
00623     for( ChannelVector::const_iterator i = _channels.begin(); 
00624          i != _channels.end(); ++i )
00625     {
00626         Channel* channel = *i;
00627         if( channel->isActive( ))
00628             _swap |= channel->update( frameID, frameNumber );
00629     }
00630 
00631     if( _swapFinish )
00632     {
00633         eq::WindowFinishPacket packet;
00634         send( packet );
00635         EQLOG( eq::LOG_TASKS ) << "TASK finish  " << &packet << endl;
00636         _swapFinish = false;
00637     }
00638 }
00639 
00640 void Window::updatePost( const uint32_t frameID, 
00641                          const uint32_t frameNumber )
00642 {
00643     _updateSwap( frameNumber );
00644 
00645     eq::WindowFrameFinishPacket finishPacket;
00646     finishPacket.frameID     = frameID;
00647     finishPacket.frameNumber = frameNumber;
00648     send( finishPacket );
00649     EQLOG( eq::LOG_TASKS ) << "TASK window finish frame  " << &finishPacket
00650                            << endl;
00651     _lastDrawChannel = 0;
00652 }
00653 
00654 void Window::_updateSwap( const uint32_t frameNumber )
00655 {
00656     if( _maxFPS < numeric_limits< float >::max( ))
00657     {
00658         eq::WindowThrottleFramerate packetThrottle;
00659         packetThrottle.minFrameTime = 1000.0f / _maxFPS;
00660         
00661         send( packetThrottle );
00662         EQLOG( eq::LOG_TASKS ) << "TASK Throttle framerate  " 
00663                                << &packetThrottle << endl;
00664 
00665         _maxFPS = numeric_limits< float >::max();
00666     }
00667     
00668     for( vector<net::Barrier*>::iterator i = _swapBarriers.begin();
00669          i != _swapBarriers.end(); ++i )
00670     {
00671         const net::Barrier*   barrier = *i;
00672 
00673         if( barrier->getHeight() <= 1 )
00674         {
00675             EQINFO << "Ignoring swap barrier of height " << barrier->getHeight()
00676                    << endl;
00677             continue;
00678         }
00679 
00680         eq::WindowBarrierPacket packet;
00681         packet.barrier = barrier;
00682         send( packet );
00683 
00684         EQLOG( eq::LOG_TASKS ) << "TASK barrier  " << &packet << endl;
00685     }
00686 
00687     if( _nvNetBarrier )
00688     {
00689         if( _nvNetBarrier->getHeight() <= 1 )
00690         {
00691             EQWARN << "Ignoring NV swap barrier of height "
00692                    << _nvNetBarrier->getHeight() << std::endl;
00693         }
00694         else
00695         {
00696             EQASSERT( _nvSwapBarrier );
00697             EQASSERT( _nvSwapBarrier->isNvSwapBarrier( ));
00698             // Entering the NV_swap_group. The _nvNetBarrier is also part of
00699             // _swapBarriers, which means that the pre-join was already sync'ed
00700             // with a barrier.
00701 
00702             // Now enter the swap group and post-sync with the barrier again.
00703             eq::WindowNVBarrierPacket packet;
00704             packet.barrier = _nvSwapBarrier->getNVSwapBarrier();
00705             packet.group   = _nvSwapBarrier->getNVSwapGroup();
00706             packet.netBarrier = _nvNetBarrier;
00707             send( packet );
00708         }
00709     }
00710 
00711     _resetSwapBarriers();
00712 
00713     if( _swap )
00714     {
00715         eq::WindowSwapPacket packet;
00716 
00717         send( packet );
00718         EQLOG( eq::LOG_TASKS ) << "TASK swap  " << &packet << endl;
00719     }
00720 }
00721 
00722 //===========================================================================
00723 // command handling
00724 //===========================================================================
00725 net::CommandResult Window::_cmdConfigInitReply( net::Command& command )
00726 {
00727     const eq::WindowConfigInitReplyPacket* packet =
00728         command.getPacket<eq::WindowConfigInitReplyPacket>();
00729     EQVERB << "handle window configInit reply " << packet << endl;
00730 
00731     if( packet->pvp.isValid( ))
00732         setPixelViewport( packet->pvp );
00733 
00734     _error = packet->error;
00735 
00736     if( packet->result )
00737     {
00738         _drawableConfig = packet->drawableConfig;
00739         _state = STATE_INIT_SUCCESS;
00740     }
00741     else
00742         _state = STATE_INIT_FAILED;
00743 
00744     return net::COMMAND_HANDLED;
00745 }
00746 
00747 net::CommandResult Window::_cmdConfigExitReply( net::Command& command )
00748 {
00749     const eq::WindowConfigExitReplyPacket* packet =
00750         command.getPacket<eq::WindowConfigExitReplyPacket>();
00751     EQVERB << "handle window configExit reply " << packet << endl;
00752 
00753     if( packet->result )
00754         _state = STATE_EXIT_SUCCESS;
00755     else
00756         _state = STATE_EXIT_FAILED;
00757 
00758     return net::COMMAND_HANDLED;
00759 }
00760 
00761 net::CommandResult Window::_cmdSetPixelViewport( net::Command& command)
00762 {
00763     const eq::WindowSetPVPPacket* packet = 
00764         command.getPacket<eq::WindowSetPVPPacket>();
00765     EQVERB << "handle window set pvp " << packet << endl;
00766 
00767     setPixelViewport( packet->pvp );
00768     return net::COMMAND_HANDLED;
00769 }
00770 
00771 std::ostream& operator << ( std::ostream& os, const Window* window )
00772 {
00773     if( !window )
00774         return os;
00775     
00776     os << disableFlush << disableHeader << "window" << endl;
00777     os << "{" << endl << indent; 
00778 
00779     const std::string& name = window->getName();
00780     if( !name.empty( ))
00781         os << "name     \"" << name << "\"" << endl;
00782 
00783     const eq::Viewport& vp  = window->getViewport();
00784     if( vp.isValid( ) && !window->_fixedPVP )
00785     {
00786         if( vp != eq::Viewport::FULL )
00787             os << "viewport " << vp << endl;
00788     }
00789     else
00790     {
00791         const eq::PixelViewport& pvp = window->getPixelViewport();
00792         if( pvp.isValid( ))
00793             os << "viewport " << pvp << endl;
00794     }
00795 
00796     bool attrPrinted   = false;
00797     
00798     for( eq::Window::IAttribute i = static_cast<eq::Window::IAttribute>( 0 );
00799          i<eq::Window::IATTR_ALL; 
00800          i = static_cast<eq::Window::IAttribute>( static_cast<uint32_t>( i )+1))
00801     {
00802         const int value = window->getIAttribute( i );
00803         if( value == Global::instance()->getWindowIAttribute( i ))
00804             continue;
00805 
00806         if( !attrPrinted )
00807         {
00808             os << endl << "attributes" << endl;
00809             os << "{" << endl << indent;
00810             attrPrinted = true;
00811         }
00812         
00813         os << ( i==eq::Window::IATTR_HINT_STEREO ?
00814                     "hint_stereo        " :
00815                 i==eq::Window::IATTR_HINT_DOUBLEBUFFER ?
00816                     "hint_doublebuffer  " :
00817                 i==eq::Window::IATTR_HINT_FULLSCREEN ?
00818                     "hint_fullscreen    " :
00819                 i==eq::Window::IATTR_HINT_DECORATION ?
00820                     "hint_decoration    " :
00821                 i==eq::Window::IATTR_HINT_SWAPSYNC ?
00822                     "hint_swapsync      " :
00823                 i==eq::Window::IATTR_HINT_DRAWABLE ?
00824                     "hint_drawable      " :
00825                 i==eq::Window::IATTR_HINT_STATISTICS ?
00826                     "hint_statistics    " :
00827                 i==eq::Window::IATTR_PLANES_COLOR ? 
00828                     "planes_color       " :
00829                 i==eq::Window::IATTR_PLANES_ALPHA ?
00830                     "planes_alpha       " :
00831                 i==eq::Window::IATTR_PLANES_DEPTH ?
00832                     "planes_depth       " :
00833                 i==eq::Window::IATTR_PLANES_STENCIL ?
00834                     "planes_stencil     " :
00835                 i==eq::Window::IATTR_PLANES_ACCUM ?
00836                     "planes_accum       " :
00837                 i==eq::Window::IATTR_PLANES_ACCUM_ALPHA ?
00838                     "planes_accum_alpha " :
00839                 i==eq::Window::IATTR_PLANES_SAMPLES ?
00840                     "planes_samples     " : "ERROR" )
00841            << static_cast<eq::IAttrValue>( value ) << endl;
00842     }
00843     
00844     if( attrPrinted )
00845         os << exdent << "}" << endl << endl;
00846 
00847     const ChannelVector& channels = window->getChannels();
00848     for( ChannelVector::const_iterator i = channels.begin(); 
00849          i != channels.end(); ++i )
00850     {
00851         const Channel* channel = *i;
00852         if( channel->getView() && channel->getSegment( ))
00853             continue; // don't print generated channels for now
00854 
00855         os << channel;
00856     }
00857 
00858     os << exdent << "}" << endl << enableHeader << enableFlush;
00859     return os;
00860 }
00861 
00862 }
00863 }
Generated on Mon Aug 10 18:58:41 2009 for Equalizer 0.9 by  doxygen 1.5.8