server/channel.cpp

00001 
00002 /* Copyright (c) 2005-2009, Stefan Eilemann <eile@equalizergraphics.com> 
00003  *
00004  * This library is free software; you can redistribute it and/or modify it under
00005  * the terms of the GNU Lesser General Public License version 2.1 as published
00006  * by the Free Software Foundation.
00007  *  
00008  * This library is distributed in the hope that it will be useful, but WITHOUT
00009  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00010  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00011  * details.
00012  * 
00013  * You should have received a copy of the GNU Lesser General Public License
00014  * along with this library; if not, write to the Free Software Foundation, Inc.,
00015  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
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     // Don't copy view and segment. Will be re-set by segment copy ctor
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( ConstChannelVisitor& 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 // viewport
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 ) // update viewport
00332         _vp = _pvp.getSubVP( windowPVP );
00333     else            // update pixel viewport
00334         _pvp = windowPVP.getSubPVP( _vp );
00335 
00336     EQINFO << "Channel viewport update: " << _pvp << ":" << _vp << endl;
00337 }
00338 
00339 //===========================================================================
00340 // Operations
00341 //===========================================================================
00342 
00343 //---------------------------------------------------------------------------
00344 // update running entities (init/exit)
00345 //---------------------------------------------------------------------------
00346 
00347 void Channel::updateRunning( const uint32_t initID )
00348 {
00349     if( !isActive() && _state == STATE_STOPPED ) // inactive
00350         return;
00351 
00352     if( isActive() && _state != STATE_RUNNING ) // becoming active
00353         _configInit( initID );
00354 
00355     if( !isActive( )) // becoming inactive
00356         _configExit();
00357 }
00358 
00359 bool Channel::syncRunning()
00360 {
00361     bool success = true;
00362     if( isActive() && _state != STATE_RUNNING  && !_syncConfigInit( ))
00363         // becoming active
00364         success = false;
00365 
00366     if( !isActive() && _state != STATE_STOPPED && !_syncConfigExit( ))
00367         // becoming inactive
00368         success = false;
00369 
00370     EQASSERT( _state == STATE_RUNNING || _state == STATE_STOPPED || 
00371               _state == STATE_INIT_FAILED );
00372     return success;
00373 }
00374 
00375 //---------------------------------------------------------------------------
00376 // init
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 // exit
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 // update
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         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 // Listener interface
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 // command handling
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     // output received events
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::FBO_NONE)
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 }
Generated on Mon Aug 10 18:58:31 2009 for Equalizer 0.9 by  doxygen 1.5.8