server/window.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
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 )
00346 _vp = _pvp.getSubVP( pipePVP );
00347 else
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
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
00397 for( WindowVector::const_iterator i = windows.begin();
00398 i != windows.end(); ++i )
00399 {
00400 Window* window = *i;
00401
00402 if( window == this )
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 )
00415 return barrier;
00416
00417
00418 barriers.erase( j );
00419 _swapBarriers.push_back( barrier );
00420 return barrier;
00421 }
00422
00423
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
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
00466
00467
00468
00469
00470
00471
00472 void Window::updateRunning( const uint32_t initID )
00473 {
00474 if( !isActive() && _state == STATE_STOPPED )
00475 return;
00476
00477 if( isActive() && _state != STATE_RUNNING )
00478 _configInit( initID );
00479
00480
00481 for( ChannelVector::const_iterator i = _channels.begin();
00482 i != _channels.end(); ++i )
00483 {
00484 (*i)->updateRunning( initID );
00485 }
00486
00487 if( !isActive( ))
00488 _configExit();
00489 }
00490
00491 bool Window::syncRunning()
00492 {
00493 if( !isActive() && _state == STATE_STOPPED )
00494 return true;
00495
00496
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
00512 success = false;
00513
00514 if( !isActive() && !_syncConfigExit( ))
00515
00516 success = false;
00517
00518 EQASSERT( _state == STATE_STOPPED || _state == STATE_RUNNING ||
00519 _state == STATE_INIT_FAILED );
00520 return success;
00521 }
00522
00523
00524
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
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;
00601 _nvSwapBarrier = 0;
00602 _tasks = eq::TASK_NONE;
00603 return success;
00604 }
00605
00606
00607
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
00699
00700
00701
00702
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
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;
00854
00855 os << channel;
00856 }
00857
00858 os << exdent << "}" << endl << enableHeader << enableFlush;
00859 return os;
00860 }
00861
00862 }
00863 }