lib/client/window.cpp

00001 
00002 /* Copyright (c) 2005-2009, Stefan Eilemann <eile@equalizergraphics.com> 
00003  *
00004  * This library is free software; you can redistribute it and/or modify it under
00005  * the terms of the GNU Lesser General Public License version 2.1 as published
00006  * by the Free Software Foundation.
00007  *  
00008  * This library is distributed in the hope that it will be useful, but WITHOUT
00009  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00010  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00011  * details.
00012  * 
00013  * You should have received a copy of the GNU Lesser General Public License
00014  * along with this library; if not, write to the Free Software Foundation, Inc.,
00015  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00016  */
00017 
00018 #include "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 ) // default set by pipe
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 ) //don't average FPS if rendering is too slow
00166     {
00167         _avgFPS = curFPS;
00168         return;
00169     }
00170     //else  average some last frames FPS
00171 
00172     // check if current frame rate too differ from average
00173     // (can happen when rendering loop was paused)
00174     if( _avgFPS > 10*curFPS || 10*_avgFPS < curFPS )
00175         _avgFPS = curFPS;
00176 
00177     // We calculate weighted sum of average frame rate with current 
00178     // frame rate to prevent FPS count flickering.
00179     //
00180     // Weighted sum calculation here is following:
00181     // _avgFPS = (curFPS * _avgFPS + 1 * curFPS ) / ( curFPS + 1 );
00182     // the higher current frame rate (FR), the less it affects averaged
00183     // FR, this is equivalent of averaging with many frames, i.e. when
00184     // rendering is fast, we suppress FPS counter flickering stronger.
00185     // following line is a simplification of the equation above:
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 // pipe-thread methods
00320 //======================================================================
00321 
00322 //----------------------------------------------------------------------
00323 // viewport
00324 //----------------------------------------------------------------------
00325 void Window::setPixelViewport( const PixelViewport& pvp )
00326 {
00327     if( !_setPixelViewport( pvp ))
00328         return; // nothing changed
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 // render context
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; // invert y to follow GL convention
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     // Initialize context-specific data
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 // configInit
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     // GL version
00524     const char* glVersion = (const char*)glGetString( GL_VERSION );
00525     if( !glVersion ) // most likely no context - fail
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     // Framebuffer capabilities
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 ); // needed to constrain channel viewport
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     //glClearColor( 1.0f, 1.0f, 1.0f, 1.0f );
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 // configExit
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     // _pipe->setCurrent done by OSWindow::makeCurrent
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 // event-handler methods
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; //ignore
00704             // else fall through
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; // screen saver stays inactive
00718                 case ON:
00719                     return false; // screen saver becomes active
00720                 default: // AUTO
00721                     if( _drawableConfig.doublebuffered &&
00722                         getIAttribute( IATTR_HINT_DRAWABLE ) == WINDOW )
00723                     {
00724                         return true; // screen saver stays inactive
00725                     }
00726                     return false;
00727             }
00728 
00729         case Event::UNKNOWN:
00730             // unknown window-system native event, which was not handled
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 // command handlers
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         // else emergency exit, no context available.
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     //_grabFrame( packet->frameNumber ); single-threaded
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     // throttle to given framerate
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         // swap
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 }
Generated on Mon Aug 10 18:58:41 2009 for Equalizer 0.9 by  doxygen 1.5.8