LCOV - code coverage report
Current view: top level - eq/server - compoundUpdateOutputVisitor.cpp (source / functions) Hit Total Coverage
Test: Equalizer Lines: 77 157 49.0 %
Date: 2017-12-16 05:07:20 Functions: 8 10 80.0 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2007-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 "compoundUpdateOutputVisitor.h"
      20             : 
      21             : #include "config.h"
      22             : #include "frame.h"
      23             : #include "frameData.h"
      24             : #include "log.h"
      25             : #include "server.h"
      26             : #include "tileQueue.h"
      27             : #include "window.h"
      28             : 
      29             : #include "tiles/zigzagStrategy.h"
      30             : 
      31             : #include <eq/fabric/iAttribute.h>
      32             : #include <eq/fabric/tile.h>
      33             : 
      34             : namespace eq
      35             : {
      36             : namespace server
      37             : {
      38          28 : CompoundUpdateOutputVisitor::CompoundUpdateOutputVisitor(const uint32_t frame)
      39          28 :     : _frameNumber(frame)
      40             : {
      41          28 : }
      42             : 
      43          72 : VisitorResult CompoundUpdateOutputVisitor::visit(Compound* compound)
      44             : {
      45          72 :     if (!compound->isActive())
      46          28 :         return TRAVERSE_PRUNE;
      47             : 
      48          44 :     _updateQueues(compound);
      49          44 :     _updateFrames(compound);
      50          44 :     _updateSwapBarriers(compound);
      51             : 
      52          44 :     return TRAVERSE_CONTINUE;
      53             : }
      54             : 
      55          44 : void CompoundUpdateOutputVisitor::_updateQueues(Compound* compound)
      56             : {
      57          44 :     const TileQueues& queues = compound->getOutputTileQueues();
      58          44 :     for (TileQueuesCIter i = queues.begin(); i != queues.end(); ++i)
      59             :     {
      60             :         //----- Check uniqueness of output queue name
      61           0 :         TileQueue* queue = *i;
      62           0 :         const std::string& name = queue->getName();
      63             : 
      64           0 :         if (_outputTileQueues.find(name) != _outputTileQueues.end())
      65             :         {
      66           0 :             LBWARN << "Multiple output queues of the same name are unsupported"
      67           0 :                    << ", ignoring output queue " << name << std::endl;
      68           0 :             queue->unsetData();
      69           0 :             continue;
      70             :         }
      71             : 
      72           0 :         queue->cycleData(_frameNumber, compound);
      73             : 
      74             :         //----- Generate tile task commands
      75           0 :         _generateTiles(queue, compound);
      76           0 :         _outputTileQueues[name] = queue;
      77             :     }
      78          44 : }
      79             : 
      80          44 : void CompoundUpdateOutputVisitor::_updateFrames(Compound* compound)
      81             : {
      82          44 :     const Frames& outputFrames = compound->getOutputFrames();
      83          44 :     if (outputFrames.empty())
      84          40 :         compound->unsetInheritTask(fabric::TASK_READBACK);
      85             : 
      86          44 :     const Channel* channel = compound->getChannel();
      87          44 :     if (!compound->testInheritTask(fabric::TASK_READBACK) || !channel)
      88          40 :         return;
      89             : 
      90           8 :     for (FramesCIter i = outputFrames.begin(); i != outputFrames.end(); ++i)
      91             :     {
      92             :         //----- Check uniqueness of output frame name
      93           4 :         Frame* frame = *i;
      94           4 :         const std::string& name = frame->getName();
      95             : 
      96           4 :         if (_outputFrames.find(name) != _outputFrames.end())
      97             :         {
      98           0 :             LBWARN << "Multiple output frames of the same name are unsupported"
      99           0 :                    << ", ignoring output frame " << name << std::endl;
     100           0 :             frame->unsetData();
     101           0 :             continue;
     102             :         }
     103             : 
     104             :         //----- compute readback area
     105           4 :         const Viewport& frameVP = frame->getViewport();
     106           4 :         const PixelViewport& inheritPVP = compound->getInheritPixelViewport();
     107           4 :         PixelViewport framePVP(inheritPVP);
     108           4 :         framePVP.apply(frameVP);
     109             : 
     110           4 :         if (!framePVP.hasArea()) // output frame has no pixels
     111             :         {
     112           0 :             LBINFO << "Skipping output frame " << name << ", no pixels"
     113           0 :                    << std::endl;
     114           0 :             frame->unsetData();
     115           0 :             continue;
     116             :         }
     117             : 
     118             :         //----- Create new frame datas
     119             :         // * one frame data used for each eye pass
     120             :         // * data is set only on master frame data (will copy to all others)
     121           4 :         frame->cycleData(_frameNumber, compound);
     122           4 :         FrameData* frameData = frame->getMasterData();
     123           4 :         LBASSERT(frameData);
     124             : 
     125           4 :         LBLOG(LOG_ASSEMBLY)
     126           0 :             << lunchbox::disableFlush << "Output frame \"" << name << "\" id "
     127           4 :             << frame->getID() << " v" << frame->getVersion() + 1 << " data id "
     128           4 :             << frameData->getID() << " v" << frameData->getVersion() + 1
     129           0 :             << " on channel \"" << channel->getName() << "\" tile pos "
     130          12 :             << framePVP.x << ", " << framePVP.y;
     131             : 
     132             :         //----- Set frame data parameters:
     133             :         // 1) offset is position wrt destination view, used only by input frames
     134           4 :         const bool tiled = !compound->getInputTileQueues().empty();
     135           8 :         frameData->setOffset(tiled ? Vector2i(0, 0)
     136           8 :                                    : Vector2i(framePVP.x, framePVP.y));
     137             : 
     138             :         // 2) pvp is area within channel
     139           4 :         framePVP.x = static_cast<int32_t>(frameVP.x * inheritPVP.w);
     140           4 :         framePVP.y = static_cast<int32_t>(frameVP.y * inheritPVP.h);
     141           4 :         frameData->setPixelViewport(framePVP);
     142             : 
     143             :         // 3) image buffers and storage type
     144           4 :         const Frame::Buffer buffers = frame->getBuffers();
     145             : 
     146           4 :         frameData->setType(frame->getType());
     147           4 :         frameData->setBuffers(buffers == Frame::Buffer::undefined
     148             :                                   ? compound->getInheritBuffers()
     149           4 :                                   : buffers);
     150             : 
     151             :         // 4) (source) render context
     152           4 :         frameData->setContext(compound->setupRenderContext(EYE_CYCLOP));
     153             : 
     154             :         //----- Set frame parameters:
     155             :         // 1) offset is position wrt window, i.e., the channel position
     156           4 :         if (compound->getInheritChannel() == channel)
     157           0 :             frame->setOffset(Vector2i(inheritPVP.x, inheritPVP.y));
     158             :         else
     159             :         {
     160           4 :             const PixelViewport& nativePVP = channel->getPixelViewport();
     161           4 :             frame->setOffset(Vector2i(nativePVP.x, nativePVP.y));
     162             :         }
     163             : 
     164             :         // 2) zoom
     165           4 :         _updateZoom(compound, frame);
     166             : 
     167             :         //----- Commit
     168           4 :         frame->commitData();
     169             : 
     170           4 :         _outputFrames[name] = frame;
     171           4 :         LBLOG(LOG_ASSEMBLY)
     172           0 :             << " buffers " << frameData->getBuffers() << " read area "
     173           0 :             << framePVP << " readback " << frame->getZoom() << " assemble "
     174           4 :             << frameData->getZoom() << lunchbox::enableFlush << std::endl;
     175             :     }
     176             : }
     177             : 
     178           0 : void CompoundUpdateOutputVisitor::_generateTiles(TileQueue* queue,
     179             :                                                  Compound* compound)
     180             : {
     181           0 :     const Vector2i& tileSize = queue->getTileSize();
     182           0 :     const PixelViewport pvp = compound->getInheritPixelViewport();
     183           0 :     if (!pvp.hasArea())
     184           0 :         return;
     185             : 
     186           0 :     const Vector2i dim(pvp.w / tileSize.x() + ((pvp.w % tileSize.x()) ? 1 : 0),
     187           0 :                        pvp.h / tileSize.y() + ((pvp.h % tileSize.y()) ? 1 : 0));
     188             : 
     189           0 :     std::vector<Vector2i> tiles;
     190           0 :     tiles.reserve(dim.x() * dim.y());
     191             : 
     192           0 :     tiles::generateZigzag(tiles, dim);
     193           0 :     _addTilesToQueue(queue, compound, tiles);
     194             : }
     195             : 
     196           0 : void CompoundUpdateOutputVisitor::_addTilesToQueue(
     197             :     TileQueue* queue, Compound* compound, const std::vector<Vector2i>& tiles)
     198             : {
     199           0 :     const Vector2i& tileSize = queue->getTileSize();
     200           0 :     PixelViewport pvp = compound->getInheritPixelViewport();
     201           0 :     const double xFraction = 1.0 / pvp.w;
     202           0 :     const double yFraction = 1.0 / pvp.h;
     203             : 
     204           0 :     for (std::vector<Vector2i>::const_iterator i = tiles.begin();
     205           0 :          i != tiles.end(); ++i)
     206             :     {
     207           0 :         const Vector2i& tile = *i;
     208           0 :         PixelViewport tilePVP(tile.x() * tileSize.x(), tile.y() * tileSize.y(),
     209           0 :                               tileSize.x(), tileSize.y());
     210             : 
     211           0 :         if (tilePVP.x + tileSize.x() > pvp.w) // no full tile
     212           0 :             tilePVP.w = pvp.w - tilePVP.x;
     213             : 
     214           0 :         if (tilePVP.y + tileSize.y() > pvp.h) // no full tile
     215           0 :             tilePVP.h = pvp.h - tilePVP.y;
     216             : 
     217           0 :         const Viewport tileVP(tilePVP.x * xFraction, tilePVP.y * yFraction,
     218           0 :                               tilePVP.w * xFraction, tilePVP.h * yFraction);
     219             : 
     220           0 :         for (fabric::Eye eye = fabric::EYE_CYCLOP; eye < fabric::EYES_ALL;
     221           0 :              eye = fabric::Eye(eye << 1))
     222             :         {
     223           0 :             if (!(compound->getInheritEyes() & eye) ||
     224           0 :                 !compound->isInheritActive(eye))
     225             :             {
     226           0 :                 continue;
     227             :             }
     228             : 
     229           0 :             Tile tileItem(tilePVP, tileVP);
     230             :             compound->computeTileFrustum(tileItem.frustum, eye, tileItem.vp,
     231           0 :                                          false);
     232             :             compound->computeTileFrustum(tileItem.ortho, eye, tileItem.vp,
     233           0 :                                          true);
     234           0 :             queue->addTile(tileItem, eye);
     235             :         }
     236             :     }
     237           0 : }
     238             : 
     239           4 : void CompoundUpdateOutputVisitor::_updateZoom(const Compound* compound,
     240             :                                               Frame* frame)
     241             : {
     242           4 :     Zoom zoom = frame->getNativeZoom();
     243           4 :     Zoom zoom_1;
     244             : 
     245           4 :     if (!zoom.isValid()) // if zoom is not set, auto-calculate from parent
     246             :     {
     247           4 :         zoom_1 = compound->getInheritZoom();
     248           4 :         LBASSERT(zoom_1.isValid());
     249           4 :         zoom.x() = 1.0f / zoom_1.x();
     250           4 :         zoom.y() = 1.0f / zoom_1.y();
     251             :     }
     252             :     else
     253             :     {
     254           0 :         zoom_1.x() = 1.0f / zoom.x();
     255           0 :         zoom_1.y() = 1.0f / zoom.y();
     256             :     }
     257             : 
     258           4 :     if (frame->getType() == Frame::TYPE_TEXTURE)
     259             :     {
     260           0 :         FrameData* frameData = frame->getMasterData();
     261           0 :         frameData->setZoom(zoom_1); // textures are zoomed by input frame
     262           0 :         frame->setZoom(Zoom::NONE);
     263             :     }
     264             :     else
     265             :     {
     266           4 :         Zoom inputZoom;
     267             :         /* Output frames downscale pixel data during readback, and upscale it on
     268             :          * the input frame by setting the input frame's inherit zoom. */
     269           4 :         if (zoom.x() > 1.0f)
     270             :         {
     271           0 :             inputZoom.x() = zoom_1.x();
     272           0 :             zoom.x() = 1.f;
     273             :         }
     274           4 :         if (zoom.y() > 1.0f)
     275             :         {
     276           0 :             inputZoom.y() = zoom_1.y();
     277           0 :             zoom.y() = 1.f;
     278             :         }
     279             : 
     280           4 :         FrameData* frameData = frame->getMasterData();
     281           4 :         frameData->setZoom(inputZoom);
     282           4 :         frame->setZoom(zoom);
     283             :     }
     284           4 : }
     285             : 
     286          44 : void CompoundUpdateOutputVisitor::_updateSwapBarriers(Compound* compound)
     287             : {
     288          44 :     SwapBarrierConstPtr swapBarrier = compound->getSwapBarrier();
     289          44 :     if (!swapBarrier)
     290          44 :         return;
     291             : 
     292           0 :     Window* window = compound->getWindow();
     293           0 :     LBASSERT(window);
     294           0 :     if (!window)
     295           0 :         return;
     296             : 
     297           0 :     if (swapBarrier->isNvSwapBarrier())
     298             :     {
     299           0 :         if (!window->hasNVSwapBarrier())
     300             :         {
     301           0 :             const std::string name("__NV_swap_group_protection_barrier__");
     302           0 :             _swapBarriers[name] =
     303           0 :                 window->joinNVSwapBarrier(swapBarrier, _swapBarriers[name]);
     304             :         }
     305             :     }
     306             :     else
     307             :     {
     308           0 :         const std::string& name = swapBarrier->getName();
     309           0 :         _swapBarriers[name] = window->joinSwapBarrier(_swapBarriers[name]);
     310             :     }
     311             : }
     312             : }
     313          60 : }

Generated by: LCOV version 1.11