LCOV - code coverage report
Current view: top level - eq/fabric - pixelViewport.h (source / functions) Hit Total Coverage
Test: lcov2.info Lines: 72 128 56.2 %
Date: 2014-06-18 Functions: 23 26 88.5 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2006-2013, Stefan Eilemann <eile@equalizergraphics.com>
       3             :  *
       4             :  * This library is free software; you can redistribute it and/or modify it under
       5             :  * the terms of the GNU Lesser General Public License version 2.1 as published
       6             :  * by the Free Software Foundation.
       7             :  *
       8             :  * This library is distributed in the hope that it will be useful, but WITHOUT
       9             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      10             :  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
      11             :  * details.
      12             :  *
      13             :  * You should have received a copy of the GNU Lesser General Public License
      14             :  * along with this library; if not, write to the Free Software Foundation, Inc.,
      15             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      16             :  */
      17             : 
      18             : #ifndef EQFABRIC_PIXELVIEWPORT_H
      19             : #define EQFABRIC_PIXELVIEWPORT_H
      20             : 
      21             : #include <eq/fabric/viewport.h> // used in inline method
      22             : #include <eq/fabric/pixel.h>    // used in inline method
      23             : #include <eq/fabric/zoom.h>     // used in inline method
      24             : 
      25             : #include <lunchbox/debug.h>
      26             : 
      27             : #include <limits>
      28             : 
      29             : namespace eq
      30             : {
      31             : namespace fabric
      32             : {
      33             :     /** Holds a 2D pixel viewport with methods for manipulation. */
      34             :     class PixelViewport
      35             :     {
      36             :     public:
      37             :         /** @name Constructors */
      38             :         //@{
      39             :         /** Construct a new, invalid pixel viewport. @version 1.0 */
      40       21028 :         PixelViewport() : x(0), y(0), w(-1), h(-1)  {}
      41             : 
      42             :         /** Construct a new pixel viewport with default values. @version 1.0 */
      43        1299 :         explicit PixelViewport( const int32_t x_, const int32_t y_,
      44             :                                 const int32_t w_, const int32_t h_ )
      45        1299 :                 : x(x_), y(y_), w(w_), h(h_)  {}
      46             : 
      47             :         /** Construct a new pixel viewport with default values. @version 1.1.6*/
      48          21 :         explicit PixelViewport( const int32_t pvp[4] )
      49          21 :                 : x( pvp[0] ), y( pvp[1] ), w( pvp[2] ), h( pvp[3] )  {}
      50             :         //@}
      51             : 
      52             :         /** @name Data Access */
      53             :         //@{
      54             :         /** Invalidate the pixel viewport. @version 1.0 */
      55         909 :         void invalidate() { x = 0; y = 0; w = -1; h = -1; }
      56             : 
      57             :         /**
      58             :          * @return true if the pixel viewport has a non-negative, but
      59             :          *         potentially empty, size.
      60             :          * @version 1.0
      61             :          */
      62        6125 :         bool isValid() const { return (w>=0 && h>=0); }
      63             : 
      64             :         /**
      65             :          * @return true if the pixel viewport has a non-zero area, i.e, it is
      66             :          *         not empty.
      67             :          * @version 1.0
      68             :          */
      69        4680 :         bool hasArea() const { return (w>0 && h>0); }
      70             : 
      71             :         /** @return the area in pixels. @version 1.0 */
      72        1959 :         uint32_t getArea() const { return w * h; }
      73             : 
      74             :         /**
      75             :          * @return true if the given point is inside the pixel viewport.
      76             :          * @version 1.0
      77             :          */
      78           0 :         bool isInside( const int32_t pX, const int32_t pY ) const
      79             :             {
      80           0 :                 if( pX < x || pY < y || pX > (x+w) || pY > (y+h) )
      81           0 :                     return false;
      82           0 :                 return true;
      83             :             }
      84             :         //@}
      85             : 
      86             :         /** @name Operations */
      87             :         //@{
      88             :         /** Apply a fractional viewport to this pixel viewport. @internal */
      89        3735 :         void apply( const Viewport& rhs )
      90             :             {
      91             :                 // honor position over size to avoid rounding artifacts
      92        3735 :                 const int32_t xEnd = x + static_cast<int32_t>((rhs.x+rhs.w)*w);
      93        3735 :                 const int32_t yEnd = y + static_cast<int32_t>((rhs.y+rhs.h)*h);
      94             : 
      95        3735 :                 x += static_cast<int32_t>( w * rhs.x );
      96        3735 :                 y += static_cast<int32_t>( h * rhs.y );
      97        3735 :                 w = xEnd - x;
      98        3735 :                 h = yEnd - y;
      99        3735 :             }
     100             : 
     101             :         /** Apply a pixel decomposition to this pixel viewport. @internal */
     102        1164 :         void apply( const Pixel& pixel )
     103             :             {
     104        1164 :                 if( pixel.w > 1 )
     105             :                 {
     106           0 :                     int32_t newWidth = w / pixel.w;
     107             :                     // This would be the correct thing to do, but it would
     108             :                     // require frustum adaptations in CUV::_computeFrustum:
     109             :                     //if( w - ( newWidth * pixel.w ) > pixel.x )
     110           0 :                     if( w - ( newWidth * pixel.w ) != 0 )
     111           0 :                         ++newWidth;
     112             : 
     113           0 :                     w = newWidth;
     114             :                 }
     115        1164 :                 if( pixel.h > 1 )
     116             :                 {
     117           0 :                     int32_t newHeight = h / pixel.h;
     118             :                     // This would be the correct thing to do, but it would
     119             :                     // require frustum adaptations in CUV::_computeFrustum:
     120             :                     // if( w - ( newWidth * pixel.h ) > pixel.y )
     121           0 :                     if( h - ( newHeight * pixel.h ) != 0 )
     122           0 :                         ++newHeight;
     123             : 
     124           0 :                     h = newHeight;
     125             :                 }
     126        1164 :         }
     127             : 
     128             :         /** Apply a zoom to this pixel viewport. @internal */
     129        1166 :         void apply( const Zoom& zoom )
     130             :             {
     131        1166 :                 if( zoom == Zoom::NONE )
     132        2332 :                     return;
     133             : 
     134           0 :                 x = static_cast< int32_t >( x * zoom.x() + .5f );
     135           0 :                 y = static_cast< int32_t >( y * zoom.y() + .5f );
     136           0 :                 w = static_cast< int32_t >( w * zoom.x() + .5f );
     137           0 :                 h = static_cast< int32_t >( h * zoom.y() + .5f );
     138             :             }
     139             : 
     140             :         /**
     141             :          * @return the zoom which would result in the given rhs pixel
     142             :          *         viewport when applied to this pixel viewport.
     143             :          * @internal
     144             :          */
     145        1164 :         const Zoom getZoom( const PixelViewport& rhs ) const
     146             :             {
     147        1164 :                 if( *this == rhs )
     148        1164 :                     return Zoom::NONE;
     149             : 
     150           0 :                 if( !rhs.hasArea( ))
     151             :                     return Zoom( std::numeric_limits< float >::max(),
     152           0 :                                  std::numeric_limits< float >::max( ));
     153             : 
     154             :                 return Zoom( w / static_cast<float>( rhs.w ),
     155           0 :                              h / static_cast<float>( rhs.h ));
     156             :             }
     157             : 
     158             :         /** @return the X end position. @version 1.0 */
     159        1934 :         int32_t getXEnd() const { return x+w; }
     160             : 
     161             :         /** @return the Y end position. @version 1.0 */
     162        1934 :         int32_t getYEnd() const { return y+h; }
     163             : 
     164             :         /** Convert into a lunchbox::Plugin usable format. @version 1.5.2 */
     165         278 :         void convertToPlugin( uint64_t dims[4] ) const
     166             :         {
     167         278 :             dims[ 0 ] = x;
     168         278 :             dims[ 1 ] = w;
     169         278 :             dims[ 2 ] = y;
     170         278 :             dims[ 3 ] = h;
     171         278 :         }
     172             : 
     173             :         /** Convert from a lunchbox::Plugin format. @version 1.5.2 */
     174           3 :         void convertFromPlugin( const uint64_t dims[4] )
     175             :         {
     176           3 :             x = int32_t( dims[ 0 ]);
     177           3 :             w = int32_t( dims[ 1 ]);
     178           3 :             y = int32_t( dims[ 2 ]);
     179           3 :             h = int32_t( dims[ 3 ]);
     180           3 :         }
     181             : 
     182             :         /** @return the addition of this pvp with an offset. @version 1.0 */
     183          69 :         const PixelViewport operator + ( const Vector2i& offset ) const
     184             :             {
     185          69 :                 return PixelViewport( x+offset.x(), y+offset.y(), w, h );
     186             :             }
     187             : 
     188             :         /** @internal
     189             :          * @return the viewport which would provide this pixel viewport when
     190             :          *         applied to the rhs pixel viewport.
     191             :          */
     192        1333 :         Viewport operator / ( const PixelViewport& rhs ) const
     193             :             {
     194        1333 :                 if( *this == rhs )
     195         979 :                     return Viewport::FULL;
     196             : 
     197         354 :                 if( !rhs.hasArea( ))
     198             :                     return Viewport( static_cast<float>( x ),
     199         309 :                                      static_cast<float>( y ), 0.f, 0.f );
     200             : 
     201          45 :                 return Viewport(  ( x - rhs.x )/ static_cast<float>( rhs.w ),
     202          45 :                                   ( y - rhs.y )/ static_cast<float>( rhs.h ),
     203             :                                   ( w )/ static_cast<float>( rhs.w ),
     204         135 :                                   ( h )/ static_cast<float>( rhs.h ));
     205             :             }
     206             : 
     207             :         /** @return this pvp minus an offset. @version 1.3.0 */
     208           2 :         const PixelViewport& operator -= ( const Vector2i& offset )
     209             :             {
     210           2 :                 x -= offset.x();
     211           2 :                 y -= offset.y();
     212           2 :                 return *this;
     213             :             }
     214             : 
     215             :         /**
     216             :          * Perform the inverse operation of applying a pixel decomposition to
     217             :          * this pixel viewport.
     218             :          * @version 1.0
     219             :          */
     220           0 :         void unapply( const Pixel& pixel )
     221             :             {
     222           0 :                 w *= pixel.w;
     223           0 :                 h *= pixel.h;
     224           0 :                 x += pixel.x;
     225           0 :                 y += pixel.y;
     226           0 :             }
     227             : 
     228             :         /**
     229             :          * @return true if the two pixel viewports are identical.
     230             :          * @version 1.0
     231             :          */
     232        3203 :         bool operator == ( const PixelViewport& rhs ) const
     233             :             {
     234        3203 :                 return ( x==rhs.x && y==rhs.y && w==rhs.w && h==rhs.h );
     235             :             }
     236             : 
     237             :         /**
     238             :          * @return true if the two pixel viewports are not identical.
     239             :          * @version 1.0
     240             :          */
     241        4384 :         bool operator != ( const PixelViewport& rhs ) const
     242             :             {
     243        4384 :                 return ( x!=rhs.x || y!=rhs.y || w!=rhs.w || h!=rhs.h );
     244             :             }
     245             : 
     246             :         /**
     247             :          * Create a pixel viewport that includes both viewports (union).
     248             :          * @version 1.0
     249             :          */
     250          84 :         void merge( const PixelViewport& rhs )
     251             :             {
     252          84 :                 if( *this == rhs || !rhs.hasArea() )
     253          54 :                     return;
     254             : 
     255          30 :                 if( !hasArea() )
     256             :                 {
     257          30 :                     *this = rhs;
     258          30 :                     return;
     259             :                 }
     260             : 
     261           0 :                 const int32_t sEx =     x +     w;
     262           0 :                 const int32_t sEy =     y +     h;
     263           0 :                 const int32_t dEx = rhs.x + rhs.w;
     264           0 :                 const int32_t dEy = rhs.y + rhs.h;
     265             : 
     266           0 :                 x = LB_MIN( x, rhs.x );
     267           0 :                 y = LB_MIN( y, rhs.y );
     268           0 :                 w = LB_MAX( sEx, dEx ) - x;
     269           0 :                 h = LB_MAX( sEy, dEy ) - y;
     270             :             }
     271             : 
     272             :         /** Create the intersection of the two pixel viewports. @version 1.0 */
     273           9 :         void intersect( const PixelViewport& rhs )
     274             :             {
     275           9 :                 if( *this == rhs )
     276           9 :                     return;
     277             : 
     278           0 :                 if( !rhs.isValid() || !isValid() )
     279             :                 {
     280           0 :                     invalidate();
     281           0 :                     return;
     282             :                 }
     283             : 
     284           0 :                 if( !rhs.hasArea() || !hasArea() )
     285             :                 {
     286           0 :                     x = 0;
     287           0 :                     y = 0;
     288           0 :                     w = 0;
     289           0 :                     h = 0;
     290           0 :                     return;
     291             :                 }
     292             : 
     293           0 :                 const int32_t sEx =     x +     w;
     294           0 :                 const int32_t sEy =     y +     h;
     295           0 :                 const int32_t dEx = rhs.x + rhs.w;
     296           0 :                 const int32_t dEy = rhs.y + rhs.h;
     297             : 
     298           0 :                 x = LB_MAX( x, rhs.x );
     299           0 :                 y = LB_MAX( y, rhs.y );
     300           0 :                 w = LB_MIN( sEx, dEx ) - x;
     301           0 :                 h = LB_MIN( sEy, dEy ) - y;
     302             :             }
     303             : 
     304             :         //@}
     305             : 
     306             :         int32_t x;
     307             :         int32_t y;
     308             :         int32_t w;
     309             :         int32_t h;
     310             :     };
     311             : 
     312         379 :     inline std::ostream& operator << ( std::ostream& os,
     313             :                                        const PixelViewport& pvp )
     314             :     {
     315         379 :         os << "[ " << pvp.x << " " << pvp.y << " " << pvp.w << " " << pvp.h
     316         379 :            <<" ]";
     317         379 :         return os;
     318             :     }
     319             : }
     320             : }
     321             : 
     322             : namespace lunchbox
     323             : {
     324           0 : template<> inline void byteswap( eq::fabric::PixelViewport& value )
     325             : {
     326           0 :     byteswap( value.x );
     327           0 :     byteswap( value.y );
     328           0 :     byteswap( value.w );
     329           0 :     byteswap( value.h );
     330           0 : }
     331             : }
     332             : #endif // EQFABRIC_PIXELVIEWPORT_H

Generated by: LCOV version 1.10