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