LCOV - code coverage report
Current view: top level - eq/server/config - resources.cpp (source / functions) Hit Total Coverage
Test: Equalizer Lines: 2 443 0.5 %
Date: 2016-09-29 05:02:09 Functions: 2 27 7.4 %

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

Generated by: LCOV version 1.11