LCOV - code coverage report
Current view: top level - eq/fabric - canvas.ipp (source / functions) Hit Total Coverage
Test: Equalizer Lines: 186 259 71.8 %
Date: 2017-12-16 05:07:20 Functions: 37 105 35.2 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2010-2016, Stefan Eilemann <eile@eyescale.ch>
       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 "canvas.h"
      20             : 
      21             : #include "commands.h"
      22             : #include "elementVisitor.h"
      23             : #include "leafVisitor.h"
      24             : #include "log.h"
      25             : #include "nameFinder.h"
      26             : #include "paths.h"
      27             : #include "segment.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 CFG, class C, class S, class L>
      38         421 : Canvas<CFG, C, S, L>::Canvas(CFG* config)
      39         421 :     : _config(config)
      40             : {
      41         421 :     LBASSERT(config);
      42         421 :     setWall(Wall()); // default frustum
      43         421 :     config->_addCanvas(static_cast<C*>(this));
      44         421 :     LBLOG(LOG_INIT) << "New " << lunchbox::className(this) << std::endl;
      45         421 : }
      46             : 
      47             : template <class CFG, class C, class S, class L>
      48         419 : Canvas<CFG, C, S, L>::~Canvas()
      49             : {
      50         419 :     LBLOG(LOG_INIT) << "Delete " << lunchbox::className(this) << std::endl;
      51        1999 :     while (!_segments.empty())
      52             :     {
      53         790 :         S* segment = _segments.back();
      54         790 :         _removeChild(segment);
      55         790 :         release(segment);
      56             :     }
      57             : 
      58         419 :     _data.activeLayout = 0;
      59         419 :     _layouts.clear();
      60         419 :     _config->_removeCanvas(static_cast<C*>(this));
      61         838 : }
      62             : 
      63             : template <class CFG, class C, class S, class L>
      64           2 : void Canvas<CFG, C, S, L>::backup()
      65             : {
      66           2 :     _backup = _data;
      67           2 :     Object::backup();
      68           2 :     Frustum::backup();
      69           2 : }
      70             : 
      71             : template <class CFG, class C, class S, class L>
      72           0 : void Canvas<CFG, C, S, L>::restore()
      73             : {
      74           0 :     Frustum::restore();
      75           0 :     Object::restore();
      76           0 :     activateLayout(_backup.activeLayout);
      77           0 :     _data = _backup;
      78           0 :     setDirty(DIRTY_LAYOUT);
      79           0 : }
      80             : 
      81             : template <class CFG, class C, class S, class L>
      82           3 : void Canvas<CFG, C, S, L>::attach(const uint128_t& id,
      83             :                                   const uint32_t instanceID)
      84             : {
      85           3 :     Object::attach(id, instanceID);
      86             : 
      87           3 :     co::CommandQueue* queue = _config->getMainThreadQueue();
      88           3 :     LBASSERT(queue);
      89             : 
      90           3 :     registerCommand(CMD_CANVAS_NEW_SEGMENT,
      91             :                     CmdFunc(this, &Canvas<CFG, C, S, L>::_cmdNewSegment),
      92             :                     queue);
      93           3 :     registerCommand(CMD_CANVAS_NEW_SEGMENT_REPLY,
      94             :                     CmdFunc(this, &Canvas<CFG, C, S, L>::_cmdNewSegmentReply),
      95             :                     0);
      96           3 : }
      97             : 
      98             : template <class CFG, class C, class S, class L>
      99          17 : uint128_t Canvas<CFG, C, S, L>::commit(const uint32_t incarnation)
     100             : {
     101          17 :     if (Serializable::isDirty(DIRTY_SEGMENTS))
     102           3 :         commitChildren<S>(_segments, CMD_CANVAS_NEW_SEGMENT, incarnation);
     103          17 :     return Object::commit(incarnation);
     104             : }
     105             : 
     106             : template <class CFG, class C, class S, class L>
     107           7 : void Canvas<CFG, C, S, L>::serialize(co::DataOStream& os,
     108             :                                      const uint64_t dirtyBits)
     109             : {
     110           7 :     Object::serialize(os, dirtyBits);
     111             : 
     112           7 :     if (dirtyBits & DIRTY_LAYOUT)
     113           4 :         os << _data.activeLayout;
     114           7 :     if (dirtyBits & DIRTY_SEGMENTS && isMaster())
     115           6 :         os.serializeChildren(_segments);
     116           7 :     if (dirtyBits & DIRTY_LAYOUTS)
     117           4 :         os.serializeChildren(_layouts);
     118           7 :     if (dirtyBits & DIRTY_FRUSTUM)
     119           7 :         Frustum::serialize(os);
     120           7 : }
     121             : 
     122             : template <class CFG, class C, class S, class L>
     123           4 : void Canvas<CFG, C, S, L>::deserialize(co::DataIStream& is,
     124             :                                        const uint64_t dirtyBits)
     125             : {
     126           4 :     Object::deserialize(is, dirtyBits);
     127             : 
     128           4 :     if (dirtyBits & DIRTY_LAYOUT)
     129             :     {
     130           1 :         uint32_t index(0);
     131           1 :         is >> index;
     132           1 :         activateLayout(index);
     133             :     }
     134             : 
     135           4 :     if (dirtyBits & DIRTY_SEGMENTS)
     136             :     {
     137           4 :         if (isMaster())
     138           2 :             syncChildren(_segments);
     139             :         else
     140             :         {
     141           4 :             Segments result;
     142           2 :             is.deserializeChildren(this, _segments, result);
     143           2 :             _segments.swap(result);
     144           2 :             LBASSERT(_segments.size() == result.size());
     145             :         }
     146             :     }
     147             : 
     148           4 :     if (dirtyBits & DIRTY_LAYOUTS)
     149             :     {
     150           1 :         _layouts.clear();
     151           2 :         co::ObjectVersions layouts;
     152           1 :         is >> layouts;
     153          24 :         for (co::ObjectVersions::const_iterator i = layouts.begin();
     154          16 :              i != layouts.end(); ++i)
     155             :         {
     156           7 :             const uint128_t& id = (*i).identifier;
     157             : 
     158           7 :             if (id == 0)
     159           0 :                 _layouts.push_back(0);
     160             :             else
     161             :             {
     162           7 :                 L* layout = 0;
     163           7 :                 _config->find(id, &layout);
     164           7 :                 LBASSERT(layout);
     165           7 :                 _layouts.push_back(layout);
     166             :             }
     167             :         }
     168             : 
     169           1 :         _config->updateCanvas(static_cast<C*>(this));
     170             :     }
     171           4 :     if (dirtyBits & DIRTY_FRUSTUM)
     172           4 :         Frustum::deserialize(is);
     173           4 : }
     174             : 
     175             : template <class CFG, class C, class S, class L>
     176        5065 : void Canvas<CFG, C, S, L>::setDirty(const uint64_t dirtyBits)
     177             : {
     178        5065 :     Object::setDirty(dirtyBits);
     179        5065 :     _config->setDirty(CFG::DIRTY_CANVASES);
     180        5065 : }
     181             : 
     182             : template <class CFG, class C, class S, class L>
     183           1 : void Canvas<CFG, C, S, L>::create(S** segment)
     184             : {
     185           1 :     *segment = _config->getServer()->getNodeFactory()->createSegment(
     186             :         static_cast<C*>(this));
     187           1 : }
     188             : 
     189             : template <class CFG, class C, class S, class L>
     190         791 : void Canvas<CFG, C, S, L>::release(S* segment)
     191             : {
     192         791 :     _config->getServer()->getNodeFactory()->releaseSegment(segment);
     193         791 : }
     194             : 
     195             : template <class CFG, class C, class S, class L>
     196           3 : void Canvas<CFG, C, S, L>::notifyDetach()
     197             : {
     198           3 :     Object::notifyDetach();
     199           3 :     releaseChildren<C, S>(_segments);
     200           3 : }
     201             : 
     202             : template <class CFG, class C, class S, class L>
     203         793 : void Canvas<CFG, C, S, L>::_addChild(S* segment)
     204             : {
     205         793 :     LBASSERT(segment);
     206         793 :     LBASSERT(segment->getCanvas() == this);
     207         793 :     _segments.push_back(segment);
     208         793 :     setDirty(DIRTY_SEGMENTS);
     209         793 : }
     210             : 
     211             : template <class CFG, class C, class S, class L>
     212        1582 : bool Canvas<CFG, C, S, L>::_removeChild(S* segment)
     213             : {
     214        1582 :     typename Segments::iterator i = lunchbox::find(_segments, segment);
     215        1582 :     if (i == _segments.end())
     216         791 :         return false;
     217             : 
     218         791 :     LBASSERT(segment->getCanvas() == this);
     219         791 :     _segments.erase(i);
     220         791 :     setDirty(DIRTY_SEGMENTS);
     221         791 :     if (isAttached() && !isMaster())
     222           1 :         postRemove(segment);
     223         791 :     return true;
     224             : }
     225             : 
     226             : template <class CFG, class C, class S, class L>
     227           1 : bool Canvas<CFG, C, S, L>::_mapViewObjects()
     228             : {
     229           1 :     return static_cast<typename CFG::Super*>(_config)->mapViewObjects();
     230             : }
     231             : 
     232             : template <class CFG, class C, class S, class L>
     233        1264 : CanvasPath Canvas<CFG, C, S, L>::getPath() const
     234             : {
     235        1264 :     const CFG* config = getConfig();
     236        1264 :     LBASSERT(config);
     237             : 
     238        1264 :     const Canvases& canvases = config->getCanvases();
     239             :     typename Canvases::const_iterator i =
     240        1264 :         std::find(canvases.begin(), canvases.end(), this);
     241        1264 :     LBASSERT(i != canvases.end());
     242             : 
     243        1264 :     CanvasPath path;
     244        1264 :     path.canvasIndex = std::distance(canvases.begin(), i);
     245        1264 :     return path;
     246             : }
     247             : 
     248             : template <class CFG, class C, class S, class L>
     249           0 : S* Canvas<CFG, C, S, L>::findSegment(const std::string& name)
     250             : {
     251           0 :     NameFinder<S, Visitor> finder(name);
     252           0 :     accept(finder);
     253           0 :     return finder.getResult();
     254             : }
     255             : 
     256             : template <class CFG, class C, class S, class L>
     257           0 : const S* Canvas<CFG, C, S, L>::findSegment(const std::string& name) const
     258             : {
     259           0 :     NameFinder<const S, Visitor> finder(name);
     260           0 :     accept(finder);
     261           0 :     return finder.getResult();
     262             : }
     263             : 
     264             : template <class CFG, class C, class S, class L>
     265         656 : void Canvas<CFG, C, S, L>::addLayout(L* layout)
     266             : {
     267         656 :     LBASSERT(lunchbox::find(_layouts, layout) == _layouts.end());
     268             : 
     269             :     // dest channel creation is done be Config::addCanvas
     270         656 :     _layouts.push_back(layout);
     271         656 :     setDirty(DIRTY_LAYOUTS);
     272         656 : }
     273             : 
     274             : template <class CFG, class C, class S, class L>
     275           0 : bool Canvas<CFG, C, S, L>::removeLayout(L* layout)
     276             : {
     277           0 :     typename Layouts::iterator i = lunchbox::find(_layouts, layout);
     278           0 :     if (i == _layouts.end())
     279           0 :         return false;
     280             : 
     281           0 :     if (getActiveLayout() == layout)
     282             :     {
     283           0 :         _data.activeLayout = 0;
     284           0 :         setDirty(DIRTY_LAYOUT);
     285             :     }
     286             : 
     287           0 :     _layouts.erase(i);
     288           0 :     setDirty(DIRTY_LAYOUTS);
     289           0 :     return true;
     290             : }
     291             : 
     292             : template <class CFG, class C, class S, class L>
     293           8 : const L* Canvas<CFG, C, S, L>::getActiveLayout() const
     294             : {
     295           8 :     LBASSERTINFO(_data.activeLayout < _layouts.size(),
     296             :                  _data.activeLayout << " >= " << _layouts.size());
     297           8 :     return _layouts[_data.activeLayout];
     298             : }
     299             : 
     300             : template <class CFG, class C, class S, class L>
     301           7 : L* Canvas<CFG, C, S, L>::getActiveLayout()
     302             : {
     303           7 :     LBASSERTINFO(_data.activeLayout < _layouts.size(),
     304             :                  _data.activeLayout << " >= " << _layouts.size());
     305           7 :     return _layouts[_data.activeLayout];
     306             : }
     307             : 
     308             : template <class CFG, class C, class S, class L>
     309           0 : bool Canvas<CFG, C, S, L>::useLayout(const uint32_t index)
     310             : {
     311           0 :     LBASSERT(index < _layouts.size());
     312           0 :     if (_data.activeLayout == index)
     313           0 :         return false;
     314             : 
     315           0 :     _data.activeLayout = index;
     316           0 :     setDirty(DIRTY_LAYOUT);
     317           0 :     return true;
     318             : }
     319             : 
     320             : template <class CFG, class C, class S, class L>
     321           8 : void Canvas<CFG, C, S, L>::setSwapBarrier(SwapBarrierPtr barrier)
     322             : {
     323           8 :     if (barrier.isValid() && barrier->getName().empty())
     324             :     {
     325           4 :         const std::string& name = getName();
     326           8 :         std::stringstream out;
     327           4 :         out << "barrier.canvas.";
     328           4 :         if (name.empty())
     329           4 :             if (getConfig())
     330           4 :                 out << getPath().canvasIndex;
     331             :             else
     332           0 :                 out << (void*)this;
     333             :         else
     334           0 :             out << name;
     335             : 
     336           4 :         barrier->setName(out.str());
     337             :     }
     338             : 
     339           8 :     _swapBarrier = barrier;
     340           8 : }
     341             : 
     342             : namespace
     343             : {
     344             : template <class C, class V>
     345        2551 : VisitorResult _accept(C* canvas, V& visitor)
     346             : {
     347        2551 :     VisitorResult result = visitor.visitPre(canvas);
     348        2551 :     if (result != TRAVERSE_CONTINUE)
     349          32 :         return result;
     350             : 
     351        2519 :     const typename C::Segments& segments = canvas->getSegments();
     352       32268 :     for (typename C::Segments::const_iterator i = segments.begin();
     353       21512 :          i != segments.end(); ++i)
     354             :     {
     355        8237 :         switch ((*i)->accept(visitor))
     356             :         {
     357             :         case TRAVERSE_TERMINATE:
     358           0 :             return TRAVERSE_TERMINATE;
     359             : 
     360             :         case TRAVERSE_PRUNE:
     361           0 :             result = TRAVERSE_PRUNE;
     362           0 :             break;
     363             : 
     364             :         case TRAVERSE_CONTINUE:
     365             :         default:
     366        8237 :             break;
     367             :         }
     368             :     }
     369             : 
     370        2519 :     switch (visitor.visitPost(canvas))
     371             :     {
     372             :     case TRAVERSE_TERMINATE:
     373           0 :         return TRAVERSE_TERMINATE;
     374             : 
     375             :     case TRAVERSE_PRUNE:
     376           0 :         return TRAVERSE_PRUNE;
     377             : 
     378             :     case TRAVERSE_CONTINUE:
     379             :     default:
     380        2519 :         break;
     381             :     }
     382             : 
     383        2519 :     return result;
     384             : }
     385             : }
     386             : 
     387             : template <class CFG, class C, class S, class L>
     388        2551 : VisitorResult Canvas<CFG, C, S, L>::accept(Visitor& visitor)
     389             : {
     390        2551 :     return _accept(static_cast<C*>(this), visitor);
     391             : }
     392             : 
     393             : template <class CFG, class C, class S, class L>
     394           0 : VisitorResult Canvas<CFG, C, S, L>::accept(Visitor& visitor) const
     395             : {
     396           0 :     return _accept(static_cast<const C*>(this), visitor);
     397             : }
     398             : 
     399             : template <class CFG, class C, class S, class L>
     400         817 : void Canvas<CFG, C, S, L>::setWall(const Wall& wall)
     401             : {
     402         817 :     if (getWall() == wall && getCurrentType() == TYPE_WALL)
     403         290 :         return;
     404             : 
     405         527 :     Frustum::setWall(wall);
     406         527 :     setDirty(DIRTY_FRUSTUM);
     407        1581 :     for (typename Segments::const_iterator i = _segments.begin();
     408        1054 :          i != _segments.end(); ++i)
     409             :     {
     410           0 :         (*i)->inheritFrustum();
     411             :     }
     412             : }
     413             : 
     414             : template <class CFG, class C, class S, class L>
     415           0 : void Canvas<CFG, C, S, L>::setProjection(const Projection& projection)
     416             : {
     417           0 :     if (getProjection() == projection && getCurrentType() == TYPE_PROJECTION)
     418           0 :         return;
     419             : 
     420           0 :     Frustum::setProjection(projection);
     421           0 :     setDirty(DIRTY_FRUSTUM);
     422           0 :     for (typename Segments::const_iterator i = _segments.begin();
     423           0 :          i != _segments.end(); ++i)
     424             :     {
     425           0 :         (*i)->inheritFrustum();
     426             :     }
     427             : }
     428             : 
     429             : template <class CFG, class C, class S, class L>
     430           0 : void Canvas<CFG, C, S, L>::unsetFrustum()
     431             : {
     432           0 :     if (getCurrentType() == TYPE_NONE)
     433           0 :         return;
     434             : 
     435           0 :     Frustum::unsetFrustum();
     436           0 :     setDirty(DIRTY_FRUSTUM);
     437             : }
     438             : 
     439             : //----------------------------------------------------------------------
     440             : // ICommand handlers
     441             : //----------------------------------------------------------------------
     442             : template <class CFG, class C, class S, class L>
     443           0 : bool Canvas<CFG, C, S, L>::_cmdNewSegment(co::ICommand& cmd)
     444             : {
     445           0 :     co::ObjectICommand command(cmd);
     446             : 
     447           0 :     S* segment = 0;
     448           0 :     create(&segment);
     449           0 :     LBASSERT(segment);
     450             : 
     451           0 :     getLocalNode()->registerObject(segment);
     452           0 :     segment->setAutoObsolete(_config->getLatency() + 1);
     453           0 :     LBASSERT(segment->isAttached());
     454             : 
     455           0 :     send(command.getRemoteNode(), CMD_CANVAS_NEW_SEGMENT_REPLY)
     456           0 :         << command.read<uint32_t>() << segment->getID();
     457             : 
     458           0 :     return true;
     459             : }
     460             : 
     461             : template <class CFG, class C, class S, class L>
     462           0 : bool Canvas<CFG, C, S, L>::_cmdNewSegmentReply(co::ICommand& cmd)
     463             : {
     464           0 :     co::ObjectICommand command(cmd);
     465             : 
     466           0 :     const uint32_t requestID = command.read<uint32_t>();
     467           0 :     const uint128_t& result = command.read<uint128_t>();
     468             : 
     469           0 :     getLocalNode()->serveRequest(requestID, result);
     470             : 
     471           0 :     return true;
     472             : }
     473             : 
     474             : template <class CFG, class C, class S, class L>
     475         212 : std::ostream& operator<<(std::ostream& os, const Canvas<CFG, C, S, L>& canvas)
     476             : {
     477         212 :     os << lunchbox::disableFlush << lunchbox::disableHeader << "canvas"
     478             :        << std::endl;
     479         212 :     os << "{" << std::endl << lunchbox::indent;
     480             : 
     481         212 :     const std::string& name = canvas.getName();
     482         212 :     if (!name.empty())
     483           6 :         os << "name     \"" << name << "\"" << std::endl;
     484             : 
     485         212 :     const std::vector<L*>& layouts = canvas.getLayouts();
     486        1680 :     for (typename std::vector<L*>::const_iterator i = layouts.begin();
     487        1120 :          i != layouts.end(); ++i)
     488             :     {
     489         348 :         L* layout = *i;
     490         348 :         if (layout)
     491             :         {
     492         346 :             const CFG* config = layout->getConfig();
     493         346 :             const std::string& layoutName = layout->getName();
     494         346 :             const L* foundLayout = 0;
     495         346 :             config->find(layoutName, &foundLayout);
     496         346 :             if (foundLayout == layout)
     497         344 :                 os << "layout   \"" << layoutName << "\"" << std::endl;
     498             :             else
     499           2 :                 os << layout->getPath() << std::endl;
     500             :         }
     501             :         else
     502           2 :             os << "layout   OFF" << std::endl;
     503             :     }
     504             : 
     505         212 :     if (canvas.getSwapBarrier().isValid())
     506           4 :         os << *canvas.getSwapBarrier();
     507         212 :     os << static_cast<const Frustum&>(canvas);
     508             : 
     509         212 :     const std::vector<S*>& segments = canvas.getSegments();
     510        1830 :     for (typename std::vector<S*>::const_iterator i = segments.begin();
     511        1220 :          i != segments.end(); ++i)
     512             :     {
     513         398 :         os << **i;
     514             :     }
     515         424 :     os << lunchbox::exdent << "}" << std::endl
     516         212 :        << lunchbox::enableHeader << lunchbox::enableFlush;
     517         212 :     return os;
     518             : }
     519             : }
     520             : }

Generated by: LCOV version 1.11