Images FrameData::startReadback( const Frame& frame, util::ObjectManager& glObjects, const DrawableConfig& config, const PixelViewports& regions ) { if( _impl->data.buffers == Frame::BUFFER_NONE ) return Images(); const Zoom& zoom = frame.getZoom(); if( !zoom.isValid( )) { LBWARN << "Invalid zoom factor, skipping frame" << std::endl; return Images(); } const eq::PixelViewport& framePVP = getPixelViewport(); const PixelViewport absPVP = framePVP + frame.getOffset(); if( !absPVP.isValid( )) return Images(); Images images; // readback the whole screen when using textures if( getType() == eq::Frame::TYPE_TEXTURE ) { Image* image = newImage( getType(), config ); if( image->startReadback( getBuffers(), absPVP, zoom, glObjects )) images.push_back( image ); image->setOffset( 0, 0 ); return images; } //else read only required regions #if 0 // TODO: issue #85: move automatic ROI detection to eq::Channel PixelViewports regions; if( _impl->data.buffers & Frame::BUFFER_DEPTH && zoom == Zoom::NONE ) regions = _impl->roiFinder->findRegions( _impl->data.buffers, absPVP, zoom, frame.getAssemblyStage(), frame.getFrameID(), glObjects); else regions.push_back( absPVP ); #endif LBASSERT( getType() == eq::Frame::TYPE_MEMORY ); const eq::Pixel& pixel = getPixel(); for( uint32_t i = 0; i < regions.size(); ++i ) { PixelViewport pvp = regions[ i ] + frame.getOffset(); pvp.intersect( absPVP ); if( !pvp.hasArea( )) continue; Image* image = newImage( getType(), config ); if( image->startReadback( getBuffers(), pvp, zoom, glObjects )) images.push_back( image ); pvp -= frame.getOffset(); pvp.apply( zoom ); image->setOffset( (pvp.x - framePVP.x) * pixel.w, (pvp.y - framePVP.y) * pixel.h ); } return images; }
bool ROITracker::useROIFinder( const PixelViewport& pvp, const uint32_t stage, const uint128_t& frameID, uint8_t*& ticket ) { LBASSERT( !_needsUpdate ); ticket = 0; const uint32_t pvpArea = pvp.getArea(); if( pvpArea < 100 ) return false; if( _lastFrameID != frameID ) // new frame { stde::hash_map< uint32_t, Stage >* tmp = _prvFrame; _prvFrame = _curFrame; _curFrame = tmp; _curFrame->clear(); _lastFrameID = frameID; } _lastStage = stage; Stage& curStage = (*_curFrame)[ stage ]; // check if proper stage is avaliable if( _prvFrame->find( stage ) == _prvFrame->end( )) // new stage { curStage.areas.push_back( Area( pvp )); return _returnPositive( ticket ); } //else existing stage, try to find matching area const Area* match = 0; uint32_t bestArea = 0; const Stage& prvStage = (*_prvFrame)[ stage ]; for( uint32_t i = 0; i < prvStage.areas.size(); i++ ) { PixelViewport tmp = prvStage.areas[i].pvp; tmp.intersect( pvp ); const uint32_t area = tmp.getArea(); if( area > bestArea ) { bestArea = area; match = &prvStage.areas[i]; if( area == pvpArea ) // full match break; } } if( bestArea < pvpArea*2/3 ) // no proper match found, new area { curStage.areas.push_back( Area( pvp )); return _returnPositive( ticket ); } // else good match if( match->skip == 0 ) // don't skip frame { curStage.areas.push_back( Area( pvp, match->lastSkip )); return _returnPositive( ticket ); } //else skip frame curStage.areas.push_back( Area( pvp, match->lastSkip, match->skip-1 )); return false; }