channelUpdateVisitor.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 "channelUpdateVisitor.h"
00019 
00020 #include "colorMask.h"
00021 #include "compound.h"
00022 #include "frame.h"
00023 #include "node.h"
00024 #include "observer.h"
00025 #include "pipe.h"
00026 #include "segment.h"
00027 #include "view.h"
00028 #include "window.h"
00029 
00030 #include "channel.ipp"
00031 
00032 #include <eq/client/log.h>
00033 
00034 using namespace std;
00035 using namespace eq::base;
00036 
00037 namespace eq
00038 {
00039 namespace server
00040 {
00041 ChannelUpdateVisitor::ChannelUpdateVisitor( Channel* channel, 
00042                                             const uint32_t frameID,
00043                                             const uint32_t frameNumber )
00044         : _channel( channel )
00045         , _eye( eq::EYE_CYCLOP )
00046         , _frameID( frameID )
00047         , _frameNumber( frameNumber )
00048         , _updated( false )
00049 {}
00050 
00051 bool ChannelUpdateVisitor::_skipCompound( const Compound* compound )
00052 {
00053     if( compound->getChannel() != _channel ||
00054         !compound->testInheritEye( _eye ) ||
00055         compound->getInheritTasks() == TASK_NONE )
00056     {
00057         return true;
00058     }
00059 
00060     return false;
00061 }
00062 
00063 VisitorResult ChannelUpdateVisitor::visitPre( const Compound* compound )
00064 {
00065     if( !compound->isActive( ))
00066         return TRAVERSE_PRUNE;    
00067 
00068     _updateDrawFinish( compound );
00069 
00070     if( _skipCompound( compound ))
00071         return TRAVERSE_CONTINUE;
00072 
00073     eq::RenderContext context;
00074     _setupRenderContext( compound, context );
00075 
00076     _updateFrameRate( compound );
00077     _updateViewStart( compound, context );
00078 
00079     if( compound->testInheritTask( eq::TASK_CLEAR ))
00080     {
00081         eq::ChannelFrameClearPacket clearPacket;        
00082         clearPacket.context = context;
00083 
00084         _channel->send( clearPacket );
00085         _updated = true;
00086         EQLOG( eq::LOG_TASKS ) << "TASK clear " << _channel->getName() <<  " "
00087                                << &clearPacket << endl;
00088     }
00089     return TRAVERSE_CONTINUE;
00090 }
00091 
00092 VisitorResult ChannelUpdateVisitor::visitLeaf( const Compound* compound )
00093 {
00094     if( !compound->isActive( ))
00095         return TRAVERSE_PRUNE;    
00096 
00097     if( _skipCompound( compound ))
00098     {
00099         _updateDrawFinish( compound );
00100         return TRAVERSE_CONTINUE;
00101     }
00102 
00103     // OPT: Send render context once before task packets?
00104     eq::RenderContext context;
00105     _setupRenderContext( compound, context );
00106     _updateFrameRate( compound );
00107     _updateViewStart( compound, context );
00108 
00109     if( compound->testInheritTask( eq::TASK_CLEAR ))
00110     {
00111         eq::ChannelFrameClearPacket clearPacket;        
00112         clearPacket.context = context;
00113         _channel->send( clearPacket );
00114         _updated = true;
00115         EQLOG( eq::LOG_TASKS ) << "TASK clear " << _channel->getName() <<  " "
00116                            << &clearPacket << endl;
00117     }
00118     if( compound->testInheritTask( eq::TASK_DRAW ))
00119     {
00120         eq::ChannelFrameDrawPacket drawPacket;
00121 
00122         drawPacket.context = context;
00123         _channel->send( drawPacket );
00124         _updated = true;
00125         EQLOG( eq::LOG_TASKS ) << "TASK draw " << _channel->getName() <<  " " 
00126                            << &drawPacket << endl;
00127     }
00128     
00129     _updateDrawFinish( compound );
00130     _updatePostDraw( compound, context );
00131     return TRAVERSE_CONTINUE;
00132 }
00133 
00134 VisitorResult ChannelUpdateVisitor::visitPost( const Compound* compound )
00135 {
00136     if( !compound->isActive( ))
00137         return TRAVERSE_PRUNE;    
00138 
00139     if( _skipCompound( compound ))
00140         return TRAVERSE_CONTINUE;
00141 
00142     eq::RenderContext context;
00143     _setupRenderContext( compound, context );
00144     _updatePostDraw( compound, context );
00145 
00146     return TRAVERSE_CONTINUE;
00147 }
00148 
00149 
00150 void ChannelUpdateVisitor::_setupRenderContext( const Compound* compound,
00151                                                 eq::RenderContext& context )
00152 {
00153     const Channel* destChannel = compound->getInheritChannel();
00154     EQASSERT( destChannel );
00155     const View* view = destChannel->getView();
00156 
00157     context.frameID       = _frameID;
00158     context.pvp           = compound->getInheritPixelViewport();
00159     context.overdraw      = compound->getInheritOverdraw();
00160     context.vp            = compound->getInheritViewport();
00161     context.range         = compound->getInheritRange();
00162     context.pixel         = compound->getInheritPixel();
00163     context.zoom          = compound->getInheritZoom();
00164     context.offset.x()    = context.pvp.x;
00165     context.offset.y()    = context.pvp.y;
00166     context.eye           = _eye;
00167     context.buffer        = _getDrawBuffer();
00168     context.bufferMask    = _getDrawBufferMask( compound );
00169     context.view          = view;
00170     context.taskID        = compound->getTaskID();
00171 
00172     if( view )
00173     {
00174         // compute inherit vp (part of view covered by segment)
00175         const Segment* segment = destChannel->getSegment();
00176         EQASSERT( segment );
00177 
00178         const PixelViewport& pvp = destChannel->getPixelViewport();
00179         if( pvp.hasArea( ))
00180             context.vp.applyView( segment->getViewport(), view->getViewport(),
00181                                   pvp, destChannel->getOverdraw( ));
00182     }
00183 
00184     if( _channel != destChannel &&
00185         compound->getIAttribute( Compound::IATTR_HINT_OFFSET ) != eq::ON )
00186     {
00187         const eq::PixelViewport& nativePVP = _channel->getPixelViewport();
00188         context.pvp.x = nativePVP.x;
00189         context.pvp.y = nativePVP.y;
00190     }
00191     // TODO: pvp size overcommit check?
00192 
00193     _computeFrustum( compound, context );
00194 }
00195 
00196 void ChannelUpdateVisitor::_updateDrawFinish( const Compound* compound ) const
00197 {
00198     // Test if this is not the last eye pass of this compound
00199     if( compound->getInheritEyes() + 1 > static_cast< uint32_t >( 1<<( _eye+1 ))
00200         // or we don't actually draw this eye
00201         || !compound->testInheritEye( _eye ))
00202     {
00203         return;
00204     }
00205 
00206     const Compound* lastDrawCompound = _channel->getLastDrawCompound();
00207     if( lastDrawCompound && lastDrawCompound != compound )
00208         return;
00209 
00210     // Channel::frameDrawFinish
00211     Node* node = _channel->getNode();
00212 
00213     eq::ChannelFrameDrawFinishPacket channelPacket;
00214     channelPacket.objectID    = _channel->getID();
00215     channelPacket.frameNumber = _frameNumber;
00216     channelPacket.frameID     = _frameID;
00217 
00218     node->send( channelPacket );
00219     EQLOG( eq::LOG_TASKS ) << "TASK channel draw finish " << _channel->getName()
00220                            <<  " " << &channelPacket <<endl;
00221 
00222     if( !lastDrawCompound )
00223         _channel->setLastDrawCompound( compound );
00224 
00225     // Window::frameDrawFinish
00226     Window* window = _channel->getWindow();
00227     const Channel* lastDrawChannel = window->getLastDrawChannel();
00228 
00229     if( lastDrawChannel && lastDrawChannel != _channel )
00230         return;
00231 
00232     eq::WindowFrameDrawFinishPacket windowPacket;
00233     windowPacket.objectID    = window->getID();
00234     windowPacket.frameNumber = _frameNumber;
00235     windowPacket.frameID     = _frameID;
00236 
00237     node->send( windowPacket );
00238     EQLOG( eq::LOG_TASKS ) << "TASK window draw finish "  << window->getName() 
00239                            <<  " " << &windowPacket << endl;
00240     if( !lastDrawChannel )
00241         window->setLastDrawChannel( _channel );
00242 
00243     // Pipe::frameDrawFinish
00244     Pipe* pipe = _channel->getPipe();
00245     const Window* lastDrawWindow = pipe->getLastDrawWindow();
00246     if( lastDrawWindow && lastDrawWindow != window )
00247         return;
00248 
00249     eq::PipeFrameDrawFinishPacket pipePacket;
00250     pipePacket.objectID    = pipe->getID();
00251     pipePacket.frameNumber = _frameNumber;
00252     pipePacket.frameID     = _frameID;
00253 
00254     node->send( pipePacket );
00255     EQLOG( eq::LOG_TASKS ) << "TASK pipe draw finish " 
00256                            << pipe->getName() <<  " " << &pipePacket << endl;
00257     if( !lastDrawWindow )
00258         pipe->setLastDrawWindow( window );
00259 
00260     // Node::frameDrawFinish
00261     const Pipe* lastDrawPipe = node->getLastDrawPipe();
00262     if( lastDrawPipe && lastDrawPipe != pipe )
00263         return;
00264 
00265     eq::NodeFrameDrawFinishPacket nodePacket;
00266     nodePacket.objectID    = node->getID();
00267     nodePacket.frameNumber = _frameNumber;
00268     nodePacket.frameID     = _frameID;
00269 
00270     node->send( nodePacket );
00271     EQLOG( eq::LOG_TASKS ) << "TASK node draw finish " << node->getName() 
00272                            <<  " " << &nodePacket << endl;
00273     if( !lastDrawPipe )
00274         node->setLastDrawPipe( pipe );
00275 }
00276 
00277 void ChannelUpdateVisitor::_updateFrameRate( const Compound* compound ) const
00278 {
00279     const float maxFPS = compound->getInheritMaxFPS();
00280     Window*     window = _channel->getWindow();
00281 
00282     if( maxFPS < window->getMaxFPS())
00283         window->setMaxFPS( maxFPS );
00284 }
00285 
00286 GLenum ChannelUpdateVisitor::_getDrawBuffer() const
00287 {
00288     const eq::Window::DrawableConfig& drawableConfig = 
00289         _channel->getWindow()->getDrawableConfig();
00290     
00291     if( !drawableConfig.stereo )
00292     {    
00293         if( drawableConfig.doublebuffered )
00294             return GL_BACK;
00295         // else singlebuffered
00296         return GL_FRONT;
00297     }
00298     else
00299     {
00300         if( drawableConfig.doublebuffered )
00301         {
00302             switch( _eye )
00303             {
00304                 case eq::EYE_LEFT:
00305                     return GL_BACK_LEFT;
00306                     break;
00307                 case eq::EYE_RIGHT:
00308                     return GL_BACK_RIGHT;
00309                     break;
00310                 default:
00311                     return GL_BACK;
00312                     break;
00313             }
00314         }
00315         // else singlebuffered
00316         switch( _eye )
00317         {
00318             case eq::EYE_LEFT:
00319                 return GL_FRONT_LEFT;
00320                 break;
00321             case eq::EYE_RIGHT:
00322                 return GL_FRONT_RIGHT;
00323                 break;
00324             default:
00325                 return GL_FRONT;
00326                 break;
00327         }
00328     }
00329 }
00330 
00331 eq::ColorMask ChannelUpdateVisitor::_getDrawBufferMask(const Compound* compound)
00332     const
00333 {
00334     if( compound->getInheritIAttribute( Compound::IATTR_STEREO_MODE ) !=
00335         eq::ANAGLYPH )
00336         return eq::ColorMask::ALL;
00337 
00338     switch( _eye )
00339     {
00340         case eq::EYE_LEFT:
00341             return ColorMask( 
00342                 compound->getInheritIAttribute(
00343                     Compound::IATTR_STEREO_ANAGLYPH_LEFT_MASK ));
00344         case eq::EYE_RIGHT:
00345             return ColorMask( 
00346                 compound->getInheritIAttribute( 
00347                     Compound::IATTR_STEREO_ANAGLYPH_RIGHT_MASK ));
00348         default:
00349             return eq::ColorMask::ALL;
00350     }
00351 }
00352 
00353 void ChannelUpdateVisitor::_computeFrustum( const Compound* compound,
00354                                             eq::RenderContext& context )
00355 {
00356     // compute eye position in screen space
00357     const Vector3f  eyeW = _getEyePosition( compound );
00358     const FrustumData& frustumData = compound->getInheritFrustumData();
00359     const Matrix4f& xfm  = frustumData.getTransform();
00360     const Vector3f  eye  = xfm * eyeW;
00361 
00362     EQVERB << "Eye position world: " << eyeW << " screen " << eye << endl;
00363 
00364     // compute perspective and orthographic frusta from size and eye position
00365     _computeFrustumCorners( context.frustum, compound, frustumData, eye, false);
00366     _computeFrustumCorners( context.ortho,   compound, frustumData, eye, true );
00367 
00368     // compute head transform
00369     // headTransform = -trans(eye) * view matrix (frustum position)
00370     Matrix4f& headTransform = context.headTransform;
00371     for( int i=0; i<16; i += 4 )
00372     {
00373         headTransform.array[i]   = xfm.array[i]   - eye[0] * xfm.array[i+3];
00374         headTransform.array[i+1] = xfm.array[i+1] - eye[1] * xfm.array[i+3];
00375         headTransform.array[i+2] = xfm.array[i+2] - eye[2] * xfm.array[i+3];
00376         headTransform.array[i+3] = xfm.array[i+3];
00377     }
00378 
00379     const bool isHMD = (frustumData.getType() != Wall::TYPE_FIXED);
00380     if( isHMD )
00381         headTransform *= _getInverseHeadMatrix( compound );
00382 }
00383 
00384 Vector3f ChannelUpdateVisitor::_getEyePosition( const Compound* compound )
00385     const
00386 {
00387     const FrustumData& frustumData = compound->getInheritFrustumData();
00388     const Channel* destChannel = compound->getInheritChannel();
00389     const View* view = destChannel->getView();
00390     const Observer* observer = static_cast< const Observer* >(
00391         view ? view->getObserver() : 0 );
00392 
00393     if( observer && frustumData.getType() == Wall::TYPE_FIXED )
00394         return observer->getEyePosition( _eye );
00395 
00396     const Config* config = compound->getConfig();
00397     const float eyeBase_2 = 0.5f * ( observer ? 
00398       observer->getEyeBase() : config->getFAttribute( Config::FATTR_EYE_BASE ));
00399 
00400     switch( _eye )
00401     {
00402         case eq::EYE_LEFT:
00403             return Vector3f(-eyeBase_2, 0.f, 0.f );
00404 
00405         case eq::EYE_RIGHT:
00406             return Vector3f( eyeBase_2, 0.f, 0.f );
00407 
00408         default:
00409             EQUNIMPLEMENTED;
00410         case eq::EYE_CYCLOP:
00411             return Vector3f( 0.f, 0.f, 0.f );
00412     }
00413 }
00414 
00415 const Matrix4f& ChannelUpdateVisitor::_getInverseHeadMatrix(
00416     const Compound* compound ) const
00417 {
00418     const Channel* destChannel = compound->getInheritChannel();
00419     const View* view = destChannel->getView();
00420     const Observer* observer = static_cast< const Observer* >(
00421         view ? view->getObserver() : 0);
00422 
00423     if( observer )
00424         return observer->getInverseHeadMatrix();
00425 
00426     return Matrix4f::IDENTITY;
00427 }
00428 
00429 void ChannelUpdateVisitor::_computeFrustumCorners( Frustumf& frustum,
00430                                                    const Compound* compound,
00431                                                  const FrustumData& frustumData,
00432                                                    const Vector3f& eye,
00433                                                    const bool ortho )
00434 {
00435     const Channel* destination = compound->getInheritChannel();
00436     destination->getNearFar( &frustum.near_plane(), &frustum.far_plane() );
00437 
00438     const float ratio    = ortho ? 1.0f : frustum.near_plane() / eye.z();
00439     const float width_2  = frustumData.getWidth()  * .5f;
00440     const float height_2 = frustumData.getHeight() * .5f;
00441 
00442     if( eye.z() > 0 || ortho )
00443     {
00444         frustum.left()   =  ( -width_2  - eye.x() ) * ratio;
00445         frustum.right()  =  (  width_2  - eye.x() ) * ratio;
00446         frustum.bottom() =  ( -height_2 - eye.y() ) * ratio;
00447         frustum.top()    =  (  height_2 - eye.y() ) * ratio;
00448     }
00449     else // eye behind near plane - 'mirror' x
00450     {
00451         frustum.left()   =  (  width_2  - eye.x() ) * ratio;
00452         frustum.right()  =  ( -width_2  - eye.x() ) * ratio;
00453         frustum.bottom() =  (  height_2 + eye.y() ) * ratio;
00454         frustum.top()    =  ( -height_2 + eye.y() ) * ratio;
00455     }
00456 
00457     // move frustum according to pixel decomposition
00458     const eq::Pixel& pixel = compound->getInheritPixel();
00459     if( pixel != eq::Pixel::ALL && pixel.isValid( ))
00460     {
00461         const Channel*    inheritChannel = compound->getInheritChannel();
00462         const eq::PixelViewport& destPVP = inheritChannel->getPixelViewport();
00463         
00464         if( pixel.w > 1 )
00465         {
00466             const float         frustumWidth = frustum.right() - frustum.left();
00467             const float           pixelWidth = frustumWidth / 
00468                                                static_cast<float>( destPVP.w );
00469             const float               jitter = pixelWidth * pixel.x - 
00470                                                pixelWidth * .5f;
00471 
00472             frustum.left()  += jitter;
00473             frustum.right() += jitter;
00474         }
00475         if( pixel.h > 1 )
00476         {
00477             const float        frustumHeight = frustum.bottom() - frustum.top();
00478             const float          pixelHeight = frustumHeight / 
00479                                                static_cast<float>( destPVP.h );
00480             const float               jitter = pixelHeight * pixel.y + 
00481                                                pixelHeight * .5f;
00482 
00483             frustum.top()    -= jitter;
00484             frustum.bottom() -= jitter;
00485         }
00486     }
00487 
00488     // adjust to viewport (screen-space decomposition)
00489     // Note: vp is computed pixel-correct by Compound::updateInheritData()
00490     const eq::Viewport vp = compound->getInheritViewport();
00491     if( vp != eq::Viewport::FULL && vp.isValid( ))
00492     {
00493         const float frustumWidth = frustum.right() - frustum.left();
00494         frustum.left()  += frustumWidth * vp.x;
00495         frustum.right()  = frustum.left() + frustumWidth * vp.w;
00496         
00497         const float frustumHeight = frustum.top() - frustum.bottom();
00498         frustum.bottom() += frustumHeight * vp.y;
00499         frustum.top()     = frustum.bottom() + frustumHeight * vp.h;
00500     }
00501 }
00502 
00503 void ChannelUpdateVisitor::_updatePostDraw( const Compound* compound, 
00504                                             const eq::RenderContext& context )
00505 {
00506     _updateAssemble( compound, context );
00507     _updateReadback( compound, context );
00508     _updateViewFinish( compound, context );
00509 }
00510 
00511 void ChannelUpdateVisitor::_updateAssemble( const Compound* compound,
00512                                             const eq::RenderContext& context )
00513 {
00514     if( !compound->testInheritTask( eq::TASK_ASSEMBLE ))
00515         return;
00516 
00517     const std::vector< Frame* >& inputFrames = compound->getInputFrames();
00518     EQASSERT( !inputFrames.empty( ));
00519 
00520     vector<net::ObjectVersion> frameIDs;
00521     for( vector<Frame*>::const_iterator iter = inputFrames.begin(); 
00522          iter != inputFrames.end(); ++iter )
00523     {
00524         Frame* frame = *iter;
00525 
00526         if( !frame->hasData( _eye )) // TODO: filter: buffers, vp, eye
00527             continue;
00528 
00529         frameIDs.push_back( net::ObjectVersion( frame ));
00530     }
00531 
00532     if( frameIDs.empty() )
00533         return;
00534 
00535     // assemble task
00536     eq::ChannelFrameAssemblePacket packet;
00537     packet.context   = context;
00538     packet.nFrames   = frameIDs.size();
00539 
00540     EQLOG( eq::LOG_ASSEMBLY | eq::LOG_TASKS ) 
00541         << "TASK assemble " << _channel->getName() <<  " " << &packet << endl;
00542     _channel->send<net::ObjectVersion>( packet, frameIDs );
00543     _updated = true;
00544 }
00545     
00546 void ChannelUpdateVisitor::_updateReadback( const Compound* compound,
00547                                             const eq::RenderContext& context )
00548 {
00549     if( !compound->testInheritTask( eq::TASK_READBACK ))
00550         return;
00551 
00552     const std::vector< Frame* >& outputFrames = compound->getOutputFrames();
00553     EQASSERT( !outputFrames.empty( ));
00554 
00555     FrameVector                frames;
00556     vector<net::ObjectVersion> frameIDs;
00557     for( vector<Frame*>::const_iterator i = outputFrames.begin(); 
00558          i != outputFrames.end(); ++i )
00559     {
00560         Frame* frame = *i;
00561 
00562         if( !frame->hasData( _eye )) // TODO: filter: buffers, vp, eye
00563             continue;
00564 
00565         frames.push_back( frame );
00566         frameIDs.push_back( net::ObjectVersion( frame ));
00567     }
00568 
00569     if( frames.empty() )
00570         return;
00571 
00572     // readback task
00573     eq::ChannelFrameReadbackPacket packet;
00574     packet.context   = context;
00575     packet.nFrames   = frames.size();
00576 
00577     _channel->send<net::ObjectVersion>( packet, frameIDs );
00578     _updated = true;
00579     EQLOG( eq::LOG_ASSEMBLY | eq::LOG_TASKS ) 
00580         << "TASK readback " << _channel->getName() <<  " " << &packet << endl;
00581 
00582     // transmit tasks
00583     Node*                 node         = _channel->getNode();
00584     net::NodePtr   netNode      = node->getNode();
00585     const net::NodeID&  outputNodeID = netNode->getNodeID();
00586     for( vector<Frame*>::const_iterator i = frames.begin(); 
00587          i != frames.end(); ++i )
00588     {
00589         Frame* outputFrame = *i;
00590 
00591         const vector<Frame*>& inputFrames = 
00592             outputFrame->getInputFrames( context.eye);
00593 
00594         vector<net::NodeID> nodeIDs;
00595         for( vector<Frame*>::const_iterator j = inputFrames.begin();
00596              j != inputFrames.end(); ++j )
00597         {
00598             const Frame* inputFrame   = *j;
00599             const Node*  inputNode    = inputFrame->getNode();
00600             net::NodePtr inputNetNode = inputNode->getNode();
00601             net::NodeID  nodeID       = inputNetNode->getNodeID();
00602             EQASSERT( node );
00603 
00604             if( nodeID == outputNodeID ) // TODO filter: buffers, vp, eye
00605                 continue;
00606 
00607             nodeID.convertToNetwork();
00608             nodeIDs.push_back( nodeID );
00609         }
00610 
00611         // sort & filter dupes
00612         stde::usort( nodeIDs );
00613 
00614         if( nodeIDs.empty( ))
00615             continue;
00616 
00617         // send
00618         eq::ChannelFrameTransmitPacket transmitPacket;
00619         transmitPacket.sessionID = packet.sessionID;
00620         transmitPacket.objectID  = packet.objectID;
00621         transmitPacket.context   = context;
00622         transmitPacket.frame     = net::ObjectVersion( outputFrame );
00623         transmitPacket.nNodes    = nodeIDs.size();
00624 
00625         EQLOG( eq::LOG_ASSEMBLY | eq::LOG_TASKS )
00626             << "TASK transmit " << _channel->getName() <<  " " << 
00627             &transmitPacket << " first " << nodeIDs[0] << endl;
00628 
00629         _channel->send<net::NodeID>( transmitPacket, nodeIDs );
00630     }        
00631 }
00632 
00633 void ChannelUpdateVisitor::_updateViewStart( const Compound* compound,
00634                                              const eq::RenderContext& context )
00635 {
00636     EQASSERT( !_skipCompound( compound ));
00637     if( !compound->testInheritTask( eq::TASK_VIEW ))
00638         return;
00639     
00640     // view start task
00641     eq::ChannelFrameViewStartPacket packet;
00642     packet.context   = context;
00643 
00644     EQLOG( eq::LOG_TASKS ) << "TASK view start " << _channel->getName() <<  " "
00645                            << &packet << endl;
00646     _channel->send( packet );
00647 }
00648 
00649 void ChannelUpdateVisitor::_updateViewFinish( const Compound* compound,
00650                                               const eq::RenderContext& context )
00651 {
00652     EQASSERT( !_skipCompound( compound ));
00653     if( !compound->testInheritTask( eq::TASK_VIEW ))
00654         return;
00655     
00656     // view finish task
00657     eq::ChannelFrameViewFinishPacket packet;
00658     packet.context   = context;
00659 
00660     EQLOG( eq::LOG_TASKS ) << "TASK view finish " << _channel->getName() <<  " "
00661                            << &packet << endl;
00662     _channel->send( packet );
00663 }
00664 
00665 }
00666 }
00667 
Generated on Mon Aug 10 18:58:31 2009 for Equalizer 0.9 by  doxygen 1.5.8