LCOV - code coverage report
Current view: top level - eq/fabric - pixelViewport.h (source / functions) Hit Total Coverage
Test: Equalizer Lines: 38 130 29.2 %
Date: 2016-09-29 05:02:09 Functions: 13 26 50.0 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2006-2015, 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       45886 :     PixelViewport() : x(0), y(0), w(-1), h(-1)  {}
      41             : 
      42             :     /** Construct a new pixel viewport with default values. @version 1.0 */
      43         575 :     PixelViewport( const int32_t x_, const int32_t y_,
      44             :                    const int32_t w_,const int32_t h_ )
      45         575 :         : x(x_), y(y_), w(w_), h(h_)  {}
      46             : 
      47             :     /** Construct a new pixel viewport with default values. @version 1.1.6*/
      48           0 :     explicit PixelViewport( const int32_t pvp[4] )
      49           0 :         : 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        1812 :     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        6090 :     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        4931 :     bool hasArea() const { return (w>0 && h>0); }
      70             : 
      71             :     /** @return the area in pixels. @version 1.0 */
      72          82 :     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        5186 :     void apply( const Viewport& rhs )
      90             :     {
      91             :         // honor position over size to avoid rounding artifacts
      92        5186 :         const int32_t xEnd = x + static_cast<int32_t>((rhs.x+rhs.w)*w);
      93        5186 :         const int32_t yEnd = y + static_cast<int32_t>((rhs.y+rhs.h)*h);
      94             : 
      95        5186 :         x += static_cast<int32_t>( w * rhs.x );
      96        5186 :         y += static_cast<int32_t>( h * rhs.y );
      97        5186 :         w = xEnd - x;
      98        5186 :         h = yEnd - y;
      99        5186 :     }
     100             : 
     101             :     /** Apply a pixel decomposition to this pixel viewport. @internal */
     102           0 :     void apply( const Pixel& pixel )
     103             :     {
     104           0 :         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           0 :         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           0 :     }
     127             : 
     128             :     /** Apply a zoom to this pixel viewport. @internal */
     129           0 :     void apply( const Zoom& zoom )
     130             :     {
     131           0 :         if( zoom == Zoom::NONE )
     132           0 :             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           0 :     const Zoom getZoom( const PixelViewport& rhs ) const
     146             :     {
     147           0 :         if( *this == rhs )
     148           0 :             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           0 :     int32_t getXEnd() const { return x+w; }
     160             : 
     161             :     /** @return the Y end position. @version 1.0 */
     162           0 :     int32_t getYEnd() const { return y+h; }
     163             : 
     164             :     /** Convert into a lunchbox::Plugin usable format. @version 1.5.2 */
     165           0 :     void convertToPlugin( uint64_t dims[4] ) const
     166             :     {
     167           0 :         dims[ 0 ] = x;
     168           0 :         dims[ 1 ] = w;
     169           0 :         dims[ 2 ] = y;
     170           0 :         dims[ 3 ] = h;
     171           0 :     }
     172             : 
     173             :     /** Convert from a lunchbox::Plugin format. @version 1.5.2 */
     174           0 :     void convertFromPlugin( const uint64_t dims[4] )
     175             :     {
     176           0 :         x = int32_t( dims[ 0 ]);
     177           0 :         w = int32_t( dims[ 1 ]);
     178           0 :         y = int32_t( dims[ 2 ]);
     179           0 :         h = int32_t( dims[ 3 ]);
     180           0 :     }
     181             : 
     182             :     /** @return the addition of this pvp with an offset. @version 1.0 */
     183          63 :     const PixelViewport operator + ( const Vector2i& offset ) const
     184             :     {
     185          63 :         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         687 :     Viewport operator / ( const PixelViewport& rhs ) const
     193             :     {
     194         687 :         if( *this == rhs )
     195           0 :             return Viewport::FULL;
     196             : 
     197         687 :         if( !rhs.hasArea( ))
     198             :             return Viewport( static_cast<float>( x ),
     199         632 :                              static_cast<float>( y ), 0.f, 0.f );
     200             : 
     201          55 :         return Viewport(  ( x - rhs.x )/ static_cast<float>( rhs.w ),
     202          55 :                           ( y - rhs.y )/ static_cast<float>( rhs.h ),
     203             :                           ( w )/ static_cast<float>( rhs.w ),
     204         165 :                           ( h )/ static_cast<float>( rhs.h ));
     205             :     }
     206             : 
     207             :     /** @return this pvp minus an offset. @version 1.3.0 */
     208           0 :     const PixelViewport& operator -= ( const Vector2i& offset )
     209             :     {
     210           0 :         x -= offset.x();
     211           0 :         y -= offset.y();
     212           0 :         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        1817 :     bool operator == ( const PixelViewport& rhs ) const
     233             :     {
     234        1817 :         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        5228 :     bool operator != ( const PixelViewport& rhs ) const
     242             :     {
     243        5228 :         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          64 :     void merge( const PixelViewport& rhs )
     251             :     {
     252          64 :         if( *this == rhs || !rhs.isValid( ))
     253          54 :             return;
     254             : 
     255          10 :         if( !hasArea( ))
     256             :         {
     257          10 :             *this = rhs;
     258          10 :             return;
     259             :         }
     260           0 :         if( !rhs.hasArea( ))
     261           0 :             return;
     262             : 
     263           0 :         const int32_t sEx =     x +     w;
     264           0 :         const int32_t sEy =     y +     h;
     265           0 :         const int32_t dEx = rhs.x + rhs.w;
     266           0 :         const int32_t dEy = rhs.y + rhs.h;
     267             : 
     268           0 :         x = LB_MIN( x, rhs.x );
     269           0 :         y = LB_MIN( y, rhs.y );
     270           0 :         w = LB_MAX( sEx, dEx ) - x;
     271           0 :         h = LB_MAX( sEy, dEy ) - y;
     272             :     }
     273             : 
     274             :     /** Create the intersection of the two pixel viewports. @version 1.0 */
     275           0 :     void intersect( const PixelViewport& rhs )
     276             :     {
     277           0 :         if( *this == rhs )
     278           0 :             return;
     279             : 
     280           0 :         if( !rhs.isValid() || !isValid() )
     281             :         {
     282           0 :             invalidate();
     283           0 :             return;
     284             :         }
     285             : 
     286           0 :         if( !rhs.hasArea() || !hasArea() )
     287             :         {
     288           0 :             x = 0;
     289           0 :             y = 0;
     290           0 :             w = 0;
     291           0 :             h = 0;
     292           0 :             return;
     293             :         }
     294             : 
     295           0 :         const int32_t sEx =     x +     w;
     296           0 :         const int32_t sEy =     y +     h;
     297           0 :         const int32_t dEx = rhs.x + rhs.w;
     298           0 :         const int32_t dEy = rhs.y + rhs.h;
     299             : 
     300           0 :         x = LB_MAX( x, rhs.x );
     301           0 :         y = LB_MAX( y, rhs.y );
     302           0 :         w = LB_MIN( sEx, dEx ) - x;
     303           0 :         h = LB_MIN( sEy, dEy ) - y;
     304             :     }
     305             : 
     306             :     //@}
     307             : 
     308             :     int32_t x;
     309             :     int32_t y;
     310             :     int32_t w;
     311             :     int32_t h;
     312             : };
     313             : 
     314         660 : inline std::ostream& operator << ( std::ostream& os,
     315             :                                    const PixelViewport& pvp )
     316             : {
     317         660 :     os << "[ " << pvp.x << " " << pvp.y << " " << pvp.w << " " << pvp.h
     318         660 :        <<" ]";
     319         660 :     return os;
     320             : }
     321             : }
     322             : }
     323             : 
     324             : namespace lunchbox
     325             : {
     326           0 : template<> inline void byteswap( eq::fabric::PixelViewport& value )
     327             : {
     328           0 :     byteswap( value.x );
     329           0 :     byteswap( value.y );
     330           0 :     byteswap( value.w );
     331           0 :     byteswap( value.h );
     332           0 : }
     333             : }
     334             : #endif // EQFABRIC_PIXELVIEWPORT_H

Generated by: LCOV version 1.11