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