Bug 1299741 part 5 - Move FastDivideBy255 into gfx/Tools.h and replace the macro in nsColor.h with it. r?jrmuizel draft
authorXidorn Quan <xidorn+moz@upsuper.org>
Thu, 01 Sep 2016 13:48:13 +1000
changeset 408666 0e0e6dde057aaa7a0780221e5da9e65f75cbab0e
parent 408482 42db3073a76bed9664449a04118a87023ac76949
child 408667 e9fbf7cb21a79b64558f5d31d2b61aedf5b11e57
push id28268
push userxquan@mozilla.com
push dateThu, 01 Sep 2016 14:08:08 +0000
reviewersjrmuizel
bugs1299741
milestone51.0a1
Bug 1299741 part 5 - Move FastDivideBy255 into gfx/Tools.h and replace the macro in nsColor.h with it. r?jrmuizel MozReview-Commit-ID: G3OYNHHawh4
gfx/2d/SIMD.h
gfx/2d/Tools.h
gfx/src/nsColor.cpp
gfx/src/nsColor.h
--- a/gfx/2d/SIMD.h
+++ b/gfx/2d/SIMD.h
@@ -660,48 +660,36 @@ PackAndSaturate16To8(Scalari16x8_t m1, S
   m.u8[11] = SaturateTo8(m2.i16[3]);
   m.u8[12] = SaturateTo8(m2.i16[4]);
   m.u8[13] = SaturateTo8(m2.i16[5]);
   m.u8[14] = SaturateTo8(m2.i16[6]);
   m.u8[15] = SaturateTo8(m2.i16[7]);
   return m;
 }
 
-// Fast approximate division by 255. It has the property that
-// for all 0 <= n <= 255*255, FAST_DIVIDE_BY_255(n) == n/255.
-// But it only uses two adds and two shifts instead of an
-// integer division (which is expensive on many processors).
-//
-// equivalent to v/255
-template<class B, class A>
-inline B FastDivideBy255(A v)
-{
-  return ((v << 8) + v + 255) >> 16;
-}
-
 inline Scalaru16x8_t
 FastDivideBy255_16(Scalaru16x8_t m)
 {
-  return FromU16<Scalaru16x8_t>(FastDivideBy255<uint16_t>(int32_t(m.u16[0])),
-                                FastDivideBy255<uint16_t>(int32_t(m.u16[1])),
-                                FastDivideBy255<uint16_t>(int32_t(m.u16[2])),
-                                FastDivideBy255<uint16_t>(int32_t(m.u16[3])),
-                                FastDivideBy255<uint16_t>(int32_t(m.u16[4])),
-                                FastDivideBy255<uint16_t>(int32_t(m.u16[5])),
-                                FastDivideBy255<uint16_t>(int32_t(m.u16[6])),
-                                FastDivideBy255<uint16_t>(int32_t(m.u16[7])));
+  return FromU16<Scalaru16x8_t>(uint16_t(FastDivideBy255(int32_t(m.u16[0]))),
+                                uint16_t(FastDivideBy255(int32_t(m.u16[1]))),
+                                uint16_t(FastDivideBy255(int32_t(m.u16[2]))),
+                                uint16_t(FastDivideBy255(int32_t(m.u16[3]))),
+                                uint16_t(FastDivideBy255(int32_t(m.u16[4]))),
+                                uint16_t(FastDivideBy255(int32_t(m.u16[5]))),
+                                uint16_t(FastDivideBy255(int32_t(m.u16[6]))),
+                                uint16_t(FastDivideBy255(int32_t(m.u16[7]))));
 }
 
 inline Scalari32x4_t
 FastDivideBy255(Scalari32x4_t m)
 {
-  return From32<Scalari32x4_t>(FastDivideBy255<int32_t>(m.i32[0]),
-                               FastDivideBy255<int32_t>(m.i32[1]),
-                               FastDivideBy255<int32_t>(m.i32[2]),
-                               FastDivideBy255<int32_t>(m.i32[3]));
+  return From32<Scalari32x4_t>(gfx::FastDivideBy255(m.i32[0]),
+                               gfx::FastDivideBy255(m.i32[1]),
+                               gfx::FastDivideBy255(m.i32[2]),
+                               gfx::FastDivideBy255(m.i32[3]));
 }
 
 inline Scalaru8x16_t
 Pick(Scalaru8x16_t mask, Scalaru8x16_t a, Scalaru8x16_t b)
 {
   return From8<Scalaru8x16_t>((a.u8[0] & (~mask.u8[0])) | (b.u8[0] & mask.u8[0]),
                               (a.u8[1] & (~mask.u8[1])) | (b.u8[1] & mask.u8[1]),
                               (a.u8[2] & (~mask.u8[2])) | (b.u8[2] & mask.u8[2]),
--- a/gfx/2d/Tools.h
+++ b/gfx/2d/Tools.h
@@ -7,16 +7,17 @@
 #define MOZILLA_GFX_TOOLS_H_
 
 #include "mozilla/CheckedInt.h"
 #include "mozilla/Move.h"
 #include "mozilla/TypeTraits.h"
 #include "Types.h"
 #include "Point.h"
 #include <math.h>
+#include <limits>
 
 namespace mozilla {
 namespace gfx {
 
 static inline bool
 IsOperatorBoundByMask(CompositionOp aOp) {
   switch (aOp) {
   case CompositionOp::OP_IN:
@@ -235,12 +236,29 @@ int32_t GetAlignedStride(int32_t aWidth,
   const int32_t mask = alignment - 1;
   CheckedInt32 stride = CheckedInt32(aWidth) * CheckedInt32(aBytesPerPixel) + CheckedInt32(mask);
   if (stride.isValid()) {
     return stride.value() & ~mask;
   }
   return 0;
 }
 
+// Fast approximate division by 255. It has the property that
+// for all 0 <= n <= 255*255, FastDivideBy255(n) == n/255.
+// But it only uses two adds and two shifts instead of an
+// integer division (which is expensive on many processors).
+//
+// equivalent to v/255
+template<typename T>
+inline T FastDivideBy255(T v)
+{
+  // If v = 255*255, the maximum intermediate value would be
+  // 255*255*256 + 255*255 + 255 = 255*256*256, so any type cannot
+  // store 255 << 16 is definitely not suitable here.
+  static_assert(std::numeric_limits<T>::max() >= 255 << 16,
+                "Given type may not enough for intermediate value");
+  return ((v << 8) + v + 255) >> 16;
+}
+
 } // namespace gfx
 } // namespace mozilla
 
 #endif /* MOZILLA_GFX_TOOLS_H_ */
--- a/gfx/src/nsColor.cpp
+++ b/gfx/src/nsColor.cpp
@@ -1,25 +1,27 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ArrayUtils.h"         // for ArrayLength
 #include "mozilla/mozalloc.h"           // for operator delete, etc
+#include "mozilla/gfx/Tools.h"          // for FastDivideBy255
 
 #include "nsColor.h"
 #include <sys/types.h>                  // for int32_t
 #include "nsColorNames.h"               // for nsColorNames
 #include "nsDebug.h"                    // for NS_ASSERTION, etc
 #include "nsStaticNameTable.h"
 #include "nsString.h"                   // for nsAutoCString, nsString, etc
 #include "nscore.h"                     // for nsAString, etc
 
 using namespace mozilla;
+using namespace mozilla::gfx;
 
 // define an array of all color names
 #define GFX_COLOR(_name, _value) #_name,
 static const char* const kColorNames[] = {
 #include "nsColorNameList.h"
 };
 #undef GFX_COLOR
 
@@ -217,47 +219,45 @@ bool NS_ColorNameToRGB(const nsAString& 
 // Returns kColorNames, an array of all possible color names, and sets
 // *aSizeArray to the size of that array. Do NOT call free() on this array.
 const char * const * NS_AllColorNames(size_t *aSizeArray)
 {
   *aSizeArray = ArrayLength(kColorNames);
   return kColorNames;
 }
 
-// Macro to blend two colors
-//
-// equivalent to target = (bg*(255-fgalpha) + fg*fgalpha)/255
-#define MOZ_BLEND(target, bg, fg, fgalpha)       \
-  FAST_DIVIDE_BY_255(target, (bg)*(255-fgalpha) + (fg)*(fgalpha))
+// Function to blend two colors
+// equivalent to (bg*(255-fgalpha) + fg*fgalpha)/255
+static uint32_t
+BlendColorComponent(uint32_t aBg, uint32_t aFg, uint32_t aFgAlpha)
+{
+  return FastDivideBy255(aBg * (255 - aFgAlpha) + aFg * aFgAlpha);
+}
 
 nscolor
 NS_ComposeColors(nscolor aBG, nscolor aFG)
 {
   // This function uses colors that are non premultiplied alpha.
-  int r, g, b, a;
-
   int bgAlpha = NS_GET_A(aBG);
   int fgAlpha = NS_GET_A(aFG);
 
   // Compute the final alpha of the blended color
   // a = fgAlpha + bgAlpha*(255 - fgAlpha)/255;
-  FAST_DIVIDE_BY_255(a, bgAlpha*(255-fgAlpha));
-  a = fgAlpha + a;
+  auto a = fgAlpha + FastDivideBy255(bgAlpha * (255 - fgAlpha));
   int blendAlpha;
   if (a == 0) {
     // In this case the blended color is totally trasparent,
     // we preserve the color information of the foreground color.
     blendAlpha = 255;
   } else {
     blendAlpha = (fgAlpha*255)/a;
   }
-  MOZ_BLEND(r, NS_GET_R(aBG), NS_GET_R(aFG), blendAlpha);
-  MOZ_BLEND(g, NS_GET_G(aBG), NS_GET_G(aFG), blendAlpha);
-  MOZ_BLEND(b, NS_GET_B(aBG), NS_GET_B(aFG), blendAlpha);
-
+  auto r = BlendColorComponent(NS_GET_R(aBG), NS_GET_R(aFG), blendAlpha);
+  auto g = BlendColorComponent(NS_GET_G(aBG), NS_GET_G(aFG), blendAlpha);
+  auto b = BlendColorComponent(NS_GET_B(aBG), NS_GET_B(aFG), blendAlpha);
   return NS_RGBA(r, g, b, a);
 }
 
 // Functions to convert from HSL color space to RGB color space.
 // This is the algorithm described in the CSS3 specification
 
 // helper
 static float
--- a/gfx/src/nsColor.h
+++ b/gfx/src/nsColor.h
@@ -40,28 +40,16 @@ inline uint_fast8_t NS_ClampColor(T aCol
     return 255;
   }
   if (aColor <= 0) {
     return 0;
   }
   return NSToIntRound(aColor);
 }
 
-// Fast approximate division by 255. It has the property that
-// for all 0 <= n <= 255*255, FAST_DIVIDE_BY_255(n) == n/255.
-// But it only uses two adds and two shifts instead of an 
-// integer division (which is expensive on many processors).
-//
-// equivalent to target=v/255
-#define FAST_DIVIDE_BY_255(target,v)               \
-  PR_BEGIN_MACRO                                   \
-    unsigned tmp_ = v;                             \
-    target = ((tmp_ << 8) + tmp_ + 255) >> 16;     \
-  PR_END_MACRO
-
 enum class nsHexColorType : uint8_t {
   NoAlpha, // 3 or 6 digit hex colors only
   AllowAlpha, // 3, 4, 6, or 8 digit hex colors
 };
 
 // Translate a hex string to a color. Return true if it parses ok,
 // otherwise return false.
 // This accepts the number of digits specified by aType.