compoundUpdateOutputVisitor.cpp

00001 
00002 /* Copyright (c) 2007-2010, Stefan Eilemann <eile@equalizergraphics.com> 
00003  *
00004  * This library is free software; you can redistribute it and/or modify it under
00005  * the terms of the GNU Lesser General Public License version 2.1 as published
00006  * by the Free Software Foundation.
00007  *  
00008  * This library is distributed in the hope that it will be useful, but WITHOUT
00009  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00010  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00011  * details.
00012  * 
00013  * You should have received a copy of the GNU Lesser General Public License
00014  * along with this library; if not, write to the Free Software Foundation, Inc.,
00015  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00016  */
00017 
00018 #include "compoundUpdateOutputVisitor.h"
00019 
00020 #include "frame.h"
00021 #include "frameData.h"
00022 #include "swapBarrier.h"
00023 #include "window.h"
00024 
00025 #include <eq/client/log.h>
00026 
00027 using namespace std;
00028 using namespace stde;
00029 using namespace eq::base;
00030 
00031 namespace eq
00032 {
00033 namespace server
00034 {
00035 CompoundUpdateOutputVisitor::CompoundUpdateOutputVisitor(  
00036     const uint32_t frameNumber )
00037         : _frameNumber( frameNumber )
00038 {}
00039 
00040 VisitorResult CompoundUpdateOutputVisitor::visit( Compound* compound )
00041 {
00042     if( !compound->isActive( ))
00043         return TRAVERSE_PRUNE;    
00044 
00045     _updateOutput( compound );
00046     _updateSwapBarriers( compound );
00047 
00048     return TRAVERSE_CONTINUE;    
00049 }
00050 
00051 void CompoundUpdateOutputVisitor::_updateOutput( Compound* compound )
00052 {
00053     const std::vector< Frame* >& outputFrames = compound->getOutputFrames();
00054     const Channel*               channel      = compound->getChannel();
00055 
00056     if( !compound->testInheritTask( eq::TASK_READBACK ) || !channel )
00057         return;
00058 
00059     if( outputFrames.empty( ))
00060     {
00061         compound->unsetInheritTask( eq::TASK_READBACK );
00062         return;
00063     }
00064 
00065     for( vector<Frame*>::const_iterator i = outputFrames.begin(); 
00066          i != outputFrames.end(); ++i )
00067     {
00068         //----- Check uniqueness of output frame name
00069         Frame*             frame  = *i;
00070         const std::string& name   = frame->getName();
00071 
00072         if( _outputFrames.find( name ) != _outputFrames.end())
00073         {
00074             EQWARN << "Multiple output frames of the same name are unsupported"
00075                    << ", ignoring output frame " << name << endl;
00076             frame->unsetData();
00077             continue;
00078         }
00079 
00080         //----- compute readback area
00081         const eq::Viewport& frameVP = frame->getViewport();
00082         const eq::PixelViewport& inheritPVP=compound->getInheritPixelViewport();
00083         eq::PixelViewport framePVP = inheritPVP.getSubPVP( frameVP );
00084         
00085         if( !framePVP.hasArea( )) // output frame has no pixels
00086         {
00087             EQINFO << "Skipping output frame " << name << ", no pixels" << endl;
00088             frame->unsetData();
00089             continue;
00090         }
00091 
00092         //----- Create new frame datas
00093         //      one frame data used for each eye pass
00094         //      data is set only on master frame data (will copy to all others)
00095         frame->cycleData( _frameNumber, compound->getInheritEyes( ));
00096         FrameData* frameData = frame->getMasterData();
00097         EQASSERT( frameData );
00098 
00099         EQLOG( eq::LOG_ASSEMBLY )
00100             << disableFlush << "Output frame \"" << name << "\" id " 
00101             << frame->getID() << " v" << frame->getVersion()+1
00102             << " data id " << frameData->getID() << " v" 
00103             << frameData->getVersion() + 1 << " on channel \""
00104             << channel->getName() << "\" tile pos " << framePVP.x << ", " 
00105             << framePVP.y;
00106 
00107         //----- Set frame data parameters:
00108         // 1) offset is position wrt destination view
00109         frameData->setOffset( Vector2i( framePVP.x, framePVP.y ));
00110 
00111         // 2) pvp is area within channel
00112         framePVP.x = (int32_t)(frameVP.x * inheritPVP.w);
00113         framePVP.y = (int32_t)(frameVP.y * inheritPVP.h);
00114         frameData->setPixelViewport( framePVP );
00115 
00116         // 3) image buffers and storage type
00117         uint32_t buffers = frame->getBuffers();
00118 
00119         frameData->setType( frame->getType() );
00120         frameData->setBuffers( buffers == eq::Frame::BUFFER_UNDEFINED ? 
00121                                    compound->getInheritBuffers() : buffers );
00122 
00123         // 4) (source) render context
00124         frameData->setRange( compound->getInheritRange( ));
00125         frameData->setPixel( compound->getInheritPixel( ));
00126         frameData->setSubPixel( compound->getInheritSubPixel( ));
00127         frameData->setPeriod( compound->getInheritPeriod( ));
00128         frameData->setPhase( compound->getInheritPhase( ));
00129 
00130         //----- Set frame parameters:
00131         // 1) offset is position wrt window, i.e., the channel position
00132         if( compound->getInheritChannel() == channel ||
00133             compound->getIAttribute( Compound::IATTR_HINT_OFFSET ) == eq::ON )
00134         {
00135             frame->setInheritOffset( Vector2i( inheritPVP.x, inheritPVP.y ));
00136         }
00137         else
00138         {
00139             const eq::PixelViewport& nativePVP = channel->getPixelViewport();
00140             frame->setInheritOffset( Vector2i( nativePVP.x, nativePVP.y ));
00141         }
00142 
00143         // 2) zoom
00144         _updateZoom( compound, frame );
00145 
00146         //----- Commit
00147         frame->commitData();
00148         frame->commit();
00149 
00150         _outputFrames[name] = frame;
00151         EQLOG( eq::LOG_ASSEMBLY ) 
00152             << " buffers " << frameData->getBuffers() << " read area "
00153             << framePVP << " readback " << frame->getInheritZoom()
00154             << " assemble " << frameData->getZoom() << endl << enableFlush;
00155     }
00156 }
00157 
00158 void CompoundUpdateOutputVisitor::_updateZoom( const Compound* compound,
00159                                                Frame* frame )
00160 {
00161     eq::Zoom zoom = frame->getZoom();
00162     eq::Zoom zoom_1;
00163 
00164     if( !zoom.isValid( )) // if zoom is not set, auto-calculate from parent
00165     {
00166         zoom_1 = compound->getInheritZoom();
00167         EQASSERT( zoom_1.isValid( ));
00168         zoom.x() = 1.0f / zoom_1.x();
00169         zoom.y() = 1.0f / zoom_1.y();
00170     }
00171     else
00172     {
00173         zoom_1.x() = 1.0f / zoom.x();
00174         zoom_1.y() = 1.0f / zoom.y();
00175     }
00176 
00177     if( frame->getType( ) == eq::Frame::TYPE_TEXTURE )
00178     {
00179         FrameData* frameData = frame->getMasterData();
00180         frameData->setZoom( zoom_1 ); // textures are zoomed by input frame
00181         frame->setInheritZoom( eq::Zoom( ));
00182     }
00183     else
00184     {
00185         eq::Zoom inputZoom;
00186         /* Output frames downscale pixel data during readback, and upscale it on
00187          * the input frame by setting the input frame's inherit zoom. */
00188         if( zoom.x() > 1.0f )
00189         {
00190             inputZoom.x() = zoom_1.x();
00191             zoom.x()      = 1.f;
00192         }
00193         if( zoom.y() > 1.0f )
00194         {
00195             inputZoom.y() = zoom_1.y();
00196             zoom.y()      = 1.f;
00197         }
00198 
00199         FrameData* frameData = frame->getMasterData();
00200         frameData->setZoom( inputZoom );
00201         frame->setInheritZoom( zoom );                
00202     }
00203 }
00204 
00205 void CompoundUpdateOutputVisitor::_updateSwapBarriers( Compound* compound )
00206 {
00207     const SwapBarrier* swapBarrier = compound->getSwapBarrier();
00208     if( !swapBarrier )
00209         return;
00210 
00211     Window* window = compound->getWindow();
00212     EQASSERT( window );
00213     if( !window )
00214         return;
00215 
00216     if( swapBarrier->isNvSwapBarrier( ))
00217     {
00218         if( !window->hasNVSwapBarrier( ))
00219         {
00220             const std::string name( "__NV_swap_group_protection_barrier__" );
00221             _swapBarriers[name] = 
00222                 window->joinNVSwapBarrier( swapBarrier, _swapBarriers[name] );
00223         }
00224     }
00225     else
00226     {
00227         const std::string& name = swapBarrier->getName();
00228         _swapBarriers[name] = window->joinSwapBarrier( _swapBarriers[name] );
00229     }
00230 }
00231 
00232 }
00233 }
Generated on Sat Feb 6 12:59:50 2010 for Equalizer 0.9.1 by  doxygen 1.6.1