LCOV - code coverage report
Current view: top level - eq/fabric - pipe.ipp (source / functions) Hit Total Coverage
Test: Equalizer Lines: 166 212 78.3 %
Date: 2017-12-16 05:07:20 Functions: 36 91 39.6 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2010-2016, Stefan Eilemann <eile@equalizergraphics.com>
       3             :  *                          Daniel Nachbaur <danielnachbaur@gmail.com>
       4             :  *                          Cedric Stalder <cedric.stalder@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 "pipe.h"
      21             : 
      22             : #include "commands.h"
      23             : #include "elementVisitor.h"
      24             : #include "leafVisitor.h"
      25             : #include "log.h"
      26             : #include "task.h"
      27             : 
      28             : #include <co/dataIStream.h>
      29             : #include <co/dataOStream.h>
      30             : #include <co/objectICommand.h>
      31             : 
      32             : namespace eq
      33             : {
      34             : namespace fabric
      35             : {
      36             : namespace
      37             : {
      38             : #define MAKE_PIPE_ATTR_STRING(attr) (std::string("EQ_PIPE_") + #attr)
      39         100 : std::string _iPipeAttributeStrings[] = {
      40         100 :     MAKE_PIPE_ATTR_STRING(IATTR_HINT_THREAD),
      41         100 :     MAKE_PIPE_ATTR_STRING(IATTR_HINT_AFFINITY),
      42         250 : };
      43             : }
      44             : 
      45             : template <class N, class P, class W, class V>
      46        1152 : Pipe<N, P, W, V>::Pipe(N* parent)
      47             :     : _node(parent)
      48             :     , _port(LB_UNDEFINED_UINT32)
      49        1152 :     , _device(LB_UNDEFINED_UINT32)
      50             : {
      51        1152 :     memset(_iAttributes, 0xff, IATTR_ALL * sizeof(int32_t));
      52        1152 :     parent->_addPipe(static_cast<P*>(this));
      53        1152 :     LBLOG(LOG_INIT) << "New " << lunchbox::className(this) << std::endl;
      54        1152 : }
      55             : 
      56             : template <class N, class P, class W, class V>
      57        1150 : Pipe<N, P, W, V>::~Pipe()
      58             : {
      59        1150 :     LBLOG(LOG_INIT) << "Delete " << lunchbox::className(this) << std::endl;
      60        4134 :     while (!_windows.empty())
      61             :     {
      62        1492 :         W* window = _windows.back();
      63        1492 :         _removeWindow(window);
      64        1492 :         delete window;
      65             :     }
      66        1150 :     _node->_removePipe(static_cast<P*>(this));
      67        2300 : }
      68             : 
      69             : template <class N, class P, class W, class V>
      70           4 : void Pipe<N, P, W, V>::backup()
      71             : {
      72           4 :     Object::backup();
      73           4 :     _backup = _data;
      74           4 : }
      75             : 
      76             : template <class N, class P, class W, class V>
      77           0 : void Pipe<N, P, W, V>::restore()
      78             : {
      79           0 :     _data = _backup;
      80           0 :     Object::restore();
      81           0 :     notifyPixelViewportChanged();
      82           0 :     setDirty(DIRTY_PIXELVIEWPORT);
      83           0 : }
      84             : 
      85             : template <class N, class P, class W, class V>
      86           6 : void Pipe<N, P, W, V>::attach(const uint128_t& id, const uint32_t instanceID)
      87             : {
      88           6 :     Object::attach(id, instanceID);
      89             : 
      90           6 :     co::CommandQueue* queue = _node->getConfig()->getMainThreadQueue();
      91           6 :     LBASSERT(queue);
      92             : 
      93           6 :     registerCommand(CMD_PIPE_NEW_WINDOW,
      94             :                     CmdFunc(this, &Pipe<N, P, W, V>::_cmdNewWindow), queue);
      95           6 :     registerCommand(CMD_PIPE_NEW_WINDOW_REPLY,
      96             :                     CmdFunc(this, &Pipe<N, P, W, V>::_cmdNewWindowReply), 0);
      97           6 : }
      98             : 
      99             : template <class N, class P, class W, class V>
     100          20 : uint128_t Pipe<N, P, W, V>::commit(const uint32_t incarnation)
     101             : {
     102          20 :     if (Serializable::isDirty(DIRTY_WINDOWS))
     103          16 :         commitChildren<W>(_windows, CMD_PIPE_NEW_WINDOW, incarnation);
     104          20 :     return Object::commit(incarnation);
     105             : }
     106             : 
     107             : template <class N, class P, class W, class V>
     108          18 : void Pipe<N, P, W, V>::serialize(co::DataOStream& os, const uint64_t dirtyBits)
     109             : {
     110          18 :     Object::serialize(os, dirtyBits);
     111          18 :     if (dirtyBits & DIRTY_ATTRIBUTES)
     112           4 :         os << co::Array<int32_t>(_iAttributes, IATTR_ALL);
     113          18 :     if (dirtyBits & DIRTY_WINDOWS && isMaster())
     114             :     {
     115          14 :         os << _mapNodeObjects();
     116          14 :         os.serializeChildren(_windows);
     117             :     }
     118          18 :     if (dirtyBits & DIRTY_PIXELVIEWPORT)
     119          10 :         os << _data.pvp;
     120          18 :     if (dirtyBits & DIRTY_MEMBER)
     121           4 :         os << _port << _device;
     122          18 : }
     123             : 
     124             : template <class N, class P, class W, class V>
     125          13 : void Pipe<N, P, W, V>::deserialize(co::DataIStream& is,
     126             :                                    const uint64_t dirtyBits)
     127             : {
     128          13 :     Object::deserialize(is, dirtyBits);
     129          13 :     if (dirtyBits & DIRTY_ATTRIBUTES)
     130           2 :         is >> co::Array<int32_t>(_iAttributes, IATTR_ALL);
     131          13 :     if (dirtyBits & DIRTY_WINDOWS)
     132             :     {
     133           9 :         if (isMaster())
     134           4 :             syncChildren(_windows);
     135             :         else
     136             :         {
     137           5 :             const bool useChildren = is.read<bool>();
     138           5 :             if (useChildren && _mapNodeObjects())
     139             :             {
     140           0 :                 Windows result;
     141           0 :                 is.deserializeChildren(this, _windows, result);
     142           0 :                 _windows.swap(result);
     143           0 :                 LBASSERT(_windows.size() == result.size());
     144             :             }
     145             :             else // consume unused ObjectVersions
     146           5 :                 is.read<co::ObjectVersions>();
     147             :         }
     148             :     }
     149          13 :     if (dirtyBits & DIRTY_PIXELVIEWPORT)
     150             :     {
     151           8 :         PixelViewport pvp;
     152           8 :         is >> pvp;
     153           8 :         setPixelViewport(pvp);
     154             :     }
     155          13 :     if (dirtyBits & DIRTY_MEMBER)
     156           2 :         is >> _port >> _device;
     157          13 : }
     158             : 
     159             : template <class N, class P, class W, class V>
     160       59328 : void Pipe<N, P, W, V>::setDirty(const uint64_t dirtyBits)
     161             : {
     162       59328 :     Object::setDirty(dirtyBits);
     163       59328 :     _node->setDirty(N::DIRTY_PIPES);
     164       59328 : }
     165             : 
     166             : template <class N, class P, class W, class V>
     167           6 : void Pipe<N, P, W, V>::notifyDetach()
     168             : {
     169           6 :     Object::notifyDetach();
     170           6 :     while (!_windows.empty())
     171             :     {
     172           4 :         W* window = _windows.back();
     173           4 :         if (!window->isAttached())
     174             :         {
     175           4 :             LBASSERT(isMaster());
     176           4 :             return;
     177             :         }
     178             : 
     179           0 :         LBASSERT(!isMaster());
     180             : 
     181           0 :         getLocalNode()->unmapObject(window);
     182           0 :         _removeWindow(window);
     183           0 :         _node->getServer()->getNodeFactory()->releaseWindow(window);
     184             :     }
     185             : }
     186             : 
     187             : template <class N, class P, class W, class V>
     188           0 : void Pipe<N, P, W, V>::create(W** window)
     189             : {
     190           0 :     *window = _node->getServer()->getNodeFactory()->createWindow(
     191             :         static_cast<P*>(this));
     192           0 :     (*window)->init(); // not in ctor, virtual method
     193           0 : }
     194             : 
     195             : template <class N, class P, class W, class V>
     196           0 : void Pipe<N, P, W, V>::release(W* window)
     197             : {
     198           0 :     _node->getServer()->getNodeFactory()->releaseWindow(window);
     199           0 : }
     200             : 
     201             : namespace
     202             : {
     203             : template <class P, class V>
     204       33356 : VisitorResult _accept(P* pipe, V& visitor)
     205             : {
     206       33356 :     VisitorResult result = visitor.visitPre(pipe);
     207       33356 :     if (result != TRAVERSE_CONTINUE)
     208           0 :         return result;
     209             : 
     210       33356 :     const typename P::Windows& windows = pipe->getWindows();
     211      197970 :     for (typename P::Windows::const_iterator i = windows.begin();
     212      131980 :          i != windows.end(); ++i)
     213             :     {
     214       38046 :         switch ((*i)->accept(visitor))
     215             :         {
     216             :         case TRAVERSE_TERMINATE:
     217        5412 :             return TRAVERSE_TERMINATE;
     218             : 
     219             :         case TRAVERSE_PRUNE:
     220           0 :             result = TRAVERSE_PRUNE;
     221           0 :             break;
     222             : 
     223             :         case TRAVERSE_CONTINUE:
     224             :         default:
     225       32634 :             break;
     226             :         }
     227             :     }
     228             : 
     229       27944 :     switch (visitor.visitPost(pipe))
     230             :     {
     231             :     case TRAVERSE_TERMINATE:
     232           0 :         return TRAVERSE_TERMINATE;
     233             : 
     234             :     case TRAVERSE_PRUNE:
     235           0 :         return TRAVERSE_PRUNE;
     236             : 
     237             :     case TRAVERSE_CONTINUE:
     238             :     default:
     239       27944 :         break;
     240             :     }
     241             : 
     242       27944 :     return result;
     243             : }
     244             : }
     245             : 
     246             : template <class N, class P, class W, class V>
     247       33356 : VisitorResult Pipe<N, P, W, V>::accept(V& visitor)
     248             : {
     249       33356 :     return _accept(static_cast<P*>(this), visitor);
     250             : }
     251             : 
     252             : template <class N, class P, class W, class V>
     253           0 : VisitorResult Pipe<N, P, W, V>::accept(V& visitor) const
     254             : {
     255           0 :     return _accept(static_cast<const P*>(this), visitor);
     256             : }
     257             : 
     258             : template <class N, class P, class W, class V>
     259           4 : PipePath Pipe<N, P, W, V>::getPath() const
     260             : {
     261           4 :     const N* node = getNode();
     262           4 :     LBASSERT(node);
     263           4 :     PipePath path(node->getPath());
     264             : 
     265           4 :     const typename std::vector<P*>& pipes = node->getPipes();
     266             :     typename std::vector<P*>::const_iterator i =
     267           4 :         std::find(pipes.begin(), pipes.end(), this);
     268           4 :     LBASSERT(i != pipes.end());
     269           4 :     path.pipeIndex = std::distance(pipes.begin(), i);
     270           4 :     return path;
     271             : }
     272             : 
     273             : template <class N, class P, class W, class V>
     274        2320 : void Pipe<N, P, W, V>::setIAttribute(const IAttribute attr, const int32_t value)
     275             : {
     276        2320 :     if (_iAttributes[attr] == value)
     277        1150 :         return;
     278             : 
     279        1170 :     _iAttributes[attr] = value;
     280        1170 :     setDirty(DIRTY_ATTRIBUTES);
     281             : }
     282             : 
     283             : template <class N, class P, class W, class V>
     284         128 : void Pipe<N, P, W, V>::setDevice(const uint32_t device)
     285             : {
     286         128 :     _device = device;
     287         128 :     setDirty(DIRTY_MEMBER);
     288         128 : }
     289             : 
     290             : template <class N, class P, class W, class V>
     291           4 : void Pipe<N, P, W, V>::setPort(const uint32_t port)
     292             : {
     293           4 :     _port = port;
     294           4 :     setDirty(DIRTY_MEMBER);
     295           4 : }
     296             : 
     297             : template <class N, class P, class W, class V>
     298        1496 : void Pipe<N, P, W, V>::_addWindow(W* window)
     299             : {
     300        1496 :     LBASSERT(window->getPipe() == this);
     301        1496 :     _windows.push_back(window);
     302        1496 :     setDirty(DIRTY_WINDOWS);
     303        1496 : }
     304             : 
     305             : template <class N, class P, class W, class V>
     306        2986 : bool Pipe<N, P, W, V>::_removeWindow(W* window)
     307             : {
     308             :     typename Windows::iterator i =
     309        2986 :         find(_windows.begin(), _windows.end(), window);
     310        2986 :     if (i == _windows.end())
     311        1492 :         return false;
     312             : 
     313        1494 :     _windows.erase(i);
     314        1494 :     setDirty(DIRTY_WINDOWS);
     315        1494 :     if (!isMaster())
     316        1494 :         postRemove(window);
     317        1494 :     return true;
     318             : }
     319             : 
     320             : template <class N, class P, class W, class V>
     321           2 : W* Pipe<N, P, W, V>::_findWindow(const uint128_t& id)
     322             : {
     323           6 :     for (typename Windows::const_iterator i = _windows.begin();
     324           4 :          i != _windows.end(); ++i)
     325             :     {
     326           2 :         W* window = *i;
     327           2 :         if (window->getID() == id)
     328           2 :             return window;
     329             :     }
     330           0 :     return 0;
     331             : }
     332             : 
     333             : template <class N, class P, class W, class V>
     334        1222 : const std::string& Pipe<N, P, W, V>::getIAttributeString(const IAttribute attr)
     335             : {
     336        1222 :     return _iPipeAttributeStrings[attr];
     337             : }
     338             : 
     339             : //----------------------------------------------------------------------
     340             : // viewport
     341             : //----------------------------------------------------------------------
     342             : template <class N, class P, class W, class V>
     343          12 : void Pipe<N, P, W, V>::setPixelViewport(const PixelViewport& pvp)
     344             : {
     345          12 :     if (pvp == _data.pvp || !pvp.hasArea())
     346           6 :         return;
     347             : 
     348           6 :     _data.pvp = pvp;
     349           6 :     notifyPixelViewportChanged();
     350           6 :     LBVERB << "Pipe pvp set: " << _data.pvp << std::endl;
     351             : }
     352             : 
     353             : template <class N, class P, class W, class V>
     354           6 : void Pipe<N, P, W, V>::notifyPixelViewportChanged()
     355             : {
     356           6 :     const Windows& windows = getWindows();
     357          18 :     for (typename Windows::const_iterator i = windows.begin();
     358          12 :          i != windows.end(); ++i)
     359             :     {
     360           0 :         (*i)->notifyViewportChanged();
     361             :     }
     362           6 :     setDirty(DIRTY_PIXELVIEWPORT);
     363           6 :     LBVERB << getName() << " pvp update: " << _data.pvp << std::endl;
     364           6 : }
     365             : 
     366             : //----------------------------------------------------------------------
     367             : // ICommand handlers
     368             : //----------------------------------------------------------------------
     369             : template <class N, class P, class W, class V>
     370           0 : bool Pipe<N, P, W, V>::_cmdNewWindow(co::ICommand& cmd)
     371             : {
     372           0 :     co::ObjectICommand command(cmd);
     373             : 
     374           0 :     W* window = 0;
     375           0 :     create(&window);
     376           0 :     LBASSERT(window);
     377             : 
     378           0 :     getLocalNode()->registerObject(window);
     379           0 :     LBASSERT(window->isAttached());
     380             : 
     381           0 :     send(command.getRemoteNode(), CMD_PIPE_NEW_WINDOW_REPLY)
     382           0 :         << command.read<uint32_t>() << window->getID();
     383             : 
     384           0 :     return true;
     385             : }
     386             : 
     387             : template <class N, class P, class W, class V>
     388           0 : bool Pipe<N, P, W, V>::_cmdNewWindowReply(co::ICommand& cmd)
     389             : {
     390           0 :     co::ObjectICommand command(cmd);
     391             : 
     392           0 :     const uint32_t requestID = command.read<uint32_t>();
     393           0 :     const uint128_t& result = command.read<uint128_t>();
     394             : 
     395           0 :     getLocalNode()->serveRequest(requestID, result);
     396             : 
     397           0 :     return true;
     398             : }
     399             : 
     400             : template <class N, class P, class W, class V>
     401         580 : std::ostream& operator<<(std::ostream& os, const Pipe<N, P, W, V>& pipe)
     402             : {
     403         580 :     os << lunchbox::disableFlush << lunchbox::disableHeader << "pipe"
     404             :        << std::endl;
     405         580 :     os << "{" << std::endl << lunchbox::indent;
     406             : 
     407         580 :     const std::string& name = pipe.getName();
     408         580 :     if (!name.empty())
     409          90 :         os << "name     \"" << name << "\"" << std::endl;
     410             : 
     411         580 :     if (pipe.getPort() != LB_UNDEFINED_UINT32)
     412           8 :         os << "port     " << pipe.getPort() << std::endl;
     413             : 
     414         580 :     if (pipe.getDevice() != LB_UNDEFINED_UINT32)
     415          70 :         os << "device   " << pipe.getDevice() << std::endl;
     416             : 
     417         580 :     const PixelViewport& pvp = pipe.getPixelViewport();
     418         580 :     if (pvp.hasArea())
     419           8 :         os << "viewport " << pvp << std::endl;
     420             : 
     421         580 :     pipe.output(os);
     422         580 :     os << std::endl;
     423             : 
     424         580 :     const typename P::Windows& windows = pipe.getWindows();
     425        3996 :     for (typename P::Windows::const_iterator i = windows.begin();
     426        2664 :          i != windows.end(); ++i)
     427             :     {
     428         752 :         os << **i;
     429             :     }
     430             : 
     431        1160 :     os << lunchbox::exdent << "}" << std::endl
     432         580 :        << lunchbox::enableHeader << lunchbox::enableFlush;
     433         580 :     return os;
     434             : }
     435             : }
     436             : }

Generated by: LCOV version 1.11