server/canvas.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "canvas.h"
00019
00020 #include "channel.h"
00021 #include "compound.h"
00022 #include "config.h"
00023 #include "layout.h"
00024 #include "log.h"
00025 #include "nameFinder.h"
00026 #include "node.h"
00027 #include "paths.h"
00028 #include "pipe.h"
00029 #include "segment.h"
00030 #include "window.h"
00031
00032 #include <eq/net/dataIStream.h>
00033 #include <eq/net/dataOStream.h>
00034
00035
00036 using namespace eq::base;
00037
00038 namespace eq
00039 {
00040 namespace server
00041 {
00042
00043 Canvas::Canvas()
00044 : _config( 0 )
00045 , _activeLayout( 0 )
00046 {}
00047
00048 Canvas::Canvas( const Canvas& from, Config* config )
00049 : eq::Frustum( from )
00050 , _config( 0 )
00051 , _activeLayout( from._activeLayout )
00052 {
00053 EQASSERT( config );
00054
00055 for( SegmentVector::const_iterator i = from._segments.begin();
00056 i != from._segments.end(); ++i )
00057 {
00058 addSegment( new Segment( **i, config ));
00059 }
00060
00061 for( LayoutVector::const_iterator i = from._layouts.begin();
00062 i != from._layouts.end(); ++i )
00063 {
00064 const Layout* layout = *i;
00065 if( layout )
00066 {
00067 const LayoutPath path( layout->getPath( ));
00068 addLayout( config->getLayout( path ));
00069 }
00070 else
00071 addLayout( 0 );
00072 }
00073
00074 config->addCanvas( this );
00075 EQASSERT( _config );
00076 }
00077
00078 Canvas::~Canvas()
00079 {
00080 for( SegmentVector::const_iterator i = _segments.begin();
00081 i != _segments.end(); ++i )
00082 {
00083 Segment* segment = *i;
00084 segment->_canvas = 0;
00085 delete segment;
00086 }
00087 _segments.clear();
00088 _layouts.clear();
00089
00090 if( _config )
00091 _config->removeCanvas( this );
00092
00093 _config = 0;
00094 _activeLayout = 0;
00095 }
00096
00097 void Canvas::getInstanceData( net::DataOStream& os )
00098 {
00099
00100
00101
00102
00103 const uint64_t dirty = eq::Canvas::DIRTY_CUSTOM - 1;
00104 os << dirty;
00105 serialize( os, dirty );
00106 }
00107
00108 void Canvas::serialize( net::DataOStream& os, const uint64_t dirtyBits )
00109 {
00110 Frustum::serialize( os, dirtyBits );
00111
00112 if( dirtyBits & eq::Canvas::DIRTY_LAYOUT )
00113 os << _activeLayout;
00114
00115 if( dirtyBits & eq::Canvas::DIRTY_CHILDREN )
00116 {
00117 for( SegmentVector::const_iterator i = _segments.begin();
00118 i != _segments.end(); ++i )
00119 {
00120 Segment* segment = *i;
00121 EQASSERT( segment->getID() != EQ_ID_INVALID );
00122 os << segment->getID();
00123 }
00124 os << EQ_ID_INVALID;
00125
00126 for( LayoutVector::const_iterator i = _layouts.begin();
00127 i != _layouts.end(); ++i )
00128 {
00129 Layout* layout = *i;
00130 if( layout )
00131 {
00132 EQASSERT( layout->getID() != EQ_ID_INVALID );
00133 os << layout->getID();
00134 }
00135 else
00136 os << EQ_ID_NONE;
00137 }
00138 os << EQ_ID_INVALID;
00139 }
00140 }
00141
00142 void Canvas::deserialize( net::DataIStream& is, const uint64_t dirtyBits )
00143 {
00144 Frustum::deserialize( is, dirtyBits );
00145
00146 if( dirtyBits & eq::Canvas::DIRTY_LAYOUT )
00147 {
00148 uint32_t index;
00149 is >> index;
00150 _useLayout( index );
00151 }
00152 }
00153
00154 Segment* Canvas::getSegment( const SegmentPath& path )
00155 {
00156 EQASSERTINFO( _segments.size() > path.segmentIndex,
00157 _segments.size() << " <= " << path.segmentIndex );
00158
00159 if( _segments.size() <= path.segmentIndex )
00160 return 0;
00161
00162 return _segments[ path.segmentIndex ];
00163 }
00164
00165 CanvasPath Canvas::getPath() const
00166 {
00167 EQASSERT( _config );
00168
00169 const CanvasVector& canvases = _config->getCanvases();
00170 CanvasVector::const_iterator i = std::find( canvases.begin(),
00171 canvases.end(), this );
00172 EQASSERT( i != canvases.end( ));
00173
00174 CanvasPath path;
00175 path.canvasIndex = std::distance( canvases.begin(), i );
00176 return path;
00177 }
00178
00179 void Canvas::addSegment( Segment* segment )
00180 {
00181 EQASSERT( segment );
00182 EQASSERT( std::find( _segments.begin(), _segments.end(), segment ) ==
00183 _segments.end( ));
00184
00185
00186 if( segment->getCurrentType() == TYPE_NONE )
00187 {
00188 if( getCurrentType() != TYPE_NONE )
00189 {
00190 eq::Wall wall( getWall( ));
00191 const Viewport& viewport( segment->getViewport( ));
00192 wall.apply( viewport );
00193
00194 switch( getCurrentType( ))
00195 {
00196 case Frustum::TYPE_WALL:
00197 segment->setWall( wall );
00198 EQLOG( LOG_VIEW ) << "Segment " << segment->getName()
00199 << segment->getWall() << std::endl;
00200 break;
00201
00202 case Frustum::TYPE_PROJECTION:
00203 {
00204 Projection projection( getProjection( ));
00205 projection = wall;
00206 segment->setProjection( projection );
00207 break;
00208 }
00209 default:
00210 EQUNIMPLEMENTED;
00211 break;
00212 }
00213 }
00214 }
00215
00216 segment->_canvas = this;
00217 _segments.push_back( segment );
00218 }
00219
00220 Segment* Canvas::findSegment( const std::string& name )
00221 {
00222 SegmentFinder finder( name );
00223 accept( finder );
00224 return finder.getResult();
00225 }
00226
00227 void Canvas::addLayout( Layout* layout )
00228 {
00229 EQASSERT( std::find( _layouts.begin(), _layouts.end(), layout ) ==
00230 _layouts.end( ));
00231
00232
00233 _layouts.push_back( layout );
00234 }
00235
00236 void Canvas::_useLayout( const uint32_t index )
00237 {
00238 if( _config && _config->isRunning( ))
00239 _switchLayout( _activeLayout, index );
00240
00241 _activeLayout = index;
00242 }
00243
00244 void Canvas::init()
00245 {
00246 _switchLayout( EQ_ID_NONE, _activeLayout );
00247 }
00248
00249 void Canvas::exit()
00250 {
00251 _switchLayout( _activeLayout, EQ_ID_NONE );
00252 }
00253
00254 namespace
00255 {
00256 class ActivateVisitor : public ConfigVisitor
00257 {
00258 public:
00259 ActivateVisitor( const ChannelVector& channels ) : _channels( channels ) {}
00260 virtual ~ActivateVisitor() {}
00261
00262 virtual VisitorResult visit( Compound* compound )
00263 {
00264 Channel* channel = compound->getChannel();
00265 if( !channel )
00266 return TRAVERSE_CONTINUE;
00267
00268 for( ChannelVector::iterator i = _channels.begin();
00269 i != _channels.end(); ++i )
00270 {
00271 Channel* destChannel = *i;
00272 if( destChannel != channel )
00273 continue;
00274
00275 compound->activate();
00276 _channels.erase( i );
00277 break;
00278 }
00279
00280 return TRAVERSE_PRUNE;
00281 }
00282
00283 virtual VisitorResult visitPost( Config* config )
00284 {
00285 if( !_channels.empty( ))
00286 EQWARN << _channels.size() << " unused destination channels"
00287 << std::endl;
00288 return TRAVERSE_CONTINUE;
00289 }
00290
00291 private:
00292 ChannelVector _channels;
00293 };
00294
00295 class DeactivateVisitor : public ConfigVisitor
00296 {
00297 public:
00298 DeactivateVisitor( ChannelVector& channels )
00299 : _channels( channels ) {}
00300 virtual ~DeactivateVisitor() {}
00301
00302 virtual VisitorResult visit( Compound* compound )
00303 {
00304 Channel* channel = compound->getChannel();
00305 if( !channel )
00306 return TRAVERSE_CONTINUE;
00307
00308 for( ChannelVector::iterator i = _channels.begin();
00309 i != _channels.end(); ++i )
00310 {
00311 Channel* destChannel = *i;
00312 if( destChannel != channel )
00313 continue;
00314
00315 compound->deactivate();
00316 _channels.erase( i );
00317 break;
00318 }
00319
00320 return TRAVERSE_PRUNE;
00321 }
00322
00323 virtual VisitorResult visitPost( Config* config )
00324 {
00325 if( !_channels.empty( ))
00326 EQWARN << _channels.size() << " unused destination channels"
00327 << std::endl;
00328 return TRAVERSE_CONTINUE;
00329 }
00330
00331 private:
00332 ChannelVector& _channels;
00333 };
00334 }
00335
00336 void Canvas::_switchLayout( const uint32_t oldIndex, const uint32_t newIndex )
00337 {
00338 EQASSERT( _config );
00339
00340 const size_t nLayouts = _layouts.size();
00341 const Layout* oldLayout = (oldIndex >= nLayouts) ? 0 :_layouts[oldIndex];
00342 const Layout* newLayout = (newIndex >= nLayouts) ? 0 :_layouts[newIndex];
00343
00344 for( SegmentVector::const_iterator i = _segments.begin();
00345 i != _segments.end(); ++i )
00346 {
00347 const Segment* segment = *i;
00348 const ChannelVector& destChannels = segment->getDestinationChannels();
00349
00350 if( newLayout )
00351 {
00352
00353 ChannelVector usedChannels;
00354 for( ChannelVector::const_iterator j = destChannels.begin();
00355 j != destChannels.end(); ++j )
00356 {
00357 Channel* channel = *j;
00358 const Layout* channelLayout = channel->getLayout();
00359 if( channelLayout == newLayout )
00360 usedChannels.push_back( channel );
00361 }
00362
00363 ActivateVisitor activator( usedChannels );
00364 _config->accept( activator );
00365 }
00366
00367 if( oldLayout )
00368 {
00369
00370 ChannelVector usedChannels;
00371
00372 for( ChannelVector::const_iterator j = destChannels.begin();
00373 j != destChannels.end(); ++j )
00374 {
00375 Channel* channel = *j;
00376 const Layout* channelLayout = channel->getLayout();
00377 if( channelLayout == oldLayout )
00378 usedChannels.push_back( channel );
00379 }
00380 DeactivateVisitor deactivator( usedChannels );
00381 _config->accept( deactivator );
00382 }
00383 }
00384 }
00385
00386 namespace
00387 {
00388 template< class C, class V >
00389 VisitorResult _accept( C* canvas, V& visitor )
00390 {
00391 VisitorResult result = visitor.visitPre( canvas );
00392 if( result != TRAVERSE_CONTINUE )
00393 return result;
00394
00395 const SegmentVector& segments = canvas->getSegments();
00396 for( SegmentVector::const_iterator i = segments.begin();
00397 i != segments.end(); ++i )
00398 {
00399 switch( (*i)->accept( visitor ))
00400 {
00401 case TRAVERSE_TERMINATE:
00402 return TRAVERSE_TERMINATE;
00403
00404 case TRAVERSE_PRUNE:
00405 result = TRAVERSE_PRUNE;
00406 break;
00407
00408 case TRAVERSE_CONTINUE:
00409 default:
00410 break;
00411 }
00412 }
00413
00414 switch( visitor.visitPost( canvas ))
00415 {
00416 case TRAVERSE_TERMINATE:
00417 return TRAVERSE_TERMINATE;
00418
00419 case TRAVERSE_PRUNE:
00420 return TRAVERSE_PRUNE;
00421
00422 case TRAVERSE_CONTINUE:
00423 default:
00424 break;
00425 }
00426
00427 return result;
00428 }
00429 }
00430
00431 VisitorResult Canvas::accept( CanvasVisitor& visitor )
00432 {
00433 return _accept( this, visitor );
00434 }
00435
00436 VisitorResult Canvas::accept( ConstCanvasVisitor& visitor ) const
00437 {
00438 return _accept( this, visitor );
00439 }
00440
00441 void Canvas::unmap()
00442 {
00443 net::Session* session = getSession();
00444 EQASSERT( session );
00445 for( SegmentVector::const_iterator i = _segments.begin();
00446 i != _segments.end(); ++i )
00447 {
00448 Segment* segment = *i;
00449 EQASSERT( segment->getID() != EQ_ID_INVALID );
00450
00451 session->unmapObject( segment );
00452 }
00453
00454 EQASSERT( getID() != EQ_ID_INVALID );
00455 session->unmapObject( this );
00456 }
00457
00458 std::ostream& operator << ( std::ostream& os, const Canvas* canvas )
00459 {
00460 if( !canvas )
00461 return os;
00462
00463 os << disableFlush << disableHeader << "canvas" << std::endl;
00464 os << "{" << std::endl << indent;
00465
00466 const std::string& name = canvas->getName();
00467 if( !name.empty( ))
00468 os << "name \"" << name << "\"" << std::endl;
00469
00470 const LayoutVector& layouts = canvas->getLayouts();
00471 for( LayoutVector::const_iterator i = layouts.begin();
00472 i != layouts.end(); ++i )
00473 {
00474 Layout* layout = *i;
00475 if( layout )
00476 {
00477 const Config* config = layout->getConfig();
00478 const std::string& layoutName = layout->getName();
00479 if( layoutName.empty() ||
00480 config->findLayout( layoutName ) != layout )
00481 os << layout->getPath() << std::endl;
00482 else
00483 os << "layout \"" << layout->getName() << "\"" << std::endl;
00484 }
00485 else
00486 os << "layout OFF" << std::endl;
00487 }
00488
00489 os << static_cast< const eq::Frustum& >( *canvas );
00490
00491 const SegmentVector& segments = canvas->getSegments();
00492 for( SegmentVector::const_iterator i = segments.begin();
00493 i != segments.end(); ++i )
00494 {
00495 os << *i;
00496 }
00497 os << exdent << "}" << std::endl << enableHeader << enableFlush;
00498 return os;
00499 }
00500
00501 }
00502 }