server/channel.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <pthread.h>
00019 #include "channel.h"
00020
00021 #include "channelListener.h"
00022 #include "channelUpdateVisitor.h"
00023 #include "channelVisitor.h"
00024 #include "compound.h"
00025 #include "compoundVisitor.h"
00026 #include "config.h"
00027 #include "global.h"
00028 #include "log.h"
00029 #include "node.h"
00030 #include "paths.h"
00031 #include "segment.h"
00032 #include "view.h"
00033 #include "window.h"
00034
00035 #include <eq/base/base.h>
00036 #include <eq/base/debug.h>
00037 #include <eq/net/command.h>
00038 #include <eq/client/commands.h>
00039 #include <eq/client/global.h>
00040 #include <eq/client/log.h>
00041 #include <eq/client/packets.h>
00042 #include <eq/client/view.h>
00043
00044 #include "channel.ipp"
00045
00046 using namespace eq::base;
00047 using namespace std;
00048
00049 namespace eq
00050 {
00051 namespace server
00052 {
00053 typedef net::CommandFunc<Channel> ChannelFunc;
00054
00055 void Channel::_construct()
00056 {
00057 _active = 0;
00058 _view = 0;
00059 _segment = 0;
00060 _window = 0;
00061 _fixedPVP = false;
00062 _lastDrawCompound = 0;
00063 _near = .1f;
00064 _far = 10.f;
00065 _overdraw = Vector4i::ZERO;
00066 _maxSize = Vector2i::ZERO;
00067
00068 _drawable = 0;
00069 _tasks = eq::TASK_NONE;
00070 EQINFO << "New channel @" << (void*)this << endl;
00071 }
00072
00073 Channel::Channel()
00074 {
00075 _construct();
00076
00077 const Global* global = Global::instance();
00078
00079 for( int i=0; i<eq::Channel::IATTR_ALL; ++i )
00080 _iAttributes[i] = global->getChannelIAttribute(
00081 static_cast<eq::Channel::IAttribute>( i ));
00082 }
00083
00084 Channel::Channel( const Channel& from, Window* window )
00085 : net::Object()
00086 {
00087 _construct();
00088
00089 _name = from._name;
00090 _vp = from._vp;
00091 _pvp = from._pvp;
00092 _fixedPVP = from._fixedPVP;
00093 _drawable = from._drawable;
00094
00095
00096 window->insertChannel( &from, this );
00097
00098 for( int i=0; i<eq::Channel::IATTR_ALL; ++i )
00099 _iAttributes[i] = from._iAttributes[i];
00100 }
00101
00102 void Channel::attachToSession( const uint32_t id, const uint32_t instanceID,
00103 net::Session* session )
00104 {
00105 net::Object::attachToSession( id, instanceID, session );
00106
00107 net::CommandQueue* serverQueue = getServerThreadQueue();
00108 net::CommandQueue* commandQueue = getCommandThreadQueue();
00109
00110 registerCommand( eq::CMD_CHANNEL_CONFIG_INIT_REPLY,
00111 ChannelFunc( this, &Channel::_cmdConfigInitReply ),
00112 commandQueue );
00113 registerCommand( eq::CMD_CHANNEL_CONFIG_EXIT_REPLY,
00114 ChannelFunc( this, &Channel::_cmdConfigExitReply ),
00115 commandQueue );
00116 registerCommand( eq::CMD_CHANNEL_SET_NEARFAR,
00117 ChannelFunc( this, &Channel::_cmdSetNearFar ),
00118 commandQueue );
00119 registerCommand( eq::CMD_CHANNEL_FRAME_FINISH_REPLY,
00120 ChannelFunc( this, &Channel::_cmdFrameFinishReply ),
00121 serverQueue );
00122 }
00123
00124 Channel::~Channel()
00125 {
00126 EQINFO << "Delete channel @" << (void*)this << endl;
00127
00128 if( _window )
00129 _window->removeChannel( this );
00130 }
00131 void Channel::setDrawable( const uint32_t drawable )
00132 {
00133 _drawable = drawable;
00134 }
00135
00136 Config* Channel::getConfig()
00137 {
00138 EQASSERT( _window );
00139 return _window ? _window->getConfig() : 0;
00140 }
00141
00142 const Config* Channel::getConfig() const
00143 {
00144 EQASSERT( _window );
00145 return _window ? _window->getConfig() : 0;
00146 }
00147
00148 Node* Channel::getNode()
00149 {
00150 EQASSERT( _window );
00151 return _window ? _window->getNode() : 0;
00152 }
00153
00154 const Node* Channel::getNode() const
00155 {
00156 EQASSERT( _window );
00157 return _window ? _window->getNode() : 0;
00158 }
00159
00160 Pipe* Channel::getPipe()
00161 {
00162 EQASSERT( _window );
00163 return _window ? _window->getPipe() : 0;
00164 }
00165
00166 const Pipe* Channel::getPipe() const
00167 {
00168 EQASSERT( _window );
00169 return _window ? _window->getPipe() : 0;
00170 }
00171
00172 ChannelPath Channel::getPath() const
00173 {
00174 EQASSERT( _window );
00175 ChannelPath path( _window->getPath( ));
00176
00177 const ChannelVector& channels = _window->getChannels();
00178 ChannelVector::const_iterator i = std::find( channels.begin(),
00179 channels.end(), this );
00180 EQASSERT( i != channels.end( ));
00181 path.channelIndex = std::distance( channels.begin(), i );
00182 return path;
00183 }
00184
00185 const CompoundVector& Channel::getCompounds() const
00186 {
00187 return getConfig()->getCompounds();
00188 }
00189
00190 net::CommandQueue* Channel::getServerThreadQueue()
00191 {
00192 EQASSERT( _window );
00193 return _window->getServerThreadQueue();
00194 }
00195
00196 net::CommandQueue* Channel::getCommandThreadQueue()
00197 {
00198 EQASSERT( _window );
00199 return _window->getCommandThreadQueue();
00200 }
00201
00202 VisitorResult Channel::accept( ChannelVisitor& visitor )
00203 {
00204 return visitor.visit( this );
00205 }
00206
00207 VisitorResult Channel::accept( ChannelVisitor& visitor ) const
00208 {
00209 return visitor.visit( this );
00210 }
00211
00212 void Channel::activate()
00213 {
00214 EQASSERT( _window );
00215
00216 ++_active;
00217 if( _window )
00218 _window->activate();
00219
00220 EQLOG( LOG_VIEW ) << "activate: " << _active << std::endl;
00221 }
00222
00223 void Channel::deactivate()
00224 {
00225 EQASSERT( _active != 0 );
00226 EQASSERT( _window );
00227
00228 --_active;
00229 if( _window )
00230 _window->deactivate();
00231
00232 EQLOG( LOG_VIEW ) << "deactivate: " << _active << std::endl;
00233 }
00234
00235 void Channel::setOutput( View* view, Segment* segment )
00236 {
00237 EQASSERT( !_view && !_segment );
00238 EQASSERT( view && segment );
00239
00240 _view = view;
00241 _segment = segment;
00242
00243 view->addChannel( this );
00244 segment->addDestinationChannel( this );
00245 }
00246
00247 void Channel::unsetOutput()
00248 {
00249 EQASSERT( _view && _segment );
00250
00251 EQCHECK( _view->removeChannel( this ));
00252 EQCHECK( _segment->removeDestinationChannel( this ));
00253
00254 _view = 0;
00255 _segment = 0;
00256 }
00257
00258 const Layout* Channel::getLayout() const
00259 {
00260 EQASSERT( _view );
00261 return _view ? _view->getLayout() : 0;
00262 }
00263
00264 void Channel::addTasks( const uint32_t tasks )
00265 {
00266 EQASSERT( _window );
00267 _tasks |= tasks;
00268 _window->addTasks( tasks );
00269 }
00270
00271 Vector3ub Channel::_getUniqueColor() const
00272 {
00273 Vector3ub color = Vector3ub::ZERO;
00274 uint32_t value = (reinterpret_cast< size_t >( this ) & 0xffffffffu);
00275
00276 for( unsigned i=0; i<8; ++i )
00277 {
00278 color.r() |= ( value&1 << (7-i) ); value >>= 1;
00279 color.g() |= ( value&1 << (7-i) ); value >>= 1;
00280 color.b() |= ( value&1 << (7-i) ); value >>= 1;
00281 }
00282
00283 return color;
00284 }
00285
00286
00287
00288
00289 void Channel::setPixelViewport( const eq::PixelViewport& pvp )
00290 {
00291 if( !pvp.isValid( ))
00292 return;
00293
00294 _fixedPVP = true;
00295
00296 if( pvp == _pvp )
00297 return;
00298
00299 _pvp = pvp;
00300 _vp.invalidate();
00301 notifyViewportChanged();
00302 }
00303
00304 void Channel::setViewport( const eq::Viewport& vp )
00305 {
00306 if( !vp.hasArea( ))
00307 return;
00308
00309 _fixedPVP = false;
00310
00311 if( vp == _vp )
00312 return;
00313
00314 _vp = vp;
00315 _pvp.invalidate();
00316 notifyViewportChanged();
00317 }
00318
00319 void Channel::notifyViewportChanged()
00320 {
00321 if( !_window )
00322 return;
00323
00324 eq::PixelViewport windowPVP = _window->getPixelViewport();
00325 if( !windowPVP.isValid( ))
00326 return;
00327
00328 windowPVP.x = 0;
00329 windowPVP.y = 0;
00330
00331 if( _fixedPVP )
00332 _vp = _pvp.getSubVP( windowPVP );
00333 else
00334 _pvp = windowPVP.getSubPVP( _vp );
00335
00336 EQINFO << "Channel viewport update: " << _pvp << ":" << _vp << endl;
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 void Channel::updateRunning( const uint32_t initID )
00348 {
00349 if( !isActive() && _state == STATE_STOPPED )
00350 return;
00351
00352 if( isActive() && _state != STATE_RUNNING )
00353 _configInit( initID );
00354
00355 if( !isActive( ))
00356 _configExit();
00357 }
00358
00359 bool Channel::syncRunning()
00360 {
00361 bool success = true;
00362 if( isActive() && _state != STATE_RUNNING && !_syncConfigInit( ))
00363
00364 success = false;
00365
00366 if( !isActive() && _state != STATE_STOPPED && !_syncConfigExit( ))
00367
00368 success = false;
00369
00370 EQASSERT( _state == STATE_RUNNING || _state == STATE_STOPPED ||
00371 _state == STATE_INIT_FAILED );
00372 return success;
00373 }
00374
00375
00376
00377
00378 void Channel::_configInit( const uint32_t initID )
00379 {
00380 EQASSERT( _state == STATE_STOPPED );
00381 _state = STATE_INITIALIZING;
00382
00383 getConfig()->registerObject( this );
00384
00385 eq::WindowCreateChannelPacket createChannelPacket;
00386 createChannelPacket.channelID = getID();
00387 _window->send( createChannelPacket );
00388
00389 eq::ChannelConfigInitPacket packet;
00390 packet.initID = initID;
00391 packet.view = _view;
00392 packet.color = _getUniqueColor();
00393 packet.tasks = _tasks;
00394 packet.drawable = _drawable;
00395
00396 if( _fixedPVP )
00397 packet.pvp = _pvp;
00398 else
00399 packet.vp = _vp;
00400 memcpy( packet.iAttributes, _iAttributes,
00401 eq::Channel::IATTR_ALL * sizeof( int32_t ));
00402
00403 EQLOG( LOG_INIT ) << "Init channel" << std::endl;
00404 send( packet, _name );
00405 }
00406
00407 bool Channel::_syncConfigInit()
00408 {
00409 EQASSERT( _state == STATE_INITIALIZING || _state == STATE_INIT_SUCCESS ||
00410 _state == STATE_INIT_FAILED );
00411
00412 _state.waitNE( STATE_INITIALIZING );
00413
00414 const bool success = ( _state == STATE_INIT_SUCCESS );
00415 if( success )
00416 _state = STATE_RUNNING;
00417 else
00418 EQWARN << "Channel initialization failed: " << _error << endl;
00419
00420 return success;
00421 }
00422
00423
00424
00425
00426 void Channel::_configExit()
00427 {
00428 EQASSERT( _state == STATE_RUNNING || _state == STATE_INIT_FAILED );
00429 _state = STATE_EXITING;
00430
00431 EQLOG( LOG_INIT ) << "Exit channel" << std::endl;
00432 eq::ChannelConfigExitPacket packet;
00433 send( packet );
00434
00435 eq::WindowDestroyChannelPacket destroyChannelPacket;
00436 destroyChannelPacket.channelID = getID();
00437 _window->send( destroyChannelPacket );
00438 }
00439
00440 bool Channel::_syncConfigExit()
00441 {
00442 EQASSERT( _state == STATE_EXITING || _state == STATE_EXIT_SUCCESS ||
00443 _state == STATE_EXIT_FAILED );
00444
00445 _state.waitNE( STATE_EXITING );
00446 const bool success = ( _state == STATE_EXIT_SUCCESS );
00447 EQASSERT( success || _state == STATE_EXIT_FAILED );
00448
00449 getConfig()->deregisterObject( this );
00450
00451 _state = STATE_STOPPED;
00452 _tasks = eq::TASK_NONE;
00453 return success;
00454 }
00455
00456
00457
00458
00459 void Channel::_setupRenderContext( const uint32_t frameID,
00460 eq::RenderContext& context )
00461 {
00462 context.frameID = frameID;
00463 context.pvp = _pvp;
00464 context.view = _view;
00465 context.vp = _vp;
00466 }
00467
00468 bool Channel::update( const uint32_t frameID, const uint32_t frameNumber )
00469 {
00470 EQASSERT( _state == STATE_RUNNING );
00471 EQASSERT( _active > 0 );
00472
00473 eq::ChannelFrameStartPacket startPacket;
00474 startPacket.frameNumber = frameNumber;
00475 _setupRenderContext( frameID, startPacket.context );
00476
00477 send( startPacket );
00478 EQLOG( eq::LOG_TASKS ) << "TASK channel " << _name << " start frame "
00479 << &startPacket << endl;
00480
00481 bool updated = false;
00482 const CompoundVector& compounds = getCompounds();
00483
00484 for( CompoundVector::const_iterator i = compounds.begin();
00485 i != compounds.end(); ++i )
00486 {
00487 const Compound* compound = *i;
00488 ChannelUpdateVisitor visitor( this, frameID, frameNumber );
00489
00490 visitor.setEye( eq::EYE_CYCLOP );
00491 compound->accept( visitor );
00492
00493 visitor.setEye( eq::EYE_LEFT );
00494 compound->accept( visitor );
00495
00496 visitor.setEye( eq::EYE_RIGHT );
00497 compound->accept( visitor );
00498
00499 updated |= visitor.isUpdated();
00500 }
00501
00502 eq::ChannelFrameFinishPacket finishPacket;
00503 finishPacket.frameNumber = frameNumber;
00504 finishPacket.context = startPacket.context;
00505
00506 send( finishPacket );
00507 EQLOG( eq::LOG_TASKS ) << "TASK channel " << _name << " finish frame "
00508 << &finishPacket << endl;
00509 _lastDrawCompound = 0;
00510
00511 return updated;
00512 }
00513
00514 void Channel::send( net::ObjectPacket& packet )
00515 {
00516 packet.objectID = getID();
00517 getNode()->send( packet );
00518 }
00519
00520 void Channel::send( net::ObjectPacket& packet, const std::string& string )
00521 {
00522 packet.objectID = getID();
00523 getNode()->send( packet, string );
00524 }
00525
00526
00527
00528
00529 void Channel::addListener( ChannelListener* listener )
00530 {
00531 CHECK_THREAD( _serverThread );
00532 EQASSERT( std::find( _listeners.begin(), _listeners.end(), listener ) ==
00533 _listeners.end( ));
00534
00535 _listeners.push_back( listener );
00536 }
00537
00538 void Channel::removeListener( ChannelListener* listener )
00539 {
00540 ChannelListeners::iterator i = find( _listeners.begin(), _listeners.end(),
00541 listener );
00542 if( i != _listeners.end( ))
00543 _listeners.erase( i );
00544 }
00545
00546 void Channel::_fireLoadData( const uint32_t frameNumber,
00547 const uint32_t nStatistics,
00548 const eq::Statistic* statistics )
00549 {
00550 CHECK_THREAD( _serverThread );
00551
00552 for( ChannelListeners::const_iterator i = _listeners.begin();
00553 i != _listeners.end(); ++i )
00554
00555 (*i)->notifyLoadData( this, frameNumber, nStatistics, statistics );
00556 }
00557
00558
00559
00560
00561 net::CommandResult Channel::_cmdConfigInitReply( net::Command& command )
00562 {
00563 const eq::ChannelConfigInitReplyPacket* packet =
00564 command.getPacket<eq::ChannelConfigInitReplyPacket>();
00565 EQVERB << "handle channel configInit reply " << packet << endl;
00566
00567 _near = packet->nearPlane;
00568 _far = packet->farPlane;
00569 _maxSize = packet->maxSize;
00570 _error = packet->error;
00571
00572 if( packet->result )
00573 _state = STATE_INIT_SUCCESS;
00574 else
00575 _state = STATE_INIT_FAILED;
00576
00577 return net::COMMAND_HANDLED;
00578 }
00579
00580 net::CommandResult Channel::_cmdConfigExitReply( net::Command& command )
00581 {
00582 const eq::ChannelConfigExitReplyPacket* packet =
00583 command.getPacket<eq::ChannelConfigExitReplyPacket>();
00584 EQVERB << "handle channel configExit reply " << packet << endl;
00585
00586 if( packet->result )
00587 _state = STATE_EXIT_SUCCESS;
00588 else
00589 _state = STATE_EXIT_FAILED;
00590
00591 return net::COMMAND_HANDLED;
00592 }
00593
00594 net::CommandResult Channel::_cmdSetNearFar( net::Command& command )
00595 {
00596 const eq::ChannelSetNearFarPacket* packet =
00597 command.getPacket<eq::ChannelSetNearFarPacket>();
00598 _near = packet->nearPlane;
00599 _far = packet->farPlane;
00600 return net::COMMAND_HANDLED;
00601 }
00602
00603 net::CommandResult Channel::_cmdFrameFinishReply( net::Command& command )
00604 {
00605 const eq::ChannelFrameFinishReplyPacket* packet =
00606 command.getPacket<eq::ChannelFrameFinishReplyPacket>();
00607
00608
00609 for( uint32_t i = 0; i<packet->nStatistics; ++i )
00610 {
00611 const eq::Statistic& data = packet->statistics[i];
00612 EQLOG( eq::LOG_STATS ) << data << endl;
00613 }
00614
00615 _fireLoadData(packet->frameNumber, packet->nStatistics, packet->statistics);
00616
00617 return net::COMMAND_HANDLED;
00618 }
00619
00620 std::ostream& operator << ( std::ostream& os, const Channel* channel)
00621 {
00622 if( !channel )
00623 return os;
00624
00625 os << disableFlush << disableHeader << "channel" << endl;
00626 os << "{" << endl << indent;
00627
00628 const std::string& name = channel->getName();
00629 if( !name.empty( ))
00630 os << "name \"" << name << "\"" << endl;
00631
00632 const Segment* segment = channel->getSegment();
00633 const View* view = channel->getView();
00634 if( view && segment )
00635 {
00636 os << "path ( ";
00637
00638 const Config* config = channel->getConfig();
00639 const std::string& segmentName = segment->getName();
00640 if( !segmentName.empty() &&
00641 config->findSegment( segmentName ) == segment )
00642 {
00643 os << "segment \"" << segmentName << "\" ";
00644 }
00645 else
00646 os << segment->getPath() << ' ';
00647
00648 const std::string& viewName = view->getName();
00649 if( !viewName.empty() &&
00650 config->findView( viewName ) == view )
00651 {
00652 os << "view \"" << viewName << '\"';
00653 }
00654 else
00655 os << view->getPath();
00656
00657 os << " )" << endl;
00658 }
00659
00660 const eq::Viewport& vp = channel->getViewport();
00661 if( vp.isValid( ) && !channel->_fixedPVP )
00662 {
00663 if( vp != eq::Viewport::FULL )
00664 os << "viewport " << vp << endl;
00665 }
00666 else
00667 {
00668 const eq::PixelViewport& pvp = channel->getPixelViewport();
00669 if( pvp.isValid( ))
00670 os << "viewport " << pvp << endl;
00671 }
00672
00673
00674 const uint32_t drawable = channel->getDrawable();
00675 if( drawable != eq::Channel::FB_WINDOW )
00676 {
00677 os << "drawable [";
00678
00679 if ((drawable & eq::Channel::FBO_COLOR) != 0 )
00680 {
00681 os << " FBO_COLOR";
00682 }
00683
00684 if ((drawable & eq::Channel::FBO_DEPTH) != 0)
00685 {
00686 os << " FBO_DEPTH";
00687 }
00688 if ((drawable & eq::Channel::FBO_STENCIL) != 0)
00689 {
00690 os << " FBO_STENCIL";
00691 }
00692
00693 os << " ]" << endl;
00694 }
00695 bool attrPrinted = false;
00696
00697 for( eq::Channel::IAttribute i = static_cast<eq::Channel::IAttribute>( 0 );
00698 i<eq::Channel::IATTR_ALL;
00699 i = static_cast<eq::Channel::IAttribute>( static_cast<uint32_t>(i)+1 ))
00700 {
00701 const int value = channel->getIAttribute( i );
00702 if( value == Global::instance()->getChannelIAttribute( i ))
00703 continue;
00704
00705 if( !attrPrinted )
00706 {
00707 os << endl << "attributes" << endl;
00708 os << "{" << endl << indent;
00709 attrPrinted = true;
00710 }
00711
00712 os << ( i==eq::Channel::IATTR_HINT_STATISTICS ?
00713 "hint_statistics " :
00714 i==eq::Channel::IATTR_HINT_SENDTOKEN ?
00715 "hint_sendtoken " : "ERROR" )
00716 << static_cast<eq::IAttrValue>( value ) << endl;
00717 }
00718
00719 if( attrPrinted )
00720 os << exdent << "}" << endl << endl;
00721
00722 os << exdent << "}" << endl << enableHeader << enableFlush;
00723
00724 return os;
00725 }
00726
00727 }
00728 }