LCOV - code coverage report
Current view: top level - eq/server - channelUpdateVisitor.cpp (source / functions) Hit Total Coverage
Test: Equalizer Lines: 197 244 80.7 %
Date: 2017-12-16 05:07:20 Functions: 20 21 95.2 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2007-2013, Stefan Eilemann <eile@equalizergraphics.com>
       3             :  *               2011-2012, Daniel Nachbaur <danielnachbaur@gmail.com>
       4             :  *                    2010, 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 "channelUpdateVisitor.h"
      21             : 
      22             : #include "colorMask.h"
      23             : #include "compound.h"
      24             : #include "frame.h"
      25             : #include "log.h"
      26             : #include "node.h"
      27             : #include "observer.h"
      28             : #include "pipe.h"
      29             : #include "segment.h"
      30             : #include "tileQueue.h"
      31             : #include "view.h"
      32             : #include "window.h"
      33             : 
      34             : #include <eq/fabric/commands.h>
      35             : #include <eq/fabric/paths.h>
      36             : 
      37             : #include <set>
      38             : 
      39             : #ifndef GL_BACK_LEFT
      40             : #define GL_FRONT_LEFT 0x0400
      41             : #define GL_FRONT_RIGHT 0x0401
      42             : #define GL_BACK_LEFT 0x0402
      43             : #define GL_BACK_RIGHT 0x0403
      44             : #define GL_FRONT 0x0404
      45             : #define GL_BACK 0x0405
      46             : #endif
      47             : 
      48             : namespace eq
      49             : {
      50             : namespace server
      51             : {
      52             : using fabric::QUAD;
      53             : 
      54             : namespace
      55             : {
      56             : static bool _setDrawBuffers();
      57             : static uint32_t _drawBuffer[2][2][NUM_EYES];
      58          20 : static bool LB_UNUSED _drawBufferInit = _setDrawBuffers();
      59          20 : bool _setDrawBuffers()
      60             : {
      61          20 :     const int32_t cyclop = lunchbox::getIndexOfLastBit(EYE_CYCLOP);
      62          20 :     const int32_t left = lunchbox::getIndexOfLastBit(EYE_LEFT);
      63          20 :     const int32_t right = lunchbox::getIndexOfLastBit(EYE_RIGHT);
      64             : 
      65             :     // [stereo][doublebuffered][eye]
      66          20 :     _drawBuffer[0][0][cyclop] = GL_FRONT;
      67          20 :     _drawBuffer[0][0][left] = GL_FRONT;
      68          20 :     _drawBuffer[0][0][right] = GL_FRONT;
      69             : 
      70          20 :     _drawBuffer[0][1][cyclop] = GL_BACK;
      71          20 :     _drawBuffer[0][1][left] = GL_BACK;
      72          20 :     _drawBuffer[0][1][right] = GL_BACK;
      73             : 
      74          20 :     _drawBuffer[1][0][cyclop] = GL_FRONT;
      75          20 :     _drawBuffer[1][0][left] = GL_FRONT_LEFT;
      76          20 :     _drawBuffer[1][0][right] = GL_FRONT_RIGHT;
      77             : 
      78          20 :     _drawBuffer[1][1][cyclop] = GL_BACK;
      79          20 :     _drawBuffer[1][1][left] = GL_BACK_LEFT;
      80          20 :     _drawBuffer[1][1][right] = GL_BACK_RIGHT;
      81             : 
      82          20 :     return true;
      83             : }
      84             : }
      85             : 
      86          28 : ChannelUpdateVisitor::ChannelUpdateVisitor(Channel* channel,
      87             :                                            const uint128_t frameID,
      88          28 :                                            const uint32_t frameNumber)
      89             :     : _channel(channel)
      90             :     , _eye(EYE_CYCLOP)
      91             :     , _frameID(frameID)
      92             :     , _frameNumber(frameNumber)
      93          28 :     , _updated(false)
      94             : {
      95          28 : }
      96             : 
      97         208 : bool ChannelUpdateVisitor::_skipCompound(const Compound* compound)
      98             : {
      99         236 :     return (compound->getChannel() != _channel ||
     100         236 :             !compound->isInheritActive(_eye) ||
     101         236 :             compound->getInheritTasks() == fabric::TASK_NONE);
     102             : }
     103             : 
     104         164 : VisitorResult ChannelUpdateVisitor::visitPre(const Compound* compound)
     105             : {
     106         164 :     if (!compound->isInheritActive(_eye))
     107          72 :         return TRAVERSE_PRUNE;
     108             : 
     109          92 :     _updateDrawFinish(compound);
     110             : 
     111          92 :     if (_skipCompound(compound))
     112          88 :         return TRAVERSE_CONTINUE;
     113             : 
     114           8 :     const RenderContext& context = _setupRenderContext(compound);
     115           4 :     _updateFrameRate(compound);
     116           4 :     _updateViewStart(compound, context);
     117             : 
     118           4 :     if (compound->testInheritTask(fabric::TASK_CLEAR))
     119           4 :         _sendClear(context);
     120           4 :     return TRAVERSE_CONTINUE;
     121             : }
     122             : 
     123          20 : VisitorResult ChannelUpdateVisitor::visitLeaf(const Compound* compound)
     124             : {
     125          20 :     if (!compound->isInheritActive(_eye))
     126          12 :         return TRAVERSE_CONTINUE;
     127             : 
     128           8 :     if (_skipCompound(compound))
     129             :     {
     130           4 :         _updateDrawFinish(compound);
     131           4 :         return TRAVERSE_CONTINUE;
     132             :     }
     133             : 
     134           8 :     const RenderContext& context = _setupRenderContext(compound);
     135           4 :     _updateFrameRate(compound);
     136           4 :     _updateViewStart(compound, context);
     137           4 :     _updateDraw(compound, context);
     138           4 :     _updateDrawFinish(compound);
     139           4 :     _updatePostDraw(compound, context);
     140           4 :     return TRAVERSE_CONTINUE;
     141             : }
     142             : 
     143          92 : VisitorResult ChannelUpdateVisitor::visitPost(const Compound* compound)
     144             : {
     145          92 :     if (_skipCompound(compound))
     146          88 :         return TRAVERSE_CONTINUE;
     147             : 
     148           8 :     const RenderContext& context = _setupRenderContext(compound);
     149           4 :     _updatePostDraw(compound, context);
     150             : 
     151           4 :     return TRAVERSE_CONTINUE;
     152             : }
     153             : 
     154          12 : RenderContext ChannelUpdateVisitor::_setupRenderContext(
     155             :     const Compound* compound)
     156             : {
     157          12 :     const Channel* destChannel = compound->getInheritChannel();
     158          12 :     LBASSERT(destChannel);
     159             : 
     160          12 :     RenderContext context = compound->setupRenderContext(_eye);
     161          12 :     context.frameID = _frameID;
     162          12 :     context.buffer = _getDrawBuffer(compound);
     163          12 :     context.bufferMask = _getDrawBufferMask(compound);
     164          12 :     context.view = destChannel->getViewVersion();
     165             : 
     166          12 :     const View* view = destChannel->getView();
     167          12 :     LBASSERT(context.view == co::ObjectVersion(view));
     168             : 
     169          12 :     if (view)
     170             :     {
     171             :         // compute inherit vp (part of view covered by segment/view channel)
     172          12 :         const Segment* segment = destChannel->getSegment();
     173          12 :         LBASSERT(segment);
     174             : 
     175          12 :         const PixelViewport& pvp = destChannel->getPixelViewport();
     176          12 :         if (pvp.hasArea())
     177          12 :             context.vp.applyView(segment->getViewport(), view->getViewport(),
     178          12 :                                  pvp, destChannel->getOverdraw());
     179             :     }
     180             : 
     181          12 :     if (_channel != destChannel)
     182             :     {
     183           2 :         const PixelViewport& nativePVP = _channel->getPixelViewport();
     184           2 :         context.pvp.x = nativePVP.x;
     185           2 :         context.pvp.y = nativePVP.y;
     186             :     }
     187             :     // TODO: pvp size overcommit check?
     188             : 
     189          12 :     return context;
     190             : }
     191             : 
     192           4 : void ChannelUpdateVisitor::_updateDraw(const Compound* compound,
     193             :                                        const RenderContext& context)
     194             : {
     195           4 :     if (compound->hasTiles())
     196             :     {
     197           0 :         _updateDrawTiles(compound, context);
     198           0 :         return;
     199             :     }
     200             : 
     201           4 :     if (compound->testInheritTask(fabric::TASK_CLEAR))
     202           2 :         _sendClear(context);
     203             : 
     204           4 :     if (compound->testInheritTask(fabric::TASK_DRAW))
     205             :     {
     206           4 :         const bool finish = _channel->hasListeners(); // finish for eq stats
     207           4 :         _channel->send(fabric::CMD_CHANNEL_FRAME_DRAW) << context << finish;
     208           4 :         _updated = true;
     209           4 :         LBLOG(LOG_TASKS) << "TASK draw " << _channel->getName() << " " << finish
     210           4 :                          << std::endl;
     211             :     }
     212             : }
     213             : 
     214           0 : void ChannelUpdateVisitor::_updateDrawTiles(const Compound* compound,
     215             :                                             const RenderContext& context)
     216             : {
     217           0 :     Frames frames;
     218           0 :     co::ObjectVersions frameIDs;
     219           0 :     const Frames& outputFrames = compound->getOutputFrames();
     220           0 :     for (FramesCIter i = outputFrames.begin(); i != outputFrames.end(); ++i)
     221             :     {
     222           0 :         Frame* frame = *i;
     223             : 
     224           0 :         if (!frame->hasData(_eye)) // TODO: filter: buffers, vp, eye
     225           0 :             continue;
     226             : 
     227           0 :         frames.push_back(frame);
     228           0 :         frameIDs.push_back(co::ObjectVersion(frame));
     229             :     }
     230             : 
     231           0 :     const Channel* destChannel = compound->getInheritChannel();
     232           0 :     const TileQueues& inputQueues = compound->getInputTileQueues();
     233           0 :     for (TileQueuesCIter i = inputQueues.begin(); i != inputQueues.end(); ++i)
     234             :     {
     235           0 :         const TileQueue* inputQueue = *i;
     236           0 :         const TileQueue* outputQueue = inputQueue->getOutputQueue(context.eye);
     237           0 :         const uint128_t& id = outputQueue->getQueueMasterID(context.eye);
     238           0 :         LBASSERT(id != 0);
     239             : 
     240           0 :         const bool isLocal = (_channel == destChannel);
     241           0 :         const uint32_t tasks = compound->getInheritTasks() &
     242             :                                (eq::fabric::TASK_CLEAR | eq::fabric::TASK_DRAW |
     243           0 :                                 eq::fabric::TASK_READBACK);
     244             : 
     245           0 :         _channel->send(fabric::CMD_CHANNEL_FRAME_TILES)
     246           0 :             << context << isLocal << id << tasks << frameIDs;
     247           0 :         _updated = true;
     248           0 :         LBLOG(LOG_TASKS) << "TASK tiles " << _channel->getName() << " "
     249           0 :                          << std::endl;
     250             :     }
     251           0 : }
     252             : 
     253         100 : void ChannelUpdateVisitor::_updateDrawFinish(const Compound* compound) const
     254             : {
     255         100 :     const Compound* lastDrawCompound = _channel->getLastDrawCompound();
     256         100 :     if (lastDrawCompound && lastDrawCompound != compound)
     257          96 :         return;
     258             : 
     259             :     // Only pass if this is the last eye pass of this compound
     260           4 :     if (!compound->isLastInheritEye(_eye))
     261           0 :         return;
     262             : 
     263           4 :     if (!lastDrawCompound)
     264           0 :         _channel->setLastDrawCompound(compound);
     265             : 
     266             :     // Channel::frameDrawFinish
     267           4 :     Node* node = _channel->getNode();
     268             : 
     269           8 :     node->send(fabric::CMD_CHANNEL_FRAME_DRAW_FINISH, _channel->getID())
     270           8 :         << _frameID << _frameNumber;
     271           4 :     LBLOG(LOG_TASKS) << "TASK channel draw finish " << _channel->getName()
     272           0 :                      << " frame " << _frameNumber << " id " << _frameID
     273           4 :                      << std::endl;
     274             : 
     275             :     // Window::frameDrawFinish
     276           4 :     Window* window = _channel->getWindow();
     277           4 :     const Channel* lastDrawChannel = window->getLastDrawChannel();
     278             : 
     279           4 :     if (lastDrawChannel && lastDrawChannel != _channel)
     280           0 :         return;
     281             : 
     282           4 :     window->setLastDrawChannel(_channel); // in case not set
     283             : 
     284           8 :     node->send(fabric::CMD_WINDOW_FRAME_DRAW_FINISH, window->getID())
     285           8 :         << _frameID << _frameNumber;
     286           4 :     LBLOG(LOG_TASKS) << "TASK window draw finish " << window->getName()
     287           0 :                      << " frame " << _frameNumber << " id " << _frameID
     288           4 :                      << std::endl;
     289             : 
     290             :     // Pipe::frameDrawFinish
     291           4 :     Pipe* pipe = _channel->getPipe();
     292           4 :     const Window* lastDrawWindow = pipe->getLastDrawWindow();
     293           4 :     if (lastDrawWindow && lastDrawWindow != window)
     294           0 :         return;
     295             : 
     296           4 :     pipe->setLastDrawWindow(window); // in case not set
     297             : 
     298           8 :     node->send(fabric::CMD_PIPE_FRAME_DRAW_FINISH, pipe->getID())
     299           8 :         << _frameID << _frameNumber;
     300           4 :     LBLOG(LOG_TASKS) << "TASK pipe draw finish " << pipe->getName() << " frame "
     301           4 :                      << _frameNumber << " id " << _frameID << std::endl;
     302             : 
     303             :     // Node::frameDrawFinish
     304           4 :     const Pipe* lastDrawPipe = node->getLastDrawPipe();
     305           4 :     if (lastDrawPipe && lastDrawPipe != pipe)
     306           2 :         return;
     307             : 
     308           2 :     node->setLastDrawPipe(pipe); // in case not set
     309             : 
     310           4 :     node->send(fabric::CMD_NODE_FRAME_DRAW_FINISH, node->getID())
     311           4 :         << _frameID << _frameNumber;
     312           2 :     LBLOG(LOG_TASKS) << "TASK node draw finish " << node->getName() << " "
     313           2 :                      << std::endl;
     314             : }
     315             : 
     316           6 : void ChannelUpdateVisitor::_sendClear(const RenderContext& context)
     317             : {
     318           6 :     _channel->send(fabric::CMD_CHANNEL_FRAME_CLEAR) << context;
     319           6 :     _updated = true;
     320           6 :     LBLOG(LOG_TASKS) << "TASK clear " << _channel->getName() << " "
     321           6 :                      << std::endl;
     322           6 : }
     323             : 
     324           8 : void ChannelUpdateVisitor::_updateFrameRate(const Compound* compound) const
     325             : {
     326           8 :     const float maxFPS = compound->getInheritMaxFPS();
     327           8 :     Window* window = _channel->getWindow();
     328             : 
     329           8 :     if (maxFPS < window->getMaxFPS())
     330           0 :         window->setMaxFPS(maxFPS);
     331           8 : }
     332             : 
     333          12 : uint32_t ChannelUpdateVisitor::_getDrawBuffer(const Compound* compound) const
     334             : {
     335          12 :     const DrawableConfig& dc = _channel->getWindow()->getDrawableConfig();
     336          12 :     const int32_t eye = lunchbox::getIndexOfLastBit(_eye);
     337             : 
     338          12 :     if (compound->getInheritIAttribute(Compound::IATTR_STEREO_MODE) == QUAD)
     339           0 :         return _drawBuffer[dc.stereo][dc.doublebuffered][eye];
     340          12 :     return _drawBuffer[0][dc.doublebuffered][eye];
     341             : }
     342             : 
     343          12 : fabric::ColorMask ChannelUpdateVisitor::_getDrawBufferMask(
     344             :     const Compound* compound) const
     345             : {
     346          12 :     if (compound->getInheritIAttribute(Compound::IATTR_STEREO_MODE) !=
     347             :         fabric::ANAGLYPH)
     348             :     {
     349           0 :         return ColorMask::ALL;
     350             :     }
     351             : 
     352          12 :     switch (_eye)
     353             :     {
     354             :     case EYE_LEFT:
     355           0 :         return ColorMask(compound->getInheritIAttribute(
     356           0 :             Compound::IATTR_STEREO_ANAGLYPH_LEFT_MASK));
     357             :     case EYE_RIGHT:
     358           0 :         return ColorMask(compound->getInheritIAttribute(
     359           0 :             Compound::IATTR_STEREO_ANAGLYPH_RIGHT_MASK));
     360             :     default:
     361          12 :         return ColorMask::ALL;
     362             :     }
     363             : }
     364             : 
     365           8 : void ChannelUpdateVisitor::_updatePostDraw(const Compound* compound,
     366             :                                            const RenderContext& context)
     367             : {
     368           8 :     _updateAssemble(compound, context);
     369           8 :     _updateReadback(compound, context);
     370           8 :     _updateViewFinish(compound, context);
     371           8 : }
     372             : 
     373           8 : void ChannelUpdateVisitor::_updateAssemble(const Compound* compound,
     374             :                                            const RenderContext& context)
     375             : {
     376           8 :     if (!compound->testInheritTask(fabric::TASK_ASSEMBLE))
     377          12 :         return;
     378             : 
     379           2 :     const Frames& inputFrames = compound->getInputFrames();
     380           2 :     LBASSERT(!inputFrames.empty());
     381             : 
     382           4 :     co::ObjectVersions frames;
     383          12 :     for (Frames::const_iterator iter = inputFrames.begin();
     384           8 :          iter != inputFrames.end(); ++iter)
     385             :     {
     386           2 :         Frame* frame = *iter;
     387             : 
     388           2 :         if (!frame->hasData(_eye)) // TODO: filter: buffers, vp, eye
     389           0 :             continue;
     390             : 
     391           2 :         LBLOG(LOG_ASSEMBLY) << *frame << std::endl;
     392           2 :         frames.push_back(co::ObjectVersion(frame));
     393             :     }
     394             : 
     395           2 :     if (frames.empty())
     396           0 :         return;
     397             : 
     398             :     // assemble task
     399           2 :     LBLOG(LOG_ASSEMBLY | LOG_TASKS) << "TASK assemble " << _channel->getName()
     400           0 :                                     << " nFrames " << frames.size()
     401           2 :                                     << std::endl;
     402           2 :     _channel->send(fabric::CMD_CHANNEL_FRAME_ASSEMBLE) << context << frames;
     403           2 :     _updated = true;
     404             : }
     405             : 
     406           8 : void ChannelUpdateVisitor::_updateReadback(const Compound* compound,
     407             :                                            const RenderContext& context)
     408             : {
     409          16 :     if (!compound->testInheritTask(fabric::TASK_READBACK) ||
     410           2 :         (compound->hasTiles() && compound->isLeaf()))
     411             :     {
     412          12 :         return;
     413             :     }
     414             : 
     415           2 :     const std::vector<Frame*>& outputFrames = compound->getOutputFrames();
     416           2 :     LBASSERT(!outputFrames.empty());
     417             : 
     418           4 :     co::ObjectVersions frames;
     419           4 :     for (FramesCIter i = outputFrames.begin(); i != outputFrames.end(); ++i)
     420             :     {
     421           2 :         Frame* frame = *i;
     422             : 
     423           2 :         if (!frame->hasData(_eye)) // TODO: filter: buffers, vp, eye
     424           0 :             continue;
     425             : 
     426           2 :         frames.push_back(co::ObjectVersion(frame));
     427           2 :         LBLOG(LOG_ASSEMBLY) << *frame << std::endl;
     428             :     }
     429             : 
     430           2 :     if (frames.empty())
     431           0 :         return;
     432             : 
     433             :     // readback task
     434           2 :     _channel->send(fabric::CMD_CHANNEL_FRAME_READBACK) << context << frames;
     435           2 :     _updated = true;
     436           2 :     LBLOG(LOG_ASSEMBLY | LOG_TASKS) << "TASK readback " << _channel->getName()
     437           0 :                                     << " nFrames " << frames.size()
     438           2 :                                     << std::endl;
     439             : }
     440             : 
     441           8 : void ChannelUpdateVisitor::_updateViewStart(const Compound* compound,
     442             :                                             const RenderContext& context)
     443             : {
     444           8 :     LBASSERT(!_skipCompound(compound));
     445           8 :     if (!compound->testInheritTask(fabric::TASK_VIEW))
     446           6 :         return;
     447             : 
     448             :     // view start task
     449           2 :     LBLOG(LOG_TASKS) << "TASK view start " << _channel->getName() << std::endl;
     450           2 :     _channel->send(fabric::CMD_CHANNEL_FRAME_VIEW_START) << context;
     451             : }
     452             : 
     453           8 : void ChannelUpdateVisitor::_updateViewFinish(const Compound* compound,
     454             :                                              const RenderContext& context)
     455             : {
     456           8 :     LBASSERT(!_skipCompound(compound));
     457           8 :     if (!compound->testInheritTask(fabric::TASK_VIEW))
     458           6 :         return;
     459             : 
     460             :     // view finish task
     461           2 :     LBLOG(LOG_TASKS) << "TASK view finish " << _channel->getName() << " "
     462           2 :                      << std::endl;
     463           2 :     _channel->send(fabric::CMD_CHANNEL_FRAME_VIEW_FINISH) << context;
     464             : }
     465             : }
     466          60 : }

Generated by: LCOV version 1.11