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 : }
|