LCOV - code coverage report
Current view: top level - eq/fabric - pixelViewport.h (source / functions) Hit Total Coverage
Test: Equalizer Lines: 107 142 75.4 %
Date: 2017-12-16 05:07:20 Functions: 23 25 92.0 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2006-2017, 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/pixel.h>    // used in inline method
      22             : #include <eq/fabric/viewport.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       30084 :     PixelViewport()
      41       30084 :         : x(0)
      42             :         , y(0)
      43             :         , w(-1)
      44       30084 :         , h(-1)
      45             :     {
      46       30084 :     }
      47             : 
      48             :     /** Construct a new pixel viewport with default values. @version 1.0 */
      49         628 :     PixelViewport(const int32_t x_, const int32_t y_, const int32_t w_,
      50             :                   const int32_t h_)
      51         628 :         : x(x_)
      52             :         , y(y_)
      53             :         , w(w_)
      54         628 :         , h(h_)
      55             :     {
      56         628 :     }
      57             : 
      58             :     /** Construct a new pixel viewport with default values. @version 1.1.6*/
      59           4 :     explicit PixelViewport(const int32_t pvp[4])
      60           4 :         : x(pvp[0])
      61           4 :         , y(pvp[1])
      62           4 :         , w(pvp[2])
      63          12 :         , h(pvp[3])
      64             :     {
      65           4 :     }
      66             :     //@}
      67             : 
      68             :     /** @name Data Access */
      69             :     //@{
      70             :     /** Invalidate the pixel viewport. @version 1.0 */
      71        1758 :     void invalidate()
      72             :     {
      73        1758 :         x = 0;
      74        1758 :         y = 0;
      75        1758 :         w = -1;
      76        1758 :         h = -1;
      77        1758 :     }
      78             : 
      79             :     /**
      80             :      * @return true if the pixel viewport has a non-negative, but
      81             :      *         potentially empty, size.
      82             :      * @version 1.0
      83             :      */
      84        7608 :     bool isValid() const { return (w >= 0 && h >= 0); }
      85             :     /**
      86             :      * @return true if the pixel viewport has a non-zero area, i.e, it is
      87             :      *         not empty.
      88             :      * @version 1.0
      89             :      */
      90        5807 :     bool hasArea() const { return (w > 0 && h > 0); }
      91             :     /** @return the area in pixels. @version 1.0 */
      92          84 :     uint32_t getArea() const { return w * h; }
      93             :     /**
      94             :      * @return true if the given point is inside the pixel viewport.
      95             :      * @version 1.0
      96             :      */
      97           0 :     bool isInside(const int32_t pX, const int32_t pY) const
      98             :     {
      99           0 :         if (pX < x || pY < y || pX > (x + w) || pY > (y + h))
     100           0 :             return false;
     101           0 :         return true;
     102             :     }
     103             :     //@}
     104             : 
     105             :     /** @name Operations */
     106             :     //@{
     107             :     /** Apply a fractional viewport to this pixel viewport. @internal */
     108        5776 :     PixelViewport& apply(const Viewport& vp)
     109             :     {
     110             :         // honor position over size to avoid rounding artifacts
     111        5776 :         const int32_t xEnd = x + int32_t((vp.x + vp.w) * w);
     112        5776 :         const int32_t yEnd = y + int32_t((vp.y + vp.h) * h);
     113             : 
     114        5776 :         x += int32_t(w * vp.x);
     115        5776 :         y += int32_t(h * vp.y);
     116        5776 :         w = xEnd - x;
     117        5776 :         h = yEnd - y;
     118        5776 :         return *this;
     119             :     }
     120             : 
     121             :     /** Apply a pixel decomposition to this pixel viewport. @internal */
     122         590 :     void apply(const Pixel& pixel)
     123             :     {
     124         590 :         if (pixel.w > 1)
     125             :         {
     126           0 :             int32_t newWidth = w / pixel.w;
     127             :             // This would be the correct thing to do, but it would
     128             :             // require frustum adaptations in CUV::_computeFrustum:
     129             :             // if( w - ( newWidth * pixel.w ) > pixel.x )
     130           0 :             if (w - (newWidth * pixel.w) != 0)
     131           0 :                 ++newWidth;
     132             : 
     133           0 :             w = newWidth;
     134             :         }
     135         590 :         if (pixel.h > 1)
     136             :         {
     137           0 :             int32_t newHeight = h / pixel.h;
     138             :             // This would be the correct thing to do, but it would
     139             :             // require frustum adaptations in CUV::_computeFrustum:
     140             :             // if( w - ( newWidth * pixel.h ) > pixel.y )
     141           0 :             if (h - (newHeight * pixel.h) != 0)
     142           0 :                 ++newHeight;
     143             : 
     144           0 :             h = newHeight;
     145             :         }
     146         590 :     }
     147             : 
     148             :     /** Apply a zoom to this pixel viewport. @internal */
     149         296 :     void apply(const Zoom& zoom)
     150             :     {
     151         296 :         if (zoom == Zoom::NONE)
     152         296 :             return;
     153             : 
     154           0 :         x = static_cast<int32_t>(x * zoom.x() + .5f);
     155           0 :         y = static_cast<int32_t>(y * zoom.y() + .5f);
     156           0 :         w = static_cast<int32_t>(w * zoom.x() + .5f);
     157           0 :         h = static_cast<int32_t>(h * zoom.y() + .5f);
     158             :     }
     159             : 
     160             :     /**
     161             :      * @return the zoom which would result in the given rhs pixel
     162             :      *         viewport when applied to this pixel viewport.
     163             :      * @internal
     164             :      */
     165         590 :     const Zoom getZoom(const PixelViewport& rhs) const
     166             :     {
     167         590 :         if (*this == rhs)
     168         590 :             return Zoom::NONE;
     169             : 
     170           0 :         if (!rhs.hasArea())
     171           0 :             return Zoom(std::numeric_limits<float>::max(),
     172           0 :                         std::numeric_limits<float>::max());
     173             : 
     174           0 :         return Zoom(w / static_cast<float>(rhs.w),
     175           0 :                     h / static_cast<float>(rhs.h));
     176             :     }
     177             : 
     178             :     /** @return the X end position. @version 1.0 */
     179         522 :     int32_t getXEnd() const { return x + w; }
     180             :     /** @return the Y end position. @version 1.0 */
     181         522 :     int32_t getYEnd() const { return y + h; }
     182             :     /** Convert into a lunchbox::Plugin usable format. @version 1.5.2 */
     183           4 :     void convertToPlugin(uint64_t dims[4]) const
     184             :     {
     185           4 :         dims[0] = x;
     186           4 :         dims[1] = w;
     187           4 :         dims[2] = y;
     188           4 :         dims[3] = h;
     189           4 :     }
     190             : 
     191             :     /** Convert from a lunchbox::Plugin format. @version 1.5.2 */
     192           1 :     void convertFromPlugin(const uint64_t dims[4])
     193             :     {
     194           1 :         x = int32_t(dims[0]);
     195           1 :         w = int32_t(dims[1]);
     196           1 :         y = int32_t(dims[2]);
     197           1 :         h = int32_t(dims[3]);
     198           1 :     }
     199             : 
     200             :     /** @return the addition of this pvp with an offset. @version 1.0 */
     201          66 :     const PixelViewport operator+(const Vector2i& offset) const
     202             :     {
     203          66 :         return PixelViewport(x + offset.x(), y + offset.y(), w, h);
     204             :     }
     205             : 
     206             :     /** @internal
     207             :      * @return the viewport which would provide this pixel viewport when
     208             :      *         applied to the rhs pixel viewport.
     209             :      */
     210        1279 :     Viewport operator/(const PixelViewport& rhs) const
     211             :     {
     212        1279 :         if (*this == rhs)
     213         488 :             return Viewport::FULL;
     214             : 
     215         791 :         if (!rhs.hasArea())
     216        1384 :             return Viewport(static_cast<float>(x), static_cast<float>(y), 0.f,
     217         692 :                             0.f);
     218             : 
     219         693 :         return Viewport((x - rhs.x) / static_cast<float>(rhs.w),
     220         198 :                         (y - rhs.y) / static_cast<float>(rhs.h),
     221         198 :                         (w) / static_cast<float>(rhs.w),
     222         297 :                         (h) / static_cast<float>(rhs.h));
     223             :     }
     224             : 
     225             :     /** @return this pvp minus an offset. @version 1.3.0 */
     226           1 :     const PixelViewport& operator-=(const Vector2i& offset)
     227             :     {
     228           1 :         x -= offset.x();
     229           1 :         y -= offset.y();
     230           1 :         return *this;
     231             :     }
     232             : 
     233             :     /**
     234             :      * Perform the inverse operation of applying a pixel decomposition to
     235             :      * this pixel viewport.
     236             :      * @version 1.0
     237             :      */
     238           0 :     void unapply(const Pixel& pixel)
     239             :     {
     240           0 :         w *= pixel.w;
     241           0 :         h *= pixel.h;
     242           0 :         x += pixel.x;
     243           0 :         y += pixel.y;
     244           0 :     }
     245             : 
     246             :     /**
     247             :      * @return true if the two pixel viewports are identical.
     248             :      * @version 1.0
     249             :      */
     250        3161 :     bool operator==(const PixelViewport& rhs) const
     251             :     {
     252        3161 :         return (x == rhs.x && y == rhs.y && w == rhs.w && h == rhs.h);
     253             :     }
     254             : 
     255             :     /**
     256             :      * @return true if the two pixel viewports are not identical.
     257             :      * @version 1.0
     258             :      */
     259        5352 :     bool operator!=(const PixelViewport& rhs) const
     260             :     {
     261        5352 :         return (x != rhs.x || y != rhs.y || w != rhs.w || h != rhs.h);
     262             :     }
     263             : 
     264             :     /**
     265             :      * Create a pixel viewport that includes both viewports (union).
     266             :      * @version 1.0
     267             :      */
     268          75 :     PixelViewport& merge(const PixelViewport& rhs)
     269             :     {
     270          75 :         if (*this == rhs || !rhs.isValid())
     271          54 :             return *this;
     272             : 
     273          21 :         if (!hasArea())
     274             :         {
     275          19 :             *this = rhs;
     276          19 :             return *this;
     277             :         }
     278           2 :         if (!rhs.hasArea())
     279           0 :             return *this;
     280             : 
     281           2 :         const int32_t sEx = x + w;
     282           2 :         const int32_t sEy = y + h;
     283           2 :         const int32_t dEx = rhs.x + rhs.w;
     284           2 :         const int32_t dEy = rhs.y + rhs.h;
     285             : 
     286           2 :         x = LB_MIN(x, rhs.x);
     287           2 :         y = LB_MIN(y, rhs.y);
     288           2 :         w = LB_MAX(sEx, dEx) - x;
     289           2 :         h = LB_MAX(sEy, dEy) - y;
     290           2 :         return *this;
     291             :     }
     292             : 
     293             :     /** Create the intersection of the two pixel viewports. @version 1.0 */
     294           6 :     void intersect(const PixelViewport& rhs)
     295             :     {
     296           6 :         if (*this == rhs)
     297           3 :             return;
     298             : 
     299           3 :         if (!rhs.isValid() || !isValid())
     300             :         {
     301           0 :             invalidate();
     302           0 :             return;
     303             :         }
     304             : 
     305           3 :         if (!rhs.hasArea() || !hasArea())
     306             :         {
     307           0 :             x = 0;
     308           0 :             y = 0;
     309           0 :             w = 0;
     310           0 :             h = 0;
     311           0 :             return;
     312             :         }
     313             : 
     314           3 :         const int32_t sEx = x + w;
     315           3 :         const int32_t sEy = y + h;
     316           3 :         const int32_t dEx = rhs.x + rhs.w;
     317           3 :         const int32_t dEy = rhs.y + rhs.h;
     318             : 
     319           3 :         x = LB_MAX(x, rhs.x);
     320           3 :         y = LB_MAX(y, rhs.y);
     321           3 :         w = LB_MIN(sEx, dEx) - x;
     322           3 :         h = LB_MIN(sEy, dEy) - y;
     323             :     }
     324             : 
     325             :     //@}
     326             : 
     327             :     int32_t x;
     328             :     int32_t y;
     329             :     int32_t w;
     330             :     int32_t h;
     331             : };
     332             : 
     333         732 : inline std::ostream& operator<<(std::ostream& os, const PixelViewport& pvp)
     334             : {
     335         732 :     os << "[ " << pvp.x << " " << pvp.y << " " << pvp.w << " " << pvp.h << " ]";
     336         732 :     return os;
     337             : }
     338             : }
     339             : }
     340             : 
     341             : #endif // EQFABRIC_PIXELVIEWPORT_H

Generated by: LCOV version 1.11