LCOV - code coverage report
Current view: top level - eq/server/config - resources.cpp (source / functions) Hit Total Coverage
Test: lcov2.info Lines: 347 438 79.2 %
Date: 2014-06-18 Functions: 25 27 92.6 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2011-2013, Stefan Eilemann <eile@eyescale.h>
       3             :  *               2012-2014, Daniel Nachbaur <danielnachbaur@gmail.com>
       4             :  *                    2013, Julio Delgado Mangas <julio.delgadomangas@epfl.ch>
       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 "resources.h"
      21             : 
      22             : #include "../compound.h"
      23             : #include "../configVisitor.h"
      24             : #include "../connectionDescription.h"
      25             : #include "../frame.h"
      26             : #include "../layout.h"
      27             : #include "../node.h"
      28             : #include "../pipe.h"
      29             : #include "../segment.h"
      30             : #include "../window.h"
      31             : #include "../equalizers/loadEqualizer.h"
      32             : 
      33             : #include <eq/client/frame.h>
      34             : #include <eq/client/windowSystem.h>
      35             : #include <eq/fabric/configParams.h>
      36             : #include <eq/fabric/gpuInfo.h>
      37             : 
      38             : #include <hwsd/gpuInfo.h>
      39             : #include <hwsd/netInfo.h>
      40             : #include <hwsd/hwsd.h>
      41             : #ifdef EQUALIZER_USE_HWSD_gpu_cgl
      42             : #  include <hwsd/gpu/cgl/module.h>
      43             : #endif
      44             : #ifdef EQUALIZER_USE_HWSD_gpu_glx
      45             : #  include <hwsd/gpu/glx/module.h>
      46             : #endif
      47             : #ifdef EQUALIZER_USE_HWSD_gpu_wgl
      48             : #  include <hwsd/gpu/wgl/module.h>
      49             : #endif
      50             : #ifdef EQUALIZER_USE_HWSD_gpu_dns_sd
      51             : #  include <hwsd/gpu/dns_sd/module.h>
      52             : #endif
      53             : #ifdef EQUALIZER_USE_HWSD_net_sys
      54             : #  include <hwsd/net/sys/module.h>
      55             : #endif
      56             : #ifdef EQUALIZER_USE_HWSD_net_dns_sd
      57             : #  include <hwsd/net/dns_sd/module.h>
      58             : #endif
      59             : 
      60             : #define USE_IPv4
      61             : 
      62             : namespace eq
      63             : {
      64             : namespace server
      65             : {
      66             : namespace config
      67             : {
      68             : namespace
      69             : {
      70          15 : co::ConnectionDescriptions _findConnections( const lunchbox::uint128_t& id,
      71             :                                              const hwsd::NetInfos& netInfos )
      72             : {
      73             :     // sort connections by bandwidth
      74             :     typedef std::multimap< int32_t, co::ConnectionDescriptionPtr > Connections;
      75          15 :     Connections connections;
      76             : 
      77          45 :     for( hwsd::NetInfosCIter i = netInfos.begin(); i != netInfos.end(); ++i )
      78             :     {
      79          30 :         const hwsd::NetInfo& netInfo = *i;
      80          60 :         if( netInfo.id != id || !netInfo.up ||
      81          30 :             netInfo.type == hwsd::NetInfo::TYPE_LOOPBACK )
      82             :         {
      83          15 :             continue;
      84             :         }
      85             : 
      86          15 :         co::ConnectionDescriptionPtr desc = new ConnectionDescription;
      87          15 :         switch( netInfo.type )
      88             :         {
      89             :             case hwsd::NetInfo::TYPE_ETHERNET:
      90          15 :                 desc->type = co::CONNECTIONTYPE_TCPIP;
      91          15 :                 desc->bandwidth = 125000;   // 1Gbit
      92          15 :                 break;
      93             : 
      94             :             case hwsd::NetInfo::TYPE_INFINIBAND:
      95           0 :                 desc->type = co::CONNECTIONTYPE_RDMA;
      96           0 :                 desc->bandwidth = 2500000;   // 20Gbit
      97           0 :                 break;
      98             : 
      99             :             default:
     100           0 :                 desc->type = co::CONNECTIONTYPE_NONE;
     101             :         }
     102          15 :         if( netInfo.linkspeed != hwsd::NetInfo::defaultValue )
     103           0 :             desc->bandwidth = netInfo.linkspeed * 125; // MBit -> Kbyte
     104             : #ifdef USE_IPv4
     105          15 :         desc->hostname = netInfo.inetAddress;
     106             : #else
     107             :         desc->hostname = netInfo.inet6Address;
     108             : #endif
     109          15 :         connections.insert( std::make_pair( desc->bandwidth, desc ));
     110          15 :     }
     111             : 
     112          15 :     co::ConnectionDescriptions result;
     113          90 :     for( Connections::const_reverse_iterator i = connections.rbegin();
     114          60 :          i != connections.rend(); ++i )
     115             :     {
     116          15 :         result.push_back( i->second );
     117             :     }
     118          15 :     return result;
     119             : }
     120             : 
     121           8 : uint32_t _configureNetworkTypes( const fabric::ConfigParams& params )
     122             : {
     123           8 :     uint32_t netTypes = 0;
     124           8 :     if( params.getFlags() & fabric::ConfigParams::FLAG_NETWORK_ALL )
     125             :     {
     126           0 :         if( params.getFlags() & fabric::ConfigParams::FLAG_NETWORK_ETHERNET )
     127           0 :             netTypes |= hwsd::NetInfo::TYPE_ETHERNET;
     128           0 :         if( params.getFlags() & fabric::ConfigParams::FLAG_NETWORK_INFINIBAND )
     129           0 :             netTypes |= hwsd::NetInfo::TYPE_INFINIBAND;
     130             :     }
     131             :     else
     132           8 :         netTypes = hwsd::NetInfo::TYPE_ALL ^ hwsd::NetInfo::TYPE_UNKNOWN;
     133             : 
     134           8 :     return netTypes;
     135             : }
     136             : 
     137           8 : hwsd::GPUInfos _discoverGPUs( const fabric::ConfigParams& params,
     138             :                               hwsd::FilterPtr filter )
     139             : {
     140          16 :     hwsd::FilterPtr gpuFilter = filter | new hwsd::MirrorFilter |
     141          24 :                                 new hwsd::GPUFilter( params.getGPUFilter( ));
     142             : 
     143           8 :     return hwsd::discoverGPUInfos( gpuFilter );
     144             : }
     145             : 
     146           8 : hwsd::NetInfos _discoverNetworks( const fabric::ConfigParams& params,
     147             :                                   hwsd::FilterPtr filter )
     148             : {
     149             : 
     150             :     hwsd::FilterPtr netFilter = filter |
     151             :                           new hwsd::NetFilter( params.getPrefixes(),
     152           8 :                                               _configureNetworkTypes( params ));
     153             : 
     154           8 :     return hwsd::discoverNetInfos( netFilter );
     155             : }
     156             : 
     157           8 : void _configureHwsdModules()
     158             : {
     159             : #ifdef EQUALIZER_USE_HWSD_gpu_cgl
     160             :     hwsd::gpu::cgl::Module::use();
     161             : #elif defined(EQUALIZER_USE_HWSD_gpu_glx)
     162           8 :     hwsd::gpu::glx::Module::use();
     163             : #endif
     164             : #ifdef EQUALIZER_USE_HWSD_gpu_wgl
     165             :     hwsd::gpu::wgl::Module::use();
     166             : #endif
     167             : #ifdef EQUALIZER_USE_HWSD_gpu_dns_sd
     168           8 :     hwsd::gpu::dns_sd::Module::use();
     169             : #endif
     170             : #ifdef EQUALIZER_USE_HWSD_net_sys
     171           8 :     hwsd::net::sys::Module::use();
     172             : #endif
     173             : #ifdef EQUALIZER_USE_HWSD_net_dns_sd
     174           8 :     hwsd::net::dns_sd::Module::use();
     175             : #endif
     176           8 : }
     177             : 
     178           8 : void _disposeHwsdModules()
     179             : {
     180             : #ifdef EQUALIZER_USE_HWSD_gpu_cgl
     181             :     hwsd::gpu::cgl::Module::dispose();
     182             : #elif defined(EQUALIZER_USE_HWSD_gpu_glx)
     183           8 :     hwsd::gpu::glx::Module::dispose();
     184             : #endif
     185             : #ifdef EQUALIZER_USE_HWSD_gpu_wgl
     186             :     hwsd::gpu::wgl::Module::dispose();
     187             : #endif
     188             : #ifdef EQUALIZER_USE_HWSD_gpu_dns_sd
     189           8 :     hwsd::gpu::dns_sd::Module::dispose();
     190             : #endif
     191             : #ifdef EQUALIZER_USE_HWSD_net_sys
     192           8 :     hwsd::net::sys::Module::dispose();
     193             : #endif
     194             : #ifdef EQUALIZER_USE_HWSD_net_dns_sd
     195           8 :     hwsd::net::dns_sd::Module::dispose();
     196             : #endif
     197           8 : }
     198             : 
     199             : } // unnamed namespace
     200             : 
     201           9 : static lunchbox::a_int32_t _frameCounter;
     202             : 
     203           8 : bool Resources::discover( ServerPtr server, Config* config,
     204             :                           const std::string& session,
     205             :                           const fabric::ConfigParams& params )
     206             : {
     207           8 :     _configureHwsdModules();
     208             : 
     209           8 :     hwsd::FilterPtr filter = hwsd::FilterPtr( new hwsd::DuplicateFilter ) |
     210          16 :                              new hwsd::SessionFilter( session );
     211             : 
     212          16 :     hwsd::GPUInfos gpuInfos = _discoverGPUs( params, filter );
     213          16 :     const hwsd::NetInfos& netInfos = _discoverNetworks( params, filter );
     214             : 
     215           8 :     _disposeHwsdModules();
     216             : 
     217           8 :     if( gpuInfos.empty( ))
     218             :     {
     219           0 :         if( hwsd::NodeInfo::isLocal( session ))
     220             :         {
     221           0 :             LBWARN << "No local GPUs found, abort configuration" << std::endl;
     222           0 :             return false;
     223             :         }
     224           0 :         LBINFO << "No resources found for session " << session
     225           0 :                << ", using default config" << std::endl;
     226           0 :         gpuInfos.push_back( hwsd::GPUInfo( ));
     227             :     }
     228             : 
     229             :     typedef stde::hash_map< uint128_t, Node* > NodeMap;
     230          16 :     NodeMap nodes;
     231             : 
     232           8 :     const uint32_t flags = params.getFlags();
     233             : 
     234           8 :     const bool multiProcess = flags & (fabric::ConfigParams::FLAG_MULTIPROCESS |
     235           8 :                                    fabric::ConfigParams::FLAG_MULTIPROCESS_DB );
     236          13 :     const bool multiNode = !hwsd::NodeInfo::isLocal( session ) ||
     237          13 :                            ( multiProcess && gpuInfos.size() > 1 );
     238           8 :     size_t gpuCounter = 0;
     239           8 :     uint128_t appNodeID;
     240             : 
     241          24 :     for( hwsd::GPUInfosCIter i = gpuInfos.begin(); i != gpuInfos.end(); ++i )
     242             :     {
     243          16 :         const hwsd::GPUInfo& info = *i;
     244          16 :         if( info.flags & hwsd::GPUInfo::FLAG_VIRTUALGL_DISPLAY )
     245           0 :             continue; // ignore, default $DISPLAY gpu uses this one
     246             : 
     247          16 :         Node* mtNode = nodes[ info.id ];
     248          16 :         Node* mpNode = 0;
     249          16 :         if( !mtNode )
     250             :         {
     251           8 :             const bool isApplicationNode = info.nodeName.empty();
     252           8 :             if( isApplicationNode )
     253           8 :                 appNodeID = info.id;
     254           8 :             mtNode = new Node( config );
     255           8 :             mtNode->setName( info.nodeName );
     256           8 :             mtNode->setHost( info.nodeName );
     257           8 :             mtNode->setApplicationNode( isApplicationNode );
     258             : 
     259           8 :             nodes[ info.id ] = mtNode;
     260             : 
     261           8 :             if( multiNode )
     262             :             {
     263             :                 const co::ConnectionDescriptions& descs =
     264           5 :                     _findConnections( info.id, netInfos );
     265             : 
     266           5 :                 if( descs.empty() && !info.nodeName.empty())
     267             :                 {
     268           0 :                     LBINFO << "No suitable connection found for node "
     269           0 :                            << info.nodeName << "; node will not be used"
     270           0 :                            << std::endl;
     271           0 :                     nodes.erase( info.id );
     272           0 :                     delete mtNode;
     273           0 :                     continue;
     274             :                 }
     275             : 
     276          30 :                 for( co::ConnectionDescriptionsCIter j = descs.begin();
     277          20 :                      j != descs.end(); ++j )
     278             :                 {
     279           5 :                     mtNode->addConnectionDescription( *j );
     280           5 :                 }
     281             :             }
     282             :         }
     283           8 :         else if( multiProcess )
     284             :         {
     285           5 :             mpNode = new Node( config );
     286           5 :             mpNode->setName( info.nodeName );
     287           5 :             mpNode->setHost( info.nodeName );
     288             : 
     289           5 :             LBASSERT( multiNode );
     290             :             const co::ConnectionDescriptions& descs =
     291           5 :                 _findConnections( info.id, netInfos );
     292             : 
     293           5 :             if( descs.empty() && !info.nodeName.empty())
     294             :             {
     295           0 :                 LBINFO << "No suitable connection found for node "
     296           0 :                        << info.nodeName << "; node will not be used"
     297           0 :                        << std::endl;
     298           0 :                 delete mpNode;
     299           0 :                 continue;
     300             :             }
     301             : 
     302          30 :             for( co::ConnectionDescriptionsCIter j = descs.begin();
     303          20 :                  j != descs.end(); ++j )
     304             :             {
     305           5 :                 mpNode->addConnectionDescription( *j );
     306           5 :             }
     307             :         }
     308             : 
     309          16 :         std::stringstream name;
     310          24 :         if( info.device == LB_UNDEFINED_UINT32 &&
     311             :             // VirtualGL display redirects to local GPU (see continue above)
     312           8 :             !(info.flags & hwsd::GPUInfo::FLAG_VIRTUALGL) )
     313             :         {
     314           8 :             name << "display";
     315             :         }
     316             :         else
     317           8 :             name << "GPU" << ++gpuCounter;
     318             : 
     319          16 :         if( mpNode ) // multi-process resource
     320             :         {
     321           5 :             Pipe* pipe = new Pipe( mpNode );
     322           5 :             pipe->setPort( info.port );
     323           5 :             pipe->setDevice( info.device );
     324           5 :             pipe->setPixelViewport( PixelViewport( info.pvp ));
     325           5 :             pipe->setName( name.str() + " mp" );
     326           5 :             name << " mt"; // mark companion GPU as multi-threaded only
     327             :         }
     328             :         else
     329          11 :             name << " mt mp"; // mark GPU as multi-threaded and multi-process
     330             : 
     331          16 :         Pipe* pipe = new Pipe( mtNode ); // standalone/multi-threaded resource
     332          16 :         pipe->setPort( info.port );
     333          16 :         pipe->setDevice( info.device );
     334          16 :         pipe->setPixelViewport( PixelViewport( info.pvp ));
     335          16 :         pipe->setName( name.str( ));
     336          16 :     }
     337             : 
     338           8 :     Node* node = config->findAppNode();
     339           8 :     if( !node )
     340             :     {
     341           0 :         node = new Node( config );
     342           0 :         node->setApplicationNode( true );
     343           0 :         node->addConnectionDescription( new ConnectionDescription );
     344             :     }
     345           8 :     if( node->getPipes().empty( )) // add display window
     346             :     {
     347           0 :         Pipe* pipe = new Pipe( node );
     348           0 :         pipe->setName( "display" );
     349             :     }
     350             : 
     351           8 :     if( config->getNodes().size() > 1 ) // add server connection for clusters
     352             :     {
     353           5 :         co::Connections connections;
     354             : 
     355           5 :         if( appNodeID == 0 )
     356             :         {
     357           0 :             co::ConnectionDescriptionPtr desc = new co::ConnectionDescription;
     358           0 :             co::ConnectionPtr connection = server->addListener( desc );
     359           0 :             LBASSERT( connection );
     360           0 :             if( connection )
     361           0 :                 connections.push_back( connection );
     362             :             else
     363           0 :                 LBWARN << "Could not add listener " << desc->hostname
     364           0 :                        << " to server" << std::endl;
     365             :         }
     366             :         else
     367             :         {
     368             :             const co::ConnectionDescriptions& descs =
     369           5 :                 _findConnections( appNodeID, netInfos );
     370             : 
     371          30 :             for( co::ConnectionDescriptionsCIter i = descs.begin();
     372          20 :                  i != descs.end(); ++i )
     373             :             {
     374           5 :                 co::ConnectionPtr connection = server->addListener( *i );
     375           5 :                 LBASSERT( connection );
     376           5 :                 if( connection )
     377           5 :                     connections.push_back( connection );
     378             :                 else
     379           0 :                     LBWARN << "Could not add listener " << (*i)->hostname
     380           0 :                            << " to server" << std::endl;
     381          10 :             }
     382             :         }
     383             : 
     384           5 :         config->setServerConnections( connections );
     385             :     }
     386             : 
     387          16 :     return true;
     388             : }
     389             : 
     390             : namespace
     391             : {
     392           8 : class AddSourcesVisitor : public ConfigVisitor
     393             : {
     394             : public:
     395           8 :     AddSourcesVisitor( const PixelViewport& pvp ) : _pvp( pvp ) {}
     396             : 
     397          21 :     virtual VisitorResult visitPre( Pipe* pipe )
     398             :     {
     399          21 :         const Node* node = pipe->getNode();
     400          21 :         if( node->isApplicationNode() && node->getPipes().front() == pipe )
     401             :         {
     402             :             // display window has discrete 'affinity' GPU
     403           8 :             if( pipe->getName() != "display mt mp" )
     404           0 :                 _channels.push_back( pipe->getChannel( ChannelPath( 0 )));
     405           8 :             return TRAVERSE_CONTINUE;
     406             :         }
     407             : 
     408          13 :         Window* window = new Window( pipe );
     409          13 :         if( !pipe->getPixelViewport().isValid( ))
     410           0 :             window->setPixelViewport( _pvp );
     411          13 :         window->setIAttribute( WindowSettings::IATTR_HINT_DRAWABLE, fabric::FBO );
     412          13 :         window->setName( pipe->getName() + " source window" );
     413             : 
     414          13 :         _channels.push_back( new Channel( window ));
     415          13 :         _channels.back()->setName( pipe->getName() + " source channel" );
     416          13 :         return TRAVERSE_CONTINUE;
     417             :     }
     418             : 
     419           8 :     const Channels& getChannels() const { return _channels; }
     420             : private:
     421             :     const PixelViewport& _pvp;
     422             :     Channels _channels;
     423             : };
     424             : }
     425             : 
     426           8 : Channels Resources::configureSourceChannels( Config* config )
     427             : {
     428           8 :     const Node* node = config->findAppNode();
     429           8 :     LBASSERT( node );
     430           8 :     if( !node )
     431           0 :         return Channels();
     432             : 
     433           8 :     const Pipes& pipes = node->getPipes();
     434           8 :     LBASSERT( !pipes.empty( ));
     435           8 :     if( pipes.empty( ))
     436           0 :         return Channels();
     437             : 
     438           8 :     Pipe* pipe = pipes.front();
     439           8 :     PixelViewport pvp = pipe->getPixelViewport();
     440           8 :     if( pvp.isValid( ))
     441             :     {
     442           8 :         pvp.x = 0;
     443           8 :         pvp.y = 0;
     444             :     }
     445             :     else
     446           0 :         pvp = PixelViewport( 0, 0, 1920, 1200 );
     447             : 
     448           8 :     AddSourcesVisitor addSources( pvp );
     449           8 :     config->accept( addSources );
     450           8 :     return addSources.getChannels();
     451             : }
     452             : 
     453             : #if 0 // LB_GCC_4_5_OR_LATER
     454             : #  pragma GCC diagnostic ignored "-Wunused-but-set-variable"
     455             : #endif
     456           8 : void Resources::configure( const Compounds& compounds, const Channels& channels,
     457             :                            const fabric::ConfigParams& params )
     458             : {
     459           8 :     LBASSERT( !compounds.empty( ));
     460           8 :     if( compounds.empty() || channels.empty( )) // No additional resources
     461           8 :         return;
     462             : 
     463             : #ifndef NDEBUG
     464           8 :     const Canvas* canvas = 0;
     465             : #endif
     466          69 :     for( CompoundsCIter i = compounds.begin(); i != compounds.end(); ++i )
     467             :     {
     468          61 :         const Compounds& children = (*i)->getChildren();
     469          61 :         LBASSERT( children.size() == 1 );
     470          61 :         if( children.size() != 1 )
     471           0 :             continue;
     472             : 
     473          61 :         Compound* segmentCompound = children.front();
     474             : #ifndef NDEBUG
     475          61 :         const Channel* channel = segmentCompound->getChannel();
     476          61 :         LBASSERT( channel );
     477          61 :         LBASSERT( !canvas || channel->getCanvas() == canvas );
     478          61 :         canvas = channel->getCanvas();
     479             : #endif
     480             : 
     481          61 :         _addMonoCompound( segmentCompound, channels, params );
     482          61 :         _addStereoCompound( segmentCompound, channels, params );
     483             :     }
     484             : }
     485             : 
     486         301 : static Channels _filter( const Channels& input, const std::string& filter )
     487             : {
     488         301 :     Channels result;
     489             : 
     490         717 :     for( ChannelsCIter i = input.begin(); i != input.end(); ++i )
     491         416 :         if( (*i)->getName().find( filter ) != std::string::npos )
     492         246 :             result.push_back( *i );
     493         301 :     return result;
     494             : }
     495             : 
     496         119 : Compound* Resources::_addMonoCompound( Compound* root, const Channels& channels,
     497             :                                        const fabric::ConfigParams& params )
     498             : {
     499         119 :     const Channel* channel = root->getChannel();
     500         119 :     const Layout* layout = channel->getLayout();
     501         119 :     const std::string& name = layout->getName();
     502             : 
     503         119 :     Compound* compound = 0;
     504             :     const bool multiProcess =
     505         119 :                     params.getFlags() & fabric::ConfigParams::FLAG_MULTIPROCESS;
     506         238 :     const bool multiProcessDB = multiProcess ||
     507         238 :              ( params.getFlags() & fabric::ConfigParams::FLAG_MULTIPROCESS_DB );
     508             :     const Channels& activeChannels = _filter( channels,
     509         119 :                                               multiProcess ? " mp " : " mt " );
     510             :     const Channels& activeDBChannels = _filter( channels,
     511         238 :                                                 multiProcessDB ? " mp ":" mt ");
     512             : 
     513         119 :     if( name == EQ_SERVER_CONFIG_LAYOUT_SIMPLE )
     514             :         /* nop */;
     515         206 :     else if( name == EQ_SERVER_CONFIG_LAYOUT_2D_DYNAMIC ||
     516          95 :              name == EQ_SERVER_CONFIG_LAYOUT_2D_STATIC )
     517             :     {
     518          32 :         compound = _add2DCompound( root, activeChannels, params );
     519             :     }
     520         142 :     else if( name == EQ_SERVER_CONFIG_LAYOUT_DB_DYNAMIC ||
     521          63 :              name == EQ_SERVER_CONFIG_LAYOUT_DB_STATIC )
     522             :     {
     523          32 :         compound = _addDBCompound( root, activeDBChannels, params );
     524             :     }
     525          47 :     else if( name == EQ_SERVER_CONFIG_LAYOUT_DB_DS )
     526          16 :         compound = _addDSCompound( root, activeDBChannels );
     527          31 :     else if( name == EQ_SERVER_CONFIG_LAYOUT_DB_2D )
     528             :     {
     529          15 :         LBASSERT( !multiProcess );
     530          15 :         LBASSERT( multiProcessDB );
     531          15 :         compound = _addDB2DCompound( root, channels, params );
     532             :     }
     533          16 :     else if( name == EQ_SERVER_CONFIG_LAYOUT_SUBPIXEL )
     534          16 :         compound = _addSubpixelCompound( root, activeChannels );
     535             :     else
     536             :     {
     537           0 :         LBASSERTINFO( false, "Unimplemented mode " << name );
     538             :     }
     539             : 
     540         119 :     if( compound )
     541         111 :         compound->setEyes( EYE_CYCLOP );
     542             : 
     543         238 :     return compound;
     544             : }
     545             : 
     546          61 : Compound* Resources::_addStereoCompound( Compound* root,
     547             :                                          const Channels& channels,
     548             :                                          const fabric::ConfigParams& params )
     549             : {
     550          61 :     const Channel* channel = root->getChannel();
     551          61 :     const Layout* layout = channel->getLayout();
     552          61 :     const std::string& name = layout->getName();
     553          61 :     if( name == EQ_SERVER_CONFIG_LAYOUT_SIMPLE )
     554           8 :         return 0;
     555             : 
     556          53 :     Compound* compound = new Compound( root );
     557          53 :     compound->setName( "Stereo" );
     558          53 :     compound->setEyes( EYE_LEFT | EYE_RIGHT );
     559             : 
     560          53 :     const bool multiProcess = params.getFlags() &
     561             :                                   (fabric::ConfigParams::FLAG_MULTIPROCESS |
     562          53 :                                    fabric::ConfigParams::FLAG_MULTIPROCESS_DB );
     563          53 :     const Channels& active = name == EQ_SERVER_CONFIG_LAYOUT_DB_2D ? channels :
     564          53 :                             _filter( channels, multiProcess ? " mp " : " mt " );
     565             : 
     566          53 :     const size_t nChannels = active.size();
     567          53 :     const ChannelsCIter split = active.begin() + (nChannels >> 1);
     568             : 
     569         106 :     Channels leftChannels( split - active.begin( ));
     570          53 :     std::copy( active.begin(), split, leftChannels.begin( ));
     571             : 
     572         106 :     Channels rightChannels( active.end() - split );
     573          53 :     std::copy( split, active.end(), rightChannels.begin( ));
     574             : 
     575          53 :     Compound* left = 0;
     576         106 :     if( leftChannels.empty() ||
     577          10 :         ( leftChannels.size() == 1 && leftChannels.front() == channel ))
     578             :     {
     579          48 :         left = new Compound( compound );
     580             :     }
     581             :     else
     582           5 :         left = _addMonoCompound( compound, leftChannels, params );
     583             : 
     584          53 :     left->setEyes( EYE_LEFT );
     585             : 
     586          53 :     Compound* right = 0;
     587         106 :     if( rightChannels.empty() ||
     588         106 :         ( rightChannels.size() == 1 && rightChannels.front() == channel ))
     589             :     {
     590           0 :         right = new Compound( compound );
     591             :     }
     592             :     else
     593          53 :         right = _addMonoCompound( compound, rightChannels, params );
     594             : 
     595          53 :     right->setEyes( EYE_RIGHT );
     596             : 
     597         106 :     return compound;
     598             : }
     599             : 
     600          32 : Compound* Resources::_add2DCompound( Compound* root, const Channels& channels,
     601             :                                      fabric::ConfigParams params )
     602             : {
     603          32 :     const Channel* channel = root->getChannel();
     604          32 :     const Layout* layout = channel->getLayout();
     605          32 :     const std::string& name = layout->getName();
     606             : 
     607          32 :     Compound* compound = new Compound( root );
     608          32 :     compound->setName( name );
     609          32 :     if( params.getEqualizer().getMode() == LoadEqualizer::MODE_DB )
     610           0 :         params.getEqualizer().setMode( LoadEqualizer::MODE_2D );
     611             : 
     612          32 :     LoadEqualizer* lb = new LoadEqualizer( params.getEqualizer( ));
     613          32 :     if( name == EQ_SERVER_CONFIG_LAYOUT_2D_STATIC )
     614          16 :         lb->setDamping( 1.f );
     615          32 :     compound->addEqualizer( lb );
     616             : 
     617          32 :     _fill2DCompound( compound, channels );
     618          32 :     return compound;
     619             : }
     620             : 
     621          32 : void Resources::_fill2DCompound( Compound* compound, const Channels& channels )
     622             : {
     623          32 :     const Compounds& children = _addSources( compound, channels );
     624          32 :     const size_t step =  size_t( 100000.0f / float( children.size( )));
     625          32 :     size_t start = 0;
     626          54 :     for( CompoundsCIter i = children.begin(); i != children.end(); ++i )
     627             :     {
     628          22 :         Compound* child = *i;
     629          22 :         if( i+1 == children.end( )) // last - correct rounding 'error'
     630             :             child->setViewport(
     631             :                 fabric::Viewport( float( start ) / 100000.f, 0.f,
     632          22 :                                   ( 100000.f - float( start ))/100000.f, 1.f ));
     633             :         else
     634             :             child->setViewport(
     635             :                 fabric::Viewport( float( start ) / 100000.f, 0.f,
     636           0 :                                   float( step ) / 100000.f, 1.f ));
     637          22 :         start += step;
     638             :     }
     639          32 : }
     640             : 
     641          32 : Compound* Resources::_addDBCompound( Compound* root, const Channels& channels,
     642             :                                      fabric::ConfigParams params )
     643             : {
     644          32 :     const Channel* channel = root->getChannel();
     645          32 :     const Layout* layout = channel->getLayout();
     646          32 :     const std::string& name = layout->getName();
     647             : 
     648          32 :     Compound* compound = new Compound( root );
     649          32 :     compound->setName( name );
     650          32 :     compound->setBuffers( eq::Frame::BUFFER_COLOR | eq::Frame::BUFFER_DEPTH );
     651          32 :     if( name == EQ_SERVER_CONFIG_LAYOUT_DB_DYNAMIC )
     652             :     {
     653          16 :         if( params.getEqualizer().getMode() != LoadEqualizer::MODE_DB )
     654          16 :             params.getEqualizer().setMode( LoadEqualizer::MODE_DB );
     655          16 :         compound->addEqualizer( new LoadEqualizer( params.getEqualizer( )));
     656             :     }
     657             : 
     658          32 :     const Compounds& children = _addSources( compound, channels );
     659          32 :     const size_t step = size_t( 100000.0f / float( children.size( )));
     660          32 :     size_t start = 0;
     661          64 :     for( CompoundsCIter i = children.begin(); i != children.end(); ++i )
     662             :     {
     663          32 :         Compound* child = *i;
     664          32 :         if( i+1 == children.end( )) // last - correct rounding 'error'
     665          32 :             child->setRange( Range( float( start ) / 100000.f, 1.f ));
     666             :         else
     667             :             child->setRange( Range( float( start ) / 100000.f,
     668           0 :                                     float( start + step ) / 100000.f ));
     669          32 :         start += step;
     670             :     }
     671             : 
     672          32 :     return compound;
     673             : }
     674             : 
     675          31 : Compound* Resources::_addDSCompound( Compound* root, const Channels& channels )
     676             : {
     677          31 :     const Channel* channel = root->getChannel();
     678          31 :     const Layout* layout = channel->getLayout();
     679          31 :     const std::string& name = layout->getName();
     680             : 
     681          31 :     Compound* compound = new Compound( root );
     682          31 :     compound->setName( name );
     683             : 
     684          31 :     const Compounds& children = _addSources( compound, channels );
     685          31 :     const size_t step = size_t( 100000.0f / float( children.size( )));
     686             : 
     687          31 :     size_t start = 0;
     688          47 :     for( CompoundsCIter i = children.begin(); i != children.end(); ++i )
     689             :     {
     690          16 :         Compound* child = *i;
     691             : 
     692             :         // leaf draw + tile readback compound
     693          16 :         Compound* drawChild = new Compound( child );
     694          16 :         if( i+1 == children.end( ) ) // last - correct rounding 'error'
     695             :         {
     696             :             drawChild->setRange(
     697          16 :                 eq::Range( static_cast< float >( start )/100000.f, 1.f ));
     698             :         }
     699             :         else
     700             :             drawChild->setRange(
     701             :                 eq::Range( static_cast< float >( start )/100000.f,
     702           0 :                            static_cast< float >( start + step )/100000.f ));
     703             : 
     704          16 :         size_t y = 0;
     705          32 :         for( CompoundsCIter j = children.begin(); j != children.end(); ++j )
     706             :         {
     707          16 :             if( i != j )
     708             :             {
     709           0 :                 std::ostringstream frameName;
     710           0 :                 frameName << "tile" << j - children.begin() << ".channel"
     711           0 :                           << i - children.begin();
     712           0 :                 Viewport vp;
     713           0 :                 if(  j+1 == children.end( ) ) // last - correct rounding 'error'
     714             :                 {
     715             :                     vp = Viewport( 0.f, static_cast< float >( y )/100000.f,
     716           0 :                               1.f, static_cast< float >( 100000-y )/100000.f );
     717             :                 }
     718             :                 else
     719             :                     vp = Viewport( 0.f, static_cast< float >( y )/100000.f,
     720           0 :                                   1.f, static_cast< float >( step )/100000.f );
     721             : 
     722           0 :                 eq::server::Frame* outputFrame = new eq::server::Frame;
     723           0 :                 outputFrame->setName( frameName.str( ));
     724           0 :                 outputFrame->setViewport( vp );
     725             :                 outputFrame->setBuffers( eq::Frame::BUFFER_COLOR |
     726           0 :                                          eq::Frame::BUFFER_DEPTH );
     727           0 :                 drawChild->addOutputFrame( outputFrame );
     728             : 
     729             :                 // input tiles from other channels
     730           0 :                 frameName.str("");
     731           0 :                 frameName << "tile" << i - children.begin() << ".channel"
     732           0 :                           << j - children.begin();
     733             : 
     734           0 :                 eq::server::Frame* inputFrame = new eq::server::Frame;
     735           0 :                 inputFrame->setName( frameName.str( ));
     736           0 :                 child->addInputFrame( inputFrame );
     737             :             }
     738             :             // else own tile, is in place
     739             : 
     740          16 :             y += step;
     741             :         }
     742             : 
     743             :         // assembled color tile output, if not already in place
     744          16 :         if( child->getChannel() != compound->getChannel( ))
     745             :         {
     746          16 :             Frame* output = child->getOutputFrames().front();
     747             : 
     748          16 :             Viewport vp;
     749          16 :             if( i+1 == children.end( )) // last - correct rounding 'error'
     750             :             {
     751             :                 vp = Viewport( 0.f, static_cast< float >( start )/100000.f,
     752             :                                1.f,
     753          16 :                                static_cast< float >( 100000-start )/100000.f );
     754             :             }
     755             :             else
     756             :                 vp = Viewport( 0.f, static_cast< float >( start )/100000.f,
     757           0 :                                1.f, static_cast< float >( step )/100000.f );
     758             : 
     759          16 :             output->setViewport( vp );
     760             :         }
     761          16 :         start += step;
     762             :     }
     763             : 
     764          31 :     return compound;
     765             : }
     766             : 
     767           0 : static Channels _filterLocalChannels( const Channels& input,
     768             :                                       const Compound& filter )
     769             : {
     770           0 :     Channels result;
     771           0 :     for( ChannelsCIter i = input.begin(); i != input.end(); ++i )
     772             :     {
     773           0 :         const Node* node = (*i)->getNode();
     774           0 :         const Node* filterNode = filter.getChannel()->getNode();
     775           0 :         if( node == filterNode )
     776           0 :             result.push_back( *i );
     777             :     }
     778           0 :     return result;
     779             : }
     780             : 
     781          15 : Compound* Resources::_addDB2DCompound( Compound* root, const Channels& channels,
     782             :                                        fabric::ConfigParams params )
     783             : {
     784             :     // TODO: Optimized compositing?
     785          15 :     root->setBuffers( eq::Frame::BUFFER_COLOR | eq::Frame::BUFFER_DEPTH );
     786          15 :     const Channels& dbChannels = _filter( channels, " mt mp " );
     787          15 :     Compound* compound = _addDSCompound( root, dbChannels );
     788             : 
     789          15 :     const Compounds& children = compound->getChildren();
     790          15 :     for( CompoundsCIter i = children.begin(); i != children.end(); ++i )
     791             :     {
     792           0 :         Compound* child = *i;
     793           0 :         Compound* drawChild = child->getChildren().front();
     794           0 :         if( params.getEqualizer().getMode() == LoadEqualizer::MODE_DB )
     795           0 :             params.getEqualizer().setMode( LoadEqualizer::MODE_2D );
     796           0 :         drawChild->addEqualizer( new LoadEqualizer( params.getEqualizer( )));
     797           0 :         drawChild->setName( EQ_SERVER_CONFIG_LAYOUT_2D_DYNAMIC );
     798             : 
     799           0 :         const Channels& localChannels = _filterLocalChannels( channels, child );
     800           0 :         _fill2DCompound( drawChild, localChannels );
     801           0 :     }
     802             : 
     803          15 :     return compound;
     804             : }
     805             : 
     806          16 : Compound* Resources::_addSubpixelCompound( Compound* root,
     807             :                                            const Channels& channels )
     808             : {
     809          16 :     Compound* compound = new Compound( root );
     810          16 :     compound->setName( EQ_SERVER_CONFIG_LAYOUT_SUBPIXEL );
     811             : 
     812          16 :     const Compounds& children = _addSources( compound, channels, true );
     813          16 :     const uint32_t nChildren = uint32_t( children.size( ));
     814          27 :     for( CompoundsCIter i = children.begin(); i != children.end(); ++i )
     815          11 :         (*i)->setSubPixel( SubPixel( i - children.begin(), nChildren ));
     816             : 
     817          16 :     return compound;
     818             : }
     819             : 
     820         111 : const Compounds& Resources::_addSources( Compound* compound,
     821             :                                          const Channels& channels,
     822             :                                          const bool destChannelFrame )
     823             : {
     824         111 :     const Channel* rootChannel = compound->getChannel();
     825         111 :     const Segment* segment = rootChannel->getSegment();
     826         111 :     const Channel* outputChannel = segment ? segment->getChannel() : 0;
     827             : 
     828         192 :     for( ChannelsCIter i = channels.begin(); i != channels.end(); ++i )
     829             :     {
     830          81 :         Channel* channel = *i;
     831          81 :         Compound* child = new Compound( compound );
     832             : 
     833          81 :         const bool isDestChannel = channel == outputChannel;
     834          81 :         if( isDestChannel && !destChannelFrame )
     835           0 :             continue;
     836          81 :         if( !isDestChannel )
     837          81 :             child->setChannel( channel );
     838             : 
     839          81 :         Frame* outFrame = new Frame;
     840          81 :         std::stringstream frameName;
     841          81 :         frameName << "Frame." << compound->getName() << '.' << ++_frameCounter;
     842          81 :         outFrame->setName( frameName.str( ));
     843          81 :         if( isDestChannel )
     844           0 :             outFrame->setType( Frame::TYPE_TEXTURE ); // OPT
     845          81 :         child->addOutputFrame( outFrame );
     846             : 
     847          81 :         Frame* inFrame = new Frame;
     848          81 :         inFrame->setName( frameName.str( ));
     849          81 :         compound->addInputFrame( inFrame );
     850          81 :     }
     851             : 
     852         111 :     return compound->getChildren();
     853             : }
     854             : 
     855             : }
     856             : }
     857          27 : }

Generated by: LCOV version 1.10