compoundUpdateOutputVisitor.cpp

00001 
00002 /* Copyright (c) 2007-2009, 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 
00127         //----- Set frame parameters:
00128         // 1) offset is position wrt window, i.e., the channel position
00129         if( compound->getInheritChannel() == channel ||
00130             compound->getIAttribute( Compound::IATTR_HINT_OFFSET ) == eq::ON )
00131         {
00132             frame->setInheritOffset( Vector2i( inheritPVP.x, inheritPVP.y ));
00133         }
00134         else
00135         {
00136             const eq::PixelViewport& nativePVP = channel->getPixelViewport();
00137             frame->setInheritOffset( Vector2i( nativePVP.x, nativePVP.y ));
00138         }
00139 
00140         // 2) zoom
00141         _updateZoom( compound, frame );
00142 
00143         //----- Commit
00144         frame->commitData();
00145         frame->commit();
00146 
00147         _outputFrames[name] = frame;
00148         EQLOG( eq::LOG_ASSEMBLY ) 
00149             << " buffers " << frameData->getBuffers() << " read area "
00150             << framePVP << " readback " << frame->getInheritZoom()
00151             << " assemble " << frameData->getZoom() << endl << enableFlush;
00152     }
00153 }
00154 
00155 void CompoundUpdateOutputVisitor::_updateZoom( const Compound* compound,
00156                                                Frame* frame )
00157 {
00158     eq::Zoom zoom = frame->getZoom();
00159     eq::Zoom zoom_1;
00160 
00161     if( !zoom.isValid( )) // if zoom is not set, auto-calculate from parent
00162     {
00163         zoom_1 = compound->getInheritZoom();
00164         EQASSERT( zoom_1.isValid( ));
00165         zoom.x() = 1.0f / zoom_1.x();
00166         zoom.y() = 1.0f / zoom_1.y();
00167     }
00168     else
00169     {
00170         zoom_1.x() = 1.0f / zoom.x();
00171         zoom_1.y() = 1.0f / zoom.y();
00172     }
00173 
00174     if( frame->getType( ) == eq::Frame::TYPE_TEXTURE )
00175     {
00176         FrameData* frameData = frame->getMasterData();
00177         frameData->setZoom( zoom_1 ); // textures are zoomed by input frame
00178         frame->setInheritZoom( eq::Zoom( ));
00179     }
00180     else
00181     {
00182         eq::Zoom inputZoom;
00183         /* Output frames downscale pixel data during readback, and upscale it on
00184          * the input frame by setting the input frame's inherit zoom. */
00185         if( zoom.x() > 1.0f )
00186         {
00187             inputZoom.x() = zoom_1.x();
00188             zoom.x()      = 1.f;
00189         }
00190         if( zoom.y() > 1.0f )
00191         {
00192             inputZoom.y() = zoom_1.y();
00193             zoom.y()      = 1.f;
00194         }
00195 
00196         FrameData* frameData = frame->getMasterData();
00197         frameData->setZoom( inputZoom );
00198         frame->setInheritZoom( zoom );                
00199     }
00200 }
00201 
00202 void CompoundUpdateOutputVisitor::_updateSwapBarriers( Compound* compound )
00203 {
00204     const SwapBarrier* swapBarrier = compound->getSwapBarrier();
00205     if( !swapBarrier )
00206         return;
00207 
00208     Window* window = compound->getWindow();
00209     EQASSERT( window );
00210     if( !window )
00211         return;
00212 
00213     if( swapBarrier->isNvSwapBarrier( ))
00214     {
00215         if( !window->hasNVSwapBarrier( ))
00216         {
00217             const std::string name( "__NV_swap_group_protection_barrier__" );
00218             _swapBarriers[name] = 
00219                 window->joinNVSwapBarrier( swapBarrier, _swapBarriers[name] );
00220         }
00221     }
00222     else
00223     {
00224         const std::string& name = swapBarrier->getName();
00225         _swapBarriers[name] = window->joinSwapBarrier( _swapBarriers[name] );
00226     }
00227 }
00228 
00229 }
00230 }
Generated on Mon Aug 10 18:58:32 2009 for Equalizer 0.9 by  doxygen 1.5.8