LCOV - code coverage report
Current view: top level - eq/fabric - layout.ipp (source / functions) Hit Total Coverage
Test: Equalizer Lines: 123 163 75.5 %
Date: 2017-12-16 05:07:20 Functions: 32 81 39.5 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2009-2017, Stefan Eilemann <eile@equalizergraphics.com>
       3             :  *                          Daniel Nachbaur <danielnachbaur@gmail.com>
       4             :  *
       5             :  * This library is free software; you can redistribute it and/or modify it under
       6             :  * the terms of the GNU Lesser General Public License version 2.1 as published
       7             :  * by the Free Software Foundation.
       8             :  *
       9             :  * This library is distributed in the hope that it will be useful, but WITHOUT
      10             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      11             :  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
      12             :  * details.
      13             :  *
      14             :  * You should have received a copy of the GNU Lesser General Public License
      15             :  * along with this library; if not, write to the Free Software Foundation, Inc.,
      16             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      17             :  */
      18             : 
      19             : #include "layout.h"
      20             : 
      21             : #include "commands.h"
      22             : #include "elementVisitor.h"
      23             : #include "leafVisitor.h"
      24             : #include "log.h"
      25             : #include "nameFinder.h"
      26             : #include "observer.h"
      27             : #include "paths.h"
      28             : 
      29             : #include <co/dataIStream.h>
      30             : #include <co/dataOStream.h>
      31             : #include <co/objectICommand.h>
      32             : 
      33             : namespace eq
      34             : {
      35             : namespace fabric
      36             : {
      37             : template <class C, class L, class V>
      38         651 : Layout<C, L, V>::Layout(C* config)
      39         651 :     : _config(config)
      40             : {
      41         651 :     LBASSERT(config);
      42         651 :     static_cast<L*>(this)->_config->_addLayout(static_cast<L*>(this));
      43         651 :     LBLOG(LOG_INIT) << "New " << lunchbox::className(this) << std::endl;
      44         651 : }
      45             : 
      46             : template <class C, class L, class V>
      47         649 : Layout<C, L, V>::~Layout()
      48             : {
      49         649 :     LBLOG(LOG_INIT) << "Delete " << lunchbox::className(this) << std::endl;
      50        2069 :     while (!_views.empty())
      51             :     {
      52         710 :         V* view = _views.back();
      53         710 :         LBCHECK(_removeChild(view));
      54         710 :         release(view);
      55             :     }
      56             : 
      57         649 :     _config->_removeLayout(static_cast<L*>(this));
      58        1298 : }
      59             : 
      60             : template <class C, class L, class V>
      61          21 : void Layout<C, L, V>::attach(const uint128_t& id, const uint32_t instanceID)
      62             : {
      63          21 :     Object::attach(id, instanceID);
      64             : 
      65          21 :     co::CommandQueue* queue = _config->getMainThreadQueue();
      66          21 :     LBASSERT(queue);
      67             : 
      68          21 :     registerCommand(CMD_LAYOUT_NEW_VIEW,
      69             :                     CmdFunc(this, &Layout<C, L, V>::_cmdNewView), queue);
      70          21 :     registerCommand(CMD_LAYOUT_NEW_VIEW_REPLY,
      71             :                     CmdFunc(this, &Layout<C, L, V>::_cmdNewViewReply), 0);
      72          21 : }
      73             : 
      74             : template <class C, class L, class V>
      75          98 : uint128_t Layout<C, L, V>::commit(const uint32_t incarnation)
      76             : {
      77             :     // Always traverse views: view proxy objects may be dirty
      78          98 :     commitChildren<V>(_views, CMD_LAYOUT_NEW_VIEW, incarnation);
      79          98 :     return Object::commit(incarnation);
      80             : }
      81             : 
      82             : template <class C, class L, class V>
      83          94 : void Layout<C, L, V>::serialize(co::DataOStream& os, const uint64_t dirtyBits)
      84             : {
      85          94 :     Object::serialize(os, dirtyBits);
      86             : 
      87          94 :     if (dirtyBits & DIRTY_VIEWS && isMaster())
      88          86 :         os.serializeChildren(_views);
      89          94 :     if (dirtyBits & DIRTY_VIEWPORT)
      90          50 :         os << _pvp;
      91          94 : }
      92             : 
      93             : template <class C, class L, class V>
      94          41 : void Layout<C, L, V>::deserialize(co::DataIStream& is, const uint64_t dirtyBits)
      95             : {
      96          41 :     Object::deserialize(is, dirtyBits);
      97             : 
      98          41 :     if (dirtyBits & DIRTY_VIEWS)
      99             :     {
     100          41 :         if (isMaster())
     101          16 :             syncChildren(_views);
     102             :         else
     103             :         {
     104          50 :             Views result;
     105          25 :             is.deserializeChildren(this, _views, result);
     106          25 :             _views.swap(result);
     107             :         }
     108             :     }
     109          41 :     if (dirtyBits & DIRTY_VIEWPORT)
     110             :     {
     111           7 :         is >> _pvp;
     112           7 :         notifyViewportChanged();
     113             :     }
     114          41 : }
     115             : 
     116             : template <class C, class L, class V>
     117        1854 : void Layout<C, L, V>::setDirty(const uint64_t dirtyBits)
     118             : {
     119        1854 :     Object::setDirty(dirtyBits);
     120        1854 :     _config->setDirty(C::DIRTY_LAYOUTS);
     121        1854 : }
     122             : 
     123             : template <class C, class L, class V>
     124          21 : void Layout<C, L, V>::notifyDetach()
     125             : {
     126          21 :     Object::notifyDetach();
     127          21 :     releaseChildren<L, V>(_views);
     128          21 : }
     129             : 
     130             : template <class C, class L, class V>
     131           7 : void Layout<C, L, V>::create(V** view)
     132             : {
     133           7 :     *view = getConfig()->getServer()->getNodeFactory()->createView(
     134             :         static_cast<L*>(this));
     135           7 : }
     136             : 
     137             : template <class C, class L, class V>
     138         717 : void Layout<C, L, V>::release(V* view)
     139             : {
     140         717 :     getConfig()->getServer()->getNodeFactory()->releaseView(view);
     141         717 : }
     142             : 
     143             : template <class C, class L, class V>
     144           0 : const PixelViewport& Layout<C, L, V>::getPixelViewport() const
     145             : {
     146           0 :     return _pvp;
     147             : }
     148             : 
     149             : template <class C, class L, class V>
     150           0 : void Layout<C, L, V>::setPixelViewport(const PixelViewport& pvp)
     151             : {
     152           0 :     if (_pvp == pvp)
     153           0 :         return;
     154           0 :     _pvp = pvp;
     155           0 :     setDirty(DIRTY_VIEWPORT);
     156             : }
     157             : 
     158             : namespace
     159             : {
     160             : template <class L, class V>
     161       19949 : VisitorResult _accept(L* layout, V& visitor)
     162             : {
     163       19949 :     VisitorResult result = visitor.visitPre(layout);
     164       19949 :     if (result != TRAVERSE_CONTINUE)
     165        1683 :         return result;
     166             : 
     167       18266 :     const typename L::Views& views = layout->getViews();
     168       38628 :     for (typename L::Views::const_iterator i = views.begin(); i != views.end();
     169             :          ++i)
     170             :     {
     171       20366 :         switch ((*i)->accept(visitor))
     172             :         {
     173             :         case TRAVERSE_TERMINATE:
     174           4 :             return TRAVERSE_TERMINATE;
     175             : 
     176             :         case TRAVERSE_PRUNE:
     177           0 :             result = TRAVERSE_PRUNE;
     178           0 :             break;
     179             : 
     180             :         case TRAVERSE_CONTINUE:
     181             :         default:
     182       20362 :             break;
     183             :         }
     184             :     }
     185             : 
     186       18262 :     switch (visitor.visitPost(layout))
     187             :     {
     188             :     case TRAVERSE_TERMINATE:
     189           0 :         return TRAVERSE_TERMINATE;
     190             : 
     191             :     case TRAVERSE_PRUNE:
     192           0 :         return TRAVERSE_PRUNE;
     193             : 
     194             :     case TRAVERSE_CONTINUE:
     195             :     default:
     196       18262 :         break;
     197             :     }
     198             : 
     199       18262 :     return result;
     200             : }
     201             : }
     202             : 
     203             : template <class C, class L, class V>
     204       19949 : VisitorResult Layout<C, L, V>::accept(Visitor& visitor)
     205             : {
     206       19949 :     return _accept(static_cast<L*>(this), visitor);
     207             : }
     208             : 
     209             : template <class C, class L, class V>
     210           0 : VisitorResult Layout<C, L, V>::accept(Visitor& visitor) const
     211             : {
     212           0 :     return _accept(static_cast<const L*>(this), visitor);
     213             : }
     214             : 
     215             : template <class C, class L, class V>
     216         719 : void Layout<C, L, V>::_addChild(V* view)
     217             : {
     218         719 :     LBASSERT(view);
     219         719 :     LBASSERT(view->getLayout() == this);
     220         719 :     _views.push_back(view);
     221         719 :     setDirty(DIRTY_VIEWS);
     222         719 : }
     223             : 
     224             : template <class C, class L, class V>
     225        1434 : bool Layout<C, L, V>::_removeChild(V* view)
     226             : {
     227        1434 :     typename Views::iterator i = lunchbox::find(_views, view);
     228        1434 :     if (i == _views.end())
     229         717 :         return false;
     230             : 
     231         717 :     LBASSERT(view->getLayout() == this);
     232         717 :     _views.erase(i);
     233         717 :     setDirty(DIRTY_VIEWS);
     234         717 :     if (!isMaster())
     235         717 :         postRemove(view);
     236         717 :     return true;
     237             : }
     238             : 
     239             : template <class C, class L, class V>
     240             : template <class O>
     241           0 : void Layout<C, L, V>::_removeObserver(const O* observer)
     242             : {
     243           0 :     for (typename Views::const_iterator i = _views.begin(); i != _views.end();
     244             :          ++i)
     245             :     {
     246           0 :         V* view = *i;
     247           0 :         if (view->getObserver() == observer)
     248             :         {
     249           0 :             LBINFO << "Removing " << lunchbox::disableHeader << *observer
     250           0 :                    << " used by " << *view << std::endl
     251           0 :                    << lunchbox::enableHeader;
     252           0 :             view->setObserver(0);
     253             :         }
     254             :     }
     255           0 : }
     256             : 
     257             : template <class C, class L, class V>
     258           7 : bool Layout<C, L, V>::isActive() const
     259             : {
     260           7 :     const typename C::Canvases& canvases = _config->getCanvases();
     261          39 :     for (typename C::Canvases::const_iterator i = canvases.begin();
     262          26 :          i != canvases.end(); ++i)
     263             :     {
     264           7 :         if ((*i)->getActiveLayout() == this)
     265           1 :             return true;
     266             :     }
     267           6 :     return false;
     268             : }
     269             : 
     270             : template <class C, class L, class V>
     271        2906 : V* Layout<C, L, V>::getView(const ViewPath& path)
     272             : {
     273        2906 :     LBASSERTINFO(_views.size() > path.viewIndex,
     274             :                  _views.size() << " <= " << path.viewIndex << " " << this);
     275             : 
     276        2906 :     if (_views.size() <= path.viewIndex)
     277           0 :         return 0;
     278             : 
     279        2906 :     return _views[path.viewIndex];
     280             : }
     281             : 
     282             : template <class C, class L, class V>
     283         928 : LayoutPath Layout<C, L, V>::getPath() const
     284             : {
     285         928 :     LBASSERT(_config);
     286         928 :     const std::vector<L*>& layouts = _config->getLayouts();
     287             :     typename std::vector<L*>::const_iterator i =
     288         928 :         std::find(layouts.begin(), layouts.end(), this);
     289         928 :     LBASSERT(i != layouts.end());
     290             : 
     291         928 :     LayoutPath path;
     292         928 :     path.layoutIndex = std::distance(layouts.begin(), i);
     293         928 :     return path;
     294             : }
     295             : 
     296             : template <class C, class L, class V>
     297           2 : V* Layout<C, L, V>::findView(const std::string& name)
     298             : {
     299           4 :     NameFinder<V, Visitor> finder(name);
     300           2 :     accept(finder);
     301           4 :     return finder.getResult();
     302             : }
     303             : 
     304             : //----------------------------------------------------------------------
     305             : // ICommand handlers
     306             : //----------------------------------------------------------------------
     307             : template <class C, class L, class V>
     308           0 : bool Layout<C, L, V>::_cmdNewView(co::ICommand& cmd)
     309             : {
     310           0 :     co::ObjectICommand command(cmd);
     311             : 
     312           0 :     V* view = 0;
     313           0 :     create(&view);
     314           0 :     LBASSERT(view);
     315             : 
     316           0 :     getLocalNode()->registerObject(view);
     317           0 :     view->setAutoObsolete(_config->getLatency() + 1);
     318           0 :     LBASSERT(view->isAttached());
     319             : 
     320           0 :     send(command.getRemoteNode(), CMD_LAYOUT_NEW_VIEW_REPLY)
     321           0 :         << command.read<uint32_t>() << view->getID();
     322             : 
     323           0 :     return true;
     324             : }
     325             : 
     326             : template <class C, class L, class V>
     327           0 : bool Layout<C, L, V>::_cmdNewViewReply(co::ICommand& cmd)
     328             : {
     329           0 :     co::ObjectICommand command(cmd);
     330           0 :     const uint32_t requestID = command.read<uint32_t>();
     331           0 :     const uint128_t& result = command.read<uint128_t>();
     332             : 
     333           0 :     getLocalNode()->serveRequest(requestID, result);
     334             : 
     335           0 :     return true;
     336             : }
     337             : 
     338             : template <class C, class L, class V>
     339         342 : std::ostream& operator<<(std::ostream& os, const Layout<C, L, V>& layout)
     340             : {
     341         342 :     os << lunchbox::disableFlush << lunchbox::disableHeader << "layout"
     342             :        << std::endl;
     343         342 :     os << "{" << std::endl << lunchbox::indent;
     344             : 
     345         342 :     const std::string& name = layout.getName();
     346         342 :     if (!name.empty())
     347         180 :         os << "name     \"" << name << "\"" << std::endl;
     348             : 
     349         342 :     const std::vector<V*>& views = layout.getViews();
     350        2154 :     for (typename std::vector<V*>::const_iterator i = views.begin();
     351        1436 :          i != views.end(); ++i)
     352             :     {
     353         376 :         os << **i;
     354             :     }
     355         684 :     os << lunchbox::exdent << "}" << std::endl
     356         342 :        << lunchbox::enableHeader << lunchbox::enableFlush;
     357         342 :     return os;
     358             : }
     359             : }
     360             : }

Generated by: LCOV version 1.11