LCOV - code coverage report
Current view: top level - eq/server - compoundUpdateOutputVisitor.cpp (source / functions) Hit Total Coverage
Test: Equalizer Lines: 1 158 0.6 %
Date: 2016-07-30 05:04:55 Functions: 2 10 20.0 %

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

Generated by: LCOV version 1.11