compound.cpp

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