void ROIFinder::_findAreas( PixelViewports& resultPVPs ) { LBASSERT( _areasToCheck.empty() ); Area area( PixelViewport( 0, 0, _w, _h )); area.pvp = _getObjectPVP( area.pvp, &_mask[0] ); if( area.pvp.w <= 0 || area.pvp.h <= 0 ) return; area.hole = _emptyFinder.getLargestEmptyArea( area.pvp ); if( area.hole.getArea() == 0 ) resultPVPs.push_back( area.pvp ); else _areasToCheck.push_back( area ); // try to split areas while( !_areasToCheck.empty() ) { Area curArea = _areasToCheck.back(); _areasToCheck.pop_back(); uint8_t n = _splitArea( curArea ); LBASSERT( n >= 2 && n <= 4 ); for( uint8_t i = 0; i < n; i++ ) { LBASSERT( _finalAreas[i].valid ); LBASSERT( _finalAreas[i].pvp.hasArea( )); if( _finalAreas[i].hole.getArea() == 0 ) resultPVPs.push_back( _finalAreas[i].pvp ); else _areasToCheck.push_back( _finalAreas[i] ); } } // correct position and sizes for( uint32_t i = 0; i < resultPVPs.size(); i++ ) { #ifndef NDEBUG // fill temporary array with found regions to // dump it later in _dumpDebug _fillWithColor( resultPVPs[i], &_tmpMask[0], uint8_t( 255 - i*200/resultPVPs.size( ))); #endif PixelViewport& pvp = resultPVPs[i]; pvp.x += _pvp.x; pvp.y += _pvp.y; pvp.apply( Zoom( GRID_SIZE, GRID_SIZE )); } }
PixelViewports ROIFinder::findRegions( const uint32_t buffers, const PixelViewport& pvp, const Zoom& zoom, const uint32_t stage, const uint128_t& frameID, util::ObjectManager& glObjects ) { PixelViewports result; result.push_back( pvp ); LBLOG( LOG_ASSEMBLY ) << "ROIFinder::getObjects " << pvp << ", buffers " << buffers << std::endl; if( zoom != Zoom::NONE ) { LBWARN << "R-B optimization impossible when zoom is used" << std::endl; return result; } #ifdef EQ_ROI_USE_TRACKER uint8_t* ticket; if( !_roiTracker.useROIFinder( pvp, stage, frameID, ticket )) return result; #endif _pvpOriginal = pvp; _resize( _getBoundingPVP( pvp )); // go through depth buffer and check min/max/BG values // render to and read-back usefull info from FBO _readbackInfo( glObjects ); glObjects.clear(); // Analyze readed back data and find regions of interest _init( ); _emptyFinder.update( &_mask[0], _wb, _hb ); _emptyFinder.setLimits( 200, 0.002f ); result.clear(); _findAreas( result ); #ifdef EQ_ROI_USE_TRACKER _roiTracker.updateDelay( result, ticket ); #endif return result; }
void ROITracker::updateDelay( const PixelViewports& pvps, const uint8_t* ticket ) { LBASSERT( _needsUpdate ); LBASSERTINFO( ticket == _ticket, "Wrong ticket" ); if( ticket != _ticket ) { LBERROR << "Wrong ticket" << std::endl; return; } uint32_t totalAreaFound = 0; for( uint32_t i = 0; i < pvps.size(); i++ ) totalAreaFound += pvps[ i ].getArea(); Area& area = (*_curFrame)[ _lastStage ].areas.back(); if( totalAreaFound < area.pvp.getArea()*4/5 ) { // ROI cutted enough, reset failure statistics area.lastSkip = 0; }else { // disable ROI for next frames, if it was failing before, // increase number of frames to skip area.lastSkip = LB_MIN( area.lastSkip*2 + 1, 64 ); area.skip = area.lastSkip; } _needsUpdate = false; }
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; }