00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #define EQ_ROI_USE_TRACKER // disable ROI in case it can't help
00020
00021
00022
00023
00024 #include "roiFinder.h"
00025
00026 #ifdef EQ_ROI_USE_DEPTH_TEXTURE
00027 #include "roiFragmentShader_glsl.h"
00028 #else
00029 #include "roiFragmentShaderRGB_glsl.h"
00030 #endif
00031
00032 #include "frameBufferObject.h"
00033 #include "log.h"
00034
00035 #include <eq/base/base.h>
00036
00037
00038 namespace eq
00039 {
00040
00041
00042 static const char seeds = 42;
00043 static const char* shaderRBInfo = &seeds;
00044
00045 #define GRID_SIZE 16 // will be replaced later by variable
00046
00047
00048 ROIFinder::ROIFinder()
00049 : _glObjects( 0 )
00050 {
00051 _tmpAreas[0].pvp = PixelViewport( 0, 0, 0, 0 );
00052 _tmpAreas[0].hole = PixelViewport( 0, 0, 0, 0 );
00053 _tmpAreas[0].emptySize = 0;
00054 }
00055
00056 void ROIFinder::_dumpDebug( const uint32_t stage )
00057 {
00058 static uint32_t counter = 0;
00059 std::ostringstream ss;
00060 ss << "_img_" << ++counter << "_" << stage;
00061
00062 _tmpImg.reset();
00063 _tmpImg.setPixelViewport( PixelViewport( 0, 0, _wb, _hb ));
00064
00065 _tmpImg.setFormat( Frame::BUFFER_COLOR, GL_RGB );
00066 _tmpImg.setType( Frame::BUFFER_COLOR, GL_UNSIGNED_BYTE );
00067
00068 _tmpImg.validatePixelData( Frame::BUFFER_COLOR );
00069
00070 uint8_t* dst = _tmpImg.getPixelPointer( Frame::BUFFER_COLOR );
00071 uint8_t* src1 = &_mask[0];
00072 uint8_t* src2 = &_tmpMask[0];
00073
00074 memset( dst, 0, _wbhb*3 );
00075
00076 for( int32_t y = 0; y < _hb; y++ )
00077 for( int32_t x = 0; x < _wb; x++ )
00078 {
00079 dst[0] = *src1++;
00080 dst[1] = *src2++;
00081 dst += 3;
00082 }
00083
00084 EQWARN << "Dumping ROI image: " << ss.str( ) << std::endl;
00085 _tmpImg.writeImages( ss.str( ));
00086 }
00087
00088
00089
00090 PixelViewport ROIFinder::_getObjectPVP( const PixelViewport& pvp,
00091 const uint8_t* src )
00092 {
00093 EQASSERT( pvp.x >= 0 && pvp.x+pvp.w <= _wb &&
00094 pvp.y >= 0 && pvp.y+pvp.h <= _hb );
00095
00096
00097 const uint8_t* s = src + pvp.y*_wb + pvp.x;
00098
00099 memset( _histX, 0, pvp.w );
00100 memset( _histY, 0, pvp.h );
00101 for( int32_t y = 0; y < pvp.h; y++ )
00102 {
00103 for( int32_t x = 0; x < pvp.w; x++ )
00104 {
00105 const uint8_t val = s[ x ] & 1;
00106 _histX[ x ] += val;
00107 _histY[ y ] += val;
00108 }
00109 s += _wb;
00110 }
00111
00112
00113 int32_t xMin = pvp.w;
00114 for( int32_t x = 0; x < pvp.w; x++ )
00115 if( _histX[x] != 0 )
00116 {
00117 xMin = x;
00118 break;
00119 }
00120
00121 int32_t xMax = 0;
00122 for( int32_t x = pvp.w-1; x >= 0; x-- )
00123 if( _histX[x] != 0 )
00124 {
00125 xMax = x;
00126 break;
00127 }
00128
00129 if( xMax < xMin )
00130 return PixelViewport( pvp.x, pvp.y, 0, 0 );
00131
00132 int32_t yMin = pvp.h;
00133 for( int32_t y = 0; y < pvp.h; y++ )
00134 if( _histY[y] != 0 )
00135 {
00136 yMin = y;
00137 break;
00138 }
00139
00140 int32_t yMax = 0;
00141 for( int32_t y = pvp.h-1; y >= 0; y-- )
00142 if( _histY[y] != 0 )
00143 {
00144 yMax = y;
00145 break;
00146 }
00147
00148 if( yMax < yMin )
00149 return PixelViewport( pvp.x, pvp.y, 0, 0 );
00150
00151 return PixelViewport( pvp.x+xMin, pvp.y+yMin, xMax-xMin+1, yMax-yMin+1 );
00152 }
00153
00154
00155 void ROIFinder::_resize( const PixelViewport& pvp )
00156 {
00157 _pvp = pvp;
00158
00159 _w = _pvp.w;
00160 _h = _pvp.h;
00161 _wh = _w * _h;
00162 _wb = _w + 1;
00163 _hb = _h + 1;
00164 _wbhb = _wb * _hb;
00165
00166 if( static_cast<int32_t>(_mask.size()) < _wbhb )
00167 {
00168 _mask.resize( _wbhb );
00169 _tmpMask.resize( _wbhb );
00170
00171
00172 _perBlockInfo.resize( _wh * 4 );
00173 }
00174 }
00175
00176
00177 void ROIFinder::_init( )
00178 {
00179 _areasToCheck.clear();
00180 memset( &_mask[0] , 0, _mask.size( ));
00181 memset( &_tmpMask[0], 0, _tmpMask.size( ));
00182
00183 EQASSERT( static_cast<int32_t>(_perBlockInfo.size()) >= _w*_h*4 );
00184 EQASSERT( static_cast<int32_t>(_mask.size()) >= _wb*_h );
00185
00186 const float* src = &_perBlockInfo[0];
00187 uint8_t* dst = &_mask[0];
00188
00189 for( int32_t y = 0; y < _h; y++ )
00190 {
00191 for( int32_t x = 0; x < _w; x++ )
00192 {
00193 if( src[x*4] < 1.0 )
00194 dst[x] = 255;
00195 }
00196 src += _w*4;
00197 dst += _wb;
00198 }
00199 }
00200
00201
00202 void ROIFinder::_fillWithColor( const PixelViewport& pvp,
00203 uint8_t* dst, const uint8_t val )
00204 {
00205 for( int32_t y = pvp.y; y < pvp.y + pvp.h; y++ )
00206 for( int32_t x = pvp.x; x < pvp.x + pvp.w; x++ )
00207 dst[ y * _wb + x ] = val;
00208 }
00209
00210 void ROIFinder::_invalidateAreas( Area* areas, uint8_t num )
00211 {
00212 for( uint8_t i = 0; i < num; i++ )
00213 areas[i].valid = false;
00214 }
00215
00216 void ROIFinder::_updateSubArea( const uint8_t type )
00217 {
00218 EQASSERT( type <= 16 );
00219
00220 if( type == 0 )
00221 return;
00222
00223 PixelViewport pvp;
00224 switch( type )
00225 {
00226 case 1: pvp = PixelViewport( _dim.x1,_dim.y2,_dim.w1,_dim.h2 ); break;
00227 case 2: pvp = PixelViewport( _dim.x2,_dim.y3,_dim.w2,_dim.h3 ); break;
00228 case 3: pvp = PixelViewport( _dim.x3,_dim.y2,_dim.w3,_dim.h2 ); break;
00229 case 4: pvp = PixelViewport( _dim.x2,_dim.y1,_dim.w2,_dim.h1 ); break;
00230 case 5: pvp = PixelViewport( _dim.x1,_dim.y1,_dim.w1,_dim.h4 ); break;
00231 case 6: pvp = PixelViewport( _dim.x1,_dim.y3,_dim.w4,_dim.h3 ); break;
00232 case 7: pvp = PixelViewport( _dim.x3,_dim.y2,_dim.w3,_dim.h5 ); break;
00233 case 8: pvp = PixelViewport( _dim.x2,_dim.y1,_dim.w5,_dim.h1 ); break;
00234 case 9: pvp = PixelViewport( _dim.x1,_dim.y2,_dim.w1,_dim.h5 ); break;
00235 case 10: pvp = PixelViewport( _dim.x2,_dim.y3,_dim.w5,_dim.h3 ); break;
00236 case 11: pvp = PixelViewport( _dim.x3,_dim.y1,_dim.w3,_dim.h4 ); break;
00237 case 12: pvp = PixelViewport( _dim.x1,_dim.y1,_dim.w4,_dim.h1 ); break;
00238 case 13: pvp = PixelViewport( _dim.x1,_dim.y1,_dim.w1,_dim.h6 ); break;
00239 case 14: pvp = PixelViewport( _dim.x3,_dim.y1,_dim.w3,_dim.h6 ); break;
00240 case 15: pvp = PixelViewport( _dim.x1,_dim.y3,_dim.w6,_dim.h3 ); break;
00241 case 16: pvp = PixelViewport( _dim.x1,_dim.y1,_dim.w6,_dim.h1 ); break;
00242 default:
00243 EQUNIMPLEMENTED;
00244 }
00245
00246 EQASSERT( pvp.hasArea( ));
00247 EQASSERT( pvp.x >=0 && pvp.y >=0 && pvp.x+pvp.w <=_w && pvp.y+pvp.h <=_h );
00248
00249 Area& a = _tmpAreas[type];
00250
00251 a.pvp = _getObjectPVP( pvp, &_mask[0] );
00252
00253 a.hole = _emptyFinder.getLargestEmptyArea( a.pvp );
00254
00255 a.emptySize = pvp.getArea() - a.pvp.getArea() + a.hole.getArea();
00256
00257 EQASSERT( !a.valid );
00258
00259 #ifndef NDEBUG
00260 a.valid = true;
00261 #endif
00262 }
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 static const uint8_t _interests[10][8] =
00278 {
00279 { 2, 3, 7,10, 0, 0, 0, 0 },
00280 { 3, 4, 8,11, 0, 0, 0, 0 },
00281 { 2, 3, 4, 7, 8,10,11,14 },
00282 { 1, 2, 6, 9, 0, 0, 0, 0 },
00283 { 1, 2, 3, 6, 7, 9,10,15 },
00284 { 1, 4, 5,12, 0, 0, 0, 0 },
00285 { 1, 2, 4, 5, 6, 9,12,13 },
00286 { 1, 3, 4, 5, 8,11,12,16 },
00287 { 1, 3, 0, 0, 0, 0, 0, 0 },
00288 { 2, 4, 0, 0, 0, 0, 0, 0 },
00289 };
00290
00291 static const uint8_t _compilNums[11][2] =
00292 {
00293 {2,2},{2,2},{4,3},{2,2},{4,3},{2,2},{4,3},{4,3},{1,2},{1,2},{18,4}
00294 };
00295
00296 static const uint8_t _compilations[10][4][3] =
00297 {
00298 {{2, 7, 0},{3,10, 0},{0,0, 0},{0,0, 0}},
00299 {{3, 8, 0},{4,11, 0},{0,0, 0},{0,0, 0}},
00300 {{2, 4,14},{4,10,11},{3,8,10},{2,7, 8}},
00301 {{1, 6, 0},{2, 9, 0},{0,0, 0},{0,0, 0}},
00302 {{1, 3,15},{3, 9,10},{2,7, 9},{1,6, 7}},
00303 {{1,12, 0},{4, 5, 0},{0,0, 0},{0,0, 0}},
00304 {{2, 4,13},{4, 5, 6},{1,6,12},{2,9,12}},
00305 {{1, 3,16},{1,11,12},{5,4,11},{3,5, 8}},
00306 {{1, 3, 0},{0, 0, 0},{0,0, 0},{0,0, 0}},
00307 {{2, 4, 0},{0, 0, 0},{0,0, 0},{0,0, 0}},
00308 };
00309
00310
00311 static const uint8_t _compilations16[18][4] =
00312 {
00313 {13,2, 4,14},{13,4,10,11},{13,3,8,10},{13,2,7, 8},
00314 {16,1, 3,15},{16,3, 9,10},{16,2,7, 9},{16,1,6, 7},
00315 {14,2, 4,13},{14,4, 5, 6},{14,1,6,12},{14,2,9,12},
00316 {15,1, 3,16},{15,1,11,12},{15,5,4,11},{15,3,5, 8},
00317 {5 ,6, 7, 8},{9,10,11,12}
00318 };
00319
00320
00321 uint8_t ROIFinder::_splitArea( Area& a )
00322 {
00323 EQASSERT( a.hole.getArea() > 0 );
00324 #ifndef NDEBUG
00325 _invalidateAreas( _tmpAreas, 17 );
00326 #endif
00327
00328 _dim.x1 = a.pvp.x;
00329 _dim.x2 = a.hole.x;
00330 _dim.x3 = a.hole.x + a.hole.w;
00331
00332 _dim.w1 = _dim.x2 - _dim.x1;
00333 _dim.w2 = a.hole.w;
00334 _dim.w3 = a.pvp.x + a.pvp.w - _dim.x3;
00335 _dim.w4 = _dim.w1 + _dim.w2;
00336 _dim.w5 = _dim.w2 + _dim.w3;
00337 _dim.w6 = _dim.w4 + _dim.w3;
00338
00339 _dim.y1 = a.pvp.y;
00340 _dim.y2 = a.hole.y;
00341 _dim.y3 = a.hole.y + a.hole.h;
00342
00343 _dim.h1 = _dim.y2 - _dim.y1;
00344 _dim.h2 = a.hole.h;
00345 _dim.h3 = a.pvp.y + a.pvp.h - _dim.y3;
00346 _dim.h4 = _dim.h1 + _dim.h2;
00347 _dim.h5 = _dim.h2 + _dim.h3;
00348 _dim.h6 = _dim.h4 + _dim.h3;
00349
00350
00351 uint8_t type;
00352 if( a.pvp.h == a.hole.h )
00353 {
00354 EQASSERT( a.pvp.w != a.hole.w );
00355 type = 8;
00356 }else
00357 if( a.pvp.w == a.hole.w )
00358 {
00359 type = 9;
00360 }else
00361 if( a.pvp.x == a.hole.x )
00362 {
00363 if( a.pvp.y == a.hole.y )
00364 {
00365 type = 0;
00366 }else
00367 if( a.pvp.y + a.pvp.h == a.hole.y + a.hole.h )
00368 {
00369 type = 1;
00370 }else
00371 {
00372 type = 2;
00373 }
00374 }else
00375 if( a.pvp.y == a.hole.y )
00376 {
00377 if( a.pvp.x + a.pvp.w == a.hole.x + a.hole.w )
00378 {
00379 type = 3;
00380 }else
00381 {
00382 type = 4;
00383 }
00384 }else
00385 if( a.pvp.x + a.pvp.w == a.hole.x + a.hole.w )
00386 {
00387 if( a.pvp.y + a.pvp.h == a.hole.y + a.hole.h )
00388 {
00389 type = 5;
00390 }else
00391 {
00392 type = 6;
00393 }
00394 }else
00395 if( a.pvp.y + a.pvp.h == a.hole.y + a.hole.h )
00396 {
00397 type = 7;
00398 }else
00399 {
00400 type = 10;
00401 }
00402
00403
00404 if( type == 10 )
00405 {
00406 for( uint8_t i = 1; i <= 16; i++ )
00407 _updateSubArea( i );
00408 }else
00409 {
00410 for( uint8_t i = 0; i < 8; i++ )
00411 _updateSubArea( _interests[ type ][ i ] );
00412 }
00413
00414
00415 const uint8_t varaintsNum = _compilNums[type][0];
00416 const uint8_t areasPerVariant = _compilNums[type][1];
00417
00418 int32_t maxSum = 0;
00419 int32_t variant = 0;
00420 if( type == 10 )
00421 {
00422 for( uint8_t i = 0; i < varaintsNum; i++ )
00423 {
00424 int32_t sum = 0;
00425 for( uint8_t j = 0; j < areasPerVariant; j++ )
00426 {
00427 EQASSERT( _tmpAreas[_compilations16[i][j]].valid );
00428 sum += _tmpAreas[_compilations16[i][j]].emptySize;
00429 }
00430
00431 if( sum > maxSum )
00432 {
00433 maxSum = sum;
00434 variant = i;
00435 }
00436 }
00437
00438 for( uint8_t j = 0; j < areasPerVariant; j++ )
00439 {
00440 EQASSERT( _tmpAreas[_compilations16[variant][j]].valid );
00441 _finalAreas[j] = &_tmpAreas[_compilations16[variant][j]];
00442 }
00443
00444 return areasPerVariant;
00445 }
00446
00447
00448 for( uint8_t i = 0; i < varaintsNum; i++ )
00449 {
00450 int32_t sum = 0;
00451 for( uint8_t j = 0; j < areasPerVariant; j++ )
00452 {
00453 EQASSERT( _tmpAreas[_compilations[type][i][j]].valid );
00454 sum += _tmpAreas[_compilations[type][i][j]].emptySize;
00455 }
00456
00457 if( sum > maxSum )
00458 {
00459 maxSum = sum;
00460 variant = i;
00461 }
00462 }
00463
00464 for( uint8_t j = 0; j < areasPerVariant; j++ )
00465 {
00466 EQASSERT( _tmpAreas[_compilations[type][variant][j]].valid );
00467 _finalAreas[j] = &_tmpAreas[_compilations[type][variant][j]];
00468 }
00469
00470 return areasPerVariant;
00471 }
00472
00473
00474 void ROIFinder::_findAreas( PixelViewportVector& resultPVPs )
00475 {
00476 EQASSERT( _areasToCheck.size() == 0 );
00477
00478 Area area( PixelViewport( 0, 0, _w, _h ));
00479 area.pvp = _getObjectPVP( area.pvp, &_mask[0] );
00480
00481 if( area.pvp.w <= 0 || area.pvp.h <= 0 )
00482 return;
00483
00484 area.hole = _emptyFinder.getLargestEmptyArea( area.pvp );
00485
00486 if( area.hole.getArea() == 0 )
00487 resultPVPs.push_back( area.pvp );
00488 else
00489 _areasToCheck.push_back( area );
00490
00491
00492 while( _areasToCheck.size() > 0 )
00493 {
00494 Area curArea = _areasToCheck.back();
00495 _areasToCheck.pop_back();
00496
00497 uint8_t n = _splitArea( curArea );
00498 EQASSERT( n >= 2 && n <= 4 );
00499
00500 for( uint8_t i = 0; i < n; i++ )
00501 {
00502 EQASSERT( _finalAreas[i]->valid );
00503 EQASSERT( _finalAreas[i]->pvp.hasArea( ));
00504
00505 if( _finalAreas[i]->hole.getArea() == 0 )
00506 resultPVPs.push_back( _finalAreas[i]->pvp );
00507 else
00508 _areasToCheck.push_back( *_finalAreas[i] );
00509 }
00510 }
00511
00512
00513 for( uint32_t i = 0; i < resultPVPs.size(); i++ )
00514 {
00515 #ifndef NDEBUG
00516
00517
00518 _fillWithColor( resultPVPs[i], &_tmpMask[0],
00519 255 - i*200/resultPVPs.size( ));
00520 #endif
00521
00522 PixelViewport& pvp = resultPVPs[i];
00523 pvp.x += _pvp.x;
00524 pvp.y += _pvp.y;
00525
00526 pvp.apply( Zoom( GRID_SIZE, GRID_SIZE ));
00527 }
00528
00529 }
00530
00531 const void* ROIFinder::_getInfoKey( ) const
00532 {
00533 return ( reinterpret_cast< const char* >( this ) + 3 );
00534 }
00535
00536
00537 void ROIFinder::_readbackInfo( )
00538 {
00539 EQASSERT( _glObjects );
00540 EQASSERT( _glObjects->supportsEqTexture( ));
00541 EQASSERT( _glObjects->supportsEqFrameBufferObject( ));
00542
00543 PixelViewport pvp = _pvp;
00544 pvp.apply( Zoom( GRID_SIZE, GRID_SIZE ));
00545 pvp.w = EQ_MIN( pvp.w+pvp.x, _pvpOriginal.w+_pvpOriginal.x ) - pvp.x;
00546 pvp.h = EQ_MIN( pvp.h+pvp.y, _pvpOriginal.h+_pvpOriginal.y ) - pvp.y;
00547
00548 EQASSERT( pvp.isValid());
00549
00550
00551 const void* bufferKey = _getInfoKey( );
00552 Texture* texture = _glObjects->obtainEqTexture( bufferKey );
00553
00554 #ifdef EQ_ROI_USE_DEPTH_TEXTURE
00555 texture->setFormat( GL_DEPTH_COMPONENT );
00556 #else
00557 texture->setFormat( GL_RGBA );
00558 #endif
00559
00560 texture->copyFromFrameBuffer( pvp );
00561
00562
00563 const void* fboKey = _getInfoKey( );
00564 FrameBufferObject* fbo = _glObjects->getEqFrameBufferObject( fboKey );
00565
00566 if( fbo )
00567 {
00568 EQCHECK( fbo->resize( _pvp.w, _pvp.h ));
00569 }
00570 else
00571 {
00572 fbo = _glObjects->newEqFrameBufferObject( fboKey );
00573 fbo->setColorFormat( GL_RGBA32F );
00574 EQCHECK( fbo->init( _pvp.w, _pvp.h, 0, 0 ));
00575 }
00576 fbo->bind();
00577
00578 texture->bind();
00579
00580
00581 glEnable( GL_TEXTURE_RECTANGLE_ARB );
00582
00583 glTexParameteri( GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MAG_FILTER,GL_LINEAR );
00584 glTexParameteri( GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MIN_FILTER,GL_LINEAR );
00585 glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
00586 GL_CLAMP_TO_EDGE );
00587 glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
00588 GL_CLAMP_TO_EDGE );
00589
00590
00591
00592 GLuint program = _glObjects->getProgram( shaderRBInfo );
00593
00594 if( program == Window::ObjectManager::INVALID )
00595 {
00596
00597
00598 const GLuint shader = _glObjects->newShader( shaderRBInfo,
00599 GL_FRAGMENT_SHADER );
00600 EQASSERT( shader != Window::ObjectManager::INVALID );
00601
00602 #ifdef EQ_ROI_USE_DEPTH_TEXTURE
00603 const GLchar* fShaderPtr = roiFragmentShader_glsl.c_str();
00604 #else
00605 const GLchar* fShaderPtr = roiFragmentShaderRGB_glsl.c_str();
00606 #endif
00607 EQ_GL_CALL( glShaderSource( shader, 1, &fShaderPtr, 0 ));
00608 EQ_GL_CALL( glCompileShader( shader ));
00609
00610 GLint status;
00611 glGetShaderiv( shader, GL_COMPILE_STATUS, &status );
00612 if( !status )
00613 EQERROR << "Failed to compile fragment shader for ROI finder"
00614 << std::endl;
00615
00616 program = _glObjects->newProgram( shaderRBInfo );
00617
00618 EQ_GL_CALL( glAttachShader( program, shader ));
00619 EQ_GL_CALL( glLinkProgram( program ));
00620
00621 glGetProgramiv( program, GL_LINK_STATUS, &status );
00622 if( !status )
00623 {
00624 EQWARN << "Failed to link shader program for ROI finder"
00625 << std::endl;
00626 return;
00627 }
00628
00629
00630 EQ_GL_CALL( glUseProgram( program ));
00631
00632 GLint param = glGetUniformLocation( program, "texture" );
00633 glUniform1i( param, 0 );
00634 }
00635 else
00636 {
00637
00638 EQ_GL_CALL( glUseProgram( program ));
00639 }
00640
00641
00642 glDisable( GL_LIGHTING );
00643 glColor3f( 1.0f, 1.0f, 1.0f );
00644
00645 glBegin( GL_QUADS );
00646 glVertex3i( 0, 0, 0 );
00647 glVertex3i( _pvp.w, 0, 0 );
00648 glVertex3i( _pvp.w, _pvp.h, 0 );
00649 glVertex3i( 0, _pvp.h, 0 );
00650 glEnd();
00651
00652
00653 glDisable( GL_TEXTURE_RECTANGLE_ARB );
00654 EQ_GL_CALL( glUseProgram( 0 ));
00655
00656 fbo->unbind();
00657
00658
00659 EQASSERT( static_cast<int32_t>(_perBlockInfo.size()) >= _pvp.w*_pvp.h*4 );
00660
00661 texture = fbo->getColorTextures()[0];
00662 texture->download( &_perBlockInfo[0], GL_RGBA, GL_FLOAT );
00663 }
00664
00665
00666 static PixelViewport _getBoundingPVP( const PixelViewport& pvp )
00667 {
00668 PixelViewport pvp_;
00669
00670 pvp_.x = ( pvp.x / GRID_SIZE );
00671 pvp_.y = ( pvp.y / GRID_SIZE );
00672
00673 pvp_.w = (( pvp.x + pvp.w + GRID_SIZE-1 )/GRID_SIZE ) - pvp_.x;
00674 pvp_.h = (( pvp.y + pvp.h + GRID_SIZE-1 )/GRID_SIZE ) - pvp_.y;
00675
00676 return pvp_;
00677 }
00678
00679
00680 PixelViewportVector ROIFinder::findRegions( const uint32_t buffers,
00681 const PixelViewport& pvp,
00682 const Zoom& zoom,
00683 const uint32_t stage,
00684 const uint32_t frameID,
00685 Window::ObjectManager* glObjects )
00686 {
00687 PixelViewportVector result;
00688 result.push_back( pvp );
00689
00690 #ifndef EQ_USE_ROI
00691 return result;
00692 #endif
00693
00694 #ifdef EQ_ROI_TEST_SPEED
00695 eq::base::Clock clock;
00696 clock.reset();
00697 for( int i = 0; i < 100; i++ ) {
00698 #endif
00699
00700 EQASSERT( glObjects );
00701 EQASSERTINFO( !_glObjects, "Another readback in progress?" );
00702 EQLOG( LOG_ASSEMBLY ) << "ROIFinder::getObjects " << pvp
00703 << ", buffers " << buffers
00704 << std::endl;
00705
00706 if( zoom != Zoom::NONE )
00707 {
00708 EQWARN << "R-B optimization impossible when zoom is used"
00709 << std::endl;
00710 return result;
00711 }
00712
00713 #ifdef EQ_ROI_USE_TRACKER
00714
00715 uint8_t* ticket;
00716 if( !_roiTracker.useROIFinder( pvp, stage, frameID, ticket ))
00717 return result;
00718 #endif
00719
00720 _pvpOriginal = pvp;
00721 _resize( _getBoundingPVP( pvp ));
00722
00723
00724
00725 _glObjects = glObjects;
00726 _readbackInfo();
00727 _glObjects = 0;
00728
00729
00730 _init( );
00731
00732
00733 _emptyFinder.update( &_mask[0], _wb, _hb );
00734 _emptyFinder.setLimits( 200, 0.002f );
00735
00736 result.clear();
00737 _findAreas( result );
00738
00739
00740 #ifdef EQ_ROI_USE_TRACKER
00741 _roiTracker.updateDelay( result, ticket );
00742 #endif
00743
00744 #ifdef EQ_ROI_TEST_SPEED
00745 }
00746 const float time = clock.getTimef() / 100;
00747 const float fps = 1000.f / time;
00748
00749 static float minFPS = 10000; minFPS = EQ_MIN( fps, minFPS );
00750 static float maxFPS = 0; maxFPS = EQ_MAX( fps, maxFPS );
00751 static float sumFPS = 0; sumFPS += fps;
00752 static float frames = 0; frames++;
00753
00754 const float avgFPS = sumFPS / frames;
00755 EQWARN << "=============================================" << std::endl;
00756 EQWARN << "ROI min fps: " << minFPS << " (" << 1000.f/minFPS
00757 << " ms) max fps: " << maxFPS << " (" << 1000.f/maxFPS
00758 << " ms) avg fps: " << avgFPS << " (" << 1000.f/avgFPS
00759 << " ms) cur fps: " << fps << " (" << 1000.f/fps
00760 << " ms) areas found: " << result.size() << std::endl;
00761
00762 if( frames < 5 ) { minFPS = 10000; maxFPS = 0; }
00763 #endif //EQ_ROI_TEST_SPEED
00764
00765
00766 return result;
00767 }
00768
00769 }
00770