compound.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 "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 // copy constructor
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 // Listener interface
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 // I/O objects access
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 // frustum operations
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( )) // only set view/segment frusta on destination
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 ) // frustum from view:
00477     {
00478         // set compound frustum =
00479         //         segment frustum X channel/view coverage
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( )); // keep distance
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 ) //frustum from segment
00512     {
00513         // set compound frustum =
00514         //         segment frustum X channel/segment coverage
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     // compute overdraw
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     // clamp to max channel size
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     // apply to frustum
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 // accept
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         //---------- down-right traversal
00671         if ( !child ) // leaf
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 // node
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         //---------- up-right traversal
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 // Operations
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 // pre-render compound state update
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; // will be reapplied below
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             // Compute the inherit viewport to be pixel-correct with the
00887             // integer-rounded pvp. This is needed to calculate the frustum
00888             // correctly.
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         // Zoom
00921         const eq::PixelViewport unzoomedPVP( _inherit.pvp );
00922         _inherit.pvp.apply( _data.zoom );
00923 
00924         // Compute the inherit zoom to be pixel-correct with the integer-rounded
00925         // pvp.
00926         const Zoom zoom = _inherit.pvp.getZoom( unzoomedPVP );
00927         _inherit.zoom *= zoom;
00928     }
00929 
00930     // Tasks
00931     if( frameNumber != 0 &&
00932         ( !_inherit.pvp.hasArea() || !_inherit.range.hasData( )) )
00933     {
00934         // Channels with no PVP or range do not execute tasks (ignored during
00935         // init)
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     // DPlex activation
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     // enlarge pvp by overdraw
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 ) // channel PVP changed
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     // attributes
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 }
Generated on Mon Aug 10 18:58:32 2009 for Equalizer 0.9 by  doxygen 1.5.8