LCOV - code coverage report
Current view: top level - eq/client - window.cpp (source / functions) Hit Total Coverage
Test: lcov2.info Lines: 316 509 62.1 %
Date: 2014-06-18 Functions: 52 69 75.4 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2005-2013, Stefan Eilemann <eile@equalizergraphics.com>
       3             :  *               2009-2011, Cedric Stalder <cedric.stalder@gmail.com>
       4             :  *               2010-2014, Daniel Nachbaur <danielnachbaur@gmail.com>
       5             :  *
       6             :  * This library is free software; you can redistribute it and/or modify it under
       7             :  * the terms of the GNU Lesser General Public License version 2.1 as published
       8             :  * by the Free Software Foundation.
       9             :  *
      10             :  * This library is distributed in the hope that it will be useful, but WITHOUT
      11             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      12             :  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
      13             :  * details.
      14             :  *
      15             :  * You should have received a copy of the GNU Lesser General Public License
      16             :  * along with this library; if not, write to the Free Software Foundation, Inc.,
      17             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      18             :  */
      19             : 
      20             : #include "window.h"
      21             : 
      22             : #include "channel.h"
      23             : #include "client.h"
      24             : #include "config.h"
      25             : #include "error.h"
      26             : #include "event.h"
      27             : #include "gl.h"
      28             : #include "global.h"
      29             : #include "log.h"
      30             : #include "node.h"
      31             : #include "nodeFactory.h"
      32             : #include "pipe.h"
      33             : #include "server.h"
      34             : #include "systemWindow.h"
      35             : #include "windowStatistics.h"
      36             : 
      37             : #include <eq/util/objectManager.h>
      38             : #include <eq/fabric/commands.h>
      39             : #include <eq/fabric/elementVisitor.h>
      40             : #include <eq/fabric/leafVisitor.h>
      41             : #include <eq/fabric/task.h>
      42             : 
      43             : #include <co/barrier.h>
      44             : #include <co/exception.h>
      45             : #include <co/objectICommand.h>
      46             : #include <lunchbox/sleep.h>
      47             : 
      48             : namespace eq
      49             : {
      50             : 
      51             : typedef fabric::Window< Pipe, Window, Channel, WindowSettings > Super;
      52             : 
      53             : /** @cond IGNORE */
      54             : typedef co::CommandFunc<Window> WindowFunc;
      55             : /** @endcond */
      56             : 
      57             : namespace
      58             : {
      59             : const char* _smallFontKey  = "eq_small_font";
      60             : const char* _mediumFontKey = "eq_medium_font";
      61             : }
      62             : 
      63         285 : Window::Window( Pipe* parent )
      64             :         : Super( parent )
      65             :         , _sharedContextWindow( 0 ) // default set below
      66             :         , _transferWindow( 0 )
      67             :         , _systemWindow( 0 )
      68             :         , _state( STATE_STOPPED )
      69             :         , _objectManager( 0 )
      70             :         , _lastTime ( 0.0f )
      71             :         , _avgFPS ( 0.0f )
      72         285 :         , _lastSwapTime( 0 )
      73             : {
      74         285 :     const Windows& windows = parent->getWindows();
      75         285 :     if( windows.empty( ))
      76           0 :         setSharedContextWindow( this );
      77             :     else
      78         285 :         setSharedContextWindow( windows.front( ));
      79         285 : }
      80             : 
      81          43 : Window::~Window()
      82             : {
      83          15 :     LBASSERT( getChannels().empty( ));
      84          28 : }
      85             : 
      86          15 : void Window::attach( const uint128_t& id, const uint32_t instanceID )
      87             : {
      88          15 :     Super::attach( id, instanceID );
      89             : 
      90          15 :     co::CommandQueue* queue = getPipeThreadQueue();
      91             : 
      92             :     registerCommand( fabric::CMD_WINDOW_CREATE_CHANNEL,
      93          15 :                      WindowFunc( this, &Window::_cmdCreateChannel ), queue );
      94             :     registerCommand( fabric::CMD_WINDOW_DESTROY_CHANNEL,
      95          15 :                      WindowFunc( this, &Window::_cmdDestroyChannel ), queue );
      96             :     registerCommand( fabric::CMD_WINDOW_CONFIG_INIT,
      97          15 :                      WindowFunc( this, &Window::_cmdConfigInit ), queue );
      98             :     registerCommand( fabric::CMD_WINDOW_CONFIG_EXIT,
      99          15 :                      WindowFunc( this, &Window::_cmdConfigExit ), queue );
     100             :     registerCommand( fabric::CMD_WINDOW_FRAME_START,
     101          15 :                      WindowFunc( this, &Window::_cmdFrameStart ), queue );
     102             :     registerCommand( fabric::CMD_WINDOW_FRAME_FINISH,
     103          15 :                      WindowFunc( this, &Window::_cmdFrameFinish ), queue );
     104             :     registerCommand( fabric::CMD_WINDOW_FLUSH,
     105          15 :                      WindowFunc( this, &Window::_cmdFlush), queue );
     106             :     registerCommand( fabric::CMD_WINDOW_FINISH,
     107          15 :                      WindowFunc( this, &Window::_cmdFinish), queue );
     108             :     registerCommand( fabric::CMD_WINDOW_THROTTLE_FRAMERATE,
     109             :                      WindowFunc( this, &Window::_cmdThrottleFramerate ),
     110          15 :                      queue );
     111             :     registerCommand( fabric::CMD_WINDOW_BARRIER,
     112          15 :                      WindowFunc( this, &Window::_cmdBarrier ), queue );
     113             :     registerCommand( fabric::CMD_WINDOW_NV_BARRIER,
     114          15 :                      WindowFunc( this, &Window::_cmdNVBarrier ), queue );
     115             :     registerCommand( fabric::CMD_WINDOW_SWAP,
     116          15 :                      WindowFunc( this, &Window::_cmdSwap), queue );
     117             :     registerCommand( fabric::CMD_WINDOW_FRAME_DRAW_FINISH,
     118          15 :                      WindowFunc( this, &Window::_cmdFrameDrawFinish ), queue );
     119          15 : }
     120             : 
     121          38 : void Window::notifyViewportChanged()
     122             : {
     123          38 :     Super::notifyViewportChanged();
     124          38 :     if( !isRunning( ))
     125          70 :         return;
     126             : 
     127             :     // Commit immediately so that the server has the new data before the app
     128             :     // does send the startFrame() after a resize event.
     129           6 :     const uint128_t version = commit();
     130           6 :     if( version != co::VERSION_NONE )
     131           5 :         send( getServer(), fabric::CMD_OBJECT_SYNC );
     132             : }
     133             : 
     134           7 : void Window::_updateFPS()
     135             : {
     136           7 :     const float curTime = float( getConfig()->getTime( ));
     137           7 :     const float curInterval = curTime - _lastTime;
     138           7 :     const bool isFirstFrame = _lastTime == 0.0f;
     139           7 :     _lastTime = curTime;
     140             : 
     141           7 :     if( isFirstFrame || curInterval < 1e-3f )
     142          11 :         return;
     143             : 
     144           2 :     const float curFPS = 1000.0f / curInterval;
     145             : 
     146           4 :     if( curFPS < 1.0f || // don't average FPS if rendering is too slow
     147             :         // or if current frame rate differs a lot from average (rendering loop
     148             :         // was paused)
     149           4 :         ( _avgFPS > 10.f * curFPS || 10.f * _avgFPS < curFPS ))
     150             :     {
     151           1 :         _avgFPS = curFPS;
     152           1 :         return;
     153             :     }
     154             :     else // average FPS over time
     155             :     {
     156             :         // We calculate weighted sum of average frame rate with current frame
     157             :         // rate to prevent FPS count flickering.
     158             :         //
     159             :         // Weighted sum calculation here is the following:
     160           1 :         _avgFPS = curFPS * ( _avgFPS + 1.f ) / ( curFPS + 1.f );
     161             : 
     162             :         // The higher current frame rate, the less it affects averaged FR. This
     163             :         // is equivalent of averaging over many frames, i.e. when rendering is
     164             :         // fast, we suppress FPS counter flickering stronger.
     165             :     }
     166             : 
     167           1 :     WindowStatistics stat( Statistic::WINDOW_FPS, this );
     168           1 :     stat.event.data.statistic.currentFPS = curFPS;
     169           1 :     stat.event.data.statistic.averageFPS = _avgFPS;
     170             : }
     171             : 
     172             : 
     173           0 : void Window::drawFPS()
     174             : {
     175           0 :     std::ostringstream fpsText;
     176           0 :     fpsText << std::setprecision(3) << getFPS() << " FPS";
     177             : 
     178           0 :     const util::BitmapFont* font = getSmallFont();
     179           0 :     const PixelViewport& pvp = getPixelViewport();
     180             : 
     181           0 :     glLogicOp( GL_XOR );
     182           0 :     glEnable( GL_COLOR_LOGIC_OP );
     183           0 :     glRasterPos3f( pvp.w - 60.f, pvp.h - 16.f , 0.99f );
     184           0 :     glColor3f( .8f, .8f, .8f );
     185             : 
     186           0 :     font->draw( fpsText.str( ));
     187           0 : }
     188             : 
     189          30 : co::CommandQueue* Window::getPipeThreadQueue()
     190             : {
     191          30 :     return getPipe()->getPipeThreadQueue();
     192             : }
     193             : 
     194          15 : co::CommandQueue* Window::getCommandThreadQueue()
     195             : {
     196          15 :     return getPipe()->getCommandThreadQueue();
     197             : }
     198             : 
     199          20 : uint32_t Window::getCurrentFrame() const
     200             : {
     201          20 :     return getPipe()->getCurrentFrame();
     202             : }
     203             : 
     204           0 : const Node* Window::getNode() const
     205             : {
     206           0 :     const Pipe* pipe = getPipe();
     207           0 :     LBASSERT( pipe );
     208           0 :     return ( pipe ? pipe->getNode() : 0 );
     209             : }
     210          28 : Node* Window::getNode()
     211             : {
     212          28 :     Pipe* pipe = getPipe();
     213          28 :     LBASSERT( pipe );
     214          28 :     return ( pipe ? pipe->getNode() : 0 );
     215             : }
     216             : 
     217           0 : const Config* Window::getConfig() const
     218             : {
     219           0 :     const Pipe* pipe = getPipe();
     220           0 :     LBASSERT( pipe );
     221           0 :     return ( pipe ? pipe->getConfig() : 0 );
     222             : }
     223         194 : Config* Window::getConfig()
     224             : {
     225         194 :     Pipe* pipe = getPipe();
     226         194 :     LBASSERT( pipe );
     227         194 :     return ( pipe ? pipe->getConfig() : 0 );
     228             : }
     229             : 
     230           0 : ClientPtr Window::getClient()
     231             : {
     232           0 :     Pipe* pipe = getPipe();
     233           0 :     LBASSERT( pipe );
     234           0 :     return ( pipe ? pipe->getClient() : 0 );
     235             : }
     236             : 
     237          27 : ServerPtr Window::getServer()
     238             : {
     239          27 :     Pipe* pipe = getPipe();
     240          27 :     LBASSERT( pipe );
     241          27 :     return ( pipe ? pipe->getServer() : 0 );
     242             : }
     243             : 
     244             : //======================================================================
     245             : // pipe-thread methods
     246             : //======================================================================
     247             : 
     248             : //----------------------------------------------------------------------
     249             : // render context
     250             : //----------------------------------------------------------------------
     251          28 : void Window::_addRenderContext( const RenderContext& context )
     252             : {
     253          28 :     LB_TS_THREAD( _pipeThread );
     254          28 :     _renderContexts[BACK].push_back( context );
     255          28 : }
     256             : 
     257           0 : bool Window::getRenderContext( const int32_t x, const int32_t y,
     258             :                                RenderContext& context ) const
     259             : {
     260           0 :     LB_TS_THREAD( _pipeThread );
     261           0 :     if( !_systemWindow )
     262           0 :         return false;
     263             : 
     264           0 :     const DrawableConfig& drawableConfig = getDrawableConfig();
     265           0 :     const unsigned which = drawableConfig.doublebuffered ? FRONT : BACK;
     266             : 
     267             :     std::vector< RenderContext >::const_reverse_iterator i   =
     268           0 :         _renderContexts[which].rbegin();
     269             :     std::vector< RenderContext >::const_reverse_iterator end =
     270           0 :         _renderContexts[which].rend();
     271             : 
     272             :     // invert y to follow GL convention
     273           0 :     const int32_t glY = getPixelViewport().h - y;
     274             : 
     275           0 :     for( ; i != end; ++i )
     276             :     {
     277           0 :         const RenderContext& candidate = *i;
     278           0 :         if( candidate.pvp.isInside( x, glY ))
     279             :         {
     280           0 :             context = candidate;
     281           0 :             return true;
     282             :         }
     283             :     }
     284           0 :     return false;
     285             : }
     286             : 
     287         285 : void Window::setSharedContextWindow( const Window* sharedContextWindow )
     288             : {
     289         285 :     _sharedContextWindow = sharedContextWindow;
     290         285 : }
     291             : 
     292          15 : const Window* Window::getSharedContextWindow() const
     293             : {
     294          15 :     return _sharedContextWindow;
     295             : }
     296             : 
     297           0 : uint32_t Window::getColorFormat() const
     298             : {
     299           0 :     return getSettings().getColorFormat();
     300             : }
     301             : 
     302           7 : void Window::flush() const
     303             : {
     304           7 :     LBASSERT( _systemWindow );
     305           7 :     if( _systemWindow )
     306           7 :         _systemWindow->flush();
     307           7 : }
     308             : 
     309          74 : void Window::finish() const
     310             : {
     311          74 :     LBASSERT( _systemWindow );
     312          74 :     if( _systemWindow )
     313          74 :         _systemWindow->finish();
     314          74 : }
     315             : 
     316          15 : void Window::setSystemWindow( SystemWindow* window )
     317             : {
     318          15 :     _systemWindow = window;
     319             : 
     320          15 :     if( !window )
     321          15 :         return;
     322             : 
     323             :     // Initialize context-specific data
     324          15 :     makeCurrent();
     325          15 :     DrawableConfig config;
     326          15 :     _systemWindow->queryDrawableConfig( config );
     327          15 :     _setDrawableConfig( config );
     328          15 :     _setupObjectManager();
     329             : }
     330             : 
     331           0 : const SystemPipe* Window::getSystemPipe() const
     332             : {
     333           0 :     const Pipe* pipe = getPipe();
     334           0 :     LBASSERT( pipe );
     335           0 :     return pipe->getSystemPipe();
     336             : }
     337             : 
     338           0 : SystemPipe* Window::getSystemPipe()
     339             : {
     340           0 :     Pipe* pipe = getPipe();
     341           0 :     LBASSERT( pipe );
     342           0 :     return pipe->getSystemPipe();
     343             : }
     344             : 
     345           7 : void Window::frameStart( const uint128_t&, const uint32_t frameNumber )
     346             : {
     347           7 :     startFrame( frameNumber );
     348           7 : }
     349             : 
     350           7 : void Window::frameDrawFinish( const uint128_t&, const uint32_t frameNumber )
     351             : {
     352           7 :     releaseFrameLocal( frameNumber );
     353             : 
     354             :     // https://github.com/Eyescale/Equalizer/issues/95
     355           7 :     if( getNode()->getPipes().size() > 1 )
     356           4 :         finish();
     357           7 : }
     358             : 
     359           7 : void Window::frameFinish( const uint128_t&, const uint32_t frameNumber )
     360             : {
     361           7 :     releaseFrame( frameNumber );
     362           7 :     flush();
     363           7 :     _updateFPS();
     364           7 : }
     365             : 
     366           7 : void Window::startFrame( const uint32_t ) { /* currently nop */ }
     367           7 : void Window::releaseFrame( const uint32_t ) { /* currently nop */ }
     368           7 : void Window::releaseFrameLocal( const uint32_t ) { /* nop */ }
     369             : 
     370             : //----------------------------------------------------------------------
     371             : // configInit
     372             : //----------------------------------------------------------------------
     373          15 : bool Window::configInit( const uint128_t& initID )
     374             : {
     375          15 :     if( !getPixelViewport().isValid( ))
     376             :     {
     377           0 :         sendError( ERROR_WINDOW_PVP_INVALID );
     378           0 :         return false;
     379             :     }
     380             : 
     381          15 :     LBASSERT( !_systemWindow );
     382             : 
     383          15 :     return configInitSystemWindow( initID ) && configInitGL( initID );
     384             : }
     385             : 
     386          15 : bool Window::configInitSystemWindow( const uint128_t& )
     387             : {
     388          15 :     const Pipe* pipe = getPipe();
     389          15 :     WindowSettings settings = getSettings();
     390             :     const SystemWindow* sysWindow = _sharedContextWindow ?
     391          15 :                                     _sharedContextWindow->getSystemWindow() : 0;
     392          15 :     settings.setSharedContextWindow( sysWindow );
     393             :     SystemWindow* systemWindow =
     394          15 :         pipe->getWindowSystem().createWindow( this, settings );
     395             : 
     396          15 :     LBASSERT( systemWindow );
     397          15 :     if( !systemWindow->configInit( ))
     398             :     {
     399           0 :         LBWARN << "System window initialization failed" << std::endl;
     400           0 :         delete systemWindow;
     401           0 :         return false;
     402             :     }
     403             : 
     404          15 :     setPixelViewport( systemWindow->getPixelViewport( ));
     405          15 :     setSystemWindow( systemWindow );
     406          15 :     return true;
     407             : }
     408             : 
     409          15 : void Window::_setupObjectManager()
     410             : {
     411          15 :     if( !glewGetContext( ))
     412          15 :         return;
     413             : 
     414          15 :     _releaseObjectManager();
     415             : 
     416          15 :     const Window* sharedWindow = getSharedContextWindow();
     417          15 :     if( sharedWindow && sharedWindow != this )
     418           0 :         _objectManager = sharedWindow->_objectManager;
     419             :     else
     420             :     {
     421          15 :         util::ObjectManager om( glewGetContext( ));
     422          15 :         _objectManager = om;
     423             :     }
     424             : }
     425             : 
     426          30 : void Window::_releaseObjectManager()
     427             : {
     428          30 :     _objectManager.deleteEqBitmapFont( _smallFontKey );
     429          30 :     _objectManager.deleteEqBitmapFont( _mediumFontKey );
     430          30 :     if( !_objectManager.isShared( ))
     431          30 :         _objectManager.deleteAll();
     432          30 :     _objectManager.clear();
     433          30 : }
     434             : 
     435           0 : const util::BitmapFont* Window::getSmallFont()
     436             : {
     437           0 :     util::BitmapFont* font = _objectManager.getEqBitmapFont( _smallFontKey );
     438           0 :     if( !font )
     439             :     {
     440           0 :         font = _objectManager.newEqBitmapFont( _smallFontKey );
     441           0 :         font->init( getPipe()->getWindowSystem(), "" );
     442             :     }
     443           0 :     return font;
     444             : }
     445             : 
     446           0 : const util::BitmapFont* Window::getMediumFont()
     447             : {
     448           0 :     util::BitmapFont* font = _objectManager.getEqBitmapFont( _mediumFontKey );
     449           0 :     if( !font )
     450             :     {
     451           0 :         font = _objectManager.newEqBitmapFont( _mediumFontKey );
     452           0 :         font->init( getPipe()->getWindowSystem(), "", 20 );
     453             :     }
     454           0 :     return font;
     455             : }
     456             : 
     457          15 : bool Window::configInitGL( const uint128_t& )
     458             : {
     459          15 :     glEnable( GL_SCISSOR_TEST ); // needed to constrain channel viewport
     460          15 :     glEnable( GL_DEPTH_TEST );
     461          15 :     glDepthFunc( GL_LESS );
     462             : 
     463          15 :     glEnable( GL_LIGHTING );
     464          15 :     glEnable( GL_LIGHT0 );
     465             : 
     466          15 :     glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
     467          15 :     glEnable( GL_COLOR_MATERIAL );
     468             : 
     469          15 :     glClearDepth( 1.f );
     470             : 
     471          15 :     glClear( GL_COLOR_BUFFER_BIT );
     472          15 :     swapBuffers();
     473          15 :     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
     474             : 
     475          15 :     return true;
     476             : }
     477             : 
     478           2 : bool Window::createTransferWindow()
     479             : {
     480           2 :     LBASSERT( _systemWindow );
     481             : 
     482           2 :     if( _transferWindow )
     483           0 :         return true;
     484             : 
     485             :     // create another (shared) osWindow with no drawable
     486           2 :     WindowSettings settings = getSettings();
     487           2 :     settings.setIAttribute( WindowSettings::IATTR_HINT_DRAWABLE, OFF );
     488             :     const SystemWindow* sysWindow = _sharedContextWindow ?
     489           2 :                                     _sharedContextWindow->getSystemWindow() : 0;
     490           2 :     settings.setSharedContextWindow( sysWindow );
     491           2 :     const Pipe* pipe = getPipe();
     492           2 :     _transferWindow = pipe->getWindowSystem().createWindow( this, settings );
     493             : 
     494           2 :     if( _transferWindow )
     495             :     {
     496           2 :         if( !_transferWindow->configInit( ))
     497             :         {
     498           0 :             LBWARN << "Transfer window initialization failed" << std::endl;
     499           0 :             delete _transferWindow;
     500           0 :             _transferWindow = 0;
     501             :         }
     502             :         else
     503           2 :             makeCurrentTransfer(); // #177
     504             :     }
     505             :     else
     506           0 :         LBERROR << "Window system " << pipe->getWindowSystem()
     507           0 :                 << " not implemented or supported" << std::endl;
     508             : 
     509           2 :     makeCurrent();
     510             : 
     511           2 :     LBVERB << "Transfer window initialization finished" << std::endl;
     512           2 :     return _transferWindow != 0;
     513             : }
     514             : 
     515           2 : const GLEWContext* Window::getTransferGlewContext()
     516             : {
     517           2 :     LBASSERT( _transferWindow );
     518           2 :     if( _transferWindow )
     519           2 :         return _transferWindow->glewGetContext();
     520           0 :     return 0;
     521             : }
     522             : 
     523           4 : void Window::makeCurrentTransfer( const bool useCache ) const
     524             : {
     525           4 :     LBASSERT( _transferWindow );
     526           4 :     if( _transferWindow )
     527           4 :         _transferWindow->makeCurrent( useCache );
     528           4 : }
     529             : 
     530             : 
     531           2 : void Window::deleteTransferSystemWindow()
     532             : {
     533           2 :     if( !_transferWindow )
     534           2 :         return;
     535             : 
     536           2 :     _transferWindow->configExit();
     537           2 :     delete _transferWindow;
     538           2 :     _transferWindow = 0;
     539             : }
     540             : 
     541             : //----------------------------------------------------------------------
     542             : // configExit
     543             : //----------------------------------------------------------------------
     544          15 : bool Window::configExit()
     545             : {
     546          15 :     if( !_systemWindow )
     547           0 :         return true;
     548             : 
     549          15 :     const bool ret = configExitGL();
     550          15 :     return configExitSystemWindow() && ret;
     551             : }
     552             : 
     553          15 : bool Window::configExitSystemWindow()
     554             : {
     555             :     // _transferWindow has to be deleted from the same thread it was
     556             :     // initialized
     557          15 :     LBASSERT( !_transferWindow );
     558             : 
     559          15 :     _releaseObjectManager();
     560             : 
     561          15 :     if( _systemWindow )
     562             :     {
     563          15 :         _systemWindow->configExit( );
     564             : 
     565          15 :         delete _systemWindow;
     566          15 :         _systemWindow = 0;
     567             :     }
     568          15 :     return true;
     569             : }
     570             : 
     571          50 : void Window::makeCurrent( const bool useCache ) const
     572             : {
     573          50 :     _systemWindow->makeCurrent( useCache );
     574             :     // _pipe->setCurrent done by SystemWindow::makeCurrent
     575          50 : }
     576             : 
     577          15 : void Window::bindFrameBuffer() const
     578             : {
     579          15 :     _systemWindow->bindFrameBuffer( );
     580          15 : }
     581             : 
     582          19 : void Window::swapBuffers()
     583             : {
     584          19 :     _systemWindow->swapBuffers();
     585          19 :     LBLOG( co::LOG_BARRIER ) << "Swap buffers done" << getName() << std::endl;
     586          19 : }
     587             : 
     588          43 : const GLEWContext* Window::glewGetContext() const
     589             : {
     590          43 :     return _systemWindow ? _systemWindow->glewGetContext() : 0;
     591             : }
     592             : 
     593           0 : void Window::_enterBarrier( co::ObjectVersion barrier )
     594             : {
     595           0 :     LBLOG( co::LOG_BARRIER ) << "swap barrier " << barrier << " " << getName()
     596           0 :                              << std::endl;
     597           0 :     Node* node = getNode();
     598           0 :     co::Barrier* netBarrier = node->getBarrier( barrier );
     599           0 :     if( !netBarrier )
     600           0 :         return;
     601             : 
     602           0 :     WindowStatistics stat( Statistic::WINDOW_SWAP_BARRIER, this );
     603           0 :     Config* config = getConfig();
     604           0 :     const uint32_t timeout = config->getTimeout()/2;
     605             :     try
     606             :     {
     607           0 :         netBarrier->enter( timeout );
     608             :     }
     609             :     catch( const co::Exception& e )
     610             :     {
     611             :         LBWARN << e.what() << " for " << *netBarrier << std::endl;
     612           0 :     }
     613             : }
     614             : 
     615          15 : void Window::_updateEvent( Event& event )
     616             : {
     617             :     // TODO 2.0 event interface will stream these and remove them from Event
     618          15 :     event.time = getConfig()->getTime();
     619          15 :     event.originator = getID();
     620          15 :     event.serial = getSerial();
     621             : 
     622          15 :     switch( event.type )
     623             :     {
     624             :         case Event::WINDOW_POINTER_MOTION:
     625             :         case Event::WINDOW_POINTER_BUTTON_PRESS:
     626             :         case Event::WINDOW_POINTER_BUTTON_RELEASE:
     627             :         case Event::WINDOW_POINTER_WHEEL:
     628             :         {
     629           0 :             const int32_t xPos = event.pointer.x;
     630           0 :             const int32_t yPos = event.pointer.y;
     631             : 
     632           0 :             if( !getRenderContext( xPos, yPos, event.context ))
     633           0 :                 LBVERB << "No rendering context for pointer event at "
     634           0 :                        << xPos << ", " << yPos << std::endl;
     635             :         }
     636             :     }
     637          15 : }
     638             : 
     639             : 
     640             : //======================================================================
     641             : // event methods
     642             : //======================================================================
     643             : 
     644           6 : EventOCommand Window::sendError( const uint32_t error )
     645             : {
     646           6 :     return getConfig()->sendError( Event::WINDOW_ERROR, getID(), error );
     647             : }
     648             : 
     649          15 : bool Window::processEvent( const Event& event )
     650             : {
     651             :     // see comment in _updateEvent
     652          15 :     _updateEvent( const_cast< Event& >( event ));
     653             : 
     654          15 :     switch( event.type )
     655             :     {
     656             :         case Event::WINDOW_HIDE:
     657           0 :             setPixelViewport( PixelViewport( 0, 0, 0, 0 ));
     658           0 :             break;
     659             : 
     660             :         case Event::WINDOW_SHOW:
     661             :         case Event::WINDOW_RESIZE:
     662             :             setPixelViewport( PixelViewport( event.resize.x, event.resize.y,
     663           6 :                                              event.resize.w, event.resize.h ));
     664           6 :             break;
     665             : 
     666             :         case Event::KEY_PRESS:
     667             :         case Event::KEY_RELEASE:
     668           0 :             if( event.key.key == KC_VOID )
     669           0 :                 return true; // ignore
     670             :             // else fall through
     671             :         case Event::WINDOW_EXPOSE:
     672             :         case Event::WINDOW_CLOSE:
     673             :         case Event::STATISTIC:
     674             :         case Event::MAGELLAN_AXIS:
     675             :         case Event::MAGELLAN_BUTTON:
     676           5 :             break;
     677             : 
     678             :         case Event::WINDOW_POINTER_GRAB:
     679           0 :             _grabbedChannels = _getEventChannels( event.pointer );
     680           0 :             break;
     681             :         case Event::WINDOW_POINTER_UNGRAB:
     682           0 :             _grabbedChannels.clear();
     683           0 :             break;
     684             : 
     685             :         case Event::WINDOW_POINTER_MOTION:
     686             :         case Event::WINDOW_POINTER_BUTTON_PRESS:
     687             :         case Event::WINDOW_POINTER_BUTTON_RELEASE:
     688             :         case Event::WINDOW_POINTER_WHEEL:
     689             :         {
     690           0 :             const Channels& channels = _getEventChannels( event.pointer );
     691           0 :             for( Channels::const_iterator i = channels.begin();
     692           0 :                  i != channels.end(); ++i )
     693             :             {
     694           0 :                 Channel* channel = *i;
     695           0 :                 Event channelEvent = event;
     696           0 :                 switch( event.type )
     697             :                 {
     698             :                   case Event::WINDOW_POINTER_MOTION:
     699           0 :                     channelEvent.type = Event::CHANNEL_POINTER_MOTION;
     700           0 :                     break;
     701             :                   case Event::WINDOW_POINTER_BUTTON_PRESS:
     702           0 :                     channelEvent.type = Event::CHANNEL_POINTER_BUTTON_PRESS;
     703           0 :                     break;
     704             :                   case Event::WINDOW_POINTER_BUTTON_RELEASE:
     705           0 :                     channelEvent.type = Event::CHANNEL_POINTER_BUTTON_RELEASE;
     706           0 :                     break;
     707             :                   case Event::WINDOW_POINTER_WHEEL:
     708           0 :                     channelEvent.type = Event::CHANNEL_POINTER_WHEEL;
     709           0 :                     break;
     710             :                   default:
     711           0 :                     LBWARN << "Unhandled window event of type " << event.type
     712           0 :                            << std::endl;
     713           0 :                     LBUNIMPLEMENTED;
     714             :                 }
     715             : 
     716             :                 // convert y to GL notation (Channel PVP uses GL coordinates)
     717           0 :                 const PixelViewport& pvp = getPixelViewport();
     718           0 :                 const int32_t y = pvp.h - event.pointer.y;
     719             :                 const PixelViewport& channelPVP =
     720           0 :                     channel->getNativePixelViewport();
     721             : 
     722           0 :                 channelEvent.originator = channel->getID();
     723           0 :                 channelEvent.serial = channel->getSerial();
     724           0 :                 channelEvent.pointer.x -= channelPVP.x;
     725           0 :                 channelEvent.pointer.y = channelPVP.h - y + channelPVP.y;
     726           0 :                 channel->processEvent( channelEvent );
     727           0 :             }
     728           0 :             break;
     729             :         }
     730             : 
     731             :         case Event::WINDOW_SCREENSAVER:
     732           0 :             switch( getIAttribute( WindowSettings::IATTR_HINT_SCREENSAVER ))
     733             :             {
     734             :                 case OFF:
     735           0 :                     return true; // screen saver stays inactive
     736             :                 case ON:
     737           0 :                     return false; // screen saver becomes active
     738             :                 default: // AUTO
     739           0 :                     if( getDrawableConfig().doublebuffered &&
     740           0 :                         getIAttribute( WindowSettings::IATTR_HINT_DRAWABLE ) == WINDOW )
     741             :                     {
     742           0 :                         return true; // screen saver stays inactive
     743             :                     }
     744           0 :                     return false;
     745             :             }
     746             : 
     747             :         case Event::UNKNOWN:
     748             :             // unknown window-system native event, which was not handled
     749           4 :             return false;
     750             : 
     751             :         default:
     752           0 :             LBWARN << "Unhandled window event of type " << event.type
     753           0 :                    << std::endl;
     754           0 :             LBUNIMPLEMENTED;
     755             :     }
     756             : 
     757          11 :     Config* config = getConfig();
     758          11 :     ConfigEvent configEvent;
     759          11 :     configEvent.data = event;
     760          11 :     config->sendEvent( configEvent );
     761          11 :     return true;
     762             : }
     763             : 
     764           0 : Channels Window::_getEventChannels( const PointerEvent& event )
     765             : {
     766           0 :     if( !_grabbedChannels.empty( ))
     767           0 :         return _grabbedChannels;
     768             : 
     769           0 :     Channels result;
     770           0 :     const Channels& channels = getChannels();
     771           0 :     for( ChannelsCIter i = channels.begin(); i != channels.end(); ++i )
     772             :     {
     773           0 :         Channel* channel = *i;
     774           0 :         if( !channel->isDestination( ))
     775           0 :             continue;
     776             : 
     777           0 :         const PixelViewport& pvp = getPixelViewport();
     778           0 :         const PixelViewport& channelPVP = channel->getNativePixelViewport();
     779             : 
     780             :         // convert y to GL notation (Channel PVP uses GL coordinates)
     781           0 :         const int32_t y = pvp.h - event.y;
     782             : 
     783           0 :         if( channelPVP.isInside( event.x, y ))
     784           0 :             result.push_back( channel );
     785             :     }
     786           0 :     return result;
     787             : }
     788             : 
     789             : //---------------------------------------------------------------------------
     790             : // command handlers
     791             : //---------------------------------------------------------------------------
     792          15 : bool Window::_cmdCreateChannel( co::ICommand& cmd )
     793             : {
     794          15 :     co::ObjectICommand command( cmd );
     795          15 :     const uint128_t& channelID = command.read< uint128_t >();
     796             : 
     797          15 :     LBLOG( LOG_INIT ) << "Create channel " << command  << " id " << channelID
     798          15 :                       << std::endl;
     799             : 
     800          15 :     Channel* channel = Global::getNodeFactory()->createChannel( this );
     801          15 :     channel->init(); // not in ctor, virtual method
     802             : 
     803          15 :     Config* config = getConfig();
     804          15 :     LBCHECK( config->mapObject( channel, channelID ));
     805          15 :     LBASSERT( channel->getSerial() != CO_INSTANCE_INVALID );
     806             : 
     807          15 :     return true;
     808             : }
     809             : 
     810          15 : bool Window::_cmdDestroyChannel( co::ICommand& cmd )
     811             : {
     812          15 :     co::ObjectICommand command( cmd );
     813          15 :     LBLOG( LOG_INIT ) << "Destroy channel " << command << std::endl;
     814             : 
     815          15 :     Channel* channel = _findChannel( command.read< uint128_t >( ));
     816          15 :     LBASSERT( channel );
     817             : 
     818          15 :     const bool stopped = channel->isStopped();
     819          15 :     Config* config = getConfig();
     820          15 :     config->unmapObject( channel );
     821             :     channel->send( getServer(), fabric::CMD_CHANNEL_CONFIG_EXIT_REPLY )
     822          15 :         << stopped;
     823          15 :     Global::getNodeFactory()->releaseChannel( channel );
     824             : 
     825          15 :     return true;
     826             : }
     827             : 
     828          15 : bool Window::_cmdConfigInit( co::ICommand& cmd )
     829             : {
     830          15 :     co::ObjectICommand command( cmd );
     831             : 
     832          15 :     LBLOG( LOG_INIT ) << "TASK window config init " << command << std::endl;
     833             : 
     834          15 :     bool result = false;
     835          15 :     if( getPipe()->isRunning( ))
     836             :     {
     837          15 :         _state = STATE_INITIALIZING;
     838          15 :         result = configInit( command.read< uint128_t >( ));
     839          15 :         if( result )
     840          15 :             _state = STATE_RUNNING;
     841             :     }
     842             :     else
     843           0 :         sendError( ERROR_WINDOW_PIPE_NOTRUNNING );
     844             : 
     845          15 :     LBLOG( LOG_INIT ) << "TASK window config init reply " << std::endl;
     846             : 
     847          15 :     commit();
     848          15 :     send( command.getRemoteNode(), fabric::CMD_WINDOW_CONFIG_INIT_REPLY ) << result;
     849          15 :     return true;
     850             : }
     851             : 
     852          15 : bool Window::_cmdConfigExit( co::ICommand& cmd )
     853             : {
     854          15 :     co::ObjectICommand command( cmd );
     855             : 
     856          15 :     LBLOG( LOG_INIT ) << "TASK window config exit " << command << std::endl;
     857             : 
     858          15 :     if( _state != STATE_STOPPED )
     859             :     {
     860          15 :         if( getPipe()->isRunning( ) && _systemWindow )
     861             :         {
     862          15 :             makeCurrent();
     863          15 :             getPipe()->flushFrames( _objectManager );
     864             :         }
     865             :         // else emergency exit, no context available.
     866             : 
     867          15 :         _state = configExit() ? STATE_STOPPED : STATE_FAILED;
     868             :     }
     869             : 
     870          15 :     getPipe()->send( getLocalNode(),
     871          30 :                      fabric::CMD_PIPE_DESTROY_WINDOW ) << getID();
     872          15 :     return true;
     873             : }
     874             : 
     875           7 : bool Window::_cmdFrameStart( co::ICommand& cmd )
     876             : {
     877           7 :     co::ObjectICommand command( cmd );
     878             : 
     879           7 :     LB_TS_THREAD( _pipeThread );
     880             : 
     881           7 :     const uint128_t& version = command.read< uint128_t >();
     882           7 :     const uint128_t& frameID = command.read< uint128_t >();
     883           7 :     const uint32_t frameNumber = command.read< uint32_t >();
     884             : 
     885           7 :     LBLOG( LOG_TASKS ) << "TASK frame start " << getName()
     886           0 :                        << " " << command << " frame " << frameNumber
     887           7 :                        << " id " << frameID << std::endl;
     888             : 
     889             :     //_grabFrame( frameNumber ); single-threaded
     890           7 :     sync( version );
     891             : 
     892           7 :     const DrawableConfig& drawableConfig = getDrawableConfig();
     893           7 :     if( drawableConfig.doublebuffered )
     894           4 :         _renderContexts[FRONT].swap( _renderContexts[BACK] );
     895           7 :     _renderContexts[BACK].clear();
     896             : 
     897           7 :     makeCurrent();
     898           7 :     frameStart( frameID, frameNumber );
     899           7 :     return true;
     900             : }
     901             : 
     902           7 : bool Window::_cmdFrameFinish( co::ICommand& cmd )
     903             : {
     904           7 :     co::ObjectICommand command( cmd );
     905             : 
     906           7 :     LBVERB << "handle window frame sync " << command << std::endl;
     907             : 
     908           7 :     const uint128_t& frameID = command.read< uint128_t >();
     909           7 :     const uint32_t frameNumber = command.read< uint32_t >();
     910             : 
     911           7 :     makeCurrent();
     912           7 :     frameFinish( frameID, frameNumber );
     913           7 :     return true;
     914             : }
     915             : 
     916           0 : bool Window::_cmdFlush( co::ICommand& )
     917             : {
     918           0 :     flush();
     919           0 :     return true;
     920             : }
     921             : 
     922           0 : bool Window::_cmdFinish( co::ICommand& )
     923             : {
     924           0 :     WindowStatistics stat( Statistic::WINDOW_FINISH, this );
     925           0 :     makeCurrent();
     926           0 :     finish();
     927           0 :     return true;
     928             : }
     929             : 
     930           0 : bool  Window::_cmdThrottleFramerate( co::ICommand& cmd )
     931             : {
     932           0 :     co::ObjectICommand command( cmd );
     933             : 
     934           0 :     LBLOG( LOG_TASKS ) << "TASK throttle framerate " << getName() << " "
     935           0 :                        << command << std::endl;
     936             : 
     937             :     // throttle to given framerate
     938           0 :     const int64_t elapsed  = getConfig()->getTime() - _lastSwapTime;
     939           0 :     const float minFrameTime = command.read< float >();
     940           0 :     const float timeLeft = minFrameTime - static_cast<float>( elapsed );
     941             : 
     942           0 :     if( timeLeft >= 1.f )
     943             :     {
     944           0 :         WindowStatistics stat( Statistic::WINDOW_THROTTLE_FRAMERATE, this );
     945           0 :         lunchbox::sleep( static_cast< uint32_t >( timeLeft ));
     946             :     }
     947             : 
     948           0 :     _lastSwapTime = getConfig()->getTime();
     949           0 :     return true;
     950             : }
     951             : 
     952           0 : bool Window::_cmdBarrier( co::ICommand& cmd )
     953             : {
     954           0 :     co::ObjectICommand command( cmd );
     955           0 :     const co::ObjectVersion& barrier = command.read< co::ObjectVersion >();
     956             : 
     957           0 :     LBVERB << "handle barrier " << command << " barrier " << barrier << std::endl;
     958           0 :     LBLOG( LOG_TASKS ) << "TASK swap barrier  " << getName() << std::endl;
     959             : 
     960           0 :     _enterBarrier( barrier );
     961           0 :     return true;
     962             : }
     963             : 
     964           0 : bool Window::_cmdNVBarrier( co::ICommand& cmd )
     965             : {
     966           0 :     co::ObjectICommand command( cmd );
     967             : 
     968           0 :     LBLOG( LOG_TASKS ) << "TASK join NV_swap_group" << std::endl;
     969           0 :     LBASSERT( _systemWindow );
     970             : 
     971           0 :     const co::ObjectVersion& netBarrier = command.read< co::ObjectVersion >();
     972           0 :     const uint32_t group = command.read< uint32_t >();
     973           0 :     const uint32_t barrier = command.read< uint32_t >();
     974             : 
     975           0 :     makeCurrent();
     976           0 :     _systemWindow->joinNVSwapBarrier( group, barrier );
     977           0 :     _enterBarrier( netBarrier );
     978           0 :     return true;
     979             : }
     980             : 
     981           7 : bool Window::_cmdSwap( co::ICommand& cmd )
     982             : {
     983           7 :     co::ObjectICommand command( cmd );
     984             : 
     985           7 :     LBLOG( LOG_TASKS ) << "TASK swap buffers " << getName() << " " << command
     986           7 :                        << std::endl;
     987             : 
     988           7 :     if( getDrawableConfig().doublebuffered )
     989             :     {
     990             :         // swap
     991           4 :         WindowStatistics stat( Statistic::WINDOW_SWAP, this );
     992           4 :         makeCurrent();
     993           4 :         swapBuffers();
     994             :     }
     995           7 :     return true;
     996             : }
     997             : 
     998           7 : bool Window::_cmdFrameDrawFinish( co::ICommand& cmd )
     999             : {
    1000           7 :     co::ObjectICommand command( cmd );
    1001           7 :     const uint128_t& frameID = command.read< uint128_t >();
    1002           7 :     const uint32_t frameNumber = command.read< uint32_t >();
    1003             : 
    1004           7 :     LBLOG( LOG_TASKS ) << "TASK draw finish " << getName() <<  " " << command
    1005           0 :                        << " frame " << frameNumber << " id " << frameID
    1006           7 :                        << std::endl;
    1007             : 
    1008           7 :     frameDrawFinish( frameID, frameNumber );
    1009           7 :     return true;
    1010             : }
    1011             : 
    1012             : }
    1013             : 
    1014             : #include "../fabric/window.ipp"
    1015             : template class eq::fabric::Window< eq::Pipe, eq::Window, eq::Channel,
    1016             :                                    eq::WindowSettings >;
    1017             : 
    1018             : /** @cond IGNORE */
    1019             : template EQFABRIC_API std::ostream& eq::fabric::operator << ( std::ostream&,
    1020          36 :                                                  const eq::Super& );
    1021             : /** @endcond */

Generated by: LCOV version 1.10