LCOV - code coverage report
Current view: top level - eq/server - view.cpp (source / functions) Hit Total Coverage
Test: lcov2.info Lines: 114 236 48.3 %
Date: 2014-06-18 Functions: 19 38 50.0 %

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

Generated by: LCOV version 1.10