void CompoundUpdateInputVisitor::_updateFrames( Compound* compound ) { const Channel* channel = compound->getChannel(); if( !compound->testInheritTask( fabric::TASK_ASSEMBLE ) || !channel ) return; const Frames& inputFrames = compound->getInputFrames(); if( inputFrames.empty( )) { compound->unsetInheritTask( fabric::TASK_ASSEMBLE ); return; } for( FramesCIter i = inputFrames.begin(); i != inputFrames.end(); ++i ) { //----- Find corresponding output frame Frame* frame = *i; const std::string& name = frame->getName(); Compound::FrameMap::const_iterator j = _outputFrames.find( name ); if( j == _outputFrames.end( )) { LBVERB << "Can't find matching output frame, ignoring input frame " << name << std::endl; frame->unsetData(); continue; } //----- Set frame parameters: // 1) Frame offset Frame* outputFrame = j->second; const Channel* iChannel = compound->getInheritChannel(); Vector2i frameOffset = outputFrame->getMasterData()->getOffset() + frame->getNativeOffset(); if( outputFrame->getCompound()->getInheritChannel() != iChannel ) frameOffset = frame->getNativeOffset(); else if( channel != iChannel ) { // compute delta offset between source and destination, since the // channel's native origin (as opposed to destination) is used. const Viewport& frameVP = frame->getViewport(); const PixelViewport& inheritPVP=compound->getInheritPixelViewport(); PixelViewport framePVP( inheritPVP ); framePVP.apply( frameVP ); frameOffset.x() -= framePVP.x; frameOffset.y() -= framePVP.y; const PixelViewport& iChannelPVP = iChannel->getPixelViewport(); frameOffset.x() -= iChannelPVP.x; frameOffset.y() -= iChannelPVP.y; } frame->setOffset( frameOffset ); // 2) zoom _updateZoom( compound, frame, outputFrame ); // 3) TODO input frames are moved using the offset. The pvp signifies // the pixels to be used from the frame data. //framePVP.x = static_cast< int32_t >( frameVP.x * inheritPVP.w ); //framePVP.y = static_cast< int32_t >( frameVP.y * inheritPVP.h ); //frame->setInheritPixelViewport( framePVP ); //----- Link input frame to output frame (connects frame data) outputFrame->addInputFrame( frame, compound ); for( unsigned k = 0; k < NUM_EYES; ++k ) { const Eye eye = Eye( 1<<k ); if( compound->isInheritActive( eye ) && // eye pass used outputFrame->hasData( eye )) // output data for eye pass { frame->commit(); LBLOG( LOG_ASSEMBLY ) << "Input frame \"" << name << "\" on channel \"" << channel->getName() << "\" id " << frame->getID() << " v" << frame->getVersion() << "\" tile pos " << frame->getOffset() << ' ' << frame->getZoom() << std::endl; break; } } } }
void CompoundUpdateOutputVisitor::_updateFrames(Compound* compound) { const Frames& outputFrames = compound->getOutputFrames(); if (outputFrames.empty()) compound->unsetInheritTask(fabric::TASK_READBACK); const Channel* channel = compound->getChannel(); if (!compound->testInheritTask(fabric::TASK_READBACK) || !channel) return; for (FramesCIter i = outputFrames.begin(); i != outputFrames.end(); ++i) { //----- Check uniqueness of output frame name Frame* frame = *i; const std::string& name = frame->getName(); if (_outputFrames.find(name) != _outputFrames.end()) { LBWARN << "Multiple output frames of the same name are unsupported" << ", ignoring output frame " << name << std::endl; frame->unsetData(); continue; } //----- compute readback area const Viewport& frameVP = frame->getViewport(); const PixelViewport& inheritPVP = compound->getInheritPixelViewport(); PixelViewport framePVP(inheritPVP); framePVP.apply(frameVP); if (!framePVP.hasArea()) // output frame has no pixels { LBINFO << "Skipping output frame " << name << ", no pixels" << std::endl; frame->unsetData(); continue; } //----- Create new frame datas // * one frame data used for each eye pass // * data is set only on master frame data (will copy to all others) frame->cycleData(_frameNumber, compound); FrameData* frameData = frame->getMasterData(); LBASSERT(frameData); LBLOG(LOG_ASSEMBLY) << lunchbox::disableFlush << "Output frame \"" << name << "\" id " << frame->getID() << " v" << frame->getVersion() + 1 << " data id " << frameData->getID() << " v" << frameData->getVersion() + 1 << " on channel \"" << channel->getName() << "\" tile pos " << framePVP.x << ", " << framePVP.y; //----- Set frame data parameters: // 1) offset is position wrt destination view, used only by input frames const bool tiled = !compound->getInputTileQueues().empty(); frameData->setOffset(tiled ? Vector2i(0, 0) : Vector2i(framePVP.x, framePVP.y)); // 2) pvp is area within channel framePVP.x = static_cast<int32_t>(frameVP.x * inheritPVP.w); framePVP.y = static_cast<int32_t>(frameVP.y * inheritPVP.h); frameData->setPixelViewport(framePVP); // 3) image buffers and storage type const Frame::Buffer buffers = frame->getBuffers(); frameData->setType(frame->getType()); frameData->setBuffers(buffers == Frame::Buffer::undefined ? compound->getInheritBuffers() : buffers); // 4) (source) render context frameData->setContext(compound->setupRenderContext(EYE_CYCLOP)); //----- Set frame parameters: // 1) offset is position wrt window, i.e., the channel position if (compound->getInheritChannel() == channel) frame->setOffset(Vector2i(inheritPVP.x, inheritPVP.y)); else { const PixelViewport& nativePVP = channel->getPixelViewport(); frame->setOffset(Vector2i(nativePVP.x, nativePVP.y)); } // 2) zoom _updateZoom(compound, frame); //----- Commit frame->commitData(); _outputFrames[name] = frame; LBLOG(LOG_ASSEMBLY) << " buffers " << frameData->getBuffers() << " read area " << framePVP << " readback " << frame->getZoom() << " assemble " << frameData->getZoom() << lunchbox::enableFlush << std::endl; } }