00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "channel.h"
00019
00020 #include "channelStatistics.h"
00021 #include "channelVisitor.h"
00022 #include "client.h"
00023 #include "compositor.h"
00024 #include "commands.h"
00025 #include "config.h"
00026 #include "configEvent.h"
00027 #include "frame.h"
00028 #include "global.h"
00029 #include "log.h"
00030 #include "node.h"
00031 #include "nodeFactory.h"
00032 #include "packets.h"
00033 #include "pipe.h"
00034 #include "range.h"
00035 #include "renderContext.h"
00036 #include "server.h"
00037 #include "task.h"
00038 #include "view.h"
00039 #include "frameBufferObject.h"
00040
00041 #include <eq/net/command.h>
00042
00043 using namespace eq::base;
00044 using namespace std;
00045
00046 namespace eq
00047 {
00049 typedef net::CommandFunc<Channel> ChannelFunc;
00052 #define MAKE_ATTR_STRING( attr ) ( string("EQ_CHANNEL_") + #attr )
00053 std::string Channel::_iAttributeStrings[IATTR_ALL] = {
00054 MAKE_ATTR_STRING( IATTR_HINT_STATISTICS ),
00055 MAKE_ATTR_STRING( IATTR_HINT_SENDTOKEN ),
00056 MAKE_ATTR_STRING( IATTR_FILL1 ),
00057 MAKE_ATTR_STRING( IATTR_FILL2 )
00058 };
00059
00060 Channel::Channel( Window* parent )
00061 : _window( parent )
00062 , _context( &_nativeContext )
00063 , _tasks( TASK_NONE )
00064 , _state( STATE_STOPPED )
00065 , _fixedPVP( false )
00066 , _fbo(0)
00067 , _drawable( 0 )
00068 , _initialSize( Vector2i::ZERO )
00069 , _maxSize( Vector2i::ZERO )
00070 {
00071 parent->_addChannel( this );
00072 EQINFO << " New eq::Channel @" << (void*)this << endl;
00073 }
00074
00075 Channel::~Channel()
00076 {
00077 EQINFO << " Delete eq::Channel @" << (void*)this << endl;
00078 _window->_removeChannel( this );
00079 }
00080
00081 void Channel::attachToSession( const uint32_t id,
00082 const uint32_t instanceID,
00083 net::Session* session )
00084 {
00085 net::Object::attachToSession( id, instanceID, session );
00086
00087 net::CommandQueue* queue = _window->getPipeThreadQueue();
00088
00089 registerCommand( CMD_CHANNEL_CONFIG_INIT,
00090 ChannelFunc( this, &Channel::_cmdConfigInit ), queue );
00091 registerCommand( CMD_CHANNEL_CONFIG_EXIT,
00092 ChannelFunc( this, &Channel::_cmdConfigExit ), queue );
00093 registerCommand( CMD_CHANNEL_FRAME_START,
00094 ChannelFunc( this, &Channel::_cmdFrameStart ), queue );
00095 registerCommand( CMD_CHANNEL_FRAME_FINISH,
00096 ChannelFunc( this, &Channel::_cmdFrameFinish ), queue );
00097 registerCommand( CMD_CHANNEL_FRAME_CLEAR,
00098 ChannelFunc( this, &Channel::_cmdFrameClear ), queue );
00099 registerCommand( CMD_CHANNEL_FRAME_DRAW,
00100 ChannelFunc( this, &Channel::_cmdFrameDraw ), queue );
00101 registerCommand( CMD_CHANNEL_FRAME_DRAW_FINISH,
00102 ChannelFunc( this, &Channel::_cmdFrameDrawFinish ), queue );
00103 registerCommand( CMD_CHANNEL_FRAME_ASSEMBLE,
00104 ChannelFunc( this, &Channel::_cmdFrameAssemble ), queue );
00105 registerCommand( CMD_CHANNEL_FRAME_READBACK,
00106 ChannelFunc( this, &Channel::_cmdFrameReadback ), queue );
00107 registerCommand( CMD_CHANNEL_FRAME_TRANSMIT,
00108 ChannelFunc( this, &Channel::_cmdFrameTransmit ), queue );
00109 registerCommand( CMD_CHANNEL_FRAME_VIEW_START,
00110 ChannelFunc( this, &Channel::_cmdFrameViewStart ), queue );
00111 registerCommand( CMD_CHANNEL_FRAME_VIEW_FINISH,
00112 ChannelFunc( this, &Channel::_cmdFrameViewFinish ), queue);
00113 }
00114
00115 Pipe* Channel::getPipe()
00116 {
00117 EQASSERT( _window );
00118 return ( _window ? _window->getPipe() : 0 );
00119 }
00120 const Pipe* Channel::getPipe() const
00121 {
00122 EQASSERT( _window );
00123 return ( _window ? _window->getPipe() : 0 );
00124 }
00125
00126 Node* Channel::getNode()
00127 {
00128 EQASSERT( _window );
00129 return ( _window ? _window->getNode() : 0 );
00130 }
00131 const Node* Channel::getNode() const
00132 {
00133 EQASSERT( _window );
00134 return ( _window ? _window->getNode() : 0 );
00135 }
00136
00137 Config* Channel::getConfig()
00138 {
00139 EQASSERT( _window );
00140 return ( _window ? _window->getConfig() : 0 );
00141 }
00142 const Config* Channel::getConfig() const
00143 {
00144 EQASSERT( _window );
00145 return ( _window ? _window->getConfig() : 0 );
00146 }
00147
00148 ServerPtr Channel::getServer()
00149 {
00150 EQASSERT( _window );
00151 return ( _window ? _window->getServer() : 0 );
00152 }
00153
00154 Window::ObjectManager* Channel::getObjectManager()
00155 {
00156 EQASSERT( _window );
00157 return _window->getObjectManager();
00158 }
00159
00160
00161 GLEWContext* Channel::glewGetContext()
00162 {
00163 EQASSERT( _window );
00164 return _window->glewGetContext();
00165 }
00166 const GLEWContext* Channel::glewGetContext() const
00167 {
00168 EQASSERT( _window );
00169 return _window->glewGetContext();
00170 }
00171
00172 VisitorResult Channel::accept( ChannelVisitor& visitor )
00173 {
00174 return visitor.visit( this );
00175 }
00176
00177 bool Channel::configExit()
00178 {
00179 delete _fbo;
00180 _fbo = 0;
00181 return true;
00182 }
00183 bool Channel::configInit( const uint32_t initID )
00184 {
00185 return _configInitFBO();
00186 }
00187
00188 bool Channel::_configInitFBO()
00189 {
00190 if ( _drawable == FBO_NONE )
00191 return true;
00192
00193 if ( !_window->getOSWindow() ||
00194 !GLEW_ARB_texture_non_power_of_two ||
00195 !GLEW_EXT_framebuffer_object )
00196 {
00197 setErrorMessage( "Can't use FBO due to missing GL extensions" );
00198 return false;
00199 }
00200
00201
00202 _fbo = new FrameBufferObject( glewGetContext( ));
00203 _fbo->setColorFormat( _window->getColorType( ));
00204
00205 if( _fbo->init( _nativeContext.pvp.w, _nativeContext.pvp.h,
00206 _drawable & FBO_DEPTH, _drawable & FBO_STENCIL ) )
00207 {
00208 return true;
00209 }
00210
00211 setErrorMessage( "FBO initialization failed" );
00212 delete _fbo;
00213 _fbo = 0;
00214 return false;
00215 }
00216
00217
00218
00219
00220 void Channel::_setPixelViewport( const PixelViewport& pvp )
00221 {
00222 EQASSERT( pvp.hasArea( ));
00223 if( !pvp.hasArea( ))
00224 return;
00225
00226 _fixedPVP = true;
00227
00228 if( _nativeContext.pvp == pvp && _nativeContext.vp.hasArea( ))
00229 return;
00230
00231 _nativeContext.pvp = pvp;
00232 _nativeContext.vp.invalidate();
00233
00234 if( !_window )
00235 return;
00236
00237 const PixelViewport& windowPVP = _window->getPixelViewport();
00238 if( windowPVP.isValid( ))
00239 _nativeContext.vp = pvp.getSubVP( windowPVP );
00240
00241 EQVERB << "Channel pvp set: " << _nativeContext.pvp << ":"
00242 << _nativeContext.vp << std::endl;
00243 }
00244
00245 void Channel::_setViewport( const Viewport& vp )
00246 {
00247 if( !vp.hasArea( ))
00248 return;
00249
00250 _fixedPVP = false;
00251
00252 if( _nativeContext.vp == vp && _nativeContext.pvp.hasArea( ))
00253 return;
00254
00255 _nativeContext.vp = vp;
00256 _nativeContext.pvp.invalidate();
00257
00258 if( !_window )
00259 return;
00260
00261 PixelViewport windowPVP = _window->getPixelViewport();
00262 if( windowPVP.isValid( ))
00263 {
00264 windowPVP.x = 0;
00265 windowPVP.y = 0;
00266 _nativeContext.pvp = windowPVP.getSubPVP( vp );
00267
00268
00269 Event event;
00270 event.type = Event::CHANNEL_RESIZE;
00271 event.originator = getID();
00272 event.resize.x = _nativeContext.pvp.x;
00273 event.resize.y = _nativeContext.pvp.y;
00274 event.resize.w = _nativeContext.pvp.w;
00275 event.resize.h = _nativeContext.pvp.h;
00276
00277 processEvent( event );
00278 }
00279
00280 EQVERB << "Channel vp set: " << _nativeContext.pvp << ":"
00281 << _nativeContext.vp << std::endl;
00282 }
00283
00284 void Channel::_notifyViewportChanged()
00285 {
00286 if( !_window )
00287 return;
00288
00289 eq::PixelViewport windowPVP = _window->getPixelViewport();
00290 if( !windowPVP.isValid( ))
00291 return;
00292
00293 windowPVP.x = 0;
00294 windowPVP.y = 0;
00295
00296 if( _fixedPVP )
00297 _nativeContext.vp = _nativeContext.pvp.getSubVP( windowPVP );
00298 else
00299 {
00300 const eq::PixelViewport pvp = windowPVP.getSubPVP( _nativeContext.vp );
00301 if( _nativeContext.pvp == pvp )
00302 return;
00303
00304 _nativeContext.pvp = pvp;
00305
00306
00307 Event event;
00308 event.type = Event::CHANNEL_RESIZE;
00309 event.originator = getID();
00310 event.resize.x = _nativeContext.pvp.x;
00311 event.resize.y = _nativeContext.pvp.y;
00312 event.resize.w = _nativeContext.pvp.w;
00313 event.resize.h = _nativeContext.pvp.h;
00314
00315 processEvent( event );
00316 }
00317
00318 EQINFO << "Channel viewport update: " << _nativeContext.pvp << ":"
00319 << _nativeContext.vp << std::endl;
00320 }
00321
00322 void Channel::setNearFar( const float nearPlane, const float farPlane )
00323 {
00324 if( _context->frustum.near_plane() == nearPlane &&
00325 _context->frustum.far_plane() == farPlane )
00326 {
00327 return;
00328 }
00329
00330 _nativeContext.frustum.adjust_near( nearPlane );
00331 _nativeContext.frustum.far_plane() = farPlane;
00332 _nativeContext.ortho.near_plane() = nearPlane;
00333 _nativeContext.ortho.far_plane() = farPlane;
00334
00335 if( _context != &_nativeContext )
00336 {
00337 _context->frustum.adjust_near( nearPlane );
00338 _context->frustum.far_plane() = farPlane;
00339 _context->ortho.near_plane() = nearPlane;
00340 _context->ortho.far_plane() = farPlane;
00341 }
00342
00343 ChannelSetNearFarPacket packet;
00344 packet.nearPlane = nearPlane;
00345 packet.farPlane = farPlane;
00346
00347 ServerPtr server = getServer();
00348 net::NodePtr node = server.get();
00349 send( node, packet );
00350 }
00351
00352 void Channel::addStatistic( Event& event )
00353 {
00354 _statistics.push_back( event.statistic );
00355 processEvent( event );
00356 }
00357
00358
00359
00360
00361
00362 void Channel::frameClear( const uint32_t frameID )
00363 {
00364 EQ_GL_CALL( applyBuffer( ));
00365 EQ_GL_CALL( applyViewport( ));
00366
00367 #ifndef NDEBUG
00368 if( getenv( "EQ_TAINT_CHANNELS" ))
00369 {
00370 const Vector3ub color = getUniqueColor();
00371 glClearColor( color.r()/255.0f, color.g()/255.0f, color.b()/255.0f, 1.0f );
00372 }
00373 #endif // NDEBUG
00374
00375 EQ_GL_CALL( glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ));
00376 }
00377
00378 void Channel::frameDraw( const uint32_t frameID )
00379 {
00380 EQ_GL_CALL( applyBuffer( ));
00381 EQ_GL_CALL( applyViewport( ));
00382
00383 EQ_GL_CALL( glMatrixMode( GL_PROJECTION ));
00384 EQ_GL_CALL( glLoadIdentity( ));
00385 EQ_GL_CALL( applyFrustum( ));
00386
00387 EQ_GL_CALL( glMatrixMode( GL_MODELVIEW ));
00388 EQ_GL_CALL( glLoadIdentity( ));
00389 EQ_GL_CALL( applyHeadTransform( ));
00390 }
00391
00392 void Channel::frameAssemble( const uint32_t frameID )
00393 {
00394 EQ_GL_CALL( applyBuffer( ));
00395 EQ_GL_CALL( applyViewport( ));
00396 EQ_GL_CALL( setupAssemblyState( ));
00397
00398 Compositor::assembleFrames( getInputFrames(), this );
00399
00400 EQ_GL_CALL( resetAssemblyState( ));
00401 }
00402
00403 void Channel::frameReadback( const uint32_t frameID )
00404 {
00405 EQ_GL_CALL( applyBuffer( ));
00406 EQ_GL_CALL( applyViewport( ));
00407 EQ_GL_CALL( setupAssemblyState( ));
00408
00409 Window::ObjectManager* glObjects = getObjectManager();
00410
00411 const FrameVector& frames = getOutputFrames();
00412 for( FrameVector::const_iterator i = frames.begin(); i != frames.end(); ++i)
00413 {
00414 Frame* frame = *i;
00415 frame->setColorType( _window->getColorType( ));
00416 frame->startReadback( glObjects );
00417 }
00418 for( FrameVector::const_iterator i = frames.begin(); i != frames.end(); ++i)
00419 {
00420 Frame* frame = *i;
00421 frame->syncReadback();
00422 }
00423
00424 EQ_GL_CALL( resetAssemblyState( ));
00425 }
00426
00427 void Channel::setupAssemblyState()
00428 {
00429 EQ_GL_ERROR( "before setupAssemblyState" );
00430 glPushAttrib( GL_ENABLE_BIT | GL_STENCIL_BUFFER_BIT | GL_VIEWPORT_BIT |
00431 GL_SCISSOR_BIT | GL_LINE_BIT | GL_PIXEL_MODE_BIT |
00432 GL_POLYGON_BIT );
00433
00434 glDisable( GL_DEPTH_TEST );
00435 glDisable( GL_BLEND );
00436 glDisable( GL_ALPHA_TEST );
00437 glDisable( GL_STENCIL_TEST );
00438 glDisable( GL_TEXTURE_1D );
00439 glDisable( GL_TEXTURE_2D );
00440 glDisable( GL_TEXTURE_3D );
00441 glDisable( GL_FOG );
00442 glDisable( GL_CLIP_PLANE0 );
00443 glDisable( GL_CLIP_PLANE1 );
00444 glDisable( GL_CLIP_PLANE2 );
00445 glDisable( GL_CLIP_PLANE3 );
00446 glDisable( GL_CLIP_PLANE4 );
00447 glDisable( GL_CLIP_PLANE5 );
00448
00449 glPolygonMode( GL_FRONT, GL_FILL );
00450
00451 EQASSERT( _window );
00452
00453 const PixelViewport pvp(
00454 _fbo ? _fbo->getPixelViewport() : _window->getPixelViewport( ));
00455
00456 if( pvp.hasArea( ))
00457 {
00458 glViewport( 0, 0, pvp.w, pvp.h );
00459 glScissor( 0, 0, pvp.w, pvp.h );
00460 }
00461 else
00462 EQERROR << "Can't apply viewport " << pvp << endl;
00463
00464 glMatrixMode( GL_PROJECTION );
00465 glPushMatrix();
00466 glLoadIdentity();
00467 if( pvp.hasArea( ))
00468 glOrtho( 0.0f, pvp.w, 0.0f, pvp.h, -1.0f, 1.0f );
00469
00470 glMatrixMode( GL_MODELVIEW );
00471 glPushMatrix();
00472 glLoadIdentity();
00473 EQ_GL_ERROR( "after setupAssemblyState" );
00474 }
00475
00476 void Channel::resetAssemblyState()
00477 {
00478 EQ_GL_ERROR( "before resetAssemblyState" );
00479 glMatrixMode( GL_PROJECTION );
00480 glPopMatrix();
00481
00482 glMatrixMode( GL_MODELVIEW );
00483 glPopMatrix();
00484
00485 glPopAttrib();
00486 EQ_GL_ERROR( "after resetAssemblyState" );
00487 }
00488
00489 void Channel::setErrorMessage( const std::string& message )
00490 {
00491 _error = message;
00492 }
00493
00494 void Channel::_setRenderContext( RenderContext& context )
00495 {
00496 _context = &context;
00497 _window->addRenderContext( context );
00498 }
00499
00500 const Viewport& Channel::getViewport() const
00501 {
00502 return _context->vp;
00503 }
00504
00505 const PixelViewport& Channel::getPixelViewport() const
00506 {
00507 return _context->pvp;
00508 }
00509
00510 const Vector2i& Channel::getPixelOffset() const
00511 {
00512 return _context->offset;
00513 }
00514
00515 uint32_t Channel::getDrawBuffer() const
00516 {
00517 return _context->buffer;
00518 }
00519
00520 uint32_t Channel::getReadBuffer() const
00521 {
00522 return _context->buffer;
00523 }
00524
00525 const ColorMask& Channel::getDrawBufferMask() const
00526 {
00527 return _context->bufferMask;
00528 }
00529
00530 const Frustumf& Channel::getFrustum() const
00531 {
00532 return _context->frustum;
00533 }
00534
00535 const Frustumf& Channel::getOrtho() const
00536 {
00537 return _context->ortho;
00538 }
00539
00540 const Range& Channel::getRange() const
00541 {
00542 return _context->range;
00543 }
00544
00545 const Pixel& Channel::getPixel() const
00546 {
00547 return _context->pixel;
00548 }
00549
00550 const Zoom& Channel::getZoom() const
00551 {
00552 return _context->zoom;
00553 }
00554
00555 Eye Channel::getEye() const
00556 {
00557 return _context->eye;
00558 }
00559
00560 const Matrix4f& Channel::getHeadTransform() const
00561 {
00562 return _context->headTransform;
00563 }
00564
00565 Frustumf Channel::getScreenFrustum() const
00566 {
00567 const Pixel& pixel = getPixel();
00568 PixelViewport pvp( getPixelViewport( ));
00569 const Viewport& vp( getViewport( ));
00570
00571 pvp.x = static_cast<int32_t>( pvp.w / vp.w * vp.x );
00572 pvp.y = static_cast<int32_t>( pvp.h / vp.h * vp.y );
00573 pvp *= pixel;
00574
00575 return eq::Frustumf( static_cast< float >( pvp.x ),
00576 static_cast< float >( pvp.getXEnd( )),
00577 static_cast< float >( pvp.y ),
00578 static_cast< float >( pvp.getYEnd( )),
00579 -1.f, 1.f );
00580 }
00581
00582 const Vector4i& Channel::getOverdraw() const
00583 {
00584 return _context->overdraw;
00585 }
00586
00587 void Channel::setMaxSize( const Vector2i& size )
00588 {
00589 _maxSize = size;
00590 }
00591
00592
00593 uint32_t Channel::getTaskID() const
00594 {
00595 return _context->taskID;
00596 }
00597
00598 FrameBufferObject* Channel::getFrameBufferObject()
00599 {
00600 return _fbo;
00601 }
00602
00603 const View* Channel::getView()
00604 {
00605 Pipe* pipe = getPipe();
00606 return pipe->getView( _context->view );
00607 }
00608
00609 const View* Channel::getNativeView()
00610 {
00611 Pipe* pipe = getPipe();
00612 return pipe->getView( _nativeContext.view );
00613 }
00614
00615
00616
00617
00618
00619 void Channel::applyFrameBufferObject()
00620 {
00621 if( _fbo )
00622 {
00623 _fbo->resize( _nativeContext.pvp.w, _nativeContext.pvp.h );
00624 _fbo->bind();
00625 }
00626 else if( GLEW_EXT_framebuffer_object )
00627 glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
00628 }
00629
00630 void Channel::applyBuffer()
00631 {
00632 if (( !_fbo )&&( !_window->isFBOWindow() ))
00633 {
00634 EQ_GL_CALL( glReadBuffer( getReadBuffer( )));
00635 EQ_GL_CALL( glDrawBuffer( getDrawBuffer( )));
00636 }
00637
00638 applyColorMask();
00639 }
00640
00641 void Channel::bindFrameBuffer()
00642 {
00643 if( !_window->getOSWindow() )
00644 return;
00645
00646 if( _fbo )
00647 applyFrameBufferObject();
00648 else
00649 _window->bindFrameBuffer();
00650 }
00651
00652 void Channel::applyColorMask() const
00653 {
00654 const ColorMask& colorMask = getDrawBufferMask();
00655 glColorMask( colorMask.red, colorMask.green, colorMask.blue, true );
00656 }
00657
00658 void Channel::applyViewport() const
00659 {
00660 const PixelViewport& pvp = getPixelViewport();
00661
00662
00663 if( !pvp.hasArea( ))
00664 {
00665 EQERROR << "Can't apply viewport " << pvp << endl;
00666 return;
00667 }
00668
00669 EQ_GL_CALL( glViewport( pvp.x, pvp.y, pvp.w, pvp.h ));
00670 EQ_GL_CALL( glScissor( pvp.x, pvp.y, pvp.w, pvp.h ));
00671 }
00672
00673 void Channel::applyFrustum() const
00674 {
00675 const Frustumf& frustum = getFrustum();
00676 EQ_GL_CALL( glFrustum( frustum.left(), frustum.right(), \
00677 frustum.bottom(), frustum.top(), \
00678 frustum.near_plane(), frustum.far_plane() ));
00679 EQVERB << "Perspective " << frustum << endl;
00680 }
00681
00682 void Channel::applyOrtho() const
00683 {
00684 const Frustumf& ortho = getOrtho();
00685 EQ_GL_CALL( glOrtho( ortho.left(), ortho.right(), \
00686 ortho.bottom(), ortho.top(), \
00687 ortho.near_plane(), ortho.far_plane() ));
00688 EQVERB << "Orthographic " << ortho << endl;
00689 }
00690
00691 void Channel::applyScreenFrustum() const
00692 {
00693 const Frustumf frustum = getScreenFrustum();
00694 EQ_GL_CALL( glOrtho( frustum.left(), frustum.right(), \
00695 frustum.bottom(), frustum.top(), \
00696 frustum.near_plane(), frustum.far_plane() ));
00697 EQVERB << "Apply " << frustum << endl;
00698 }
00699
00700 void Channel::applyHeadTransform() const
00701 {
00702 const Matrix4f& xfm = getHeadTransform();
00703 EQ_GL_CALL( glMultMatrixf( xfm.array ));
00704 EQVERB << "Apply head transform: " << xfm << endl;
00705 }
00706
00707 bool Channel::processEvent( const Event& event )
00708 {
00709 ConfigEvent configEvent;
00710 configEvent.data = event;
00711
00712 switch( event.type )
00713 {
00714 case Event::STATISTIC:
00715 break;
00716
00717 case Event::CHANNEL_RESIZE:
00718 {
00719 const uint32_t viewID = _nativeContext.view.id;
00720 if( viewID == EQ_ID_INVALID )
00721 return true;
00722
00723
00724 configEvent.data.type = Event::VIEW_RESIZE;
00725 configEvent.data.originator = viewID;
00726
00727 ResizeEvent& resize = configEvent.data.resize;
00728 resize.dw = resize.w / static_cast< float >( _initialSize.x() );
00729 resize.dh = resize.h / static_cast< float >( _initialSize.y() );
00730 break;
00731 }
00732
00733 default:
00734 EQWARN << "Unhandled channel event of type " << event.type
00735 << endl;
00736 EQUNIMPLEMENTED;
00737 }
00738
00739 Config* config = getConfig();
00740 config->sendEvent( configEvent );
00741 return true;
00742 }
00743
00744 namespace
00745 {
00746 #define HEIGHT 12
00747 #define SPACE 2
00748
00749 struct EntityData
00750 {
00751 EntityData() : yPos( 0 ) {}
00752 uint32_t yPos;
00753 std::string name;
00754 };
00755
00756 struct IdleData
00757 {
00758 IdleData() : idle( 0 ), nIdle( 0 ) {}
00759 uint32_t idle;
00760 uint32_t nIdle;
00761 std::string name;
00762 };
00763
00764 }
00765
00766 void Channel::drawStatistics()
00767 {
00768 Config* config = getConfig();
00769 EQASSERT( config );
00770
00771 vector< FrameStatistics > statistics;
00772 config->getStatistics( statistics );
00773
00774 if( statistics.empty( ))
00775 return;
00776
00777 EQ_GL_CALL( applyBuffer( ));
00778 EQ_GL_CALL( applyViewport( ));
00779 EQ_GL_CALL( setupAssemblyState( ));
00780
00781 glClear( GL_DEPTH_BUFFER_BIT );
00782
00783 glDisable( GL_LIGHTING );
00784 glEnable( GL_DEPTH_TEST );
00785
00786 const util::BitmapFont& font = getObjectManager()->getDefaultFont();
00787
00788 int64_t xStart = 0;
00789 PixelViewport pvp = _window->getPixelViewport();
00790 pvp.x = 0;
00791 pvp.y = 0;
00792
00793
00794 int64_t xMax = 0;
00795 int64_t xMin = std::numeric_limits< int64_t >::max();
00796
00797 for( vector< FrameStatistics >::const_iterator i = statistics.begin();
00798 i != statistics.end(); ++i )
00799 {
00800 const FrameStatistics& frameStats = *i;
00801 const SortedStatistics& configStats = frameStats.second;
00802
00803 for( SortedStatistics::const_iterator j = configStats.begin();
00804 j != configStats.end(); ++j )
00805 {
00806 const Statistics& stats = j->second;
00807
00808 for( Statistics::const_iterator k = stats.begin();
00809 k != stats.end(); ++k )
00810 {
00811 const Statistic& stat = *k;
00812 if( stat.type == Statistic::PIPE_IDLE )
00813 continue;
00814
00815 xMax = EQ_MAX( xMax, stat.endTime );
00816 xMin = EQ_MIN( xMin, stat.endTime );
00817 }
00818 }
00819 }
00820 uint32_t scale = 1;
00821 while( (xMax - xMin) / scale > pvp.w )
00822 scale *= 10;
00823
00824 xMax /= scale;
00825 xStart = xMax - pvp.getXEnd() + SPACE;
00826 uint32_t nextY = pvp.getYEnd() - SPACE;
00827
00828 std::map< uint32_t, EntityData > entities;
00829 std::map< uint32_t, IdleData > idles;
00830
00831 float dim = 0.0f;
00832 for( vector< FrameStatistics >::reverse_iterator i = statistics.rbegin();
00833 i != statistics.rend(); ++i )
00834 {
00835 const FrameStatistics& frameStats = *i;
00836 const SortedStatistics& configStats = frameStats.second;
00837
00838 int64_t frameMin = xMax;
00839 int64_t frameMax = 0;
00840
00841
00842 for( SortedStatistics::const_iterator j = configStats.begin();
00843 j != configStats.end(); ++j )
00844 {
00845 const uint32_t id = j->first;
00846 const Statistics& stats = j->second;
00847
00848 if( stats.empty( ))
00849 continue;
00850
00851 if( entities.find( id ) == entities.end( ))
00852 {
00853 EntityData& data = entities[ id ];
00854 data.yPos = nextY;
00855 data.name = stats.front().resourceName;
00856
00857 nextY -= (HEIGHT + SPACE);
00858 }
00859
00860 const uint32_t y = entities[ id ].yPos;
00861
00862 for( Statistics::const_iterator k = stats.begin();
00863 k != stats.end(); ++k )
00864 {
00865 const Statistic& stat = *k;
00866
00867 if( stat.type == Statistic::PIPE_IDLE )
00868 {
00869 IdleData& data = idles[ id ];
00870 std::map< uint32_t, EntityData >::iterator l =
00871 entities.find( id );
00872
00873 if( l != entities.end( ))
00874 {
00875 entities.erase( l );
00876 nextY += (HEIGHT + SPACE);
00877 data.name = stat.resourceName;
00878 }
00879
00880 data.idle += (stat.idleTime * 100ll / stat.totalTime);
00881 ++data.nIdle;
00882 continue;
00883 }
00884
00885 const int64_t startTime = stat.startTime / scale;
00886 const int64_t endTime = stat.endTime / scale;
00887
00888 frameMin = EQ_MIN( frameMin, startTime );
00889 frameMax = EQ_MAX( frameMax, endTime );
00890
00891 if( endTime < xStart || endTime == startTime )
00892 continue;
00893
00894 float y1 = static_cast< float >( y );
00895 float y2 = static_cast< float >( y - HEIGHT );
00896 float z = 0.0f;
00897 const float x1 = static_cast< float >( startTime - xStart );
00898 const float x2 = static_cast< float >( endTime - xStart );
00899
00900 switch( stat.type )
00901 {
00902 case Statistic::FRAME_COMPRESS:
00903 {
00904 z = 0.7f;
00905
00906 glColor3f( 0.f, 0.f, 0.f );
00907 stringstream text;
00908 text << static_cast< unsigned >( 100.f * stat.ratio )
00909 << '%';
00910 glRasterPos3f( x1+1, y2, 0.99f );
00911
00912 font.draw( text.str( ));
00913 break;
00914 }
00915
00916 case Statistic::FRAME_TRANSMIT:
00917 case Statistic::FRAME_RECEIVE:
00918 z = 0.5f;
00919 break;
00920
00921 case Statistic::CHANNEL_WAIT_FRAME:
00922 case Statistic::CONFIG_WAIT_FINISH_FRAME:
00923 y1 -= SPACE;
00924 y2 += SPACE;
00925
00926 case Statistic::CONFIG_START_FRAME:
00927 z = 0.1f;
00928 break;
00929
00930 default:
00931 z = 0.0f;
00932 break;
00933 }
00934
00935 const Vector3f color( Statistic::getColor( stat.type ) - dim );
00936 glColor3fv( color.array );
00937
00938 glBegin( GL_QUADS );
00939 glVertex3f( x2, y1, z );
00940 glVertex3f( x1, y1, z );
00941 glVertex3f( x1, y2, z );
00942 glVertex3f( x2, y2, z );
00943 glEnd();
00944 }
00945 }
00946
00947 frameMin -= xStart;
00948 frameMax -= xStart;
00949
00950 float x = static_cast< float >( frameMin );
00951 const float y1 = static_cast< float >( nextY );
00952 const float y2 = static_cast< float >( pvp.getYEnd( ));
00953
00954 glBegin( GL_QUADS );
00955 glColor3f( .5f-dim, 1.0f-dim, .5f-dim );
00956 glVertex3f( x+1.0f, y2, 0.3f );
00957 glVertex3f( x, y2, 0.3f );
00958 glVertex3f( x, y1, 0.3f );
00959 glVertex3f( x+1.0f, y1, 0.3f );
00960
00961 x = static_cast< float >( frameMax );
00962 glColor3f( .5f-dim, .5f-dim, .5f-dim );
00963 glVertex3f( x+1.0f, y2, 0.3f );
00964 glVertex3f( x, y2, 0.3f );
00965 glVertex3f( x, y1, 0.3f );
00966 glVertex3f( x+1.0f, y1, 0.3f );
00967 glEnd();
00968
00969 dim += .1f;
00970 }
00971
00972
00973 for( std::map< uint32_t, EntityData >::const_iterator i = entities.begin();
00974 i != entities.end(); ++i )
00975 {
00976 const EntityData& data = i->second;
00977
00978 glColor3f( 1.f, 1.f, 1.f );
00979 glRasterPos3f( 60.f, data.yPos-SPACE-12.0f, 0.99f );
00980 font.draw( data.name );
00981 }
00982
00983
00984 glColor3f( 1.f, 1.f, 1.f );
00985 nextY -= (HEIGHT + SPACE);
00986 glRasterPos3f( 60.f, static_cast< float >( nextY ), 0.99f );
00987 ostringstream text;
00988 text << scale << "ms/pixel";
00989
00990 if( !idles.empty( ))
00991 text << ", Idle:";
00992
00993 for( std::map< uint32_t, IdleData >::const_iterator i = idles.begin();
00994 i != idles.end(); ++i )
00995 {
00996 const IdleData& data = i->second;
00997 EQASSERT( data.nIdle > 0 );
00998
00999 text << " " << data.name << ":" << data.idle / data.nIdle << "%";
01000 }
01001
01002 font.draw( text.str( ));
01003
01004
01005 nextY -= SPACE;
01006 float x = 0.f;
01007 float z = 0.f;
01008
01009 glRasterPos3f( x+1.f, nextY-12.f, z );
01010 glColor3f( 1.f, 1.f, 1.f );
01011 font.draw( "channel" );
01012
01013 for( size_t i = 1; i < Statistic::CONFIG_START_FRAME; ++i )
01014 {
01015 const Statistic::Type type = static_cast< Statistic::Type >( i );
01016 if( type == Statistic::CHANNEL_DRAW_FINISH ||
01017 type == Statistic::PIPE_IDLE )
01018 {
01019 continue;
01020 }
01021
01022 if( type == Statistic::WINDOW_FINISH )
01023 {
01024 x = 0.f;
01025 nextY -= (HEIGHT + SPACE);
01026 z = 0.f;
01027
01028 glColor3f( 1.f, 1.f, 1.f );
01029 glRasterPos3f( x+1.f, nextY-12.f, z );
01030 font.draw( "window" );
01031 }
01032 else if( type == Statistic::FRAME_TRANSMIT )
01033 {
01034 x = 0.f;
01035 nextY -= (HEIGHT + SPACE);
01036 z = 0.f;
01037
01038 glColor3f( 1.f, 1.f, 1.f );
01039 glRasterPos3f( x+1.f, nextY-12.f, z );
01040 font.draw( "frame" );
01041 }
01042
01043 x += 60.f;
01044 const float x2 = x + 60.f - SPACE;
01045 const float y1 = static_cast< float >( nextY );
01046 const float y2 = static_cast< float >( nextY - HEIGHT );
01047
01048 z += 0.01f;
01049 glColor3fv( Statistic::getColor( type ).array );
01050 glBegin( GL_QUADS );
01051 glVertex3f( x2, y1, z );
01052 glVertex3f( x, y1, z );
01053 glVertex3f( x, y2, z );
01054 glVertex3f( x2, y2, z );
01055 glEnd();
01056
01057 z += 0.01f;
01058 glColor3f( 0.f, 0.f, 0.f );
01059 glRasterPos3f( x+1.f, nextY-12.f, z );
01060 font.draw( Statistic::getName( type ));
01061 }
01062
01063
01064 glColor3f( 1.f, 1.f, 1.f );
01065 _window->drawFPS();
01066 EQ_GL_CALL( resetAssemblyState( ));
01067 }
01068
01069 void Channel::outlineViewport()
01070 {
01071 setupAssemblyState();
01072
01073 const PixelViewport& pvp = getPixelViewport();
01074 glDisable( GL_LIGHTING );
01075 glColor3f( 1.0f, 1.0f, 1.0f );
01076 glBegin( GL_LINE_LOOP );
01077 {
01078 glVertex3f( pvp.x + .5f, pvp.y + .5f, 0.f );
01079 glVertex3f( pvp.getXEnd() - .5f, pvp.y + .5f, 0.f );
01080 glVertex3f( pvp.getXEnd() - .5f, pvp.getYEnd() - .5f, 0.f );
01081 glVertex3f( pvp.x + .5f, pvp.getYEnd() - .5f, 0.f );
01082 }
01083 glEnd();
01084
01085 resetAssemblyState();
01086 }
01087
01088 int32_t Channel::getIAttribute( const IAttribute attr ) const
01089 {
01090 return _iAttributes[attr];
01091 }
01092
01093 const std::string& Channel::getIAttributeString( const IAttribute attr )
01094 {
01095 return _iAttributeStrings[attr];
01096 }
01097
01098
01099
01100
01101 net::CommandResult Channel::_cmdConfigInit( net::Command& command )
01102 {
01103 const ChannelConfigInitPacket* packet =
01104 command.getPacket<ChannelConfigInitPacket>();
01105 EQLOG( LOG_INIT ) << "TASK channel config init " << packet << endl;
01106
01107 ChannelConfigInitReplyPacket reply;
01108 _error.clear();
01109
01110 if( _window->isRunning( ))
01111 {
01112 _state = STATE_INITIALIZING;
01113 if( packet->pvp.isValid( ))
01114 _setPixelViewport( packet->pvp );
01115 else
01116 _setViewport( packet->vp );
01117
01118 _name = packet->name;
01119 _tasks = packet->tasks;
01120 _color = packet->color;
01121 _drawable = packet->drawable;
01122 _nativeContext.view = packet->view;
01123 _initialSize.x() = _nativeContext.pvp.w;
01124 _initialSize.y() = _nativeContext.pvp.h;
01125
01126 memcpy( _iAttributes, packet->iAttributes, IATTR_ALL * sizeof(int32_t));
01127
01128 reply.result = configInit( packet->initID );
01129
01130 reply.nearPlane = _nativeContext.frustum.near_plane();
01131 reply.farPlane = _nativeContext.frustum.far_plane();
01132 reply.maxSize = _maxSize;
01133
01134 if( reply.result )
01135 _state = STATE_RUNNING;
01136 }
01137 else
01138 reply.result = false;
01139
01140 EQLOG( LOG_INIT ) << "TASK channel config init reply " << &reply << endl;
01141 send( command.getNode(), reply, _error );
01142 return net::COMMAND_HANDLED;
01143 }
01144
01145 net::CommandResult Channel::_cmdConfigExit( net::Command& command )
01146 {
01147 const ChannelConfigExitPacket* packet =
01148 command.getPacket<ChannelConfigExitPacket>();
01149 EQLOG( LOG_INIT ) << "Exit channel " << packet << endl;
01150
01151 ChannelConfigExitReplyPacket reply;
01152 if( _state == STATE_STOPPED )
01153 reply.result = true;
01154 else
01155 reply.result = configExit();
01156
01157 send( command.getNode(), reply );
01158 _state = STATE_STOPPED;
01159 return net::COMMAND_HANDLED;
01160 }
01161
01162 net::CommandResult Channel::_cmdFrameStart( net::Command& command )
01163 {
01164 ChannelFrameStartPacket* packet =
01165 command.getPacket<ChannelFrameStartPacket>();
01166 EQVERB << "handle channel frame start " << packet << endl;
01167
01168
01169 _nativeContext.view = packet->context.view;
01170 _nativeContext.overdraw = packet->context.overdraw;
01171
01172 _context = &packet->context;
01173 bindFrameBuffer();
01174 frameStart( packet->context.frameID, packet->frameNumber );
01175 _context = &_nativeContext;
01176
01177 return net::COMMAND_HANDLED;
01178 }
01179
01180 net::CommandResult Channel::_cmdFrameFinish( net::Command& command )
01181 {
01182 ChannelFrameFinishPacket* packet =
01183 command.getPacket<ChannelFrameFinishPacket>();
01184 EQLOG( LOG_TASKS ) << "TASK frame finish " << getName() << " " << packet
01185 << endl;
01186
01187 _context = &packet->context;
01188 frameFinish( packet->context.frameID, packet->frameNumber );
01189 _context = &_nativeContext;
01190
01191 ChannelFrameFinishReplyPacket reply( packet );
01192 reply.nStatistics = _statistics.size();
01193
01194 command.getNode()->send( reply, _statistics );
01195
01196 _statistics.clear();
01197 return net::COMMAND_HANDLED;
01198 }
01199
01200 net::CommandResult Channel::_cmdFrameClear( net::Command& command )
01201 {
01202 ChannelFrameClearPacket* packet =
01203 command.getPacket<ChannelFrameClearPacket>();
01204 EQLOG( LOG_TASKS ) << "TASK clear " << getName() << " " << packet << endl;
01205
01206 _setRenderContext( packet->context );
01207 ChannelStatistics event( Statistic::CHANNEL_CLEAR, this );
01208 frameClear( packet->context.frameID );
01209 _context = &_nativeContext;
01210
01211 return net::COMMAND_HANDLED;
01212 }
01213
01214 net::CommandResult Channel::_cmdFrameDraw( net::Command& command )
01215 {
01216 ChannelFrameDrawPacket* packet =
01217 command.getPacket<ChannelFrameDrawPacket>();
01218 EQLOG( LOG_TASKS ) << "TASK draw " << getName() << " " << packet << endl;
01219
01220 _setRenderContext( packet->context );
01221 ChannelStatistics event( Statistic::CHANNEL_DRAW, this );
01222 frameDraw( packet->context.frameID );
01223 _context = &_nativeContext;
01224
01225 return net::COMMAND_HANDLED;
01226 }
01227
01228 net::CommandResult Channel::_cmdFrameDrawFinish( net::Command& command )
01229 {
01230 ChannelFrameDrawFinishPacket* packet =
01231 command.getPacket< ChannelFrameDrawFinishPacket >();
01232 EQLOG( LOG_TASKS ) << "TASK draw finish " << getName() << " " << packet
01233 << endl;
01234
01235 ChannelStatistics event( Statistic::CHANNEL_DRAW_FINISH, this );
01236 frameDrawFinish( packet->frameID, packet->frameNumber );
01237
01238 return net::COMMAND_HANDLED;
01239 }
01240
01241 net::CommandResult Channel::_cmdFrameAssemble( net::Command& command )
01242 {
01243 ChannelFrameAssemblePacket* packet =
01244 command.getPacket<ChannelFrameAssemblePacket>();
01245 EQLOG( LOG_TASKS | LOG_ASSEMBLY ) << "TASK assemble " << getName() << " "
01246 << packet << endl;
01247
01248 _setRenderContext( packet->context );
01249 ChannelStatistics event( Statistic::CHANNEL_ASSEMBLE, this );
01250
01251 for( uint32_t i=0; i<packet->nFrames; ++i )
01252 {
01253 Pipe* pipe = getPipe();
01254 Frame* frame = pipe->getFrame( packet->frames[i], getEye( ));
01255 _inputFrames.push_back( frame );
01256 }
01257
01258 frameAssemble( packet->context.frameID );
01259
01260 for( FrameVector::const_iterator i = _inputFrames.begin();
01261 i != _inputFrames.end(); ++i )
01262 {
01263
01264
01265 (*i)->setData( 0 );
01266 }
01267 _inputFrames.clear();
01268 _context = &_nativeContext;
01269
01270 return net::COMMAND_HANDLED;
01271 }
01272
01273 net::CommandResult Channel::_cmdFrameReadback( net::Command& command )
01274 {
01275 ChannelFrameReadbackPacket* packet =
01276 command.getPacket<ChannelFrameReadbackPacket>();
01277 EQLOG( LOG_TASKS | LOG_ASSEMBLY ) << "TASK readback " << getName() << " "
01278 << packet << endl;
01279
01280 _setRenderContext( packet->context );
01281 ChannelStatistics event( Statistic::CHANNEL_READBACK, this );
01282
01283 for( uint32_t i=0; i<packet->nFrames; ++i )
01284 {
01285 Pipe* pipe = getPipe();
01286 Frame* frame = pipe->getFrame( packet->frames[i], getEye( ));
01287 _outputFrames.push_back( frame );
01288 }
01289
01290 frameReadback( packet->context.frameID );
01291
01292 for( FrameVector::const_iterator i = _outputFrames.begin();
01293 i != _outputFrames.end(); ++i)
01294 {
01295 Frame* frame = *i;
01296 frame->setReady();
01297 }
01298
01299 _outputFrames.clear();
01300 _context = &_nativeContext;
01301 return net::COMMAND_HANDLED;
01302 }
01303
01304 net::CommandResult Channel::_cmdFrameTransmit( net::Command& command )
01305 {
01306 const ChannelFrameTransmitPacket* packet =
01307 command.getPacket<ChannelFrameTransmitPacket>();
01308 EQLOG( LOG_TASKS | LOG_ASSEMBLY ) << "TASK transmit " << getName() << " "
01309 << packet << endl;
01310
01311 net::Session* session = getSession();
01312 net::NodePtr localNode = session->getLocalNode();
01313 net::NodePtr server = session->getServer();
01314 Pipe* pipe = getPipe();
01315 Frame* frame = pipe->getFrame( packet->frame,
01316 packet->context.eye );
01317
01318 for( uint32_t i=0; i<packet->nNodes; ++i )
01319 {
01320 net::NodeID nodeID = packet->nodes[i];
01321 nodeID.convertToHost();
01322
01323 net::NodePtr toNode = localNode->connect( nodeID );
01324 EQASSERT( toNode->isConnected( ));
01325 EQLOG( LOG_ASSEMBLY ) << "channel \"" << getName() << "\" transmit "
01326 << frame << " to " << nodeID << endl;
01327
01328 frame->useSendToken( getIAttribute( IATTR_HINT_SENDTOKEN ) == ON );
01329 getNode()->transmitter.send( frame->getData(), toNode,
01330 getPipe()->getCurrentFrame( ));
01331 }
01332
01333 return net::COMMAND_HANDLED;
01334 }
01335
01336 net::CommandResult Channel::_cmdFrameViewStart( net::Command& command )
01337 {
01338 ChannelFrameViewStartPacket* packet =
01339 command.getPacket<ChannelFrameViewStartPacket>();
01340 EQLOG( LOG_TASKS | LOG_ASSEMBLY ) << "TASK view start " << getName() << " "
01341 << packet << endl;
01342
01343 _setRenderContext( packet->context );
01344
01345 frameViewStart( packet->context.frameID );
01346 _context = &_nativeContext;
01347
01348 return net::COMMAND_HANDLED;
01349 }
01350
01351 net::CommandResult Channel::_cmdFrameViewFinish( net::Command& command )
01352 {
01353 ChannelFrameViewFinishPacket* packet =
01354 command.getPacket<ChannelFrameViewFinishPacket>();
01355 EQLOG( LOG_TASKS | LOG_ASSEMBLY ) << "TASK view finish " << getName()
01356 << " " << packet << endl;
01357
01358 _setRenderContext( packet->context );
01359
01360 frameViewFinish( packet->context.frameID );
01361 _context = &_nativeContext;
01362
01363 return net::COMMAND_HANDLED;
01364 }
01365
01366 }