LCOV - code coverage report
Current view: top level - eq/server - view.cpp (source / functions) Hit Total Coverage
Test: Equalizer Lines: 116 245 47.3 %
Date: 2016-07-30 05:04:55 Functions: 19 39 48.7 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2009-2013, Stefan Eilemann <eile@equalizergraphics.com>
       3             :  *               2011-2012, Daniel Nachbaur <danielnachbaur@gmail.com>
       4             :  *                    2010, Cedric Stalder <cedric.stalder@gmail.com
       5             :  *
       6             :  * This library is free software; you can redistribute it and/or modify it under
       7             :  * the terms of the GNU Lesser General Public License version 2.1 as published
       8             :  * by the Free Software Foundation.
       9             :  *
      10             :  * This library is distributed in the hope that it will be useful, but WITHOUT
      11             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      12             :  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
      13             :  * details.
      14             :  *
      15             :  * You should have received a copy of the GNU Lesser General Public License
      16             :  * along with this library; if not, write to the Free Software Foundation, Inc.,
      17             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      18             :  */
      19             : 
      20             : #include "view.h"
      21             : 
      22             : #include "canvas.h"
      23             : #include "channel.h"
      24             : #include "compound.h"
      25             : #include "config.h"
      26             : #include "configDestCompoundVisitor.h"
      27             : #include "global.h"
      28             : #include "layout.h"
      29             : #include "log.h"
      30             : #include "observer.h"
      31             : #include "segment.h"
      32             : #include "equalizers/equalizer.h"
      33             : #include "equalizers/tileEqualizer.h"
      34             : #include "tileQueue.h"
      35             : 
      36             : #include <eq/fabric/commands.h>
      37             : #include <eq/fabric/paths.h>
      38             : 
      39             : #include <co/dataIStream.h>
      40             : #include <co/dataOStream.h>
      41             : #include <co/iCommand.h>
      42             : 
      43             : namespace eq
      44             : {
      45             : namespace server
      46             : {
      47             : typedef fabric::View< Layout, View, Observer > Super;
      48             : typedef co::CommandFunc<View> ViewFunc;
      49             : 
      50         722 : View::View( Layout* parent )
      51             :         : Super( parent )
      52         722 :         , _private( 0 )
      53             : {
      54         722 :     const Global* global = Global::instance();
      55        5776 :     for( unsigned i = 0; i < SATTR_ALL; ++i )
      56             :     {
      57        5054 :         const SAttribute attr = static_cast< SAttribute >( i );
      58        5054 :         setSAttribute( attr, global->getViewSAttribute( attr ));
      59             :     }
      60         722 : }
      61             : 
      62        2160 : View::~View()
      63             : {
      64             :     // Use copy - Channel::unsetOutput modifies vector
      65         720 :     Channels channels = _channels;
      66        2160 :     for( Channels::const_iterator i = channels.begin();
      67        1440 :          i != channels.end(); ++i )
      68             :     {
      69           0 :         Channel* channel = *i;
      70           0 :         channel->unsetOutput();
      71             :     }
      72             : 
      73         720 :     LBASSERT( _channels.empty( ));
      74         720 :     _channels.clear();
      75        1440 : }
      76             : 
      77             : namespace
      78             : {
      79             : class FrustumUpdater : public ConfigVisitor
      80             : {
      81             : public:
      82           4 :     FrustumUpdater( const Channels& channels, const Vector3f& eye,
      83             :                     const float ratio )
      84             :             : _channels( channels )
      85             :             , _eye( eye )
      86           4 :             , _ratio( ratio )
      87           4 :         {}
      88           4 :     virtual ~FrustumUpdater() {}
      89             : 
      90           8 :     virtual VisitorResult visit( Compound* compound )
      91             :         {
      92           8 :             const Channel* channel = compound->getChannel();
      93           8 :             if( !channel )
      94           4 :                 return TRAVERSE_CONTINUE;
      95             : 
      96           4 :             if( !compound->isDestination( ))
      97           0 :                 return TRAVERSE_PRUNE; // only change destination compounds
      98             : 
      99           4 :             if( std::find( _channels.begin(), _channels.end(), channel ) !=
     100           4 :                 _channels.end( )) // our destination channel
     101             :             {
     102           4 :                 compound->updateFrustum( _eye, _ratio );
     103             :             }
     104             : 
     105           4 :             return TRAVERSE_PRUNE;
     106             :         }
     107             : private:
     108             :     const Channels& _channels;
     109             :     const Vector3f& _eye;
     110             :     const float _ratio;
     111             : };
     112             : 
     113             : class CapabilitiesUpdater : public ConfigVisitor
     114             : {
     115             : public:
     116           0 :     explicit CapabilitiesUpdater( View* view )
     117             :         : _view( view )
     118           0 :         , _capabilities( _view->getMaximumCapabilities( ))
     119           0 :     {}
     120             : 
     121           0 :     virtual ~CapabilitiesUpdater(){}
     122             : 
     123           0 :     virtual VisitorResult visit( Compound* compound )
     124             :     {
     125           0 :         const Channel* dest = compound->getInheritChannel();
     126           0 :         if( !dest || dest->getView() != _view )
     127           0 :             return TRAVERSE_CONTINUE;
     128             : 
     129           0 :         const Channel* src = compound->getChannel();
     130           0 :         if( !src->supportsView( _view ))
     131           0 :             return TRAVERSE_CONTINUE;
     132             : 
     133           0 :         const uint64_t supported = src->getCapabilities();
     134           0 :         _capabilities &= supported;
     135           0 :         return TRAVERSE_CONTINUE;
     136             :     }
     137             : 
     138           0 :     uint64_t getCapabilities() const { return _capabilities; }
     139             : 
     140             : private:
     141             :     View* const _view;
     142             :     uint64_t _capabilities;
     143             : };
     144             : 
     145           0 : class UseEqualizerVisitor : public ConfigVisitor
     146             : {
     147             : public:
     148           0 :     explicit UseEqualizerVisitor( const View* view ) : _view( view ) {}
     149             : 
     150             :     // No need to go down on nodes.
     151           0 :     VisitorResult visitPre( Node* ) override { return TRAVERSE_PRUNE; }
     152             : 
     153           0 :     VisitorResult visit( Compound* compound ) override
     154             :     {
     155           0 :         const Channel* dest = compound->getInheritChannel();
     156           0 :         if( !dest )
     157           0 :             return TRAVERSE_CONTINUE;
     158             : 
     159           0 :         if( dest->getView() != _view )
     160           0 :             return TRAVERSE_PRUNE;
     161             : 
     162           0 :         Equalizers equalizers = compound->getEqualizers();
     163           0 :         for( EqualizersCIter i = equalizers.begin(); i != equalizers.end(); ++i)
     164             :         {
     165           0 :             Equalizer* equalizer = *i;
     166           0 :             const uint32_t bitmask = _view->getEqualizers();
     167           0 :             equalizer->setActive( ( equalizer->getType() & bitmask ) != 0 );
     168             :         }
     169           0 :         return TRAVERSE_CONTINUE;
     170             :     }
     171             : 
     172             : 
     173             : private:
     174             :     const View* const _view;
     175             : };
     176             : 
     177           0 : class UpdateEqualizersVisitor : public ConfigVisitor
     178             : {
     179             : public:
     180           0 :     explicit UpdateEqualizersVisitor( const View* view ) : _view( view ) {}
     181             : 
     182             :     // No need to go down on nodes.
     183           0 :     VisitorResult visitPre( Node* ) override { return TRAVERSE_PRUNE; }
     184             : 
     185           0 :     VisitorResult visit( Compound* compound ) override
     186             :     {
     187           0 :         const Channel* dest = compound->getInheritChannel();
     188           0 :         if( !dest )
     189           0 :             return TRAVERSE_CONTINUE;
     190             : 
     191           0 :         if( dest->getView() != _view )
     192           0 :             return TRAVERSE_PRUNE;
     193             : 
     194           0 :         const TileQueues& queues = compound->getOutputTileQueues();
     195           0 :         for( TileQueuesCIter i = queues.begin(); i != queues.end(); ++i )
     196             :         {
     197           0 :             TileQueue* queue = *i;
     198           0 :             queue->setTileSize( _view->getEqualizer().getTileSize( ));
     199             :         }
     200             : 
     201           0 :         Equalizers equalizers = compound->getEqualizers();
     202           0 :         for( EqualizersIter i = equalizers.begin(); i != equalizers.end(); ++i)
     203           0 :             *(*i) = _view->getEqualizer();
     204             : 
     205           0 :         return TRAVERSE_CONTINUE;
     206             :     }
     207             : 
     208             : private:
     209             :     const View* const _view;
     210             : };
     211             : 
     212             : }
     213             : 
     214        6332 : void View::setDirty( const uint64_t bits )
     215             : {
     216        6332 :     if( bits == 0 || !isAttached( ))
     217       12646 :         return;
     218             : 
     219          18 :     Super::setDirty( bits );
     220          18 :     _updateChannels();
     221             : }
     222             : 
     223          22 : void View::_updateChannels() const
     224             : {
     225          22 :     LBASSERT( isMaster( ));
     226          22 :     co::ObjectVersion version( this );
     227          22 :     if( isDirty( ))
     228          18 :         ++version.version;
     229             : 
     230         132 :     for( Channels::const_iterator i = _channels.begin();
     231          88 :          i != _channels.end(); ++i )
     232             :     {
     233          22 :         Channel* channel = *i;
     234          22 :         channel->setViewVersion( version );
     235             :     }
     236          22 : }
     237             : 
     238           0 : void View::deserialize( co::DataIStream& is, const uint64_t dirtyBits )
     239             : {
     240           0 :     LBASSERT( isMaster( ));
     241           0 :     Super::deserialize( is, dirtyBits );
     242             : 
     243           0 :     if( dirtyBits & ( DIRTY_FRUSTUM | DIRTY_OVERDRAW | DIRTY_MODELUNIT ))
     244           0 :         updateFrusta();
     245           0 :     if( dirtyBits & DIRTY_EQUALIZER )
     246             :     {
     247           0 :         UpdateEqualizersVisitor visitor ( this );
     248           0 :         getConfig()->accept( visitor );
     249             :     }
     250           0 :     if( dirtyBits & DIRTY_EQUALIZERS )
     251             :     {
     252           0 :         UseEqualizerVisitor visitor ( this );
     253           0 :         getConfig()->accept( visitor );
     254           0 :         getConfig()->postNeedsFinish(); // @bug? Why?
     255             :     }
     256           0 : }
     257             : 
     258          46 : Config* View::getConfig()
     259             : {
     260          46 :     Layout* layout = getLayout();
     261          46 :     LBASSERT( layout );
     262          46 :     return layout ? layout->getConfig() : 0;
     263             : }
     264             : 
     265           0 : const Config* View::getConfig() const
     266             : {
     267           0 :     const Layout* layout = getLayout();
     268           0 :     LBASSERT( layout );
     269           0 :     return layout ? layout->getConfig() : 0;
     270             : }
     271             : 
     272           4 : ServerPtr View::getServer()
     273             : {
     274           4 :     Config* config = getConfig();
     275           4 :     LBASSERT( config );
     276           4 :     return config ? config->getServer() : 0;
     277             : }
     278             : 
     279        1174 : void View::addChannel( Channel* channel )
     280             : {
     281        1174 :     _channels.push_back( channel );
     282        1174 : }
     283             : 
     284        1172 : bool View::removeChannel( Channel* channel )
     285             : {
     286        1172 :     Channels::iterator i = lunchbox::find( _channels, channel );
     287             : 
     288        1172 :     LBASSERT( i != _channels.end( ));
     289        1172 :     if( i == _channels.end( ))
     290           0 :         return false;
     291             : 
     292        1172 :     _channels.erase( i );
     293        1172 :     return true;
     294             : }
     295             : 
     296         592 : ViewPath View::getPath() const
     297             : {
     298         592 :     const Layout* layout = getLayout();
     299         592 :     LBASSERT( layout );
     300         592 :     ViewPath path( layout->getPath( ));
     301             : 
     302         592 :     const Views& views = layout->getViews();
     303         592 :     Views::const_iterator i = std::find( views.begin(), views.end(), this );
     304         592 :     LBASSERT( i != views.end( ));
     305         592 :     path.viewIndex = std::distance( views.begin(), i );
     306         592 :     return path;
     307             : }
     308             : 
     309           2 : void View::init()
     310             : {
     311             :     // All contributors to the same view must share the same Deflect ID for
     312             :     // streaming to the same target.
     313           2 :     if( getSAttribute( View::SATTR_DEFLECT_ID ).empty( ))
     314           2 :         setSAttribute( View::SATTR_DEFLECT_ID, getName().empty()
     315           2 :                        ? "View " + getID().getShortString() : getName( ));
     316           2 : }
     317             : 
     318           4 : void View::trigger( const Canvas* canvas, const bool active )
     319             : {
     320           4 :     const Mode mode = getMode();
     321           4 :     Config* config = getConfig();
     322             : 
     323             :     // (De)activate destination compounds for canvas/eye(s)
     324          24 :     for( Channels::const_iterator i = _channels.begin();
     325          16 :          i != _channels.end(); ++i )
     326             :     {
     327           4 :         Channel* channel = *i;
     328           4 :         const Canvas* channelCanvas = channel->getCanvas();
     329           4 :         const Layout* canvasLayout = channelCanvas->getActiveLayout();
     330             : 
     331           4 :         if((  canvas && channelCanvas != canvas ) ||
     332           0 :            ( !canvas && canvasLayout  != getLayout( )))
     333             :         {
     334           0 :             continue;
     335             :         }
     336             : 
     337           4 :         const Segment* segment = channel->getSegment();
     338           4 :         const uint32_t segmentEyes = segment->getEyes();
     339             :         const uint32_t eyes = ( mode == MODE_MONO ) ?
     340           4 :                            EYE_CYCLOP & segmentEyes : EYES_STEREO & segmentEyes;
     341           4 :         if( eyes == 0 )
     342           0 :             continue;
     343             : 
     344           4 :         ConfigDestCompoundVisitor visitor( channel, true /*activeOnly*/ );
     345           4 :         config->accept( visitor );
     346             : 
     347           4 :         const Compounds& compounds = visitor.getResult();
     348          24 :         for( Compounds::const_iterator j = compounds.begin();
     349          16 :              j != compounds.end(); ++j )
     350             :         {
     351           4 :             Compound* compound = *j;
     352           4 :             if( active )
     353             :             {
     354           2 :                 compound->activate( eyes );
     355           2 :                 LBLOG( LOG_VIEW ) << "Activate " << compound->getName()
     356           2 :                                   << std::endl;
     357             :             }
     358             :             else
     359             :             {
     360           2 :                 compound->deactivate( eyes );
     361           2 :                 LBLOG( LOG_VIEW ) << "Deactivate " << compound->getName()
     362           2 :                                   << std::endl;
     363             :             }
     364             :         }
     365           4 :     }
     366           4 : }
     367             : 
     368           0 : void View::activateMode( const Mode mode )
     369             : {
     370           0 :     if( getMode() == mode )
     371           0 :         return;
     372             : 
     373           0 :     Config* config = getConfig();
     374           0 :     if( config->isRunning( ))
     375             :     {
     376           0 :         config->postNeedsFinish();
     377           0 :         trigger( 0, false );
     378             :     }
     379             : 
     380           0 :     Super::activateMode( mode );
     381             : 
     382           0 :     if( config->isRunning( ))
     383           0 :         trigger( 0, true );
     384             : }
     385             : 
     386           0 : void View::updateCapabilities()
     387             : {
     388           0 :     CapabilitiesUpdater visitor( this );
     389           0 :     getConfig()->accept( visitor );
     390           0 :     setCapabilities( visitor.getCapabilities( ));
     391           0 : }
     392             : 
     393           4 : void View::updateFrusta()
     394             : {
     395           4 :     const Channels& channels = getChannels();
     396           4 :     Vector3f eye;
     397           4 :     const float ratio = _computeFocusRatio( eye );
     398             : 
     399           4 :     Config* config = getConfig();
     400           4 :     FrustumUpdater updater( channels, eye, ratio );
     401             : 
     402           4 :     config->accept( updater );
     403           4 : }
     404             : 
     405           4 : float View::_computeFocusRatio( Vector3f& eye )
     406             : {
     407           4 :     eye = Vector3f::ZERO;
     408           4 :     const Observer* observer = getObserver();
     409           4 :     const FocusMode mode = observer ? observer->getFocusMode() :FOCUSMODE_FIXED;
     410           4 :     if( mode == FOCUSMODE_FIXED )
     411           4 :         return 1.f;
     412             : 
     413           0 :     const Channels& channels = getChannels();
     414           0 :     if( channels.empty( ))
     415           0 :         return 1.f;
     416             : 
     417           0 :     Vector4f view4( Vector3f::FORWARD );
     418           0 :     if( mode == FOCUSMODE_RELATIVE_TO_OBSERVER )
     419             :     {
     420           0 :         view4 = observer->getHeadMatrix() * view4;
     421           0 :         eye = observer->getEyeWorld( EYE_CYCLOP );
     422             :     }
     423           0 :     Vector3f view = view4;
     424           0 :     view.normalize();
     425             : 
     426           0 :     float distance = std::numeric_limits< float >::max();
     427           0 :     if( getCurrentType() != Frustum::TYPE_NONE ) // frustum from view
     428             :     {
     429           0 :         const Wall& wall = getWall();
     430           0 :         const Vector3f w = wall.getW();
     431           0 :         const float denom = view.dot( w );
     432           0 :         if( denom != 0.f ) // view parallel to wall
     433             :         {
     434           0 :             const float d = (wall.bottomLeft - eye).dot( w ) / denom;
     435           0 :             if( d > 0.f )
     436           0 :                 distance = d;
     437             :         }
     438             :     }
     439             :     else
     440             :     {
     441             :         // Find closest segment and its distance from cyclop eye
     442           0 :         for( ChannelsCIter i = channels.begin(); i != channels.end(); ++i )
     443             :         {
     444           0 :             Segment* segment = (*i)->getSegment();
     445           0 :             segment->inheritFrustum();
     446           0 :             if( segment->getCurrentType() == Frustum::TYPE_NONE )
     447           0 :                 continue;
     448             : 
     449             :             // http://en.wikipedia.org/wiki/Line-plane_intersection
     450           0 :             const Wall& wall = segment->getWall();
     451           0 :             const Vector3f w = wall.getW();
     452           0 :             const float denom = view.dot( w );
     453           0 :             if( denom == 0.f ) // view parallel to wall
     454           0 :                 continue;
     455             : 
     456           0 :             const float d = (wall.bottomLeft - eye).dot( w ) / denom;
     457           0 :             if( d > distance || d <= 0.f ) // further away or behind
     458           0 :                 continue;
     459             : 
     460           0 :             distance = d;
     461             :             //LBINFO << "Eye " << eye << " is " << d << " from " << wall
     462             :             // << std::endl;
     463             :         }
     464             :     }
     465             : 
     466           0 :     float focusDistance = observer->getFocusDistance();
     467           0 :     if( mode == FOCUSMODE_RELATIVE_TO_ORIGIN )
     468             :     {
     469           0 :         eye = observer->getEyeWorld( EYE_CYCLOP );
     470             : 
     471           0 :         if( distance != std::numeric_limits< float >::max( ))
     472             :         {
     473           0 :             distance += eye.z();
     474           0 :             focusDistance += eye.z();
     475           0 :             if( fabsf( distance ) <= std::numeric_limits< float >::epsilon( ))
     476           0 :                 distance = 2.f * std::numeric_limits< float >::epsilon();
     477             :         }
     478             :     }
     479             : 
     480           0 :     if( distance == std::numeric_limits< float >::max( ))
     481           0 :         return 1.f;
     482           0 :     return focusDistance / distance;
     483             : }
     484             : 
     485             : }
     486             : }
     487             : 
     488             : #include "../fabric/view.ipp"
     489             : 
     490             : template class eq::fabric::View< eq::server::Layout, eq::server::View,
     491             :                                  eq::server::Observer >;
     492             : /** @cond IGNORE */
     493             : template std::ostream& eq::fabric::operator << ( std::ostream&,
     494             :                          const eq::fabric::View< eq::server::Layout,
     495             :                                                  eq::server::View,
     496          84 :                                                  eq::server::Observer >& );
     497             : /** @endcond */

Generated by: LCOV version 1.11