00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
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
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
00195
00196 _computeFrustum( compound, context );
00197 }
00198
00199 void ChannelUpdateVisitor::_updateDrawFinish( const Compound* compound ) const
00200 {
00201
00202 if( compound->getInheritEyes() + 1 > static_cast< uint32_t >( 1<<( _eye+1 ))
00203
00204 || !compound->testInheritEye( _eye ))
00205 {
00206 return;
00207 }
00208
00209 const Compound* lastDrawCompound = _channel->getLastDrawCompound();
00210 if( lastDrawCompound && lastDrawCompound != compound )
00211 return;
00212
00213
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
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
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
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
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
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
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
00368 _computeFrustumCorners( context.frustum, compound, frustumData, eye, false);
00369 _computeFrustumCorners( context.ortho, compound, frustumData, eye, true );
00370
00371
00372
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
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
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
00492
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 ))
00530 continue;
00531
00532 frameIDs.push_back( net::ObjectVersion( frame ));
00533 }
00534
00535 if( frameIDs.empty() )
00536 return;
00537
00538
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 ))
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
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
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 )
00608 continue;
00609
00610 nodeID.convertToNetwork();
00611 nodeIDs.push_back( nodeID );
00612 }
00613
00614
00615 stde::usort( nodeIDs );
00616
00617 if( nodeIDs.empty( ))
00618 continue;
00619
00620
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
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
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