LCOV - code coverage report
Current view: top level - eq - window.cpp (source / functions) Hit Total Coverage
Test: Equalizer Lines: 341 583 58.5 %
Date: 2017-12-16 05:07:20 Functions: 53 79 67.1 %

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

Generated by: LCOV version 1.11