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

Generated by: LCOV version 1.11