LCOV - code coverage report
Current view: top level - eq/server - channel.cpp (source / functions) Hit Total Coverage
Test: Equalizer Lines: 209 278 75.2 %
Date: 2017-12-16 05:07:20 Functions: 37 47 78.7 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2005-2016, Stefan Eilemann <eile@equalizergraphics.com>
       3             :  *                          Daniel Nachbaur <danielnachbaur@gmail.com>
       4             :  *                          Julio Delgado Mangas <julio.delgadomangas@epfl.ch>
       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 "channel.h"
      21             : 
      22             : #include "channelListener.h"
      23             : #include "channelUpdateVisitor.h"
      24             : #include "compound.h"
      25             : #include "compoundVisitor.h"
      26             : #include "config.h"
      27             : #include "configVisitor.h"
      28             : #include "global.h"
      29             : #include "log.h"
      30             : #include "node.h"
      31             : #include "segment.h"
      32             : #include "view.h"
      33             : #include "window.h"
      34             : 
      35             : #include <eq/fabric/commands.h>
      36             : #include <eq/fabric/paths.h>
      37             : #include <eq/fabric/statistic.h>
      38             : 
      39             : #include <co/objectICommand.h>
      40             : 
      41             : #include <lunchbox/debug.h>
      42             : 
      43             : #include <set>
      44             : 
      45             : namespace eq
      46             : {
      47             : namespace server
      48             : {
      49             : typedef co::CommandFunc<Channel> CmdFunc;
      50             : typedef fabric::Channel<Window, Channel> Super;
      51             : 
      52             : namespace
      53             : {
      54             : typedef std::set<View*> ViewSet;
      55             : 
      56             : class ViewFinder : public ConfigVisitor
      57             : {
      58             : public:
      59           0 :     explicit ViewFinder(const Channel* channel)
      60           0 :         : _channel(channel)
      61             :     {
      62           0 :     }
      63           0 :     virtual ~ViewFinder() {}
      64           0 :     virtual VisitorResult visit(Compound* compound)
      65             :     {
      66           0 :         Channel* channel = compound->getChannel();
      67           0 :         if (channel != _channel)
      68           0 :             return TRAVERSE_CONTINUE;
      69             : 
      70           0 :         channel = compound->getInheritChannel();
      71           0 :         if (channel->getView())
      72           0 :             _viewSet.insert(channel->getView());
      73           0 :         return TRAVERSE_CONTINUE;
      74             :     }
      75             : 
      76           0 :     ViewSet& getViews() { return _viewSet; }
      77             : private:
      78             :     const Channel* _channel;
      79             :     ViewSet _viewSet;
      80             : };
      81             : }
      82             : 
      83        1650 : Channel::Channel(Window* parent)
      84             :     : Super(parent)
      85             :     , _active(0)
      86             :     , _view(0)
      87             :     , _segment(0)
      88             :     , _state(STATE_STOPPED)
      89             :     , _lastDrawCompound(0)
      90        1650 :     , _private(0)
      91             : {
      92        1650 :     const Global* global = Global::instance();
      93       13200 :     for (unsigned i = 0; i < IATTR_ALL; ++i)
      94             :     {
      95       11550 :         const IAttribute attr = static_cast<IAttribute>(i);
      96       11550 :         setIAttribute(attr, global->getChannelIAttribute(attr));
      97             :     }
      98       11550 :     for (unsigned i = 0; i < SATTR_ALL; ++i)
      99             :     {
     100        9900 :         const SAttribute attr = static_cast<SAttribute>(i);
     101        9900 :         setSAttribute(attr, global->getChannelSAttribute(attr));
     102             :     }
     103        1650 : }
     104             : 
     105        1224 : Channel::Channel(const Channel& from)
     106             :     : Super(from)
     107             :     , _active(0)
     108             :     , _view(0)
     109             :     , _segment(0)
     110             :     , _state(STATE_STOPPED)
     111             :     , _lastDrawCompound(0)
     112        1224 :     , _private(0)
     113             : {
     114             :     // Don't copy view and segment. Will be re-set by segment copy ctor
     115        1224 : }
     116             : 
     117          18 : void Channel::attach(const uint128_t& id, const uint32_t instanceID)
     118             : {
     119          18 :     Super::attach(id, instanceID);
     120             : 
     121          18 :     co::CommandQueue* mainQ = getMainThreadQueue();
     122          18 :     co::CommandQueue* cmdQ = getCommandThreadQueue();
     123             : 
     124          18 :     registerCommand(fabric::CMD_CHANNEL_CONFIG_INIT_REPLY,
     125          36 :                     CmdFunc(this, &Channel::_cmdConfigInitReply), cmdQ);
     126          18 :     registerCommand(fabric::CMD_CHANNEL_CONFIG_EXIT_REPLY,
     127          36 :                     CmdFunc(this, &Channel::_cmdConfigExitReply), cmdQ);
     128          18 :     registerCommand(fabric::CMD_CHANNEL_FRAME_FINISH_REPLY,
     129          36 :                     CmdFunc(this, &Channel::_cmdFrameFinishReply), mainQ);
     130          18 : }
     131             : 
     132        5740 : Channel::~Channel()
     133             : {
     134        5740 : }
     135             : 
     136           0 : void Channel::postDelete()
     137             : {
     138             :     // Deregister server-queue command handler to avoid assertion in
     139             :     // command invokation after channel deletion
     140           0 :     registerCommand(fabric::CMD_CHANNEL_FRAME_FINISH_REPLY,
     141           0 :                     CmdFunc(this, &Channel::_cmdNop), 0);
     142           0 : }
     143             : 
     144         618 : Config* Channel::getConfig()
     145             : {
     146         618 :     Window* window = getWindow();
     147         618 :     LBASSERT(window);
     148         618 :     return window ? window->getConfig() : 0;
     149             : }
     150             : 
     151           4 : const Config* Channel::getConfig() const
     152             : {
     153           4 :     const Window* window = getWindow();
     154           4 :     LBASSERT(window);
     155           4 :     return window ? window->getConfig() : 0;
     156             : }
     157             : 
     158          46 : Node* Channel::getNode()
     159             : {
     160          46 :     Window* window = getWindow();
     161          46 :     LBASSERT(window);
     162          46 :     return window ? window->getNode() : 0;
     163             : }
     164             : 
     165           0 : const Node* Channel::getNode() const
     166             : {
     167           0 :     const Window* window = getWindow();
     168           0 :     LBASSERT(window);
     169           0 :     return window ? window->getNode() : 0;
     170             : }
     171             : 
     172           4 : Pipe* Channel::getPipe()
     173             : {
     174           4 :     Window* window = getWindow();
     175           4 :     LBASSERT(window);
     176           4 :     return window ? window->getPipe() : 0;
     177             : }
     178             : 
     179           0 : const Pipe* Channel::getPipe() const
     180             : {
     181           0 :     const Window* window = getWindow();
     182           0 :     LBASSERT(window);
     183           0 :     return window ? window->getPipe() : 0;
     184             : }
     185             : 
     186          18 : ServerPtr Channel::getServer()
     187             : {
     188          18 :     Window* window = getWindow();
     189          18 :     LBASSERT(window);
     190          18 :     return (window ? window->getServer() : 0);
     191             : }
     192             : 
     193          34 : const Canvas* Channel::getCanvas() const
     194             : {
     195          34 :     if (!_segment)
     196           0 :         return 0;
     197          34 :     return _segment->getCanvas();
     198             : }
     199             : 
     200           4 : const Compounds& Channel::getCompounds() const
     201             : {
     202           4 :     return getConfig()->getCompounds();
     203             : }
     204             : 
     205          18 : co::CommandQueue* Channel::getMainThreadQueue()
     206             : {
     207          18 :     Window* window = getWindow();
     208          18 :     LBASSERT(window);
     209          18 :     return window->getMainThreadQueue();
     210             : }
     211             : 
     212          18 : co::CommandQueue* Channel::getCommandThreadQueue()
     213             : {
     214          18 :     Window* window = getWindow();
     215          18 :     LBASSERT(window);
     216          18 :     return window->getCommandThreadQueue();
     217             : }
     218             : 
     219         650 : bool Channel::supportsView(const View* view) const
     220             : {
     221         650 :     if (!view)
     222           0 :         return true;
     223             : 
     224         650 :     const uint64_t minimum = view->getMinimumCapabilities();
     225         650 :     const uint64_t supported = getCapabilities();
     226         650 :     return ((supported & minimum) == minimum);
     227             : }
     228             : 
     229           8 : void Channel::activate()
     230             : {
     231           8 :     Window* window = getWindow();
     232           8 :     LBASSERT(window);
     233             : 
     234           8 :     ++_active;
     235           8 :     window->activate();
     236             : 
     237           8 :     LBLOG(LOG_VIEW) << "activate: " << _active << " " << (void*)this
     238           8 :                     << std::endl;
     239           8 : }
     240             : 
     241           8 : void Channel::deactivate()
     242             : {
     243           8 :     Window* window = getWindow();
     244           8 :     LBASSERT(_active != 0);
     245           8 :     LBASSERT(window);
     246             : 
     247           8 :     --_active;
     248           8 :     window->deactivate();
     249             : 
     250           8 :     LBLOG(LOG_VIEW) << "deactivate: " << _active << " " << (void*)this
     251           8 :                     << std::endl;
     252           8 : }
     253             : 
     254        1224 : void Channel::setOutput(View* view, Segment* segment)
     255             : {
     256        1224 :     if (_view == view && _segment == segment)
     257           0 :         return;
     258             : 
     259        1224 :     LBASSERT(!_view && !_segment);
     260        1224 :     LBASSERT(view && segment);
     261             : 
     262        1224 :     _view = view;
     263        1224 :     _segment = segment;
     264             : 
     265        1224 :     view->addChannel(this);
     266        1224 :     segment->addDestinationChannel(this);
     267             : 
     268        1224 :     co::ObjectVersion viewVersion(view);
     269        1224 :     if (view && view->isDirty())
     270           0 :         ++viewVersion.version;
     271             : 
     272        1224 :     setViewVersion(viewVersion);
     273             : }
     274             : 
     275        1222 : void Channel::unsetOutput()
     276             : {
     277        1222 :     LBASSERT(_view && _segment);
     278             : 
     279        1222 :     LBCHECK(_view->removeChannel(this));
     280        1222 :     LBCHECK(_segment->removeDestinationChannel(this));
     281             : 
     282        1222 :     _view = 0;
     283        1222 :     _segment = 0;
     284        1222 : }
     285             : 
     286         482 : const Layout* Channel::getLayout() const
     287             : {
     288         482 :     LBASSERT(_view);
     289         482 :     return _view ? _view->getLayout() : 0;
     290             : }
     291             : 
     292         126 : void Channel::addTasks(const uint32_t tasks)
     293             : {
     294         126 :     Window* window = getWindow();
     295         126 :     LBASSERT(window);
     296         126 :     setTasks(getTasks() | tasks);
     297         126 :     window->addTasks(tasks);
     298         126 : }
     299             : 
     300             : //===========================================================================
     301             : // Operations
     302             : //===========================================================================
     303             : 
     304             : //---------------------------------------------------------------------------
     305             : // init
     306             : //---------------------------------------------------------------------------
     307           4 : void Channel::configInit(const uint128_t& initID, const uint32_t /*frame*/)
     308             : {
     309           4 :     LBASSERT(_state == STATE_STOPPED);
     310           4 :     _state = STATE_INITIALIZING;
     311             : 
     312           4 :     LBLOG(LOG_INIT) << "Init channel" << std::endl;
     313           4 :     getWindow()->send(fabric::CMD_WINDOW_CREATE_CHANNEL) << getID();
     314           4 :     send(fabric::CMD_CHANNEL_CONFIG_INIT) << initID;
     315           4 : }
     316             : 
     317           4 : bool Channel::syncConfigInit()
     318             : {
     319           4 :     LBASSERT(_state == STATE_INITIALIZING || _state == STATE_INIT_SUCCESS ||
     320             :              _state == STATE_INIT_FAILED);
     321             : 
     322           4 :     _state.waitNE(STATE_INITIALIZING);
     323             : 
     324           4 :     if (_state == STATE_INIT_SUCCESS)
     325             :     {
     326           4 :         _state = STATE_RUNNING;
     327           4 :         return true;
     328             :     }
     329             : 
     330           0 :     configExit();
     331           0 :     return false;
     332             : }
     333             : 
     334             : //---------------------------------------------------------------------------
     335             : // exit
     336             : //---------------------------------------------------------------------------
     337           4 : void Channel::configExit()
     338             : {
     339           4 :     LBASSERT(_state == STATE_RUNNING || _state == STATE_INIT_FAILED);
     340           4 :     _state = STATE_EXITING;
     341             : 
     342           4 :     LBLOG(LOG_INIT) << "Exit channel" << std::endl;
     343           4 :     send(fabric::CMD_CHANNEL_CONFIG_EXIT);
     344           4 : }
     345             : 
     346           4 : bool Channel::syncConfigExit()
     347             : {
     348           4 :     LBASSERT(_state == STATE_EXITING || _state == STATE_EXIT_SUCCESS ||
     349             :              _state == STATE_EXIT_FAILED);
     350             : 
     351           4 :     _state.waitNE(STATE_EXITING);
     352           4 :     const bool success = (_state == STATE_EXIT_SUCCESS);
     353           4 :     LBASSERT(success || _state == STATE_EXIT_FAILED);
     354             : 
     355           4 :     _state = isActive() ? STATE_FAILED : STATE_STOPPED;
     356           4 :     return success;
     357             : }
     358             : 
     359             : //---------------------------------------------------------------------------
     360             : // update
     361             : //---------------------------------------------------------------------------
     362           4 : void Channel::_setupRenderContext(const uint128_t& frameID,
     363             :                                   RenderContext& context)
     364             : {
     365           4 :     context.frameID = frameID;
     366           4 :     context.pvp = getPixelViewport();
     367           4 :     context.view = _view;
     368           4 :     context.vp = getViewport();
     369           4 :     LBASSERTINFO(getNativeContext().view == context.view,
     370             :                  getNativeContext().view << " != " << context.view << " "
     371             :                                          << getName());
     372           4 : }
     373             : 
     374          18 : bool Channel::update(const uint128_t& frameID, const uint32_t frameNumber)
     375             : {
     376          18 :     if (!isRunning())
     377          14 :         return false; // not updated
     378             : 
     379           4 :     LBASSERT(isActive())
     380           4 :     LBASSERT(getWindow()->isActive());
     381             : 
     382           8 :     RenderContext context;
     383           4 :     _setupRenderContext(frameID, context);
     384           8 :     send(fabric::CMD_CHANNEL_FRAME_START) << context << getVersion()
     385           4 :                                           << frameNumber;
     386           4 :     LBLOG(LOG_TASKS) << "TASK channel " << getName() << " start frame  "
     387           4 :                      << frameNumber << std::endl;
     388             : 
     389           4 :     bool updated = false;
     390           4 :     const Compounds& compounds = getCompounds();
     391          32 :     for (Compounds::const_iterator i = compounds.begin(); i != compounds.end();
     392             :          ++i)
     393             :     {
     394          28 :         const Compound* compound = *i;
     395          56 :         ChannelUpdateVisitor visitor(this, frameID, frameNumber);
     396             : 
     397          28 :         visitor.setEye(EYE_CYCLOP);
     398          28 :         compound->accept(visitor);
     399             : 
     400          28 :         visitor.setEye(EYE_LEFT);
     401          28 :         compound->accept(visitor);
     402             : 
     403          28 :         visitor.setEye(EYE_RIGHT);
     404          28 :         compound->accept(visitor);
     405             : 
     406          28 :         updated |= visitor.isUpdated();
     407             :     }
     408             : 
     409           4 :     send(fabric::CMD_CHANNEL_FRAME_FINISH) << context << frameNumber;
     410           4 :     LBLOG(LOG_TASKS) << "TASK channel " << getName() << " finish frame  "
     411           4 :                      << frameNumber << std::endl;
     412           4 :     _lastDrawCompound = 0;
     413             : 
     414           4 :     return updated;
     415             : }
     416             : 
     417          34 : co::ObjectOCommand Channel::send(const uint32_t cmd)
     418             : {
     419          34 :     return getNode()->send(cmd, getID());
     420             : }
     421             : 
     422             : //---------------------------------------------------------------------------
     423             : // Listener interface
     424             : //---------------------------------------------------------------------------
     425          20 : void Channel::addListener(ChannelListener* listener)
     426             : {
     427          40 :     LB_TS_SCOPED(_serverThread);
     428          20 :     LBASSERT(std::find(_listeners.begin(), _listeners.end(), listener) ==
     429             :              _listeners.end());
     430             : 
     431          20 :     _listeners.push_back(listener);
     432          20 : }
     433             : 
     434          20 : void Channel::removeListener(ChannelListener* listener)
     435             : {
     436             :     ChannelListeners::iterator i =
     437          20 :         find(_listeners.begin(), _listeners.end(), listener);
     438          20 :     if (i != _listeners.end())
     439          20 :         _listeners.erase(i);
     440          20 : }
     441             : 
     442           4 : void Channel::_fireLoadData(const uint32_t frameNumber,
     443             :                             const fabric::Statistics& statistics,
     444             :                             const Viewport& region)
     445             : {
     446           8 :     LB_TS_SCOPED(_serverThread);
     447           8 :     for (ChannelListener* listener : _listeners)
     448           4 :         listener->notifyLoadData(this, frameNumber, statistics, region);
     449           4 : }
     450             : 
     451             : //===========================================================================
     452             : // command handling
     453             : //===========================================================================
     454           4 : bool Channel::_cmdConfigInitReply(co::ICommand& cmd)
     455             : {
     456           8 :     co::ObjectICommand command(cmd);
     457           4 :     const bool result = command.read<bool>();
     458             : 
     459           4 :     LBLOG(LOG_INIT) << "handle channel configInit reply " << command
     460           4 :                     << " result " << result << std::endl;
     461             : 
     462           4 :     _state = result ? STATE_INIT_SUCCESS : STATE_INIT_FAILED;
     463           8 :     return true;
     464             : }
     465             : 
     466           4 : bool Channel::_cmdConfigExitReply(co::ICommand& cmd)
     467             : {
     468           8 :     co::ObjectICommand command(cmd);
     469           4 :     LBLOG(LOG_INIT) << "handle channel configExit reply " << command
     470           4 :                     << std::endl;
     471             : 
     472           4 :     _state = command.read<bool>() ? STATE_EXIT_SUCCESS : STATE_EXIT_FAILED;
     473           8 :     return true;
     474             : }
     475             : 
     476           4 : bool Channel::_cmdFrameFinishReply(co::ICommand& cmd)
     477             : {
     478           8 :     co::ObjectICommand command(cmd);
     479           4 :     const Viewport& region = command.read<Viewport>();
     480           4 :     const uint32_t frameNumber = command.read<uint32_t>();
     481           8 :     const Statistics& statistics = command.read<Statistics>();
     482             : 
     483           4 :     _fireLoadData(frameNumber, statistics, region);
     484           8 :     return true;
     485             : }
     486             : 
     487        1462 : bool Channel::omitOutput() const
     488             : {
     489             :     // don't print generated channels for now
     490        1462 :     return _view || _segment;
     491             : }
     492             : 
     493           0 : void Channel::output(std::ostream& os) const
     494             : {
     495           0 :     bool attrPrinted = false;
     496             : 
     497           0 :     for (IAttribute i = static_cast<IAttribute>(0); i < IATTR_LAST;
     498           0 :          i = static_cast<IAttribute>(static_cast<uint32_t>(i) + 1))
     499             :     {
     500           0 :         const int value = getIAttribute(i);
     501           0 :         if (value == Global::instance()->getChannelIAttribute(i))
     502           0 :             continue;
     503             : 
     504           0 :         if (!attrPrinted)
     505             :         {
     506           0 :             os << std::endl
     507           0 :                << "attributes" << std::endl
     508           0 :                << "{" << std::endl
     509           0 :                << lunchbox::indent;
     510           0 :             attrPrinted = true;
     511             :         }
     512             : 
     513             :         os << (i == IATTR_HINT_STATISTICS
     514             :                    ? "hint_statistics   "
     515           0 :                    : i == IATTR_HINT_SENDTOKEN ? "hint_sendtoken    "
     516           0 :                                                : "ERROR ")
     517           0 :            << static_cast<fabric::IAttribute>(value) << std::endl;
     518             :     }
     519           0 :     for (SAttribute i = static_cast<SAttribute>(0); i < SATTR_LAST;
     520           0 :          i = static_cast<SAttribute>(static_cast<uint32_t>(i) + 1))
     521             :     {
     522           0 :         const std::string& value = getSAttribute(i);
     523           0 :         if (value == Global::instance()->getChannelSAttribute(i))
     524           0 :             continue;
     525             : 
     526           0 :         if (!attrPrinted)
     527             :         {
     528           0 :             os << std::endl
     529           0 :                << "attributes" << std::endl
     530           0 :                << "{" << std::endl
     531           0 :                << lunchbox::indent;
     532           0 :             attrPrinted = true;
     533             :         }
     534             : 
     535             :         os << (i == SATTR_DUMP_IMAGE ? "dump_image        " : "ERROR ") << "\""
     536           0 :            << value << "\"" << std::endl;
     537             :     }
     538             : 
     539           0 :     if (attrPrinted)
     540           0 :         os << lunchbox::exdent << "}" << std::endl << std::endl;
     541           0 : }
     542             : 
     543           0 : void Channel::updateCapabilities()
     544             : {
     545           0 :     ViewFinder visitor(this);
     546           0 :     getConfig()->accept(visitor);
     547           0 :     ViewSet& views = visitor.getViews();
     548             : 
     549           0 :     for (ViewSet::const_iterator i = views.begin(); i != views.end(); ++i)
     550           0 :         (*i)->updateCapabilities();
     551           0 : }
     552             : }
     553             : }
     554             : 
     555             : #include "../fabric/channel.ipp"
     556             : template class eq::fabric::Channel<eq::server::Window, eq::server::Channel>;
     557             : /** @cond IGNORE */
     558             : template std::ostream& eq::fabric::operator<<(std::ostream&,
     559          60 :                                               const eq::server::Super&);
     560             : /** @endcond */

Generated by: LCOV version 1.11