00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "window.h"
00019
00020 #include "channel.h"
00021 #include "client.h"
00022 #include "commands.h"
00023 #include "configEvent.h"
00024 #include "config.h"
00025 #include "event.h"
00026 #include "global.h"
00027 #include "log.h"
00028 #include "nodeFactory.h"
00029 #include "pipe.h"
00030 #include "osWindow.h"
00031 #include "packets.h"
00032 #include "server.h"
00033 #include "task.h"
00034 #include "windowStatistics.h"
00035 #include "windowVisitor.h"
00036
00037 #ifdef AGL
00038 # include "aglWindow.h"
00039 #endif
00040 #ifdef GLX
00041 # include "glXWindow.h"
00042 #endif
00043 #ifdef WGL
00044 # include "wglWindow.h"
00045 #endif
00046
00047 #include <eq/net/barrier.h>
00048 #include <eq/net/command.h>
00049 #include <eq/base/sleep.h>
00050
00051 using namespace eq::base;
00052 using namespace std;
00053
00054 namespace eq
00055 {
00056
00058 typedef net::CommandFunc<Window> WindowFunc;
00061 #define MAKE_ATTR_STRING( attr ) ( string("EQ_WINDOW_") + #attr )
00062 std::string Window::_iAttributeStrings[IATTR_ALL] = {
00063 MAKE_ATTR_STRING( IATTR_HINT_STEREO ),
00064 MAKE_ATTR_STRING( IATTR_HINT_DOUBLEBUFFER ),
00065 MAKE_ATTR_STRING( IATTR_HINT_FULLSCREEN ),
00066 MAKE_ATTR_STRING( IATTR_HINT_DECORATION ),
00067 MAKE_ATTR_STRING( IATTR_HINT_SWAPSYNC ),
00068 MAKE_ATTR_STRING( IATTR_HINT_DRAWABLE ),
00069 MAKE_ATTR_STRING( IATTR_HINT_STATISTICS ),
00070 MAKE_ATTR_STRING( IATTR_HINT_SCREENSAVER ),
00071 MAKE_ATTR_STRING( IATTR_PLANES_COLOR ),
00072 MAKE_ATTR_STRING( IATTR_PLANES_ALPHA ),
00073 MAKE_ATTR_STRING( IATTR_PLANES_DEPTH ),
00074 MAKE_ATTR_STRING( IATTR_PLANES_STENCIL ),
00075 MAKE_ATTR_STRING( IATTR_PLANES_ACCUM ),
00076 MAKE_ATTR_STRING( IATTR_PLANES_ACCUM_ALPHA ),
00077 MAKE_ATTR_STRING( IATTR_PLANES_SAMPLES ),
00078 MAKE_ATTR_STRING( IATTR_FILL1 ),
00079 MAKE_ATTR_STRING( IATTR_FILL2 )
00080 };
00081
00082 Window::Window( Pipe* parent )
00083 : _pipe( parent )
00084 , _sharedContextWindow( 0 )
00085 , _osWindow( 0 )
00086 , _tasks( TASK_NONE )
00087 , _state( STATE_STOPPED )
00088 , _objectManager( 0 )
00089 , _lastTime ( 0.0 )
00090 , _avgFPS ( 0.0 )
00091 , _lastSwapTime( 0 )
00092 {
00093 parent->_addWindow( this );
00094 EQINFO << " New eq::Window @" << (void*)this << endl;
00095 }
00096
00097 Window::~Window()
00098 {
00099 if( _pipe->isCurrent( this ))
00100 _pipe->setCurrent( 0 );
00101
00102 _pipe->_removeWindow( this );
00103
00104 delete _objectManager;
00105 _objectManager = 0;
00106 }
00107
00108 void Window::attachToSession( const uint32_t id,
00109 const uint32_t instanceID,
00110 net::Session* session )
00111 {
00112 net::Object::attachToSession( id, instanceID, session );
00113
00114 net::CommandQueue* queue = _pipe->getPipeThreadQueue();
00115
00116 registerCommand( CMD_WINDOW_CREATE_CHANNEL,
00117 WindowFunc( this, &Window::_cmdCreateChannel ),
00118 queue );
00119 registerCommand( CMD_WINDOW_DESTROY_CHANNEL,
00120 WindowFunc( this, &Window::_cmdDestroyChannel ),
00121 queue );
00122 registerCommand( CMD_WINDOW_CONFIG_INIT,
00123 WindowFunc( this, &Window::_cmdConfigInit ),
00124 queue );
00125 registerCommand( CMD_WINDOW_CONFIG_EXIT,
00126 WindowFunc( this, &Window::_cmdConfigExit ),
00127 queue );
00128 registerCommand( CMD_WINDOW_FRAME_START,
00129 WindowFunc( this, &Window::_cmdFrameStart ),
00130 queue );
00131 registerCommand( CMD_WINDOW_FRAME_FINISH,
00132 WindowFunc( this, &Window::_cmdFrameFinish ),
00133 queue );
00134 registerCommand( CMD_WINDOW_FINISH,
00135 WindowFunc( this, &Window::_cmdFinish), queue );
00136 registerCommand( CMD_WINDOW_THROTTLE_FRAMERATE,
00137 WindowFunc( this, &Window::_cmdThrottleFramerate ),
00138 queue );
00139 registerCommand( CMD_WINDOW_BARRIER,
00140 WindowFunc( this, &Window::_cmdBarrier ),
00141 queue );
00142 registerCommand( CMD_WINDOW_NV_BARRIER,
00143 WindowFunc( this, &Window::_cmdNVBarrier ),
00144 queue );
00145 registerCommand( CMD_WINDOW_SWAP,
00146 WindowFunc( this, &Window::_cmdSwap), queue );
00147 registerCommand( CMD_WINDOW_FRAME_DRAW_FINISH,
00148 WindowFunc( this, &Window::_cmdFrameDrawFinish ),
00149 queue );
00150 }
00151
00152 void Window::_updateFPS()
00153 {
00154 const double curTime = static_cast< float >( getConfig()->getTime( ));
00155 const double curInterval = curTime - _lastTime;
00156
00157 const bool isFirstFrame = _lastTime == 0.0;
00158 _lastTime = curTime;
00159
00160 if( isFirstFrame || curInterval < 1e-3 )
00161 return;
00162
00163 const double curFPS = 1000.0 / curInterval;
00164
00165 if( curFPS < 1.0 )
00166 {
00167 _avgFPS = curFPS;
00168 return;
00169 }
00170
00171
00172
00173
00174 if( _avgFPS > 10*curFPS || 10*_avgFPS < curFPS )
00175 _avgFPS = curFPS;
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186 _avgFPS = curFPS * ( _avgFPS + 1 ) / ( curFPS + 1 );
00187 }
00188
00189
00190 void Window::drawFPS() const
00191 {
00192 ostringstream fpsText;
00193 fpsText << setprecision(3) << getFPS() << " FPS";
00194
00195 const util::BitmapFont& font = getObjectManager()->getDefaultFont();
00196 const PixelViewport& pvp = getPixelViewport();
00197
00198 glRasterPos3f( pvp.w - 60.f, 10.f , 0.99f );
00199 glColor3f( 1.f, 1.f, 1.f );
00200
00201 font.draw( fpsText.str( ));
00202 }
00203
00204 void Window::_addChannel( Channel* channel )
00205 {
00206 EQASSERT( channel->getWindow() == this );
00207 _channels.push_back( channel );
00208 }
00209
00210 void Window::_removeChannel( Channel* channel )
00211 {
00212 ChannelVector::iterator i = find( _channels.begin(), _channels.end(),
00213 channel );
00214 EQASSERT( i != _channels.end( ))
00215
00216 _channels.erase( i );
00217 }
00218
00219 Channel* Window::_findChannel( const uint32_t id )
00220 {
00221 for( ChannelVector::const_iterator i = _channels.begin();
00222 i != _channels.end(); ++i )
00223 {
00224 Channel* channel = *i;
00225 if( channel->getID() == id )
00226 return channel;
00227 }
00228 return 0;
00229 }
00230
00231 net::CommandQueue* Window::getPipeThreadQueue()
00232 {
00233 EQASSERT( _pipe );
00234 return _pipe->getPipeThreadQueue();
00235 }
00236
00237 const Node* Window::getNode() const
00238 {
00239 EQASSERT( _pipe );
00240 return ( _pipe ? _pipe->getNode() : 0 );
00241 }
00242 Node* Window::getNode()
00243 {
00244 EQASSERT( _pipe );
00245 return ( _pipe ? _pipe->getNode() : 0 );
00246 }
00247
00248 const Config* Window::getConfig() const
00249 {
00250 EQASSERT( _pipe );
00251 return (_pipe ? _pipe->getConfig() : 0);
00252 }
00253 Config* Window::getConfig()
00254 {
00255 EQASSERT( _pipe );
00256 return (_pipe ? _pipe->getConfig() : 0);
00257 }
00258
00259 ClientPtr Window::getClient()
00260 {
00261 EQASSERT( _pipe );
00262 return ( _pipe ? _pipe->getClient() : 0 );
00263 }
00264 ServerPtr Window::getServer()
00265 {
00266 EQASSERT( _pipe );
00267 return ( _pipe ? _pipe->getServer() : 0 );
00268 }
00269
00270 WGLEWContext* Window::wglewGetContext()
00271 {
00272 EQASSERT( _pipe );
00273 return _pipe->wglewGetContext();
00274 }
00275
00276 VisitorResult Window::accept( WindowVisitor& visitor )
00277 {
00278 VisitorResult result = visitor.visitPre( this );
00279 if( result != TRAVERSE_CONTINUE )
00280 return result;
00281
00282 for( ChannelVector::const_iterator i = _channels.begin();
00283 i != _channels.end(); ++i )
00284 {
00285 Channel* channel = *i;
00286 switch( channel->accept( visitor ))
00287 {
00288 case TRAVERSE_TERMINATE:
00289 return TRAVERSE_TERMINATE;
00290
00291 case TRAVERSE_PRUNE:
00292 result = TRAVERSE_PRUNE;
00293 break;
00294
00295 case TRAVERSE_CONTINUE:
00296 default:
00297 break;
00298 }
00299 }
00300
00301 switch( visitor.visitPost( this ))
00302 {
00303 case TRAVERSE_TERMINATE:
00304 return TRAVERSE_TERMINATE;
00305
00306 case TRAVERSE_PRUNE:
00307 return TRAVERSE_PRUNE;
00308
00309 case TRAVERSE_CONTINUE:
00310 default:
00311 break;
00312 }
00313
00314 return result;
00315 }
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 void Window::setPixelViewport( const PixelViewport& pvp )
00326 {
00327 if( !_setPixelViewport( pvp ))
00328 return;
00329
00330 WindowSetPVPPacket packet;
00331 packet.pvp = pvp;
00332 ServerPtr server = getServer();
00333 net::NodePtr node = server.get();
00334 send( node, packet );
00335
00336 for( std::vector<Channel*>::iterator i = _channels.begin();
00337 i != _channels.end(); ++i )
00338 {
00339 (*i)->_notifyViewportChanged();
00340 }
00341 }
00342
00343 bool Window::_setPixelViewport( const PixelViewport& pvp )
00344 {
00345 if( pvp == _pvp || !pvp.isValid( ))
00346 return false;
00347
00348 _pvp = pvp;
00349 _vp.invalidate();
00350
00351 EQASSERT( _pipe );
00352
00353 const PixelViewport& pipePVP = _pipe->getPixelViewport();
00354 if( pipePVP.isValid( ))
00355 _vp = pvp.getSubVP( pipePVP );
00356
00357 EQINFO << "Window pvp set: " << _pvp << ":" << _vp << endl;
00358 return true;
00359 }
00360
00361 void Window::_setViewport( const Viewport& vp )
00362 {
00363 if( !vp.hasArea( ))
00364 return;
00365
00366 _vp = vp;
00367 _pvp.invalidate();
00368
00369 if( !_pipe )
00370 return;
00371
00372 PixelViewport pipePVP = _pipe->getPixelViewport();
00373 if( pipePVP.isValid( ))
00374 _pvp = pipePVP.getSubPVP( vp );
00375 EQINFO << "Window vp set: " << _pvp << ":" << _vp << endl;
00376 }
00377
00378
00379
00380
00381 void Window::addRenderContext( const RenderContext& context )
00382 {
00383 CHECK_THREAD( _pipeThread );
00384 _renderContexts[BACK].push_back( context );
00385 }
00386
00387 bool Window::getRenderContext( const int32_t x, const int32_t y,
00388 RenderContext& context ) const
00389 {
00390 CHECK_THREAD( _pipeThread );
00391 if( !_osWindow )
00392 return false;
00393
00394 const DrawableConfig& drawableConfig = getDrawableConfig();
00395 const unsigned which = drawableConfig.doublebuffered ? FRONT : BACK;
00396
00397 vector< RenderContext >::const_reverse_iterator i =
00398 _renderContexts[which].rbegin();
00399 vector< RenderContext >::const_reverse_iterator end =
00400 _renderContexts[which].rend();
00401
00402 const int32_t glY = _pvp.h - y;
00403
00404 for( ; i != end; ++i )
00405 {
00406 const RenderContext& candidate = *i;
00407 if( candidate.pvp.isPointInside( x, glY ))
00408 {
00409 context = candidate;
00410 return true;
00411 }
00412 }
00413 return false;
00414 }
00415
00416 void Window::setIAttribute( const IAttribute attr, const int32_t value )
00417 {
00418 _iAttributes[attr] = value;
00419 }
00420
00421 int32_t Window::getIAttribute( const IAttribute attr ) const
00422 {
00423 return _iAttributes[attr];
00424 }
00425
00426 const std::string& Window::getIAttributeString( const IAttribute attr )
00427 {
00428 return _iAttributeStrings[attr];
00429 }
00430
00431 void Window::setOSWindow( OSWindow* window )
00432 {
00433 if( _osWindow )
00434 _osWindow->exitGLEW();
00435
00436 _osWindow = window;
00437
00438 if( !window )
00439 return;
00440
00441
00442 makeCurrent();
00443 _osWindow->initGLEW();
00444 _queryDrawableConfig();
00445 _setupObjectManager();
00446 }
00447
00448 void Window::frameFinish( const uint32_t frameID, const uint32_t frameNumber )
00449 {
00450 releaseFrame( frameNumber );
00451 flush();
00452 _updateFPS();
00453 }
00454
00455
00456
00457
00458 bool Window::configInit( const uint32_t initID )
00459 {
00460 if( !_pvp.isValid( ))
00461 {
00462 setErrorMessage( "Window pixel viewport invalid - pipe init failed?" );
00463 return false;
00464 }
00465
00466 EQASSERT( !_osWindow );
00467
00468 if( !configInitOSWindow( initID )) return false;
00469 if( !configInitGL( initID )) return false;
00470
00471 EQ_GL_ERROR( "after Window::configInitGL" );
00472 return true;
00473 }
00474
00475 bool Window::configInitOSWindow( const uint32_t initID )
00476 {
00477 const Pipe* pipe = getPipe();
00478 OSWindow* osWindow = 0;
00479
00480 switch( pipe->getWindowSystem( ))
00481 {
00482 #ifdef GLX
00483 case WINDOW_SYSTEM_GLX:
00484 EQINFO << "Using GLXWindow" << std::endl;
00485 osWindow = new GLXWindow( this );
00486 break;
00487 #endif
00488
00489 #ifdef AGL
00490 case WINDOW_SYSTEM_AGL:
00491 EQINFO << "Using AGLWindow" << std::endl;
00492 osWindow = new AGLWindow( this );
00493 break;
00494 #endif
00495
00496 #ifdef WGL
00497 case WINDOW_SYSTEM_WGL:
00498 EQINFO << "Using WGLWindow" << std::endl;
00499 osWindow = new WGLWindow( this );
00500 break;
00501 #endif
00502
00503 default:
00504 EQERROR << "Window system " << pipe->getWindowSystem()
00505 << " not implemented or supported" << endl;
00506 return false;
00507 }
00508
00509 EQASSERT( osWindow );
00510 if( !osWindow->configInit( ))
00511 {
00512 EQWARN << "OS Window initialization failed: " << _error << endl;
00513 delete osWindow;
00514 return false;
00515 }
00516
00517 setOSWindow( osWindow );
00518 return true;
00519 }
00520
00521 void Window::_queryDrawableConfig()
00522 {
00523
00524 const char* glVersion = (const char*)glGetString( GL_VERSION );
00525 if( !glVersion )
00526 {
00527 EQWARN << "glGetString(GL_VERSION) returned 0, assuming GL version 1.1"
00528 << endl;
00529 _drawableConfig.glVersion = 1.1f;
00530 }
00531 else
00532 _drawableConfig.glVersion = static_cast<float>( atof( glVersion ));
00533
00534
00535 GLboolean result;
00536 glGetBooleanv( GL_STEREO, &result );
00537 _drawableConfig.stereo = result;
00538
00539 glGetBooleanv( GL_DOUBLEBUFFER, &result );
00540 _drawableConfig.doublebuffered = result;
00541
00542 GLint stencilBits;
00543 glGetIntegerv( GL_STENCIL_BITS, &stencilBits );
00544 _drawableConfig.stencilBits = stencilBits;
00545
00546 GLint alphaBits;
00547 glGetIntegerv( GL_ALPHA_BITS, &alphaBits );
00548 _drawableConfig.alphaBits = alphaBits;
00549
00550 EQINFO << "Window drawable config: " << _drawableConfig << endl;
00551 }
00552
00553 void Window::_setupObjectManager()
00554 {
00555 _releaseObjectManager();
00556
00557 Window* sharedWindow = getSharedContextWindow();
00558 ObjectManager* sharedOM = sharedWindow ? sharedWindow->getObjectManager():0;
00559
00560 if( sharedOM )
00561 _objectManager = new ObjectManager( this, sharedOM );
00562 else
00563 _objectManager = new ObjectManager( this );
00564
00565 _objectManager->_smallFont.initFont();
00566 _objectManager->_mediumFont.initFont( util::BitmapFont::normal, 20 );
00567 }
00568
00569 void Window::_releaseObjectManager()
00570 {
00571 if( _objectManager && _objectManager->getSharedUsage() == 1 )
00572 _objectManager->deleteAll();
00573
00574 delete _objectManager;
00575 _objectManager = 0;
00576 }
00577
00578 bool Window::configInitGL( const uint32_t initID )
00579 {
00580 glEnable( GL_SCISSOR_TEST );
00581 glEnable( GL_DEPTH_TEST );
00582 glDepthFunc( GL_LESS );
00583
00584 glEnable( GL_LIGHTING );
00585 glEnable( GL_LIGHT0 );
00586
00587 glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
00588 glEnable( GL_COLOR_MATERIAL );
00589
00590 glClearDepth( 1.f );
00591
00592
00593 glClear( GL_COLOR_BUFFER_BIT );
00594 swapBuffers();
00595 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
00596
00597 return true;
00598 }
00599
00600
00601
00602
00603 bool Window::configExit()
00604 {
00605 const bool ret = configExitGL();
00606 return configExitOSWindow() && ret;
00607 }
00608
00609 bool Window::configExitOSWindow()
00610 {
00611 _releaseObjectManager();
00612
00613 if( _osWindow )
00614 {
00615 _osWindow->configExit( );
00616
00617 delete _osWindow;
00618 _osWindow = 0;
00619 }
00620
00621 if( _pipe->isCurrent( this ))
00622 _pipe->setCurrent( 0 );
00623
00624 return true;
00625 }
00626
00627 void Window::makeCurrent( const bool useCache ) const
00628 {
00629 if( useCache && _pipe->isCurrent( this ))
00630 return;
00631
00632 _osWindow->makeCurrent();
00633
00634 }
00635
00636 void Window::bindFrameBuffer() const
00637 {
00638 _osWindow->bindFrameBuffer( );
00639 }
00640
00641 bool Window::isFBOWindow()
00642 {
00643 return _osWindow->getFBO();
00644 }
00645
00646 void Window::swapBuffers()
00647 {
00648 _osWindow->swapBuffers();
00649 EQVERB << "----- SWAP -----" << endl;
00650 }
00651
00652 int Window::getColorType()
00653 {
00654 switch ( getIAttribute( Window::IATTR_PLANES_COLOR ) )
00655 {
00656 case RGBA32F: return GL_RGBA32F;
00657 case RGBA16F: return GL_RGBA16F;
00658 default: return GL_RGBA;
00659 }
00660 }
00661
00662 GLEWContext* Window::glewGetContext()
00663 {
00664 return _osWindow->glewGetContext();
00665 }
00666
00667 void Window::_enterBarrier( net::ObjectVersion barrier )
00668 {
00669 EQLOG( net::LOG_BARRIER ) << "swap barrier " << barrier << std::endl;
00670 Node* node = getNode();
00671 net::Barrier* netBarrier = node->getBarrier( barrier );
00672
00673 WindowStatistics stat( Statistic::WINDOW_SWAP_BARRIER, this );
00674 netBarrier->enter();
00675 }
00676
00677 void Window::setErrorMessage( const std::string& message )
00678 {
00679 _error = message;
00680 }
00681
00682
00683
00684
00685 bool Window::processEvent( const Event& event )
00686 {
00687 ConfigEvent configEvent;
00688 switch( event.type )
00689 {
00690 case Event::WINDOW_HIDE:
00691 setPixelViewport( PixelViewport( 0, 0, 0, 0 ));
00692 break;
00693
00694 case Event::WINDOW_SHOW:
00695 case Event::WINDOW_RESIZE:
00696 setPixelViewport( PixelViewport( event.resize.x, event.resize.y,
00697 event.resize.w, event.resize.h ));
00698 break;
00699
00700 case Event::KEY_PRESS:
00701 case Event::KEY_RELEASE:
00702 if( event.key.key == KC_VOID )
00703 return true;
00704
00705 case Event::WINDOW_EXPOSE:
00706 case Event::WINDOW_CLOSE:
00707 case Event::POINTER_MOTION:
00708 case Event::POINTER_BUTTON_PRESS:
00709 case Event::POINTER_BUTTON_RELEASE:
00710 case Event::STATISTIC:
00711 break;
00712
00713 case Event::WINDOW_SCREENSAVER:
00714 switch( getIAttribute( IATTR_HINT_SCREENSAVER ))
00715 {
00716 case OFF:
00717 return true;
00718 case ON:
00719 return false;
00720 default:
00721 if( _drawableConfig.doublebuffered &&
00722 getIAttribute( IATTR_HINT_DRAWABLE ) == WINDOW )
00723 {
00724 return true;
00725 }
00726 return false;
00727 }
00728
00729 case Event::UNKNOWN:
00730
00731 return false;
00732
00733 default:
00734 EQWARN << "Unhandled window event of type " << event.type
00735 << endl;
00736 EQUNIMPLEMENTED;
00737 }
00738
00739 configEvent.data = event;
00740
00741 Config* config = getConfig();
00742 config->sendEvent( configEvent );
00743 return true;
00744 }
00745
00746
00747
00748
00749 net::CommandResult Window::_cmdCreateChannel( net::Command& command )
00750 {
00751 const WindowCreateChannelPacket* packet =
00752 command.getPacket<WindowCreateChannelPacket>();
00753 EQLOG( LOG_INIT ) << "Create channel " << packet << endl;
00754
00755 Channel* channel = Global::getNodeFactory()->createChannel( this );
00756 getConfig()->attachObject( channel, packet->channelID, EQ_ID_INVALID );
00757
00758 return net::COMMAND_HANDLED;
00759 }
00760
00761 net::CommandResult Window::_cmdDestroyChannel( net::Command& command )
00762 {
00763 const WindowDestroyChannelPacket* packet =
00764 command.getPacket<WindowDestroyChannelPacket>();
00765 EQLOG( LOG_INIT ) << "Destroy channel " << packet << endl;
00766
00767 Channel* channel = _findChannel( packet->channelID );
00768 EQASSERT( channel )
00769
00770 Config* config = getConfig();
00771 config->detachObject( channel );
00772 Global::getNodeFactory()->releaseChannel( channel );
00773
00774 return net::COMMAND_HANDLED;
00775 }
00776
00777 net::CommandResult Window::_cmdConfigInit( net::Command& command )
00778 {
00779 const WindowConfigInitPacket* packet =
00780 command.getPacket<WindowConfigInitPacket>();
00781 EQLOG( LOG_INIT ) << "TASK window config init " << packet << endl;
00782
00783 WindowConfigInitReplyPacket reply;
00784 _error.clear();
00785
00786 if( _pipe->isRunning( ))
00787 {
00788 _state = STATE_INITIALIZING;
00789 if( packet->pvp.isValid( ))
00790 _setPixelViewport( packet->pvp );
00791 else
00792 _setViewport( packet->vp );
00793
00794 _name = packet->name;
00795 _tasks = packet->tasks;
00796
00797 memcpy( _iAttributes, packet->iAttributes, IATTR_ALL * sizeof(int32_t));
00798
00799 reply.result = configInit( packet->initID );
00800 }
00801 else
00802 reply.result = false;
00803
00804 EQLOG( LOG_INIT ) << "TASK window config init reply " << &reply << endl;
00805
00806 net::NodePtr node = command.getNode();
00807 if( !reply.result )
00808 {
00809 send( node, reply, _error );
00810 return net::COMMAND_HANDLED;
00811 }
00812
00813 reply.pvp = _pvp;
00814 reply.drawableConfig = getDrawableConfig();
00815 send( node, reply );
00816
00817 _state = STATE_RUNNING;
00818 return net::COMMAND_HANDLED;
00819 }
00820
00821 net::CommandResult Window::_cmdConfigExit( net::Command& command )
00822 {
00823 const WindowConfigExitPacket* packet =
00824 command.getPacket<WindowConfigExitPacket>();
00825 EQLOG( LOG_INIT ) << "TASK window config exit " << packet << endl;
00826
00827 WindowConfigExitReplyPacket reply;
00828
00829 if( _state == STATE_STOPPED )
00830 reply.result = true;
00831 else
00832 {
00833 if( _pipe->isRunning( ) && _osWindow )
00834 {
00835 EQ_GL_CALL( makeCurrent( ));
00836 _pipe->flushFrames();
00837 }
00838
00839
00840 reply.result = configExit();
00841 }
00842
00843 send( command.getNode(), reply );
00844 _state = STATE_STOPPED;
00845 return net::COMMAND_HANDLED;
00846 }
00847
00848 net::CommandResult Window::_cmdFrameStart( net::Command& command )
00849 {
00850 CHECK_THREAD( _pipeThread );
00851
00852 const WindowFrameStartPacket* packet =
00853 command.getPacket<WindowFrameStartPacket>();
00854 EQLOG( LOG_TASKS ) << "TASK frame start " << getName() << " " << packet
00855 << std::endl;
00856
00857
00858
00859 EQASSERT( _osWindow );
00860 const DrawableConfig& drawableConfig = getDrawableConfig();
00861 if( drawableConfig.doublebuffered )
00862 _renderContexts[FRONT].swap( _renderContexts[BACK] );
00863 _renderContexts[BACK].clear();
00864
00865 EQ_GL_CALL( makeCurrent( ));
00866
00867 frameStart( packet->frameID, packet->frameNumber );
00868 return net::COMMAND_HANDLED;
00869 }
00870
00871 net::CommandResult Window::_cmdFrameFinish( net::Command& command )
00872 {
00873 const WindowFrameFinishPacket* packet =
00874 command.getPacket<WindowFrameFinishPacket>();
00875 EQVERB << "handle window frame sync " << packet << endl;
00876
00877 EQ_GL_CALL( makeCurrent( ));
00878 frameFinish( packet->frameID, packet->frameNumber );
00879 return net::COMMAND_HANDLED;
00880 }
00881
00882 net::CommandResult Window::_cmdFinish(net::Command& command )
00883 {
00884 EQ_GL_CALL( makeCurrent( ));
00885
00886 WindowStatistics stat( Statistic::WINDOW_FINISH, this );
00887 finish();
00888
00889 return net::COMMAND_HANDLED;
00890 }
00891
00892 net::CommandResult Window::_cmdThrottleFramerate( net::Command& command )
00893 {
00894 WindowThrottleFramerate* packet =
00895 command.getPacket< WindowThrottleFramerate >();
00896 EQLOG( LOG_TASKS ) << "TASK throttle framerate " << getName() << " "
00897 << packet << endl;
00898
00899
00900 const int64_t elapsed = getConfig()->getTime() - _lastSwapTime;
00901 const float timeLeft = packet->minFrameTime - static_cast<float>( elapsed );
00902
00903 if( timeLeft >= 1.f )
00904 {
00905 WindowStatistics stat( Statistic::WINDOW_THROTTLE_FRAMERATE, this );
00906 base::sleep( static_cast< uint32_t >( timeLeft ));
00907 }
00908
00909 _lastSwapTime = getConfig()->getTime();
00910 return net::COMMAND_HANDLED;
00911 }
00912
00913 net::CommandResult Window::_cmdBarrier( net::Command& command )
00914 {
00915 const WindowBarrierPacket* packet =
00916 command.getPacket<WindowBarrierPacket>();
00917 EQVERB << "handle barrier " << packet << endl;
00918 EQLOG( LOG_TASKS ) << "TASK swap barrier " << getName() << endl;
00919
00920 _enterBarrier( packet->barrier );
00921 return net::COMMAND_HANDLED;
00922 }
00923
00924 net::CommandResult Window::_cmdNVBarrier( net::Command& command )
00925 {
00926 const WindowNVBarrierPacket* packet =
00927 command.getPacket<WindowNVBarrierPacket>();
00928 EQLOG( LOG_TASKS ) << "TASK join NV_swap_group" << endl;
00929
00930 EQASSERT( _osWindow );
00931 _osWindow->joinNVSwapBarrier( packet->group, packet->barrier );
00932
00933 _enterBarrier( packet->netBarrier );
00934 return net::COMMAND_HANDLED;
00935 }
00936
00937 net::CommandResult Window::_cmdSwap( net::Command& command )
00938 {
00939 WindowSwapPacket* packet = command.getPacket< WindowSwapPacket >();
00940 EQLOG( LOG_TASKS ) << "TASK swap buffers " << getName() << " " << packet
00941 << endl;
00942
00943
00944 if( _drawableConfig.doublebuffered )
00945 {
00946
00947 WindowStatistics stat( Statistic::WINDOW_SWAP, this );
00948 EQ_GL_CALL( makeCurrent( ));
00949 swapBuffers();
00950 }
00951 return net::COMMAND_HANDLED;
00952 }
00953
00954 net::CommandResult Window::_cmdFrameDrawFinish( net::Command& command )
00955 {
00956 WindowFrameDrawFinishPacket* packet =
00957 command.getPacket< WindowFrameDrawFinishPacket >();
00958 EQLOG( LOG_TASKS ) << "TASK draw finish " << getName() << " " << packet
00959 << endl;
00960
00961 frameDrawFinish( packet->frameID, packet->frameNumber );
00962 return net::COMMAND_HANDLED;
00963 }
00964
00965 std::ostream& operator << ( std::ostream& os,
00966 const Window::DrawableConfig& config )
00967 {
00968 os << "GL" << config.glVersion;
00969 if( config.stereo )
00970 os << "|ST";
00971 if( config.doublebuffered )
00972 os << "|DB";
00973 if( config.stencilBits )
00974 os << "|st" << config.stencilBits;
00975 if( config.alphaBits )
00976 os << "|a" << config.alphaBits;
00977 return os;
00978 }
00979 }