LCOV - code coverage report
Current view: top level - eq - window.cpp (source / functions) Hit Total Coverage
Test: Equalizer Lines: 91 540 16.9 %
Date: 2016-07-30 05:04:55 Functions: 18 73 24.7 %

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

Generated by: LCOV version 1.11