00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "compound.h"
00019
00020 #include "canvas.h"
00021 #include "channel.h"
00022 #include "colorMask.h"
00023 #include "compoundExitVisitor.h"
00024 #include "compoundInitVisitor.h"
00025 #include "compoundListener.h"
00026 #include "compoundUpdateDataVisitor.h"
00027 #include "compoundUpdateInputVisitor.h"
00028 #include "compoundUpdateOutputVisitor.h"
00029 #include "config.h"
00030 #include "constCompoundVisitor.h"
00031 #include "equalizers/equalizer.h"
00032 #include "frame.h"
00033 #include "frameData.h"
00034 #include "global.h"
00035 #include "layout.h"
00036 #include "log.h"
00037 #include "paths.h"
00038 #include "segment.h"
00039 #include "swapBarrier.h"
00040 #include "view.h"
00041
00042 #include <eq/base/base.h>
00043 #include <eq/base/stdExt.h>
00044 #include <eq/client/colorMask.h>
00045 #include <eq/client/global.h>
00046 #include <eq/client/packets.h>
00047 #include <eq/client/windowSystem.h>
00048 #include <eq/net/session.h>
00049
00050 #include <algorithm>
00051 #include <math.h>
00052 #include <vector>
00053
00054 #include "compoundActivateVisitor.h"
00055
00056 using namespace eq::base;
00057 using namespace std;
00058 using namespace stde;
00059
00060 namespace eq
00061 {
00062 namespace server
00063 {
00064 #define MAKE_ATTR_STRING( attr ) ( string("EQ_COMPOUND_") + #attr )
00065 std::string Compound::_iAttributeStrings[IATTR_ALL] = {
00066 MAKE_ATTR_STRING( IATTR_STEREO_MODE ),
00067 MAKE_ATTR_STRING( IATTR_STEREO_ANAGLYPH_LEFT_MASK ),
00068 MAKE_ATTR_STRING( IATTR_STEREO_ANAGLYPH_RIGHT_MASK ),
00069 MAKE_ATTR_STRING( IATTR_HINT_OFFSET ),
00070 MAKE_ATTR_STRING( IATTR_FILL1 ),
00071 MAKE_ATTR_STRING( IATTR_FILL2 )
00072 };
00073
00074 Compound::Compound()
00075 : _config( 0 )
00076 , _parent( 0 )
00077 , _active( false )
00078 , _usage( 1.0f )
00079 , _taskID( 0 )
00080 , _frustum( _data.frustumData )
00081 , _swapBarrier( 0 )
00082 {
00083 EQINFO << "New Compound @" << (void*)this << endl;
00084 }
00085
00086
00087 Compound::Compound( const Compound& from, Config* config, Compound* parent )
00088 : _name( from._name )
00089 , _config( 0 )
00090 , _parent( 0 )
00091 , _active( false )
00092 , _usage( from._usage )
00093 , _taskID( from._taskID )
00094 , _data( from._data )
00095 , _frustum( from._frustum, _data.frustumData )
00096 , _swapBarrier( 0 )
00097 {
00098 EQASSERTINFO( (config && !parent) || (!config && parent),
00099 "Either config or parent has to be given" );
00100
00101 if( config )
00102 config->addCompound( this );
00103 else
00104 {
00105 EQASSERT( parent );
00106 parent->addChild( this );
00107 }
00108
00109 if( from._data.channel )
00110 {
00111 const Channel* oldChannel = from._data.channel;
00112 const ChannelPath path = oldChannel->getPath();
00113
00114 _data.channel = getConfig()->getChannel( path );
00115 EQASSERT( _data.channel );
00116 }
00117
00118 for( CompoundVector::const_iterator i = from._children.begin();
00119 i != from._children.end(); ++i )
00120 {
00121 new Compound( **i, 0, this );
00122 }
00123
00124 for( EqualizerVector::const_iterator i = from._equalizers.begin();
00125 i != from._equalizers.end(); ++i )
00126 {
00127 addEqualizer( (*i)->clone( ));
00128 }
00129
00130 if( from._swapBarrier )
00131 _swapBarrier = new SwapBarrier( *from._swapBarrier );
00132
00133 for( FrameVector::const_iterator i = from._inputFrames.begin();
00134 i != from._inputFrames.end(); ++i )
00135 {
00136 addInputFrame( new Frame( **i ));
00137 }
00138
00139 for( FrameVector::const_iterator i = from._outputFrames.begin();
00140 i != from._outputFrames.end(); ++i )
00141 {
00142 addOutputFrame( new Frame( **i ));
00143 }
00144 }
00145
00146 Compound::~Compound()
00147 {
00148 delete _swapBarrier;
00149 _swapBarrier = 0;
00150
00151 for( EqualizerVector::const_iterator i = _equalizers.begin();
00152 i != _equalizers.end(); ++i )
00153 {
00154 Equalizer* equalizer = *i;
00155 equalizer->attach( 0 );
00156 delete equalizer;
00157 }
00158 _equalizers.clear();
00159
00160 for( CompoundVector::const_iterator i = _children.begin();
00161 i != _children.end(); ++i )
00162 {
00163 Compound* compound = *i;
00164 delete compound;
00165 }
00166 _children.clear();
00167
00168 if( _config )
00169 _config->removeCompound( this );
00170
00171 _config = 0;
00172
00173 for( FrameVector::const_iterator i = _inputFrames.begin();
00174 i != _inputFrames.end(); ++i )
00175 {
00176 Frame* frame = *i;
00177
00178 frame->_compound = 0;
00179 delete frame;
00180 }
00181 _inputFrames.clear();
00182
00183 for( FrameVector::const_iterator i = _outputFrames.begin();
00184 i != _outputFrames.end(); ++i )
00185 {
00186 Frame* frame = *i;
00187
00188 frame->_compound = 0;
00189 delete frame;
00190 }
00191 _outputFrames.clear();
00192
00193 _parent = 0;
00194 }
00195
00196 Compound::InheritData::InheritData()
00197 : channel( 0 )
00198 , overdraw( Vector4i::ZERO )
00199 , buffers( eq::Frame::BUFFER_UNDEFINED )
00200 , eyes( EYE_UNDEFINED )
00201 , tasks( eq::TASK_DEFAULT )
00202 , period( EQ_UNDEFINED_UINT32 )
00203 , phase( EQ_UNDEFINED_UINT32 )
00204 , maxFPS( numeric_limits< float >::max( ))
00205 , active( true )
00206 {
00207 const Global* global = Global::instance();
00208 for( int i=0; i<IATTR_ALL; ++i )
00209 iAttributes[i] =
00210 global->getCompoundIAttribute( static_cast< IAttribute >( i ));
00211 }
00212
00213 void Compound::addChild( Compound* child )
00214 {
00215 _children.push_back( child );
00216 EQASSERT( !child->_parent );
00217 child->_parent = this;
00218 _fireChildAdded( child );
00219 }
00220
00221 bool Compound::removeChild( Compound* child )
00222 {
00223 CompoundVector::iterator i = find( _children.begin(), _children.end(),
00224 child );
00225 if( i == _children.end( ))
00226 return false;
00227
00228 _fireChildRemove( child );
00229 _children.erase( i );
00230 child->_parent = 0;
00231 return true;
00232 }
00233
00234 Compound* Compound::getNext() const
00235 {
00236 if( !_parent )
00237 return 0;
00238
00239 vector<Compound*>& siblings = _parent->_children;
00240 vector<Compound*>::iterator result = find( siblings.begin(),
00241 siblings.end(), this);
00242
00243 if( result == siblings.end() )
00244 return 0;
00245 result++;
00246 if( result == siblings.end() )
00247 return 0;
00248
00249 return *result;
00250 }
00251
00252 Node* Compound::getNode()
00253 {
00254 Channel* channel = getChannel();
00255 return channel ? channel->getNode() : 0;
00256 }
00257
00258 void Compound::setChannel( Channel* channel )
00259 {
00260 _data.channel = channel;
00261 }
00262
00263 const Channel* Compound::getChannel() const
00264 {
00265 if( _data.channel )
00266 return _data.channel;
00267 if( _parent )
00268 return _parent->getChannel();
00269 return 0;
00270 }
00271
00272 Channel* Compound::getChannel()
00273 {
00274 if( _data.channel )
00275 return _data.channel;
00276 if( _parent )
00277 return _parent->getChannel();
00278 return 0;
00279 }
00280
00281 Window* Compound::getWindow()
00282 {
00283 Channel* channel = getChannel();
00284 if( channel )
00285 return channel->getWindow();
00286 return 0;
00287 }
00288
00289 const Window* Compound::getWindow() const
00290 {
00291 const Channel* channel = getChannel();
00292 if( channel )
00293 return channel->getWindow();
00294 return 0;
00295 }
00296
00297 Pipe* Compound::getPipe()
00298 {
00299 Channel* channel = getChannel();
00300 if( channel )
00301 return channel->getPipe();
00302 return 0;
00303 }
00304
00305 const Pipe* Compound::getPipe() const
00306 {
00307 const Channel* channel = getChannel();
00308 if( channel )
00309 return channel->getPipe();
00310 return 0;
00311 }
00312
00313 void Compound::addEqualizer( Equalizer* equalizer )
00314 {
00315 if( equalizer )
00316 equalizer->attach( this );
00317
00318 _equalizers.push_back( equalizer );
00319 }
00320
00321 bool Compound::isActive() const
00322 {
00323 const Channel* channel = getChannel();
00324 if( channel )
00325 return _inherit.active && channel->isActive();
00326
00327 return _inherit.active;
00328 }
00329
00330
00331
00332
00333 void Compound::addListener( CompoundListener* listener )
00334 {
00335 _listeners.push_back( listener );
00336 }
00337
00338 void Compound::removeListener( CompoundListener* listener )
00339 {
00340 CompoundListeners::iterator i = find( _listeners.begin(), _listeners.end(),
00341 listener );
00342 if( i != _listeners.end( ))
00343 _listeners.erase( i );
00344 }
00345
00346 void Compound::fireUpdatePre( const uint32_t frameNumber )
00347 {
00348 CHECK_THREAD( _serverThread );
00349
00350 for( CompoundListeners::const_iterator i = _listeners.begin();
00351 i != _listeners.end(); ++i )
00352
00353 (*i)->notifyUpdatePre( this, frameNumber );
00354 }
00355
00356 void Compound::_fireChildAdded( Compound* child )
00357 {
00358 CHECK_THREAD( _serverThread );
00359
00360 for( CompoundListeners::const_iterator i = _listeners.begin();
00361 i != _listeners.end(); ++i )
00362
00363 (*i)->notifyChildAdded( this, child );
00364 }
00365
00366 void Compound::_fireChildRemove( Compound* child )
00367 {
00368 CHECK_THREAD( _serverThread );
00369
00370 for( CompoundListeners::const_iterator i = _listeners.begin();
00371 i != _listeners.end(); ++i )
00372
00373 (*i)->notifyChildRemove( this, child );
00374 }
00375
00376
00377
00378
00379 void Compound::setSwapBarrier( SwapBarrier* barrier )
00380 {
00381 if( barrier && barrier->getName().empty( ))
00382 {
00383 const Compound* root = getRoot();
00384 const string& rootName = root->getName();
00385 if( rootName.empty( ))
00386 barrier->setName( "barrier" );
00387 else
00388 barrier->setName( "barrier." + rootName );
00389 }
00390
00391 _swapBarrier = barrier;
00392 }
00393
00394 void Compound::addInputFrame( Frame* frame )
00395 {
00396 EQASSERT( frame );
00397 if( frame->getName().empty() )
00398 _setDefaultFrameName( frame );
00399 _inputFrames.push_back( frame );
00400 frame->_compound = this;
00401 }
00402 void Compound::addOutputFrame( Frame* frame )
00403 {
00404 if( frame->getName().empty() )
00405 _setDefaultFrameName( frame );
00406 _outputFrames.push_back( frame );
00407 frame->_compound = this;
00408 }
00409
00410 void Compound::_setDefaultFrameName( Frame* frame )
00411 {
00412 for( Compound* compound = this; compound; compound = compound->getParent())
00413 {
00414 if( !compound->getName().empty( ))
00415 {
00416 frame->setName( "frame." + compound->getName( ));
00417 return;
00418 }
00419
00420 const Channel* channel = compound->getChannel();
00421 if( channel && !channel->getName().empty( ))
00422 {
00423 frame->setName( "frame." + channel->getName( ));
00424 return;
00425 }
00426 }
00427 frame->setName( "frame" );
00428 }
00429
00430 bool Compound::isDestination() const
00431 {
00432 if( !getChannel( ))
00433 return false;
00434
00435 if( !getParent( ))
00436 return true;
00437
00438 for( const Compound* compound = getParent(); compound;
00439 compound = compound->getParent())
00440 {
00441 if( compound->getChannel() )
00442 return false;
00443 }
00444
00445 return true;
00446 }
00447
00448
00449
00450 void Compound::setWall( const eq::Wall& wall )
00451 {
00452 _frustum.setWall( wall );
00453 EQVERB << "Wall: " << _data.frustumData << endl;
00454 }
00455
00456 void Compound::setProjection( const eq::Projection& projection )
00457 {
00458 _frustum.setProjection( projection );
00459 EQVERB << "Projection: " << _data.frustumData << endl;
00460 }
00461
00462 void Compound::updateFrustum()
00463 {
00464 if( !isDestination( ))
00465 return;
00466
00467 Channel* channel = getChannel();
00468 if( !channel )
00469 return;
00470
00471 const Segment* segment = channel->getSegment();
00472 const View* view = channel->getView();
00473 if( !segment || !view )
00474 return;
00475
00476 if( view->getCurrentType() != Frustum::TYPE_NONE )
00477 {
00478
00479
00480 const Viewport& segmentVP = segment->getViewport();
00481 const Viewport& viewVP = view->getViewport();
00482 const Viewport coverage = viewVP.getCoverage( segmentVP );
00483
00484 Wall wall( view->getWall( ));
00485
00486 wall.apply( coverage );
00487 _updateOverdraw( wall );
00488
00489 switch( view->getCurrentType( ))
00490 {
00491 case Frustum::TYPE_WALL:
00492 setWall( wall );
00493 EQLOG( LOG_VIEW ) << "Compound wall: " << wall << std::endl;
00494 return;
00495
00496 case Frustum::TYPE_PROJECTION:
00497 {
00498 Projection projection( view->getProjection( ));
00499 projection = wall;
00500 setProjection( projection );
00501 EQLOG( LOG_VIEW ) << "Compound projection: " << projection
00502 << std::endl;
00503 return;
00504 }
00505
00506 default:
00507 EQUNIMPLEMENTED;
00508 }
00509 }
00510
00511 if( segment->getCurrentType() != Frustum::TYPE_NONE )
00512 {
00513
00514
00515 const Channel* outputChannel = segment->getChannel();
00516 EQASSERT( outputChannel );
00517
00518 const Viewport& outputVP = outputChannel->getViewport();
00519 const Viewport& channelVP = channel->getViewport();
00520 const Viewport coverage = outputVP.getCoverage( channelVP );
00521
00522 Wall wall( segment->getWall( ));
00523
00524 wall.apply( coverage );
00525 _updateOverdraw( wall );
00526
00527 switch( segment->getCurrentType( ))
00528 {
00529 case Frustum::TYPE_WALL:
00530 {
00531 setWall( wall );
00532 EQLOG( LOG_VIEW ) << "Compound wall: " << wall << std::endl;
00533 return;
00534 }
00535
00536 case Frustum::TYPE_PROJECTION:
00537 {
00538 Projection projection( segment->getProjection( ));
00539 projection = wall;
00540 setProjection( projection );
00541 EQLOG( LOG_VIEW ) << "Compound projection: " << projection
00542 << std::endl;
00543 return;
00544 }
00545 default:
00546 EQUNIMPLEMENTED;
00547 }
00548 }
00549 }
00550
00551 void Compound::_updateOverdraw( Wall& wall )
00552 {
00553 Channel* channel = getChannel();
00554 EQASSERT( channel );
00555 if( !channel )
00556 return;
00557
00558 const Segment* segment = channel->getSegment();
00559 const View* view = channel->getView();
00560 EQASSERT( segment && view );
00561 if( !segment || !view )
00562 return;
00563
00564 const Viewport& segmentVP = segment->getViewport();
00565 const Viewport& viewVP = view->getViewport();
00566 const Vector2i& overdraw = view->getOverdraw();
00567 Vector4i channelOverdraw( Vector4i::ZERO );
00568
00569
00570 if( overdraw.x() && viewVP.x < segmentVP.x )
00571 channelOverdraw.x() = overdraw.x();
00572
00573 if( overdraw.x() && viewVP.getXEnd() > segmentVP.getXEnd( ))
00574 channelOverdraw.z() = overdraw.x();
00575
00576 if( overdraw.y() && viewVP.y < segmentVP.y )
00577 channelOverdraw.y() = overdraw.y();
00578
00579 if( overdraw.y() && viewVP.getYEnd() > segmentVP.getYEnd( ))
00580 channelOverdraw.w() = overdraw.y();
00581
00582
00583 const Vector2i& maxSize = channel->getMaxSize();
00584 if( maxSize != Vector2i::ZERO )
00585 {
00586 const PixelViewport& channelPVP = channel->getPixelViewport();
00587
00588 const int32_t xOverdraw = channelOverdraw.x() + channelOverdraw.z();
00589 const int32_t xSize = xOverdraw + channelPVP.w;
00590 if( xSize > maxSize.x( ))
00591 {
00592 const uint32_t maxOverdraw = maxSize.x() - channelPVP.w;
00593 const float ratio = static_cast< float >( maxOverdraw ) /
00594 static_cast< float >( xOverdraw );
00595 channelOverdraw.x() = static_cast< int >(
00596 channelOverdraw.x() * ratio + .5f );
00597 channelOverdraw.z() = maxOverdraw - channelOverdraw.x();
00598 }
00599
00600 const int32_t yOverdraw = channelOverdraw.y() + channelOverdraw.w();
00601 const int32_t ySize = yOverdraw + channelPVP.h;
00602 if( ySize > maxSize.y( ))
00603 {
00604 const uint32_t maxOverdraw = maxSize.y() - channelPVP.h;
00605 const float ratio = static_cast< float >( maxOverdraw ) /
00606 static_cast< float >( yOverdraw );
00607 channelOverdraw.y() = static_cast< int >(
00608 channelOverdraw.y() * ratio +.5f );
00609 channelOverdraw.w() = maxOverdraw - channelOverdraw.y();
00610 }
00611 }
00612
00613
00614 if( channelOverdraw.x() > 0 )
00615 {
00616 const PixelViewport& pvp = channel->getPixelViewport();
00617 const float ratio = static_cast<float>( pvp.w + channelOverdraw.x( )) /
00618 static_cast<float>( pvp.w );
00619 wall.resizeLeft( ratio );
00620 }
00621
00622 if( channelOverdraw.z() > 0 )
00623 {
00624 const PixelViewport& pvp = channel->getPixelViewport();
00625 const float ratio = static_cast<float>( pvp.w + channelOverdraw.z( )) /
00626 static_cast<float>( pvp.w );
00627 wall.resizeRight( ratio );
00628 }
00629
00630 if( channelOverdraw.y() > 0 )
00631 {
00632 const PixelViewport& pvp = channel->getPixelViewport();
00633 const float ratio = static_cast<float>( pvp.h + channelOverdraw.y( )) /
00634 static_cast<float>( pvp.h );
00635 wall.resizeBottom( ratio );
00636 }
00637
00638 if( channelOverdraw.w() > 0 )
00639 {
00640 const PixelViewport& pvp = channel->getPixelViewport();
00641 const float ratio = static_cast<float>( pvp.h + channelOverdraw.w( )) /
00642 static_cast<float>( pvp.h );
00643 wall.resizeTop( ratio );
00644 }
00645
00646 channel->setOverdraw( channelOverdraw );
00647 }
00648
00649
00650
00651
00652 namespace
00653 {
00654 template< class C, class V > VisitorResult _accept( C* compound, V& visitor )
00655 {
00656 if( compound->isLeaf( ))
00657 return visitor.visitLeaf( compound );
00658
00659 C* current = compound;
00660 VisitorResult result = TRAVERSE_CONTINUE;
00661
00662 while( true )
00663 {
00664 C* parent = current->getParent();
00665 C* next = current->getNext();
00666
00667 const CompoundVector& children = current->getChildren();
00668 C* child = children.empty() ? 0 : children[0];
00669
00670
00671 if ( !child )
00672 {
00673 switch( visitor.visitLeaf( current ))
00674 {
00675 case TRAVERSE_TERMINATE:
00676 return TRAVERSE_TERMINATE;
00677
00678 case TRAVERSE_PRUNE:
00679 result = TRAVERSE_PRUNE;
00680 current = next;
00681 break;
00682
00683 case TRAVERSE_CONTINUE:
00684 current = next;
00685 break;
00686
00687 default:
00688 EQASSERTINFO( 0, "Unreachable" );
00689 }
00690 }
00691 else
00692 {
00693 switch( visitor.visitPre( current ))
00694 {
00695 case TRAVERSE_TERMINATE:
00696 return TRAVERSE_TERMINATE;
00697
00698 case TRAVERSE_PRUNE:
00699 result = TRAVERSE_PRUNE;
00700 current = next;
00701 break;
00702
00703 case TRAVERSE_CONTINUE:
00704 current = child;
00705 break;
00706
00707 default:
00708 EQASSERTINFO( 0, "Unreachable" );
00709 }
00710 }
00711
00712
00713 if( !current && !parent ) return TRAVERSE_CONTINUE;
00714
00715 while( !current )
00716 {
00717 current = parent;
00718 parent = current->getParent();
00719 next = current->getNext();
00720
00721 switch( visitor.visitPost( current ))
00722 {
00723 case TRAVERSE_TERMINATE:
00724 return TRAVERSE_TERMINATE;
00725
00726 case TRAVERSE_PRUNE:
00727 result = TRAVERSE_PRUNE;
00728 break;
00729
00730 case TRAVERSE_CONTINUE:
00731 break;
00732
00733 default:
00734 EQASSERTINFO( 0, "Unreachable" );
00735 }
00736
00737 if ( current == compound )
00738 return result;
00739
00740 current = next;
00741 }
00742 }
00743 return result;
00744 }
00745 }
00746
00747 VisitorResult Compound::accept( CompoundVisitor& visitor )
00748 {
00749 return _accept( this, visitor );
00750 }
00751
00752 VisitorResult Compound::accept( ConstCompoundVisitor& visitor ) const
00753 {
00754 return _accept( this, visitor );
00755 }
00756
00757
00758
00759
00760
00761 void Compound::activate()
00762 {
00763 EQASSERT( isDestination( ));
00764
00765 CompoundActivateVisitor activator( true );
00766 accept( activator );
00767 }
00768
00769 void Compound::deactivate()
00770 {
00771 EQASSERT( isDestination( ));
00772
00773 CompoundActivateVisitor deactivator( false );
00774 accept( deactivator );
00775 }
00776
00777 void Compound::init()
00778 {
00779 CompoundInitVisitor initVisitor;
00780 accept( initVisitor );
00781 }
00782
00783 void Compound::exit()
00784 {
00785 CompoundExitVisitor visitor;
00786 accept( visitor );
00787 }
00788
00789
00790
00791
00792 void Compound::update( const uint32_t frameNumber )
00793 {
00794 CompoundUpdateDataVisitor updateDataVisitor( frameNumber );
00795 accept( updateDataVisitor );
00796
00797 CompoundUpdateOutputVisitor updateOutputVisitor( frameNumber );
00798 accept( updateOutputVisitor );
00799
00800 const hash_map<std::string, Frame*>& outputFrames =
00801 updateOutputVisitor.getOutputFrames();
00802 CompoundUpdateInputVisitor updateInputVisitor( outputFrames );
00803 accept( updateInputVisitor );
00804
00805 const BarrierMap& swapBarriers = updateOutputVisitor.getSwapBarriers();
00806
00807 for( hash_map<string, net::Barrier*>::const_iterator i =
00808 swapBarriers.begin(); i != swapBarriers.end(); ++i )
00809 {
00810 net::Barrier* barrier = i->second;
00811 if( barrier->getHeight() > 1 )
00812 barrier->commit();
00813 }
00814 }
00815
00816 void Compound::updateInheritData( const uint32_t frameNumber )
00817 {
00818 _data.pixel.validate();
00819 _data.zoom.validate();
00820
00821 if( !_parent )
00822 {
00823 _inherit = _data;
00824 _inherit.zoom = eq::Zoom::NONE;
00825
00826 if( _inherit.eyes == EYE_UNDEFINED )
00827 _inherit.eyes = EYE_CYCLOP_BIT;
00828
00829 if( _inherit.period == EQ_UNDEFINED_UINT32 )
00830 _inherit.period = 1;
00831
00832 if( _inherit.phase == EQ_UNDEFINED_UINT32 )
00833 _inherit.phase = 0;
00834
00835 if( _inherit.channel )
00836 _updateInheritPVP();
00837
00838 if( _inherit.buffers == eq::Frame::BUFFER_UNDEFINED )
00839 _inherit.buffers = eq::Frame::BUFFER_COLOR;
00840
00841 if( _inherit.iAttributes[IATTR_STEREO_MODE] == eq::UNDEFINED )
00842 _inherit.iAttributes[IATTR_STEREO_MODE] = eq::QUAD;
00843
00844 if( _inherit.iAttributes[IATTR_STEREO_ANAGLYPH_LEFT_MASK] ==
00845 eq::UNDEFINED )
00846 {
00847 _inherit.iAttributes[IATTR_STEREO_ANAGLYPH_LEFT_MASK] =
00848 COLOR_MASK_RED;
00849 }
00850 if( _inherit.iAttributes[IATTR_STEREO_ANAGLYPH_RIGHT_MASK] ==
00851 eq::UNDEFINED )
00852 {
00853 _inherit.iAttributes[IATTR_STEREO_ANAGLYPH_RIGHT_MASK] =
00854 COLOR_MASK_GREEN | COLOR_MASK_BLUE;
00855 }
00856 }
00857 else
00858 {
00859 _inherit = _parent->_inherit;
00860
00861 if( !_inherit.channel )
00862 _inherit.channel = _data.channel;
00863
00864 if( _data.frustumData.isValid( ))
00865 _inherit.frustumData = _data.frustumData;
00866
00867 _inherit.range.apply( _data.range );
00868 _inherit.pixel.apply( _data.pixel );
00869
00870 if( _data.eyes != EYE_UNDEFINED )
00871 _inherit.eyes = _data.eyes;
00872
00873 if( _data.period != EQ_UNDEFINED_UINT32 )
00874 _inherit.period = _data.period;
00875
00876 if( _data.phase != EQ_UNDEFINED_UINT32 )
00877 _inherit.phase = _data.phase;
00878
00879 _inherit.maxFPS = _data.maxFPS;
00880
00881 if ( _inherit.pvp.isValid( ))
00882 {
00883 EQASSERT( _data.vp.isValid( ));
00884 _inherit.pvp.apply( _data.vp );
00885
00886
00887
00888
00889 const Viewport vp = _inherit.pvp.getSubVP( _parent->_inherit.pvp );
00890 _inherit.vp.apply( vp );
00891
00892 _updateInheritOverdraw();
00893 }
00894 else if( _inherit.channel )
00895 {
00896 _updateInheritPVP();
00897 _inherit.vp.apply( _data.vp );
00898 }
00899
00900 if( _data.buffers != eq::Frame::BUFFER_UNDEFINED )
00901 _inherit.buffers = _data.buffers;
00902
00903 if( _data.iAttributes[IATTR_STEREO_MODE] != eq::UNDEFINED )
00904 _inherit.iAttributes[IATTR_STEREO_MODE] =
00905 _data.iAttributes[IATTR_STEREO_MODE];
00906
00907 if( _data.iAttributes[IATTR_STEREO_ANAGLYPH_LEFT_MASK] != eq::UNDEFINED)
00908 _inherit.iAttributes[IATTR_STEREO_ANAGLYPH_LEFT_MASK] =
00909 _data.iAttributes[IATTR_STEREO_ANAGLYPH_LEFT_MASK];
00910
00911 if( _data.iAttributes[IATTR_STEREO_ANAGLYPH_RIGHT_MASK] !=eq::UNDEFINED)
00912 _inherit.iAttributes[IATTR_STEREO_ANAGLYPH_RIGHT_MASK] =
00913 _data.iAttributes[IATTR_STEREO_ANAGLYPH_RIGHT_MASK];
00914 }
00915
00916 if( _inherit.pvp.isValid( ))
00917 {
00918 _inherit.pvp.apply( _data.pixel );
00919
00920
00921 const eq::PixelViewport unzoomedPVP( _inherit.pvp );
00922 _inherit.pvp.apply( _data.zoom );
00923
00924
00925
00926 const Zoom zoom = _inherit.pvp.getZoom( unzoomedPVP );
00927 _inherit.zoom *= zoom;
00928 }
00929
00930
00931 if( frameNumber != 0 &&
00932 ( !_inherit.pvp.hasArea() || !_inherit.range.hasData( )) )
00933 {
00934
00935
00936 _inherit.tasks = eq::TASK_NONE;
00937 }
00938 else if( _data.tasks == eq::TASK_DEFAULT )
00939 {
00940 if( isLeaf( ))
00941 _inherit.tasks = eq::TASK_ALL;
00942 else
00943 _inherit.tasks = eq::TASK_ASSEMBLE | eq::TASK_READBACK;
00944 }
00945 else
00946 _inherit.tasks = _data.tasks;
00947
00948 if( isDestination() && getChannel()->getView( ))
00949 _inherit.tasks |= eq::TASK_VIEW;
00950 else
00951 _inherit.tasks &= ~eq::TASK_VIEW;
00952
00953
00954 _inherit.active = (( frameNumber % _inherit.period ) == _inherit.phase);
00955 }
00956
00957 void Compound::_updateInheritPVP()
00958 {
00959 const PixelViewport oldPVP( _inherit.pvp );
00960
00961 const Channel* channel = _inherit.channel;
00962 const View* view = channel->getView();
00963
00964 _inherit.pvp = channel->getPixelViewport( );
00965
00966 if( !view || !_inherit.pvp.isValid( ))
00967 {
00968 EQASSERT( channel->getOverdraw() == Vector4i::ZERO );
00969 return;
00970 }
00971 EQASSERT( channel == getChannel( ));
00972
00973
00974 const Vector4i& overdraw = channel->getOverdraw();
00975 _inherit.pvp.w += overdraw.x() + overdraw.z();
00976 _inherit.pvp.h += overdraw.y() + overdraw.w();
00977
00978 if( oldPVP != _inherit.pvp )
00979 {
00980 updateFrustum();
00981 EQASSERT( overdraw == channel->getOverdraw( ));
00982 }
00983
00984 _inherit.overdraw = overdraw;
00985 }
00986
00987 void Compound::_updateInheritOverdraw()
00988 {
00989 const PixelViewport& pvp = _inherit.pvp;
00990 const PixelViewport& parentPVP = _parent->_inherit.pvp;
00991
00992 _inherit.overdraw.x() -= pvp.x - parentPVP.x;
00993 _inherit.overdraw.y() -= pvp.y - parentPVP.y;
00994 _inherit.overdraw.z() -= parentPVP.getXEnd() - pvp.getXEnd();
00995 _inherit.overdraw.w() -= parentPVP.getYEnd() - pvp.getYEnd();
00996
00997 _inherit.overdraw.x() = EQ_MAX( _inherit.overdraw.x(), 0 );
00998 _inherit.overdraw.y() = EQ_MAX( _inherit.overdraw.y(), 0 );
00999 _inherit.overdraw.z() = EQ_MAX( _inherit.overdraw.z(), 0 );
01000 _inherit.overdraw.w() = EQ_MAX( _inherit.overdraw.w(), 0 );
01001
01002 _inherit.overdraw.x() = EQ_MIN( _inherit.overdraw.x(), pvp.w );
01003 _inherit.overdraw.y() = EQ_MIN( _inherit.overdraw.y(), pvp.h );
01004 _inherit.overdraw.z() = EQ_MIN( _inherit.overdraw.z(), pvp.w );
01005 _inherit.overdraw.w() = EQ_MIN( _inherit.overdraw.w(), pvp.h );
01006
01007 EQASSERTINFO( pvp.w >= _inherit.overdraw.x() + _inherit.overdraw.z(),
01008 pvp.w << " < " <<
01009 _inherit.overdraw.x() + _inherit.overdraw.z( ));
01010 EQASSERTINFO( pvp.h >= _inherit.overdraw.y() + _inherit.overdraw.w(),
01011 pvp.h << " < " <<
01012 _inherit.overdraw.y() + _inherit.overdraw.w( ));
01013 }
01014
01015 std::ostream& operator << (std::ostream& os, const Compound* compound)
01016 {
01017 if( !compound )
01018 return os;
01019
01020 os << disableFlush << "compound" << endl;
01021 os << "{" << endl << indent;
01022
01023 const std::string& name = compound->getName();
01024 if( !name.empty( ))
01025 os << "name \"" << name << "\"" << endl;
01026
01027 const Channel* channel = compound->getChannel();
01028 if( channel )
01029 {
01030 Compound* parent = compound->getParent();
01031 if( !parent || parent->getChannel() != channel )
01032 {
01033 const std::string& channelName = channel->getName();
01034 const Config* config = compound->getConfig();
01035 EQASSERT( config );
01036
01037 if( !channelName.empty() &&
01038 config->findChannel( channelName ) == channel )
01039 {
01040 os << "channel \"" << channelName << "\"" << endl;
01041 }
01042 else
01043 {
01044 const Segment* segment = channel->getSegment();
01045 const View* view = channel->getView();
01046
01047 if( view && segment )
01048 {
01049 os << "channel ( ";
01050
01051 const std::string& segmentName = segment->getName();
01052 if( !segmentName.empty() &&
01053 config->findSegment( segmentName ) == segment )
01054 {
01055 const Canvas* canvas = segment->getCanvas();
01056 const std::string& canvasName = canvas->getName();
01057 if( !canvasName.empty() &&
01058 config->findCanvas( canvasName ) == canvas )
01059 {
01060 os << "canvas \"" << canvasName << "\" ";
01061 }
01062 else
01063 os << canvas->getPath() << ' ';
01064
01065 os << "segment \"" << segmentName << "\" ";
01066 }
01067 else
01068 os << segment->getPath() << ' ';
01069
01070 const std::string& viewName = view->getName();
01071 if( !viewName.empty() &&
01072 config->findView( viewName ) == view )
01073 {
01074 const Layout* layout = view->getLayout();
01075 const std::string& layoutName = layout->getName();
01076 if( !layoutName.empty() &&
01077 config->findLayout( layoutName ) == layout )
01078 {
01079 os << "layout \"" << layoutName << "\" ";
01080 }
01081 else
01082 os << layout->getPath() << ' ';
01083
01084 os << "view \"" << viewName << '\"';
01085 }
01086 else
01087 os << view->getPath();
01088
01089 os << " )" << endl;
01090 }
01091 else
01092 os << "channel ( " << channel->getPath() << " )" << endl;
01093 }
01094 }
01095 }
01096
01097 const uint32_t tasks = compound->getTasks();
01098 if( tasks != eq::TASK_DEFAULT )
01099 {
01100 os << "task [";
01101 if( tasks & eq::TASK_CLEAR ) os << " CLEAR";
01102 if( tasks & eq::TASK_CULL ) os << " CULL";
01103 if( compound->isLeaf() &&
01104 ( tasks & eq::TASK_DRAW )) os << " DRAW";
01105 if( tasks & eq::TASK_ASSEMBLE ) os << " ASSEMBLE";
01106 if( tasks & eq::TASK_READBACK ) os << " READBACK";
01107 os << " ]" << endl;
01108 }
01109
01110 const uint32_t buffers = compound->getBuffers();
01111 if( buffers != eq::Frame::BUFFER_UNDEFINED )
01112 {
01113 os << "buffers [";
01114 if( buffers & eq::Frame::BUFFER_COLOR ) os << " COLOR";
01115 if( buffers & eq::Frame::BUFFER_DEPTH ) os << " DEPTH";
01116 os << " ]" << endl;
01117 }
01118
01119 const eq::Viewport& vp = compound->getViewport();
01120 if( vp.isValid() && vp != eq::Viewport::FULL )
01121 os << "viewport " << vp << endl;
01122
01123 const eq::Range& range = compound->getRange();
01124 if( range.isValid() && range != eq::Range::ALL )
01125 os << range << endl;
01126
01127 const eq::Pixel& pixel = compound->getPixel();
01128 if( pixel.isValid() && pixel != eq::Pixel::ALL )
01129 os << pixel << endl;
01130
01131 const eq::Zoom& zoom = compound->getZoom();
01132 if( zoom.isValid() && zoom != eq::Zoom::NONE )
01133 os << zoom << endl;
01134
01135 const uint32_t eye = compound->getEyes();
01136 if( eye )
01137 {
01138 os << "eye [ ";
01139 if( eye & Compound::EYE_CYCLOP_BIT )
01140 os << "CYCLOP ";
01141 if( eye & Compound::EYE_LEFT_BIT )
01142 os << "LEFT ";
01143 if( eye & Compound::EYE_RIGHT_BIT )
01144 os << "RIGHT ";
01145 os << "]" << endl;
01146 }
01147
01148 const uint32_t period = compound->getPeriod();
01149 const uint32_t phase = compound->getPhase();
01150 if( period != EQ_UNDEFINED_UINT32 )
01151 os << "period " << period << " ";
01152
01153 if( phase != EQ_UNDEFINED_UINT32 )
01154 os << "phase " << phase;
01155
01156 if( period != EQ_UNDEFINED_UINT32 || phase != EQ_UNDEFINED_UINT32 )
01157 os << endl;
01158
01159
01160 bool attrPrinted = false;
01161
01162 for( Compound::IAttribute i = static_cast< Compound::IAttribute >( 0 );
01163 i<Compound::IATTR_ALL;
01164 i = static_cast< Compound::IAttribute >( static_cast<uint32_t>( i )+1))
01165 {
01166 const int value = compound->getIAttribute( i );
01167 if( value == Global::instance()->getCompoundIAttribute( i ))
01168 continue;
01169
01170 if( !attrPrinted )
01171 {
01172 os << endl << "attributes" << endl;
01173 os << "{" << endl << indent;
01174 attrPrinted = true;
01175 }
01176
01177 os << ( i==Compound::IATTR_STEREO_MODE ?
01178 "stereo_mode " :
01179 i==Compound::IATTR_STEREO_ANAGLYPH_LEFT_MASK ?
01180 "stereo_anaglyph_left_mask " :
01181 i==Compound::IATTR_STEREO_ANAGLYPH_RIGHT_MASK ?
01182 "stereo_anaglyph_right_mask " : "ERROR" );
01183
01184 switch( i )
01185 {
01186 case Compound::IATTR_STEREO_MODE:
01187 os << static_cast<eq::IAttrValue>( value ) << endl;
01188 break;
01189
01190 case Compound::IATTR_STEREO_ANAGLYPH_LEFT_MASK:
01191 case Compound::IATTR_STEREO_ANAGLYPH_RIGHT_MASK:
01192 os << ColorMask( value ) << endl;
01193 break;
01194
01195 default:
01196 EQASSERTINFO( 0, "unimplemented" );
01197 }
01198 }
01199
01200 if( attrPrinted )
01201 os << exdent << "}" << endl << endl;
01202
01203 switch( compound->getFrustumType( ))
01204 {
01205 case eq::Frustum::TYPE_WALL:
01206 os << compound->getWall() << endl;
01207 break;
01208 case eq::Frustum::TYPE_PROJECTION:
01209 os << compound->getProjection() << endl;
01210 break;
01211 default:
01212 break;
01213 }
01214
01215 const EqualizerVector& equalizers = compound->getEqualizers();
01216 for( EqualizerVector::const_iterator i = equalizers.begin();
01217 i != equalizers.end(); ++i )
01218 {
01219 os << *i;
01220 }
01221
01222 const CompoundVector& children = compound->getChildren();
01223 if( !children.empty( ))
01224 {
01225 os << endl;
01226 for( CompoundVector::const_iterator i = children.begin();
01227 i != children.end(); ++i )
01228
01229 os << *i;
01230 }
01231
01232 const FrameVector& inputFrames = compound->getInputFrames();
01233 for( FrameVector::const_iterator i = inputFrames.begin();
01234 i != inputFrames.end(); ++i )
01235
01236 os << "input" << *i;
01237
01238 const FrameVector& outputFrames = compound->getOutputFrames();
01239 for( FrameVector::const_iterator i = outputFrames.begin();
01240 i != outputFrames.end(); ++i )
01241
01242 os << "output" << *i;
01243
01244 os << compound->getSwapBarrier();
01245
01246 os << exdent << "}" << endl << enableFlush;
01247 return os;
01248 }
01249
01250 }
01251 }