LCOV - code coverage report
Current view: top level - eq - roiFinder.cpp (source / functions) Hit Total Coverage
Test: Equalizer Lines: 7 294 2.4 %
Date: 2016-07-30 05:04:55 Functions: 3 14 21.4 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c)      2009, Maxim Makhinya
       3             :  *               2010-2014, Stefan Eilemann <eile@equalizergraphics.com>
       4             :  *
       5             :  * This library is free software; you can redistribute it and/or modify it under
       6             :  * the terms of the GNU Lesser General Public License version 2.1 as published
       7             :  * by the Free Software Foundation.
       8             :  *
       9             :  * This library is distributed in the hope that it will be useful, but WITHOUT
      10             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      11             :  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
      12             :  * details.
      13             :  *
      14             :  * You should have received a copy of the GNU Lesser General Public License
      15             :  * along with this library; if not, write to the Free Software Foundation, Inc.,
      16             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      17             :  */
      18             : 
      19             : #define EQ_ROI_USE_TRACKER        // disable ROI in case it can't help
      20             : //#define EQ_ROI_USE_DEPTH_TEXTURE  // use depth texture instead of color
      21             : 
      22             : #include "roiFinder.h"
      23             : 
      24             : #ifdef EQ_ROI_USE_DEPTH_TEXTURE
      25             : #include "roiFragmentShader_glsl.h"
      26             : #else
      27             : #include "roiFragmentShaderRGB_glsl.h"
      28             : #endif
      29             : 
      30             : #include "gl.h"
      31             : #include "log.h"
      32             : 
      33             : #include <eq/util/frameBufferObject.h>
      34             : #include <eq/util/objectManager.h>
      35             : #include <eq/util/shader.h>
      36             : #include <lunchbox/os.h>
      37             : #include <pression/plugins/compressor.h>
      38             : 
      39             : 
      40             : namespace eq
      41             : {
      42             : 
      43             : #define glewGetContext glObjects.glewGetContext
      44             : 
      45             : // use to address one shader and program per shared context set
      46             : static const char seeds = 42;
      47             : static const char* shaderRBInfo = &seeds;
      48             : 
      49             : #define GRID_SIZE 16 // will be replaced later by variable
      50             : 
      51             : 
      52           1 : ROIFinder::ROIFinder()
      53             :     : _dim()
      54             :     , _w( 0 )
      55             :     , _h( 0 )
      56             :     , _wh( 0 )
      57             :     , _wb( 0 )
      58             :     , _hb( 0 )
      59             :     , _wbhb( 0 )
      60             :     , _histX()
      61           1 :     , _histY()
      62             : {
      63           1 :     _tmpAreas[0].pvp       = PixelViewport( 0, 0, 0, 0 );
      64           1 :     _tmpAreas[0].hole      = PixelViewport( 0, 0, 0, 0 );
      65           1 :     _tmpAreas[0].emptySize = 0;
      66           1 : }
      67             : 
      68           0 : PixelViewport ROIFinder::_getObjectPVP( const PixelViewport& pvp,
      69             :                                         const uint8_t*       src )
      70             : {
      71           0 :     LBASSERT( pvp.x >= 0 && pvp.x+pvp.w <= _wb &&
      72             :               pvp.y >= 0 && pvp.y+pvp.h <= _hb );
      73             : 
      74             :     // Calculate per-pixel histograms
      75           0 :     const uint8_t* s = src + pvp.y*_wb + pvp.x;
      76             : 
      77           0 :     memset( _histX, 0, pvp.w );
      78           0 :     memset( _histY, 0, pvp.h );
      79           0 :     for( int32_t y = 0; y < pvp.h; y++ )
      80             :     {
      81           0 :         for( int32_t x = 0; x < pvp.w; x++ )
      82             :         {
      83           0 :             const uint8_t val = s[ x ] & 1;
      84           0 :             _histX[ x ] += val;
      85           0 :             _histY[ y ] += val;
      86             :         }
      87           0 :         s += _wb;
      88             :     }
      89             : 
      90             :     // Find AABB based on X and Y axis historgams
      91           0 :     int32_t xMin = pvp.w;
      92           0 :     for( int32_t x = 0; x < pvp.w; x++ )
      93           0 :         if( _histX[x] != 0 )
      94             :         {
      95           0 :             xMin = x;
      96           0 :             break;
      97             :         }
      98             : 
      99           0 :     int32_t xMax = 0;
     100           0 :     for( int32_t x = pvp.w-1; x >= 0; x-- )
     101           0 :         if( _histX[x] != 0 )
     102             :         {
     103           0 :             xMax = x;
     104           0 :             break;
     105             :         }
     106             : 
     107           0 :     if( xMax < xMin )
     108           0 :         return PixelViewport( pvp.x, pvp.y, 0, 0 );
     109             : 
     110           0 :     int32_t yMin = pvp.h;
     111           0 :     for( int32_t y = 0; y < pvp.h; y++ )
     112           0 :         if( _histY[y] != 0 )
     113             :         {
     114           0 :             yMin = y;
     115           0 :             break;
     116             :         }
     117             : 
     118           0 :     int32_t yMax = 0;
     119           0 :     for( int32_t y = pvp.h-1; y >= 0; y-- )
     120           0 :         if( _histY[y] != 0 )
     121             :         {
     122           0 :             yMax = y;
     123           0 :             break;
     124             :         }
     125             : 
     126           0 :     if( yMax < yMin )
     127           0 :         return PixelViewport( pvp.x, pvp.y, 0, 0 );
     128             : 
     129           0 :     return PixelViewport( pvp.x+xMin, pvp.y+yMin, xMax-xMin+1, yMax-yMin+1 );
     130             : }
     131             : 
     132             : 
     133           0 : void ROIFinder::_resize( const PixelViewport& pvp )
     134             : {
     135           0 :     _pvp = pvp;
     136             : 
     137           0 :     _w   = _pvp.w;
     138           0 :     _h   = _pvp.h;
     139           0 :     _wh  = _w * _h;
     140           0 :     _wb  = _w + 1; // borders are only on left and
     141           0 :     _hb  = _h + 1; // top borders of the image
     142           0 :     _wbhb = _wb * _hb;
     143             : 
     144           0 :     if( static_cast<int32_t>(_mask.size()) < _wbhb )
     145             :     {
     146           0 :         _mask.resize( _wbhb );
     147             : 
     148             :         // w * h * sizeof( GL_FLOAT ) * RGBA
     149           0 :         _perBlockInfo.resize( _wh * 4 );
     150             :     }
     151           0 : }
     152             : 
     153             : 
     154           0 : void ROIFinder::_init( )
     155             : {
     156           0 :     _areasToCheck.clear();
     157           0 :     memset( &_mask[0]   , 0, _mask.size( ));
     158             : 
     159           0 :     LBASSERT( static_cast<int32_t>(_perBlockInfo.size()) >= _w*_h*4 );
     160           0 :     LBASSERT( static_cast<int32_t>(_mask.size())         >= _wb*_h  );
     161             : 
     162           0 :     const float*    src = &_perBlockInfo[0];
     163           0 :           uint8_t*  dst = &_mask[0];
     164             : 
     165           0 :     for( int32_t y = 0; y < _h; y++ )
     166             :     {
     167           0 :         for( int32_t x = 0; x < _w; x++ )
     168             :         {
     169           0 :             if( src[x*4] < 1.0 )
     170           0 :                 dst[x] = 255;
     171             :         }
     172           0 :         src += _w*4;
     173           0 :         dst += _wb;
     174             :     }
     175           0 : }
     176             : 
     177           0 : void ROIFinder::_invalidateAreas( Area* areas, uint8_t num )
     178             : {
     179           0 :     for( uint8_t i = 0; i < num; i++ )
     180           0 :         areas[i].valid = false;
     181           0 : }
     182             : 
     183           0 : void ROIFinder::_updateSubArea( const uint8_t type )
     184             : {
     185           0 :     LBASSERT( type <= 16 );
     186             : 
     187           0 :     if( type == 0 )
     188           0 :         return;
     189             : 
     190           0 :     PixelViewport pvp;
     191           0 :     switch( type )
     192             :     {
     193           0 :         case 1:  pvp = PixelViewport( _dim.x1,_dim.y2,_dim.w1,_dim.h2 ); break;
     194           0 :         case 2:  pvp = PixelViewport( _dim.x2,_dim.y3,_dim.w2,_dim.h3 ); break;
     195           0 :         case 3:  pvp = PixelViewport( _dim.x3,_dim.y2,_dim.w3,_dim.h2 ); break;
     196           0 :         case 4:  pvp = PixelViewport( _dim.x2,_dim.y1,_dim.w2,_dim.h1 ); break;
     197           0 :         case 5:  pvp = PixelViewport( _dim.x1,_dim.y1,_dim.w1,_dim.h4 ); break;
     198           0 :         case 6:  pvp = PixelViewport( _dim.x1,_dim.y3,_dim.w4,_dim.h3 ); break;
     199           0 :         case 7:  pvp = PixelViewport( _dim.x3,_dim.y2,_dim.w3,_dim.h5 ); break;
     200           0 :         case 8:  pvp = PixelViewport( _dim.x2,_dim.y1,_dim.w5,_dim.h1 ); break;
     201           0 :         case 9:  pvp = PixelViewport( _dim.x1,_dim.y2,_dim.w1,_dim.h5 ); break;
     202           0 :         case 10: pvp = PixelViewport( _dim.x2,_dim.y3,_dim.w5,_dim.h3 ); break;
     203           0 :         case 11: pvp = PixelViewport( _dim.x3,_dim.y1,_dim.w3,_dim.h4 ); break;
     204           0 :         case 12: pvp = PixelViewport( _dim.x1,_dim.y1,_dim.w4,_dim.h1 ); break;
     205           0 :         case 13: pvp = PixelViewport( _dim.x1,_dim.y1,_dim.w1,_dim.h6 ); break;
     206           0 :         case 14: pvp = PixelViewport( _dim.x3,_dim.y1,_dim.w3,_dim.h6 ); break;
     207           0 :         case 15: pvp = PixelViewport( _dim.x1,_dim.y3,_dim.w6,_dim.h3 ); break;
     208           0 :         case 16: pvp = PixelViewport( _dim.x1,_dim.y1,_dim.w6,_dim.h1 ); break;
     209             :         default:
     210           0 :             LBUNIMPLEMENTED;
     211             :     }
     212             : 
     213           0 :     LBASSERT( pvp.hasArea( ));
     214           0 :     LBASSERT( pvp.x >=0 && pvp.y >=0 && pvp.x+pvp.w <=_w && pvp.y+pvp.h <=_h );
     215             : 
     216           0 :     Area& a = _tmpAreas[type];
     217             : 
     218           0 :     a.pvp = _getObjectPVP( pvp, &_mask[0] );
     219             : 
     220           0 :     a.hole = _emptyFinder.getLargestEmptyArea( a.pvp );
     221             : 
     222           0 :     a.emptySize = pvp.getArea() - a.pvp.getArea() + a.hole.getArea();
     223             : 
     224             : #ifndef NDEBUG
     225           0 :     LBASSERT( !a.valid );
     226           0 :     a.valid = true;
     227             : #endif
     228             : }
     229             : 
     230             : 
     231             : // positions of a hole:
     232             : //
     233             : //  1 7 5
     234             : //  2 8 6
     235             : //  0 4 3
     236             : //
     237             : // 0, 1, 3, 5 - corners
     238             : // 2, 4, 6, 7 - sides
     239             : // 8          - center
     240             : //
     241             : 
     242             : 
     243             : static const uint8_t _interests[10][8] =
     244             : {
     245             :     { 2, 3, 7,10, 0, 0, 0, 0 }, // corner
     246             :     { 3, 4, 8,11, 0, 0, 0, 0 }, // corner
     247             :     { 2, 3, 4, 7, 8,10,11,14 }, // side
     248             :     { 1, 2, 6, 9, 0, 0, 0, 0 }, // corner
     249             :     { 1, 2, 3, 6, 7, 9,10,15 }, // side
     250             :     { 1, 4, 5,12, 0, 0, 0, 0 }, // corner
     251             :     { 1, 2, 4, 5, 6, 9,12,13 }, // side
     252             :     { 1, 3, 4, 5, 8,11,12,16 },  // side
     253             :     { 1, 3, 0, 0, 0, 0, 0, 0 }, // vertical
     254             :     { 2, 4, 0, 0, 0, 0, 0, 0 }, // horizontal
     255             : };                              // center is 1..16
     256             : 
     257             : static const uint8_t _compilNums[11][2] =
     258             : {
     259             :     {2,2},{2,2},{4,3},{2,2},{4,3},{2,2},{4,3},{4,3},{1,2},{1,2},{18,4}
     260             : };
     261             : 
     262             : static const uint8_t _compilations[10][4][3] =
     263             : {
     264             :     {{2, 7, 0},{3,10, 0},{0,0, 0},{0,0, 0}}, // corner
     265             :     {{3, 8, 0},{4,11, 0},{0,0, 0},{0,0, 0}}, // corner
     266             :     {{2, 4,14},{4,10,11},{3,8,10},{2,7, 8}}, // side
     267             :     {{1, 6, 0},{2, 9, 0},{0,0, 0},{0,0, 0}}, // corner
     268             :     {{1, 3,15},{3, 9,10},{2,7, 9},{1,6, 7}}, // side
     269             :     {{1,12, 0},{4, 5, 0},{0,0, 0},{0,0, 0}}, // corner
     270             :     {{2, 4,13},{4, 5, 6},{1,6,12},{2,9,12}}, // side
     271             :     {{1, 3,16},{1,11,12},{5,4,11},{3,5, 8}}, // side
     272             :     {{1, 3, 0},{0, 0, 0},{0,0, 0},{0,0, 0}}, // vertical
     273             :     {{2, 4, 0},{0, 0, 0},{0,0, 0},{0,0, 0}}, // horizontal
     274             : };
     275             : 
     276             : 
     277             : static const uint8_t _compilations16[18][4] =// center
     278             : {
     279             :     {13,2, 4,14},{13,4,10,11},{13,3,8,10},{13,2,7, 8},
     280             :     {16,1, 3,15},{16,3, 9,10},{16,2,7, 9},{16,1,6, 7},
     281             :     {14,2, 4,13},{14,4, 5, 6},{14,1,6,12},{14,2,9,12},
     282             :     {15,1, 3,16},{15,1,11,12},{15,5,4,11},{15,3,5, 8},
     283             :     {5 ,6, 7, 8},{9,10,11,12}
     284             : };
     285             : 
     286             : 
     287           0 : uint8_t ROIFinder::_splitArea( Area& a )
     288             : {
     289           0 :     LBASSERT( a.hole.getArea() > 0 );
     290             : #ifndef NDEBUG
     291           0 :     _invalidateAreas( _tmpAreas, 17 );
     292             : #endif
     293             : 
     294           0 :     _dim.x1 = a.pvp.x;
     295           0 :     _dim.x2 = a.hole.x;
     296           0 :     _dim.x3 = a.hole.x + a.hole.w;
     297             : 
     298           0 :     _dim.w1 = _dim.x2 - _dim.x1;
     299           0 :     _dim.w2 = a.hole.w;
     300           0 :     _dim.w3 = a.pvp.x + a.pvp.w - _dim.x3;
     301           0 :     _dim.w4 = _dim.w1 + _dim.w2;
     302           0 :     _dim.w5 = _dim.w2 + _dim.w3;
     303           0 :     _dim.w6 = _dim.w4 + _dim.w3;
     304             : 
     305           0 :     _dim.y1 = a.pvp.y;
     306           0 :     _dim.y2 = a.hole.y;
     307           0 :     _dim.y3 = a.hole.y + a.hole.h;
     308             : 
     309           0 :     _dim.h1 = _dim.y2 - _dim.y1;
     310           0 :     _dim.h2 = a.hole.h;
     311           0 :     _dim.h3 = a.pvp.y + a.pvp.h - _dim.y3;
     312           0 :     _dim.h4 = _dim.h1 + _dim.h2;
     313           0 :     _dim.h5 = _dim.h2 + _dim.h3;
     314           0 :     _dim.h6 = _dim.h4 + _dim.h3;
     315             : 
     316             :     // other cases
     317             :     uint8_t type;
     318           0 :     if( a.pvp.h == a.hole.h ) // hole through the whole block
     319             :     {
     320           0 :         LBASSERT( a.pvp.w != a.hole.w );
     321           0 :         type = 8;
     322             :     }
     323           0 :     else if( a.pvp.w == a.hole.w ) // hole through the whole block
     324             :     {
     325           0 :         type = 9;
     326             :     }
     327           0 :     else if( a.pvp.x == a.hole.x ) // left side
     328             :     {
     329           0 :         if( a.pvp.y == a.hole.y )
     330             :             // in the lower left corner
     331           0 :             type = 0;
     332           0 :         else if( a.pvp.y + a.pvp.h == a.hole.y + a.hole.h )
     333             :             // in the upper left corner
     334           0 :             type = 1;
     335             :         else
     336             :             // in the left middle
     337           0 :             type = 2;
     338             :     }
     339           0 :     else if( a.pvp.y == a.hole.y ) // bottom side
     340             :     {
     341           0 :         if( a.pvp.x + a.pvp.w == a.hole.x + a.hole.w )
     342             :             // in the bottom right corner
     343           0 :             type = 3;
     344             :         else
     345             :             // in the bottom middle
     346           0 :             type = 4;
     347             :     }
     348           0 :     else if( a.pvp.x + a.pvp.w == a.hole.x + a.hole.w ) // right side
     349             :     {
     350           0 :         if( a.pvp.y + a.pvp.h == a.hole.y + a.hole.h )
     351             :             // in the upper right corner
     352           0 :             type = 5;
     353             :         else
     354             :             // in the right middle
     355           0 :             type = 6;
     356             :     }
     357           0 :     else if( a.pvp.y + a.pvp.h == a.hole.y + a.hole.h ) // top side
     358             :         // in the upper middle corner
     359           0 :         type = 7;
     360             :     else
     361             :         // must be in the center
     362           0 :         type = 10;
     363             : 
     364             :     // Calculate areas of interest
     365           0 :     if( type == 10 ) // center hole position
     366             :     {
     367           0 :         for( uint8_t i = 1; i <= 16; i++ )
     368           0 :             _updateSubArea( i );
     369             :     }
     370             :     else
     371             :     {
     372           0 :         for( uint8_t i = 0; i < 8; i++ )
     373           0 :             _updateSubArea( _interests[ type ][ i ] );
     374             :     }
     375             : 
     376             :     // find best combinations of areas of interest
     377           0 :     const uint8_t varaintsNum     = _compilNums[type][0];
     378           0 :     const uint8_t areasPerVariant = _compilNums[type][1];
     379             : 
     380           0 :     int32_t maxSum  = 0;
     381           0 :     int32_t variant = 0;
     382           0 :     if( type == 10 ) // center hole
     383             :     {
     384           0 :         for( uint8_t i = 0; i < varaintsNum; i++ )
     385             :         {
     386           0 :             int32_t sum = 0;
     387           0 :             for( uint8_t j = 0; j < areasPerVariant; j++ )
     388             :             {
     389           0 :                 LBASSERT( _tmpAreas[_compilations16[i][j]].valid );
     390           0 :                 sum += _tmpAreas[_compilations16[i][j]].emptySize;
     391             :             }
     392             : 
     393           0 :             if( sum > maxSum )
     394             :             {
     395           0 :                 maxSum  = sum;
     396           0 :                 variant = i;
     397             :             }
     398             :         }
     399             : 
     400           0 :         for( uint8_t j = 0; j < areasPerVariant; j++ )
     401             :         {
     402           0 :             LBASSERT( _tmpAreas[_compilations16[variant][j]].valid );
     403           0 :             _finalAreas[j] = _tmpAreas[_compilations16[variant][j]];
     404             :         }
     405             : 
     406           0 :         return areasPerVariant;
     407             :     }
     408             :     // else any other hole
     409             : 
     410           0 :     for( uint8_t i = 0; i < varaintsNum; i++ )
     411             :     {
     412           0 :         int32_t sum = 0;
     413           0 :         for( uint8_t j = 0; j < areasPerVariant; j++ )
     414             :         {
     415           0 :             LBASSERT( _tmpAreas[_compilations[type][i][j]].valid );
     416           0 :             sum += _tmpAreas[_compilations[type][i][j]].emptySize;
     417             :         }
     418             : 
     419           0 :         if( sum > maxSum )
     420             :         {
     421           0 :             maxSum  = sum;
     422           0 :             variant = i;
     423             :         }
     424             :     }
     425             : 
     426           0 :     for( uint8_t j = 0; j < areasPerVariant; j++ )
     427             :     {
     428           0 :         LBASSERT( _tmpAreas[_compilations[type][variant][j]].valid );
     429           0 :         _finalAreas[j] = _tmpAreas[_compilations[type][variant][j]];
     430             :     }
     431             : 
     432           0 :     return areasPerVariant;
     433             : }
     434             : 
     435             : 
     436           0 : void ROIFinder::_findAreas( PixelViewports& resultPVPs )
     437             : {
     438           0 :     LBASSERT( _areasToCheck.empty() );
     439             : 
     440           0 :     Area area( PixelViewport( 0, 0, _w, _h ));
     441           0 :     area.pvp  = _getObjectPVP( area.pvp, &_mask[0] );
     442             : 
     443           0 :     if( area.pvp.w <= 0 || area.pvp.h <= 0 )
     444           0 :         return;
     445             : 
     446           0 :     area.hole = _emptyFinder.getLargestEmptyArea( area.pvp );
     447             : 
     448           0 :     if( area.hole.getArea() == 0 )
     449           0 :         resultPVPs.push_back( area.pvp );
     450             :     else
     451           0 :         _areasToCheck.push_back( area );
     452             : 
     453             :     // try to split areas
     454           0 :     while( !_areasToCheck.empty() )
     455             :     {
     456           0 :         Area curArea = _areasToCheck.back();
     457           0 :         _areasToCheck.pop_back();
     458             : 
     459           0 :         uint8_t n = _splitArea( curArea );
     460           0 :         LBASSERT( n >= 2 && n <= 4 );
     461             : 
     462           0 :         for( uint8_t i = 0; i < n; i++ )
     463             :         {
     464           0 :             LBASSERT( _finalAreas[i].valid );
     465           0 :             LBASSERT( _finalAreas[i].pvp.hasArea( ));
     466             : 
     467           0 :             if( _finalAreas[i].hole.getArea() == 0 )
     468           0 :                 resultPVPs.push_back( _finalAreas[i].pvp );
     469             :             else
     470           0 :                 _areasToCheck.push_back( _finalAreas[i] );
     471             :         }
     472             :     }
     473             : 
     474             :     // correct position and sizes
     475           0 :     for( uint32_t i = 0; i < resultPVPs.size(); i++ )
     476             :     {
     477           0 :         PixelViewport& pvp = resultPVPs[i];
     478           0 :         pvp.x += _pvp.x;
     479           0 :         pvp.y += _pvp.y;
     480             : 
     481           0 :         pvp.apply( Zoom( GRID_SIZE, GRID_SIZE ));
     482             :     }
     483             : 
     484             : }
     485             : 
     486           0 : const void* ROIFinder::_getInfoKey( ) const
     487             : {
     488           0 :     return ( reinterpret_cast< const char* >( this ) + 3 );
     489             : }
     490             : 
     491           0 : void ROIFinder::_readbackInfo( util::ObjectManager& glObjects )
     492             : {
     493           0 :     LBASSERT( glObjects.supportsEqTexture( ));
     494           0 :     LBASSERT( glObjects.supportsEqFrameBufferObject( ));
     495             : 
     496           0 :     PixelViewport pvp = _pvp;
     497           0 :     pvp.apply( Zoom( GRID_SIZE, GRID_SIZE ));
     498           0 :     pvp.w = LB_MIN( pvp.w+pvp.x, _pvpOriginal.w+_pvpOriginal.x ) - pvp.x;
     499           0 :     pvp.h = LB_MIN( pvp.h+pvp.y, _pvpOriginal.h+_pvpOriginal.y ) - pvp.y;
     500             : 
     501           0 :     LBASSERT( pvp.isValid());
     502             : 
     503             :     // copy frame buffer to texture
     504           0 :     const void* bufferKey = _getInfoKey( );
     505             :     util::Texture* texture =
     506           0 :         glObjects.obtainEqTexture( bufferKey, GL_TEXTURE_RECTANGLE_ARB );
     507             : 
     508             : #ifdef EQ_ROI_USE_DEPTH_TEXTURE
     509             :     texture->copyFromFrameBuffer( GL_DEPTH_COMPONENT, pvp );
     510             : #else
     511           0 :     texture->copyFromFrameBuffer( GL_RGBA, pvp );
     512             : #endif
     513             : 
     514             :     // draw zoomed quad into FBO
     515           0 :     const void*     fboKey = _getInfoKey( );
     516           0 :     util::FrameBufferObject* fbo = glObjects.getEqFrameBufferObject( fboKey );
     517             : 
     518           0 :     if( fbo )
     519             :     {
     520           0 :         LBCHECK( fbo->resize( _pvp.w, _pvp.h ));
     521             :     }
     522             :     else
     523             :     {
     524           0 :         fbo = glObjects.newEqFrameBufferObject( fboKey );
     525           0 :         LBCHECK( fbo->init( _pvp.w, _pvp.h, GL_RGBA32F, 0, 0 ));
     526             :     }
     527           0 :     fbo->bind();
     528             : 
     529           0 :     texture->bind();
     530             : 
     531             :     // Enable & download depth texture
     532           0 :     glEnable( GL_TEXTURE_RECTANGLE_ARB );
     533             : 
     534           0 :     texture->applyWrap();
     535           0 :     texture->applyZoomFilter( FILTER_LINEAR );
     536             : 
     537             :     // Enable shaders
     538           0 :     GLuint program = glObjects.getProgram( shaderRBInfo );
     539           0 :     if( program == util::ObjectManager::INVALID )
     540             :     {
     541             :         // Create fragment shader which reads depth values from
     542             :         // rectangular textures
     543             :         const GLuint shader = glObjects.newShader( shaderRBInfo,
     544           0 :                                                         GL_FRAGMENT_SHADER );
     545           0 :         LBASSERT( shader != util::ObjectManager::INVALID );
     546             : 
     547             : #ifdef EQ_ROI_USE_DEPTH_TEXTURE
     548             :         const GLchar* fShaderPtr = roiFragmentShader_glsl.c_str();
     549             : #else
     550           0 :         const GLchar* fShaderPtr = roiFragmentShaderRGB_glsl.c_str();
     551             : #endif
     552           0 :         LBCHECK( util::shader::compile( glewGetContext(), shader, fShaderPtr ));
     553           0 :         program = glObjects.newProgram( shaderRBInfo );
     554             : 
     555           0 :         EQ_GL_CALL( glAttachShader( program, shader ));
     556           0 :         EQ_GL_CALL( glLinkProgram( program ));
     557             : 
     558             :         GLint status;
     559           0 :         glGetProgramiv( program, GL_LINK_STATUS, &status );
     560           0 :         if( !status )
     561             :         {
     562           0 :             LBWARN << "Failed to link shader program for ROI finder"
     563           0 :                    << std::endl;
     564           0 :             return;
     565             :         }
     566             : 
     567             :         // use fragment shader and setup uniforms
     568           0 :         EQ_GL_CALL( glUseProgram( program ));
     569             : 
     570           0 :         GLint param = glGetUniformLocation( program, "texture" );
     571           0 :         glUniform1i( param, 0 );
     572             :     }
     573             :     else
     574             :     {
     575             :         // use fragment shader
     576           0 :         EQ_GL_CALL( glUseProgram( program ));
     577             :     }
     578             : 
     579             :     // Draw Quad
     580           0 :     glDisable( GL_LIGHTING );
     581           0 :     glColor3f( 1.0f, 1.0f, 1.0f );
     582             : 
     583           0 :     glBegin( GL_QUADS );
     584           0 :         glVertex3i(      0,      0, 0 );
     585           0 :         glVertex3i( _pvp.w,      0, 0 );
     586           0 :         glVertex3i( _pvp.w, _pvp.h, 0 );
     587           0 :         glVertex3i(      0, _pvp.h, 0 );
     588           0 :     glEnd();
     589             : 
     590             :     // restore state
     591           0 :     glDisable( GL_TEXTURE_RECTANGLE_ARB );
     592           0 :     EQ_GL_CALL( glUseProgram( 0 ));
     593             : 
     594           0 :     fbo->unbind();
     595             : 
     596             :     // finish readback of info
     597           0 :     LBASSERT( static_cast<int32_t>(_perBlockInfo.size()) >= _pvp.w*_pvp.h*4 );
     598             : 
     599           0 :     texture = fbo->getColorTextures()[0];
     600           0 :     LBASSERT( texture->getFormat() == GL_RGBA );
     601           0 :     LBASSERT( texture->getType() == GL_FLOAT );
     602           0 :     texture->download( &_perBlockInfo[0] );
     603             : }
     604             : 
     605             : 
     606           0 : static PixelViewport _getBoundingPVP( const PixelViewport& pvp )
     607             : {
     608           0 :     PixelViewport pvp_;
     609             : 
     610           0 :     pvp_.x = ( pvp.x / GRID_SIZE );
     611           0 :     pvp_.y = ( pvp.y / GRID_SIZE );
     612             : 
     613           0 :     pvp_.w = (( pvp.x + pvp.w + GRID_SIZE-1 )/GRID_SIZE ) - pvp_.x;
     614           0 :     pvp_.h = (( pvp.y + pvp.h + GRID_SIZE-1 )/GRID_SIZE ) - pvp_.y;
     615             : 
     616           0 :     return pvp_;
     617             : }
     618             : 
     619             : 
     620           0 : PixelViewports ROIFinder::findRegions( const uint32_t         buffers,
     621             :                                        const PixelViewport&   pvp,
     622             :                                        const Zoom&            zoom,
     623             :                                        const uint32_t         stage,
     624             :                                        const uint128_t&       frameID,
     625             :                                        util::ObjectManager&   glObjects )
     626             : {
     627           0 :     PixelViewports result;
     628           0 :     result.push_back( pvp );
     629             : 
     630           0 :     LBLOG( LOG_ASSEMBLY ) << "ROIFinder::getObjects " << pvp << ", buffers "
     631           0 :                           << buffers << std::endl;
     632             : 
     633           0 :     if( zoom != Zoom::NONE )
     634             :     {
     635           0 :         LBWARN << "R-B optimization impossible when zoom is used"
     636           0 :                << std::endl;
     637           0 :         return result;
     638             :     }
     639             : 
     640             : #ifdef EQ_ROI_USE_TRACKER
     641             :     uint8_t* ticket;
     642           0 :     if( !_roiTracker.useROIFinder( pvp, stage, frameID, ticket ))
     643           0 :         return result;
     644             : #endif
     645             : 
     646           0 :     _pvpOriginal = pvp;
     647           0 :     _resize( _getBoundingPVP( pvp ));
     648             : 
     649             :     // go through depth buffer and check min/max/BG values
     650             :     // render to and read-back usefull info from FBO
     651           0 :     _readbackInfo( glObjects );
     652           0 :     glObjects.clear();
     653             : 
     654             :     // Analyze readed back data and find regions of interest
     655           0 :     _init( );
     656             : 
     657           0 :     _emptyFinder.update( &_mask[0], _wb, _hb );
     658           0 :     _emptyFinder.setLimits( 200, 0.002f );
     659             : 
     660           0 :     result.clear();
     661           0 :     _findAreas( result );
     662             : 
     663             : #ifdef EQ_ROI_USE_TRACKER
     664           0 :     _roiTracker.updateDelay( result, ticket );
     665             : #endif
     666             : 
     667           0 :     return result;
     668             : }
     669             : 
     670          42 : }

Generated by: LCOV version 1.11