LCOV - code coverage report
Current view: top level - gfx/2d - Tools.h (source / functions) Hit Total Coverage
Test: output.info Lines: 56 82 68.3 %
Date: 2017-07-14 16:53:18 Functions: 13 22 59.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #ifndef MOZILLA_GFX_TOOLS_H_
       7             : #define MOZILLA_GFX_TOOLS_H_
       8             : 
       9             : #include "mozilla/CheckedInt.h"
      10             : #include "mozilla/Move.h"
      11             : #include "mozilla/TypeTraits.h"
      12             : #include "Types.h"
      13             : #include "Point.h"
      14             : #include <math.h>
      15             : 
      16             : namespace mozilla {
      17             : namespace gfx {
      18             : 
      19             : static inline bool
      20         429 : IsOperatorBoundByMask(CompositionOp aOp) {
      21         429 :   switch (aOp) {
      22             :   case CompositionOp::OP_IN:
      23             :   case CompositionOp::OP_OUT:
      24             :   case CompositionOp::OP_DEST_IN:
      25             :   case CompositionOp::OP_DEST_ATOP:
      26             :   case CompositionOp::OP_SOURCE:
      27          14 :     return false;
      28             :   default:
      29         415 :     return true;
      30             :   }
      31             : }
      32             : 
      33             : template <class T>
      34             : struct ClassStorage
      35             : {
      36             :   char bytes[sizeof(T)];
      37             : 
      38             :   const T *addr() const { return (const T *)bytes; }
      39           0 :   T *addr() { return (T *)(void *)bytes; }
      40             : };
      41             : 
      42             : static inline bool
      43        4040 : FuzzyEqual(Float aA, Float aB, Float aErr)
      44             : {
      45        4040 :   if ((aA + aErr >= aB) && (aA - aErr <= aB)) {
      46        4032 :     return true;
      47             :   }
      48           8 :   return false;
      49             : }
      50             : 
      51             : static inline void
      52        3718 : NudgeToInteger(float *aVal)
      53             : {
      54        3718 :   float r = floorf(*aVal + 0.5f);
      55             :   // The error threshold should be proportional to the rounded value. This
      56             :   // bounds the relative error introduced by the nudge operation. However,
      57             :   // when the rounded value is 0, the error threshold can't be proportional
      58             :   // to the rounded value (we'd never round), so we just choose the same
      59             :   // threshold as for a rounded value of 1.
      60        3718 :   if (FuzzyEqual(r, *aVal, r == 0.0f ? 1e-6f : fabs(r*1e-6f))) {
      61        3710 :     *aVal = r;
      62             :   }
      63        3718 : }
      64             : 
      65             : static inline void
      66          96 : NudgeToInteger(float *aVal, float aErr)
      67             : {
      68          96 :   float r = floorf(*aVal + 0.5f);
      69          96 :   if (FuzzyEqual(r, *aVal, aErr)) {
      70          96 :     *aVal = r;
      71             :   }
      72          96 : }
      73             : 
      74             : static inline void
      75         324 : NudgeToInteger(double *aVal)
      76             : {
      77         324 :   float f = float(*aVal);
      78         324 :   NudgeToInteger(&f);
      79         324 :   *aVal = f;
      80         324 : }
      81             : 
      82             : static inline Float
      83           0 : Distance(Point aA, Point aB)
      84             : {
      85           0 :   return hypotf(aB.x - aA.x, aB.y - aA.y);
      86             : }
      87             : 
      88             : static inline int
      89         296 : BytesPerPixel(SurfaceFormat aFormat)
      90             : {
      91         296 :   switch (aFormat) {
      92             :   case SurfaceFormat::A8:
      93           0 :     return 1;
      94             :   case SurfaceFormat::R5G6B5_UINT16:
      95           0 :     return 2;
      96             :   case SurfaceFormat::R8G8B8:
      97             :   case SurfaceFormat::B8G8R8:
      98           0 :     return 3;
      99             :   case SurfaceFormat::HSV:
     100             :   case SurfaceFormat::Lab:
     101           0 :     return 3 * sizeof(float);
     102             :   case SurfaceFormat::Depth:
     103           0 :     return sizeof(uint16_t);
     104             :   default:
     105         296 :     return 4;
     106             :   }
     107             : }
     108             : 
     109             : static inline bool
     110           0 : IsOpaqueFormat(SurfaceFormat aFormat) {
     111           0 :   switch (aFormat) {
     112             :     case SurfaceFormat::B8G8R8X8:
     113             :     case SurfaceFormat::R8G8B8X8:
     114             :     case SurfaceFormat::X8R8G8B8:
     115             :     case SurfaceFormat::YUV:
     116             :     case SurfaceFormat::NV12:
     117             :     case SurfaceFormat::YUV422:
     118             :     case SurfaceFormat::R5G6B5_UINT16:
     119           0 :       return true;
     120             :     default:
     121           0 :       return false;
     122             :   }
     123             : }
     124             : 
     125             : template<typename T, int alignment = 16>
     126             : struct AlignedArray
     127             : {
     128             :   typedef T value_type;
     129             : 
     130           0 :   AlignedArray()
     131             :     : mPtr(nullptr)
     132           0 :     , mStorage(nullptr)
     133             :   {
     134           0 :   }
     135             : 
     136           1 :   explicit MOZ_ALWAYS_INLINE AlignedArray(size_t aCount, bool aZero = false)
     137             :     : mStorage(nullptr)
     138           1 :     , mCount(0)
     139             :   {
     140           1 :     Realloc(aCount, aZero);
     141           1 :   }
     142             : 
     143           1 :   MOZ_ALWAYS_INLINE ~AlignedArray()
     144             :   {
     145           1 :     Dealloc();
     146           1 :   }
     147             : 
     148           1 :   void Dealloc()
     149             :   {
     150             :     // If we fail this assert we'll need to uncomment the loop below to make
     151             :     // sure dtors are properly invoked. If we do that, we should check that the
     152             :     // comment about compiler dead code elimination is in fact true for all the
     153             :     // compilers that we care about.
     154             :     static_assert(mozilla::IsPod<T>::value,
     155             :                   "Destructors must be invoked for this type");
     156             : #if 0
     157             :     for (size_t i = 0; i < mCount; ++i) {
     158             :       // Since we used the placement |operator new| function to construct the
     159             :       // elements of this array we need to invoke their destructors manually.
     160             :       // For types where the destructor does nothing the compiler's dead code
     161             :       // elimination step should optimize this loop away.
     162             :       mPtr[i].~T();
     163             :     }
     164             : #endif
     165             : 
     166           1 :     free(mStorage);
     167           1 :     mStorage = nullptr;
     168           1 :     mPtr = nullptr;
     169           1 :   }
     170             : 
     171           1 :   MOZ_ALWAYS_INLINE void Realloc(size_t aCount, bool aZero = false)
     172             :   {
     173           1 :     free(mStorage);
     174             :     CheckedInt32 storageByteCount =
     175           1 :       CheckedInt32(sizeof(T)) * aCount + (alignment - 1);
     176           1 :     if (!storageByteCount.isValid()) {
     177           0 :       mStorage = nullptr;
     178           0 :       mPtr = nullptr;
     179           0 :       mCount = 0;
     180           0 :       return;
     181             :     }
     182             :     // We don't create an array of T here, since we don't want ctors to be
     183             :     // invoked at the wrong places if we realign below.
     184           1 :     if (aZero) {
     185             :       // calloc can be more efficient than new[] for large chunks,
     186             :       // so we use calloc/malloc/free for everything.
     187           0 :       mStorage = static_cast<uint8_t *>(calloc(1, storageByteCount.value()));
     188             :     } else {
     189           1 :       mStorage = static_cast<uint8_t *>(malloc(storageByteCount.value()));
     190             :     }
     191           1 :     if (!mStorage) {
     192           0 :       mStorage = nullptr;
     193           0 :       mPtr = nullptr;
     194           0 :       mCount = 0;
     195           0 :       return;
     196             :     }
     197           1 :     if (uintptr_t(mStorage) % alignment) {
     198             :       // Our storage does not start at a <alignment>-byte boundary. Make sure mPtr does!
     199           0 :       mPtr = (T*)(uintptr_t(mStorage) + alignment - (uintptr_t(mStorage) % alignment));
     200             :     } else {
     201           1 :       mPtr = (T*)(mStorage);
     202             :     }
     203             :     // Now that mPtr is pointing to the aligned position we can use placement
     204             :     // |operator new| to invoke any ctors at the correct positions. For types
     205             :     // that have a no-op default constructor the compiler's dead code
     206             :     // elimination step should optimize this away.
     207           1 :     mPtr = new (mPtr) T[aCount];
     208           1 :     mCount = aCount;
     209             :   }
     210             : 
     211             :   void Swap(AlignedArray<T, alignment>& aOther)
     212             :   {
     213             :     mozilla::Swap(mPtr, aOther.mPtr);
     214             :     mozilla::Swap(mStorage, aOther.mStorage);
     215             :     mozilla::Swap(mCount, aOther.mCount);
     216             :   }
     217             : 
     218           4 :   MOZ_ALWAYS_INLINE operator T*()
     219             :   {
     220           4 :     return mPtr;
     221             :   }
     222             : 
     223             :   T *mPtr;
     224             : 
     225             : private:
     226             :   uint8_t *mStorage;
     227             :   size_t mCount;
     228             : };
     229             : 
     230             : /**
     231             :  * Returns aWidth * aBytesPerPixel increased, if necessary, so that it divides
     232             :  * exactly into |alignment|.
     233             :  *
     234             :  * Note that currently |alignment| must be a power-of-2. If for some reason we
     235             :  * want to support NPOT alignment we can revert back to this functions old
     236             :  * implementation.
     237             :  */
     238             : template<int alignment>
     239         133 : int32_t GetAlignedStride(int32_t aWidth, int32_t aBytesPerPixel)
     240             : {
     241             :   static_assert(alignment > 0 && (alignment & (alignment-1)) == 0,
     242             :                 "This implementation currently require power-of-two alignment");
     243         133 :   const int32_t mask = alignment - 1;
     244         133 :   CheckedInt32 stride = CheckedInt32(aWidth) * CheckedInt32(aBytesPerPixel) + CheckedInt32(mask);
     245         133 :   if (stride.isValid()) {
     246         133 :     return stride.value() & ~mask;
     247             :   }
     248           0 :   return 0;
     249             : }
     250             : 
     251             : } // namespace gfx
     252             : } // namespace mozilla
     253             : 
     254             : #endif /* MOZILLA_GFX_TOOLS_H_ */

Generated by: LCOV version 1.13