summaryrefslogtreecommitdiffstats
path: root/gfx/angle/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/src/common')
-rwxr-xr-xgfx/angle/src/common/BitSetIterator.h155
-rwxr-xr-xgfx/angle/src/common/BitSetIterator_unittest.cpp91
-rwxr-xr-xgfx/angle/src/common/Color.h53
-rwxr-xr-xgfx/angle/src/common/Color.inl37
-rwxr-xr-xgfx/angle/src/common/Float16ToFloat32.cpp2205
-rwxr-xr-xgfx/angle/src/common/Float16ToFloat32.py80
-rwxr-xr-xgfx/angle/src/common/MemoryBuffer.cpp80
-rwxr-xr-xgfx/angle/src/common/MemoryBuffer.h38
-rwxr-xr-xgfx/angle/src/common/Optional.h74
-rwxr-xr-xgfx/angle/src/common/Optional_unittest.cpp47
-rwxr-xr-xgfx/angle/src/common/angleutils.cpp52
-rwxr-xr-xgfx/angle/src/common/angleutils.h187
-rwxr-xr-xgfx/angle/src/common/debug.cpp179
-rwxr-xr-xgfx/angle/src/common/debug.h174
-rwxr-xr-xgfx/angle/src/common/event_tracer.cpp56
-rwxr-xr-xgfx/angle/src/common/event_tracer.h22
-rwxr-xr-xgfx/angle/src/common/mathutil.cpp73
-rwxr-xr-xgfx/angle/src/common/mathutil.h852
-rwxr-xr-xgfx/angle/src/common/mathutil_unittest.cpp210
-rwxr-xr-xgfx/angle/src/common/matrix_utils.h386
-rwxr-xr-xgfx/angle/src/common/matrix_utils_unittest.cpp184
-rwxr-xr-xgfx/angle/src/common/platform.h92
-rwxr-xr-xgfx/angle/src/common/string_utils.cpp182
-rwxr-xr-xgfx/angle/src/common/string_utils.h67
-rwxr-xr-xgfx/angle/src/common/string_utils_unittest.cpp163
-rwxr-xr-xgfx/angle/src/common/third_party/numerics/README.angle16
-rwxr-xr-xgfx/angle/src/common/third_party/numerics/base/logging.h22
-rwxr-xr-xgfx/angle/src/common/third_party/numerics/base/numerics/OWNERS3
-rwxr-xr-xgfx/angle/src/common/third_party/numerics/base/numerics/safe_conversions.h174
-rwxr-xr-xgfx/angle/src/common/third_party/numerics/base/numerics/safe_conversions_impl.h269
-rwxr-xr-xgfx/angle/src/common/third_party/numerics/base/numerics/safe_math.h324
-rwxr-xr-xgfx/angle/src/common/third_party/numerics/base/numerics/safe_math_impl.h570
-rwxr-xr-xgfx/angle/src/common/third_party/numerics/base/numerics/safe_numerics_unittest.cc771
-rwxr-xr-xgfx/angle/src/common/tls.cpp156
-rwxr-xr-xgfx/angle/src/common/tls.h46
-rwxr-xr-xgfx/angle/src/common/utilities.cpp843
-rwxr-xr-xgfx/angle/src/common/utilities.h172
-rwxr-xr-xgfx/angle/src/common/utilities_unittest.cpp55
-rwxr-xr-xgfx/angle/src/common/version.h28
39 files changed, 9188 insertions, 0 deletions
diff --git a/gfx/angle/src/common/BitSetIterator.h b/gfx/angle/src/common/BitSetIterator.h
new file mode 100755
index 000000000..7fecd3769
--- /dev/null
+++ b/gfx/angle/src/common/BitSetIterator.h
@@ -0,0 +1,155 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// BitSetIterator:
+// A helper class to quickly bitscan bitsets for set bits.
+//
+
+#ifndef COMMON_BITSETITERATOR_H_
+#define COMMON_BITSETITERATOR_H_
+
+#include <stdint.h>
+
+#include <bitset>
+
+#include "common/angleutils.h"
+#include "common/debug.h"
+#include "common/mathutil.h"
+#include "common/platform.h"
+
+namespace angle
+{
+template <size_t N>
+class BitSetIterator final
+{
+ public:
+ BitSetIterator(const std::bitset<N> &bitset);
+ BitSetIterator(const BitSetIterator &other);
+ BitSetIterator &operator=(const BitSetIterator &other);
+
+ class Iterator final
+ {
+ public:
+ Iterator(const std::bitset<N> &bits);
+ Iterator &operator++();
+
+ bool operator==(const Iterator &other) const;
+ bool operator!=(const Iterator &other) const;
+ unsigned long operator*() const { return mCurrentBit; }
+
+ private:
+ unsigned long getNextBit();
+
+ static const size_t BitsPerWord = sizeof(unsigned long) * 8;
+ std::bitset<N> mBits;
+ unsigned long mCurrentBit;
+ unsigned long mOffset;
+ };
+
+ Iterator begin() const { return Iterator(mBits); }
+ Iterator end() const { return Iterator(std::bitset<N>(0)); }
+
+ private:
+ const std::bitset<N> mBits;
+};
+
+template <size_t N>
+BitSetIterator<N>::BitSetIterator(const std::bitset<N> &bitset)
+ : mBits(bitset)
+{
+}
+
+template <size_t N>
+BitSetIterator<N>::BitSetIterator(const BitSetIterator &other)
+ : mBits(other.mBits)
+{
+}
+
+template <size_t N>
+BitSetIterator<N> &BitSetIterator<N>::operator=(const BitSetIterator &other)
+{
+ mBits = other.mBits;
+ return *this;
+}
+
+template <size_t N>
+BitSetIterator<N>::Iterator::Iterator(const std::bitset<N> &bits)
+ : mBits(bits), mCurrentBit(0), mOffset(0)
+{
+ if (bits.any())
+ {
+ mCurrentBit = getNextBit();
+ }
+ else
+ {
+ mOffset = static_cast<unsigned long>(rx::roundUp(N, BitsPerWord));
+ }
+}
+
+template <size_t N>
+typename BitSetIterator<N>::Iterator &BitSetIterator<N>::Iterator::operator++()
+{
+ ASSERT(mBits.any());
+ mBits.set(mCurrentBit - mOffset, 0);
+ mCurrentBit = getNextBit();
+ return *this;
+}
+
+inline unsigned long ScanForward(unsigned long bits)
+{
+ ASSERT(bits != 0);
+#if defined(ANGLE_PLATFORM_WINDOWS)
+ unsigned long firstBitIndex = 0ul;
+ unsigned char ret = _BitScanForward(&firstBitIndex, bits);
+ ASSERT(ret != 0);
+ return firstBitIndex;
+#elif defined(ANGLE_PLATFORM_POSIX)
+ return static_cast<unsigned long>(__builtin_ctzl(bits));
+#else
+#error Please implement bit-scan-forward for your platform!
+#endif
+}
+
+template <size_t N>
+bool BitSetIterator<N>::Iterator::operator==(const Iterator &other) const
+{
+ return mOffset == other.mOffset && mBits == other.mBits;
+}
+
+template <size_t N>
+bool BitSetIterator<N>::Iterator::operator!=(const Iterator &other) const
+{
+ return !(*this == other);
+}
+
+template <size_t N>
+unsigned long BitSetIterator<N>::Iterator::getNextBit()
+{
+ static std::bitset<N> wordMask(std::numeric_limits<unsigned long>::max());
+
+ while (mOffset < N)
+ {
+ unsigned long wordBits = (mBits & wordMask).to_ulong();
+ if (wordBits != 0ul)
+ {
+ return ScanForward(wordBits) + mOffset;
+ }
+
+ mBits >>= BitsPerWord;
+ mOffset += BitsPerWord;
+ }
+ return 0;
+}
+
+// Helper to avoid needing to specify the template parameter size
+template <size_t N>
+BitSetIterator<N> IterateBitSet(const std::bitset<N> &bitset)
+{
+ return BitSetIterator<N>(bitset);
+}
+
+} // angle
+
+#endif // COMMON_BITSETITERATOR_H_
diff --git a/gfx/angle/src/common/BitSetIterator_unittest.cpp b/gfx/angle/src/common/BitSetIterator_unittest.cpp
new file mode 100755
index 000000000..e965f2c56
--- /dev/null
+++ b/gfx/angle/src/common/BitSetIterator_unittest.cpp
@@ -0,0 +1,91 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// BitSetIteratorTest:
+// Test the IterableBitSet class.
+//
+
+#include <gtest/gtest.h>
+
+#include "common/BitSetIterator.h"
+
+using namespace angle;
+
+namespace
+{
+class BitSetIteratorTest : public testing::Test
+{
+ protected:
+ std::bitset<40> mStateBits;
+};
+
+// Simple iterator test.
+TEST_F(BitSetIteratorTest, Iterator)
+{
+ std::set<unsigned long> originalValues;
+ originalValues.insert(2);
+ originalValues.insert(6);
+ originalValues.insert(8);
+ originalValues.insert(35);
+
+ for (unsigned long value : originalValues)
+ {
+ mStateBits.set(value);
+ }
+
+ std::set<unsigned long> readValues;
+ for (unsigned long bit : IterateBitSet(mStateBits))
+ {
+ EXPECT_EQ(1u, originalValues.count(bit));
+ EXPECT_EQ(0u, readValues.count(bit));
+ readValues.insert(bit);
+ }
+
+ EXPECT_EQ(originalValues.size(), readValues.size());
+}
+
+// Test an empty iterator.
+TEST_F(BitSetIteratorTest, EmptySet)
+{
+ // We don't use the FAIL gtest macro here since it returns immediately,
+ // causing an unreachable code warning in MSVS
+ bool sawBit = false;
+ for (unsigned long bit : IterateBitSet(mStateBits))
+ {
+ sawBit = true;
+ UNUSED_VARIABLE(bit);
+ }
+ EXPECT_FALSE(sawBit);
+}
+
+// Test iterating a result of combining two bitsets.
+TEST_F(BitSetIteratorTest, NonLValueBitset)
+{
+ std::bitset<40> otherBits;
+
+ mStateBits.set(1);
+ mStateBits.set(2);
+ mStateBits.set(3);
+ mStateBits.set(4);
+
+ otherBits.set(0);
+ otherBits.set(1);
+ otherBits.set(3);
+ otherBits.set(5);
+
+ std::set<unsigned long> seenBits;
+
+ for (unsigned long bit : IterateBitSet(mStateBits & otherBits))
+ {
+ EXPECT_EQ(0u, seenBits.count(bit));
+ seenBits.insert(bit);
+ EXPECT_TRUE(mStateBits[bit]);
+ EXPECT_TRUE(otherBits[bit]);
+ }
+
+ EXPECT_EQ((mStateBits & otherBits).count(), seenBits.size());
+}
+
+} // anonymous namespace
diff --git a/gfx/angle/src/common/Color.h b/gfx/angle/src/common/Color.h
new file mode 100755
index 000000000..2b4d2f6fb
--- /dev/null
+++ b/gfx/angle/src/common/Color.h
@@ -0,0 +1,53 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Color.h : Defines the Color type used throughout the ANGLE libraries
+
+#ifndef COMMON_COLOR_H_
+#define COMMON_COLOR_H_
+
+namespace angle
+{
+
+template <typename T>
+struct Color
+{
+ T red;
+ T green;
+ T blue;
+ T alpha;
+
+ Color();
+ Color(T r, T g, T b, T a);
+};
+
+template <typename T>
+bool operator==(const Color<T> &a, const Color<T> &b);
+
+template <typename T>
+bool operator!=(const Color<T> &a, const Color<T> &b);
+
+typedef Color<float> ColorF;
+typedef Color<int> ColorI;
+typedef Color<unsigned int> ColorUI;
+
+} // namespace angle
+
+// TODO: Move this fully into the angle namespace
+namespace gl
+{
+
+template <typename T>
+using Color = angle::Color<T>;
+using ColorF = angle::ColorF;
+using ColorI = angle::ColorI;
+using ColorUI = angle::ColorUI;
+
+} // namespace gl
+
+#include "Color.inl"
+
+#endif // COMMON_COLOR_H_
diff --git a/gfx/angle/src/common/Color.inl b/gfx/angle/src/common/Color.inl
new file mode 100755
index 000000000..c3073256b
--- /dev/null
+++ b/gfx/angle/src/common/Color.inl
@@ -0,0 +1,37 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Color.inl : Inline definitions of some functions from Color.h
+
+namespace angle
+{
+
+template <typename T>
+Color<T>::Color() : Color(0, 0, 0, 0)
+{
+}
+
+template <typename T>
+Color<T>::Color(T r, T g, T b, T a) : red(r), green(g), blue(b), alpha(a)
+{
+}
+
+template <typename T>
+bool operator==(const Color<T> &a, const Color<T> &b)
+{
+ return a.red == b.red &&
+ a.green == b.green &&
+ a.blue == b.blue &&
+ a.alpha == b.alpha;
+}
+
+template <typename T>
+bool operator!=(const Color<T> &a, const Color<T> &b)
+{
+ return !(a == b);
+}
+
+} // namespace angle
diff --git a/gfx/angle/src/common/Float16ToFloat32.cpp b/gfx/angle/src/common/Float16ToFloat32.cpp
new file mode 100755
index 000000000..acd0d88b6
--- /dev/null
+++ b/gfx/angle/src/common/Float16ToFloat32.cpp
@@ -0,0 +1,2205 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// This file is automatically generated.
+
+#include "common/mathutil.h"
+
+namespace gl
+{
+
+const static unsigned g_mantissa[2048] = {
+ 0x00000000,
+ 0x33800000,
+ 0x34000000,
+ 0x34400000,
+ 0x34800000,
+ 0x34a00000,
+ 0x34c00000,
+ 0x34e00000,
+ 0x35000000,
+ 0x35100000,
+ 0x35200000,
+ 0x35300000,
+ 0x35400000,
+ 0x35500000,
+ 0x35600000,
+ 0x35700000,
+ 0x35800000,
+ 0x35880000,
+ 0x35900000,
+ 0x35980000,
+ 0x35a00000,
+ 0x35a80000,
+ 0x35b00000,
+ 0x35b80000,
+ 0x35c00000,
+ 0x35c80000,
+ 0x35d00000,
+ 0x35d80000,
+ 0x35e00000,
+ 0x35e80000,
+ 0x35f00000,
+ 0x35f80000,
+ 0x36000000,
+ 0x36040000,
+ 0x36080000,
+ 0x360c0000,
+ 0x36100000,
+ 0x36140000,
+ 0x36180000,
+ 0x361c0000,
+ 0x36200000,
+ 0x36240000,
+ 0x36280000,
+ 0x362c0000,
+ 0x36300000,
+ 0x36340000,
+ 0x36380000,
+ 0x363c0000,
+ 0x36400000,
+ 0x36440000,
+ 0x36480000,
+ 0x364c0000,
+ 0x36500000,
+ 0x36540000,
+ 0x36580000,
+ 0x365c0000,
+ 0x36600000,
+ 0x36640000,
+ 0x36680000,
+ 0x366c0000,
+ 0x36700000,
+ 0x36740000,
+ 0x36780000,
+ 0x367c0000,
+ 0x36800000,
+ 0x36820000,
+ 0x36840000,
+ 0x36860000,
+ 0x36880000,
+ 0x368a0000,
+ 0x368c0000,
+ 0x368e0000,
+ 0x36900000,
+ 0x36920000,
+ 0x36940000,
+ 0x36960000,
+ 0x36980000,
+ 0x369a0000,
+ 0x369c0000,
+ 0x369e0000,
+ 0x36a00000,
+ 0x36a20000,
+ 0x36a40000,
+ 0x36a60000,
+ 0x36a80000,
+ 0x36aa0000,
+ 0x36ac0000,
+ 0x36ae0000,
+ 0x36b00000,
+ 0x36b20000,
+ 0x36b40000,
+ 0x36b60000,
+ 0x36b80000,
+ 0x36ba0000,
+ 0x36bc0000,
+ 0x36be0000,
+ 0x36c00000,
+ 0x36c20000,
+ 0x36c40000,
+ 0x36c60000,
+ 0x36c80000,
+ 0x36ca0000,
+ 0x36cc0000,
+ 0x36ce0000,
+ 0x36d00000,
+ 0x36d20000,
+ 0x36d40000,
+ 0x36d60000,
+ 0x36d80000,
+ 0x36da0000,
+ 0x36dc0000,
+ 0x36de0000,
+ 0x36e00000,
+ 0x36e20000,
+ 0x36e40000,
+ 0x36e60000,
+ 0x36e80000,
+ 0x36ea0000,
+ 0x36ec0000,
+ 0x36ee0000,
+ 0x36f00000,
+ 0x36f20000,
+ 0x36f40000,
+ 0x36f60000,
+ 0x36f80000,
+ 0x36fa0000,
+ 0x36fc0000,
+ 0x36fe0000,
+ 0x37000000,
+ 0x37010000,
+ 0x37020000,
+ 0x37030000,
+ 0x37040000,
+ 0x37050000,
+ 0x37060000,
+ 0x37070000,
+ 0x37080000,
+ 0x37090000,
+ 0x370a0000,
+ 0x370b0000,
+ 0x370c0000,
+ 0x370d0000,
+ 0x370e0000,
+ 0x370f0000,
+ 0x37100000,
+ 0x37110000,
+ 0x37120000,
+ 0x37130000,
+ 0x37140000,
+ 0x37150000,
+ 0x37160000,
+ 0x37170000,
+ 0x37180000,
+ 0x37190000,
+ 0x371a0000,
+ 0x371b0000,
+ 0x371c0000,
+ 0x371d0000,
+ 0x371e0000,
+ 0x371f0000,
+ 0x37200000,
+ 0x37210000,
+ 0x37220000,
+ 0x37230000,
+ 0x37240000,
+ 0x37250000,
+ 0x37260000,
+ 0x37270000,
+ 0x37280000,
+ 0x37290000,
+ 0x372a0000,
+ 0x372b0000,
+ 0x372c0000,
+ 0x372d0000,
+ 0x372e0000,
+ 0x372f0000,
+ 0x37300000,
+ 0x37310000,
+ 0x37320000,
+ 0x37330000,
+ 0x37340000,
+ 0x37350000,
+ 0x37360000,
+ 0x37370000,
+ 0x37380000,
+ 0x37390000,
+ 0x373a0000,
+ 0x373b0000,
+ 0x373c0000,
+ 0x373d0000,
+ 0x373e0000,
+ 0x373f0000,
+ 0x37400000,
+ 0x37410000,
+ 0x37420000,
+ 0x37430000,
+ 0x37440000,
+ 0x37450000,
+ 0x37460000,
+ 0x37470000,
+ 0x37480000,
+ 0x37490000,
+ 0x374a0000,
+ 0x374b0000,
+ 0x374c0000,
+ 0x374d0000,
+ 0x374e0000,
+ 0x374f0000,
+ 0x37500000,
+ 0x37510000,
+ 0x37520000,
+ 0x37530000,
+ 0x37540000,
+ 0x37550000,
+ 0x37560000,
+ 0x37570000,
+ 0x37580000,
+ 0x37590000,
+ 0x375a0000,
+ 0x375b0000,
+ 0x375c0000,
+ 0x375d0000,
+ 0x375e0000,
+ 0x375f0000,
+ 0x37600000,
+ 0x37610000,
+ 0x37620000,
+ 0x37630000,
+ 0x37640000,
+ 0x37650000,
+ 0x37660000,
+ 0x37670000,
+ 0x37680000,
+ 0x37690000,
+ 0x376a0000,
+ 0x376b0000,
+ 0x376c0000,
+ 0x376d0000,
+ 0x376e0000,
+ 0x376f0000,
+ 0x37700000,
+ 0x37710000,
+ 0x37720000,
+ 0x37730000,
+ 0x37740000,
+ 0x37750000,
+ 0x37760000,
+ 0x37770000,
+ 0x37780000,
+ 0x37790000,
+ 0x377a0000,
+ 0x377b0000,
+ 0x377c0000,
+ 0x377d0000,
+ 0x377e0000,
+ 0x377f0000,
+ 0x37800000,
+ 0x37808000,
+ 0x37810000,
+ 0x37818000,
+ 0x37820000,
+ 0x37828000,
+ 0x37830000,
+ 0x37838000,
+ 0x37840000,
+ 0x37848000,
+ 0x37850000,
+ 0x37858000,
+ 0x37860000,
+ 0x37868000,
+ 0x37870000,
+ 0x37878000,
+ 0x37880000,
+ 0x37888000,
+ 0x37890000,
+ 0x37898000,
+ 0x378a0000,
+ 0x378a8000,
+ 0x378b0000,
+ 0x378b8000,
+ 0x378c0000,
+ 0x378c8000,
+ 0x378d0000,
+ 0x378d8000,
+ 0x378e0000,
+ 0x378e8000,
+ 0x378f0000,
+ 0x378f8000,
+ 0x37900000,
+ 0x37908000,
+ 0x37910000,
+ 0x37918000,
+ 0x37920000,
+ 0x37928000,
+ 0x37930000,
+ 0x37938000,
+ 0x37940000,
+ 0x37948000,
+ 0x37950000,
+ 0x37958000,
+ 0x37960000,
+ 0x37968000,
+ 0x37970000,
+ 0x37978000,
+ 0x37980000,
+ 0x37988000,
+ 0x37990000,
+ 0x37998000,
+ 0x379a0000,
+ 0x379a8000,
+ 0x379b0000,
+ 0x379b8000,
+ 0x379c0000,
+ 0x379c8000,
+ 0x379d0000,
+ 0x379d8000,
+ 0x379e0000,
+ 0x379e8000,
+ 0x379f0000,
+ 0x379f8000,
+ 0x37a00000,
+ 0x37a08000,
+ 0x37a10000,
+ 0x37a18000,
+ 0x37a20000,
+ 0x37a28000,
+ 0x37a30000,
+ 0x37a38000,
+ 0x37a40000,
+ 0x37a48000,
+ 0x37a50000,
+ 0x37a58000,
+ 0x37a60000,
+ 0x37a68000,
+ 0x37a70000,
+ 0x37a78000,
+ 0x37a80000,
+ 0x37a88000,
+ 0x37a90000,
+ 0x37a98000,
+ 0x37aa0000,
+ 0x37aa8000,
+ 0x37ab0000,
+ 0x37ab8000,
+ 0x37ac0000,
+ 0x37ac8000,
+ 0x37ad0000,
+ 0x37ad8000,
+ 0x37ae0000,
+ 0x37ae8000,
+ 0x37af0000,
+ 0x37af8000,
+ 0x37b00000,
+ 0x37b08000,
+ 0x37b10000,
+ 0x37b18000,
+ 0x37b20000,
+ 0x37b28000,
+ 0x37b30000,
+ 0x37b38000,
+ 0x37b40000,
+ 0x37b48000,
+ 0x37b50000,
+ 0x37b58000,
+ 0x37b60000,
+ 0x37b68000,
+ 0x37b70000,
+ 0x37b78000,
+ 0x37b80000,
+ 0x37b88000,
+ 0x37b90000,
+ 0x37b98000,
+ 0x37ba0000,
+ 0x37ba8000,
+ 0x37bb0000,
+ 0x37bb8000,
+ 0x37bc0000,
+ 0x37bc8000,
+ 0x37bd0000,
+ 0x37bd8000,
+ 0x37be0000,
+ 0x37be8000,
+ 0x37bf0000,
+ 0x37bf8000,
+ 0x37c00000,
+ 0x37c08000,
+ 0x37c10000,
+ 0x37c18000,
+ 0x37c20000,
+ 0x37c28000,
+ 0x37c30000,
+ 0x37c38000,
+ 0x37c40000,
+ 0x37c48000,
+ 0x37c50000,
+ 0x37c58000,
+ 0x37c60000,
+ 0x37c68000,
+ 0x37c70000,
+ 0x37c78000,
+ 0x37c80000,
+ 0x37c88000,
+ 0x37c90000,
+ 0x37c98000,
+ 0x37ca0000,
+ 0x37ca8000,
+ 0x37cb0000,
+ 0x37cb8000,
+ 0x37cc0000,
+ 0x37cc8000,
+ 0x37cd0000,
+ 0x37cd8000,
+ 0x37ce0000,
+ 0x37ce8000,
+ 0x37cf0000,
+ 0x37cf8000,
+ 0x37d00000,
+ 0x37d08000,
+ 0x37d10000,
+ 0x37d18000,
+ 0x37d20000,
+ 0x37d28000,
+ 0x37d30000,
+ 0x37d38000,
+ 0x37d40000,
+ 0x37d48000,
+ 0x37d50000,
+ 0x37d58000,
+ 0x37d60000,
+ 0x37d68000,
+ 0x37d70000,
+ 0x37d78000,
+ 0x37d80000,
+ 0x37d88000,
+ 0x37d90000,
+ 0x37d98000,
+ 0x37da0000,
+ 0x37da8000,
+ 0x37db0000,
+ 0x37db8000,
+ 0x37dc0000,
+ 0x37dc8000,
+ 0x37dd0000,
+ 0x37dd8000,
+ 0x37de0000,
+ 0x37de8000,
+ 0x37df0000,
+ 0x37df8000,
+ 0x37e00000,
+ 0x37e08000,
+ 0x37e10000,
+ 0x37e18000,
+ 0x37e20000,
+ 0x37e28000,
+ 0x37e30000,
+ 0x37e38000,
+ 0x37e40000,
+ 0x37e48000,
+ 0x37e50000,
+ 0x37e58000,
+ 0x37e60000,
+ 0x37e68000,
+ 0x37e70000,
+ 0x37e78000,
+ 0x37e80000,
+ 0x37e88000,
+ 0x37e90000,
+ 0x37e98000,
+ 0x37ea0000,
+ 0x37ea8000,
+ 0x37eb0000,
+ 0x37eb8000,
+ 0x37ec0000,
+ 0x37ec8000,
+ 0x37ed0000,
+ 0x37ed8000,
+ 0x37ee0000,
+ 0x37ee8000,
+ 0x37ef0000,
+ 0x37ef8000,
+ 0x37f00000,
+ 0x37f08000,
+ 0x37f10000,
+ 0x37f18000,
+ 0x37f20000,
+ 0x37f28000,
+ 0x37f30000,
+ 0x37f38000,
+ 0x37f40000,
+ 0x37f48000,
+ 0x37f50000,
+ 0x37f58000,
+ 0x37f60000,
+ 0x37f68000,
+ 0x37f70000,
+ 0x37f78000,
+ 0x37f80000,
+ 0x37f88000,
+ 0x37f90000,
+ 0x37f98000,
+ 0x37fa0000,
+ 0x37fa8000,
+ 0x37fb0000,
+ 0x37fb8000,
+ 0x37fc0000,
+ 0x37fc8000,
+ 0x37fd0000,
+ 0x37fd8000,
+ 0x37fe0000,
+ 0x37fe8000,
+ 0x37ff0000,
+ 0x37ff8000,
+ 0x38000000,
+ 0x38004000,
+ 0x38008000,
+ 0x3800c000,
+ 0x38010000,
+ 0x38014000,
+ 0x38018000,
+ 0x3801c000,
+ 0x38020000,
+ 0x38024000,
+ 0x38028000,
+ 0x3802c000,
+ 0x38030000,
+ 0x38034000,
+ 0x38038000,
+ 0x3803c000,
+ 0x38040000,
+ 0x38044000,
+ 0x38048000,
+ 0x3804c000,
+ 0x38050000,
+ 0x38054000,
+ 0x38058000,
+ 0x3805c000,
+ 0x38060000,
+ 0x38064000,
+ 0x38068000,
+ 0x3806c000,
+ 0x38070000,
+ 0x38074000,
+ 0x38078000,
+ 0x3807c000,
+ 0x38080000,
+ 0x38084000,
+ 0x38088000,
+ 0x3808c000,
+ 0x38090000,
+ 0x38094000,
+ 0x38098000,
+ 0x3809c000,
+ 0x380a0000,
+ 0x380a4000,
+ 0x380a8000,
+ 0x380ac000,
+ 0x380b0000,
+ 0x380b4000,
+ 0x380b8000,
+ 0x380bc000,
+ 0x380c0000,
+ 0x380c4000,
+ 0x380c8000,
+ 0x380cc000,
+ 0x380d0000,
+ 0x380d4000,
+ 0x380d8000,
+ 0x380dc000,
+ 0x380e0000,
+ 0x380e4000,
+ 0x380e8000,
+ 0x380ec000,
+ 0x380f0000,
+ 0x380f4000,
+ 0x380f8000,
+ 0x380fc000,
+ 0x38100000,
+ 0x38104000,
+ 0x38108000,
+ 0x3810c000,
+ 0x38110000,
+ 0x38114000,
+ 0x38118000,
+ 0x3811c000,
+ 0x38120000,
+ 0x38124000,
+ 0x38128000,
+ 0x3812c000,
+ 0x38130000,
+ 0x38134000,
+ 0x38138000,
+ 0x3813c000,
+ 0x38140000,
+ 0x38144000,
+ 0x38148000,
+ 0x3814c000,
+ 0x38150000,
+ 0x38154000,
+ 0x38158000,
+ 0x3815c000,
+ 0x38160000,
+ 0x38164000,
+ 0x38168000,
+ 0x3816c000,
+ 0x38170000,
+ 0x38174000,
+ 0x38178000,
+ 0x3817c000,
+ 0x38180000,
+ 0x38184000,
+ 0x38188000,
+ 0x3818c000,
+ 0x38190000,
+ 0x38194000,
+ 0x38198000,
+ 0x3819c000,
+ 0x381a0000,
+ 0x381a4000,
+ 0x381a8000,
+ 0x381ac000,
+ 0x381b0000,
+ 0x381b4000,
+ 0x381b8000,
+ 0x381bc000,
+ 0x381c0000,
+ 0x381c4000,
+ 0x381c8000,
+ 0x381cc000,
+ 0x381d0000,
+ 0x381d4000,
+ 0x381d8000,
+ 0x381dc000,
+ 0x381e0000,
+ 0x381e4000,
+ 0x381e8000,
+ 0x381ec000,
+ 0x381f0000,
+ 0x381f4000,
+ 0x381f8000,
+ 0x381fc000,
+ 0x38200000,
+ 0x38204000,
+ 0x38208000,
+ 0x3820c000,
+ 0x38210000,
+ 0x38214000,
+ 0x38218000,
+ 0x3821c000,
+ 0x38220000,
+ 0x38224000,
+ 0x38228000,
+ 0x3822c000,
+ 0x38230000,
+ 0x38234000,
+ 0x38238000,
+ 0x3823c000,
+ 0x38240000,
+ 0x38244000,
+ 0x38248000,
+ 0x3824c000,
+ 0x38250000,
+ 0x38254000,
+ 0x38258000,
+ 0x3825c000,
+ 0x38260000,
+ 0x38264000,
+ 0x38268000,
+ 0x3826c000,
+ 0x38270000,
+ 0x38274000,
+ 0x38278000,
+ 0x3827c000,
+ 0x38280000,
+ 0x38284000,
+ 0x38288000,
+ 0x3828c000,
+ 0x38290000,
+ 0x38294000,
+ 0x38298000,
+ 0x3829c000,
+ 0x382a0000,
+ 0x382a4000,
+ 0x382a8000,
+ 0x382ac000,
+ 0x382b0000,
+ 0x382b4000,
+ 0x382b8000,
+ 0x382bc000,
+ 0x382c0000,
+ 0x382c4000,
+ 0x382c8000,
+ 0x382cc000,
+ 0x382d0000,
+ 0x382d4000,
+ 0x382d8000,
+ 0x382dc000,
+ 0x382e0000,
+ 0x382e4000,
+ 0x382e8000,
+ 0x382ec000,
+ 0x382f0000,
+ 0x382f4000,
+ 0x382f8000,
+ 0x382fc000,
+ 0x38300000,
+ 0x38304000,
+ 0x38308000,
+ 0x3830c000,
+ 0x38310000,
+ 0x38314000,
+ 0x38318000,
+ 0x3831c000,
+ 0x38320000,
+ 0x38324000,
+ 0x38328000,
+ 0x3832c000,
+ 0x38330000,
+ 0x38334000,
+ 0x38338000,
+ 0x3833c000,
+ 0x38340000,
+ 0x38344000,
+ 0x38348000,
+ 0x3834c000,
+ 0x38350000,
+ 0x38354000,
+ 0x38358000,
+ 0x3835c000,
+ 0x38360000,
+ 0x38364000,
+ 0x38368000,
+ 0x3836c000,
+ 0x38370000,
+ 0x38374000,
+ 0x38378000,
+ 0x3837c000,
+ 0x38380000,
+ 0x38384000,
+ 0x38388000,
+ 0x3838c000,
+ 0x38390000,
+ 0x38394000,
+ 0x38398000,
+ 0x3839c000,
+ 0x383a0000,
+ 0x383a4000,
+ 0x383a8000,
+ 0x383ac000,
+ 0x383b0000,
+ 0x383b4000,
+ 0x383b8000,
+ 0x383bc000,
+ 0x383c0000,
+ 0x383c4000,
+ 0x383c8000,
+ 0x383cc000,
+ 0x383d0000,
+ 0x383d4000,
+ 0x383d8000,
+ 0x383dc000,
+ 0x383e0000,
+ 0x383e4000,
+ 0x383e8000,
+ 0x383ec000,
+ 0x383f0000,
+ 0x383f4000,
+ 0x383f8000,
+ 0x383fc000,
+ 0x38400000,
+ 0x38404000,
+ 0x38408000,
+ 0x3840c000,
+ 0x38410000,
+ 0x38414000,
+ 0x38418000,
+ 0x3841c000,
+ 0x38420000,
+ 0x38424000,
+ 0x38428000,
+ 0x3842c000,
+ 0x38430000,
+ 0x38434000,
+ 0x38438000,
+ 0x3843c000,
+ 0x38440000,
+ 0x38444000,
+ 0x38448000,
+ 0x3844c000,
+ 0x38450000,
+ 0x38454000,
+ 0x38458000,
+ 0x3845c000,
+ 0x38460000,
+ 0x38464000,
+ 0x38468000,
+ 0x3846c000,
+ 0x38470000,
+ 0x38474000,
+ 0x38478000,
+ 0x3847c000,
+ 0x38480000,
+ 0x38484000,
+ 0x38488000,
+ 0x3848c000,
+ 0x38490000,
+ 0x38494000,
+ 0x38498000,
+ 0x3849c000,
+ 0x384a0000,
+ 0x384a4000,
+ 0x384a8000,
+ 0x384ac000,
+ 0x384b0000,
+ 0x384b4000,
+ 0x384b8000,
+ 0x384bc000,
+ 0x384c0000,
+ 0x384c4000,
+ 0x384c8000,
+ 0x384cc000,
+ 0x384d0000,
+ 0x384d4000,
+ 0x384d8000,
+ 0x384dc000,
+ 0x384e0000,
+ 0x384e4000,
+ 0x384e8000,
+ 0x384ec000,
+ 0x384f0000,
+ 0x384f4000,
+ 0x384f8000,
+ 0x384fc000,
+ 0x38500000,
+ 0x38504000,
+ 0x38508000,
+ 0x3850c000,
+ 0x38510000,
+ 0x38514000,
+ 0x38518000,
+ 0x3851c000,
+ 0x38520000,
+ 0x38524000,
+ 0x38528000,
+ 0x3852c000,
+ 0x38530000,
+ 0x38534000,
+ 0x38538000,
+ 0x3853c000,
+ 0x38540000,
+ 0x38544000,
+ 0x38548000,
+ 0x3854c000,
+ 0x38550000,
+ 0x38554000,
+ 0x38558000,
+ 0x3855c000,
+ 0x38560000,
+ 0x38564000,
+ 0x38568000,
+ 0x3856c000,
+ 0x38570000,
+ 0x38574000,
+ 0x38578000,
+ 0x3857c000,
+ 0x38580000,
+ 0x38584000,
+ 0x38588000,
+ 0x3858c000,
+ 0x38590000,
+ 0x38594000,
+ 0x38598000,
+ 0x3859c000,
+ 0x385a0000,
+ 0x385a4000,
+ 0x385a8000,
+ 0x385ac000,
+ 0x385b0000,
+ 0x385b4000,
+ 0x385b8000,
+ 0x385bc000,
+ 0x385c0000,
+ 0x385c4000,
+ 0x385c8000,
+ 0x385cc000,
+ 0x385d0000,
+ 0x385d4000,
+ 0x385d8000,
+ 0x385dc000,
+ 0x385e0000,
+ 0x385e4000,
+ 0x385e8000,
+ 0x385ec000,
+ 0x385f0000,
+ 0x385f4000,
+ 0x385f8000,
+ 0x385fc000,
+ 0x38600000,
+ 0x38604000,
+ 0x38608000,
+ 0x3860c000,
+ 0x38610000,
+ 0x38614000,
+ 0x38618000,
+ 0x3861c000,
+ 0x38620000,
+ 0x38624000,
+ 0x38628000,
+ 0x3862c000,
+ 0x38630000,
+ 0x38634000,
+ 0x38638000,
+ 0x3863c000,
+ 0x38640000,
+ 0x38644000,
+ 0x38648000,
+ 0x3864c000,
+ 0x38650000,
+ 0x38654000,
+ 0x38658000,
+ 0x3865c000,
+ 0x38660000,
+ 0x38664000,
+ 0x38668000,
+ 0x3866c000,
+ 0x38670000,
+ 0x38674000,
+ 0x38678000,
+ 0x3867c000,
+ 0x38680000,
+ 0x38684000,
+ 0x38688000,
+ 0x3868c000,
+ 0x38690000,
+ 0x38694000,
+ 0x38698000,
+ 0x3869c000,
+ 0x386a0000,
+ 0x386a4000,
+ 0x386a8000,
+ 0x386ac000,
+ 0x386b0000,
+ 0x386b4000,
+ 0x386b8000,
+ 0x386bc000,
+ 0x386c0000,
+ 0x386c4000,
+ 0x386c8000,
+ 0x386cc000,
+ 0x386d0000,
+ 0x386d4000,
+ 0x386d8000,
+ 0x386dc000,
+ 0x386e0000,
+ 0x386e4000,
+ 0x386e8000,
+ 0x386ec000,
+ 0x386f0000,
+ 0x386f4000,
+ 0x386f8000,
+ 0x386fc000,
+ 0x38700000,
+ 0x38704000,
+ 0x38708000,
+ 0x3870c000,
+ 0x38710000,
+ 0x38714000,
+ 0x38718000,
+ 0x3871c000,
+ 0x38720000,
+ 0x38724000,
+ 0x38728000,
+ 0x3872c000,
+ 0x38730000,
+ 0x38734000,
+ 0x38738000,
+ 0x3873c000,
+ 0x38740000,
+ 0x38744000,
+ 0x38748000,
+ 0x3874c000,
+ 0x38750000,
+ 0x38754000,
+ 0x38758000,
+ 0x3875c000,
+ 0x38760000,
+ 0x38764000,
+ 0x38768000,
+ 0x3876c000,
+ 0x38770000,
+ 0x38774000,
+ 0x38778000,
+ 0x3877c000,
+ 0x38780000,
+ 0x38784000,
+ 0x38788000,
+ 0x3878c000,
+ 0x38790000,
+ 0x38794000,
+ 0x38798000,
+ 0x3879c000,
+ 0x387a0000,
+ 0x387a4000,
+ 0x387a8000,
+ 0x387ac000,
+ 0x387b0000,
+ 0x387b4000,
+ 0x387b8000,
+ 0x387bc000,
+ 0x387c0000,
+ 0x387c4000,
+ 0x387c8000,
+ 0x387cc000,
+ 0x387d0000,
+ 0x387d4000,
+ 0x387d8000,
+ 0x387dc000,
+ 0x387e0000,
+ 0x387e4000,
+ 0x387e8000,
+ 0x387ec000,
+ 0x387f0000,
+ 0x387f4000,
+ 0x387f8000,
+ 0x387fc000,
+ 0x38000000,
+ 0x38002000,
+ 0x38004000,
+ 0x38006000,
+ 0x38008000,
+ 0x3800a000,
+ 0x3800c000,
+ 0x3800e000,
+ 0x38010000,
+ 0x38012000,
+ 0x38014000,
+ 0x38016000,
+ 0x38018000,
+ 0x3801a000,
+ 0x3801c000,
+ 0x3801e000,
+ 0x38020000,
+ 0x38022000,
+ 0x38024000,
+ 0x38026000,
+ 0x38028000,
+ 0x3802a000,
+ 0x3802c000,
+ 0x3802e000,
+ 0x38030000,
+ 0x38032000,
+ 0x38034000,
+ 0x38036000,
+ 0x38038000,
+ 0x3803a000,
+ 0x3803c000,
+ 0x3803e000,
+ 0x38040000,
+ 0x38042000,
+ 0x38044000,
+ 0x38046000,
+ 0x38048000,
+ 0x3804a000,
+ 0x3804c000,
+ 0x3804e000,
+ 0x38050000,
+ 0x38052000,
+ 0x38054000,
+ 0x38056000,
+ 0x38058000,
+ 0x3805a000,
+ 0x3805c000,
+ 0x3805e000,
+ 0x38060000,
+ 0x38062000,
+ 0x38064000,
+ 0x38066000,
+ 0x38068000,
+ 0x3806a000,
+ 0x3806c000,
+ 0x3806e000,
+ 0x38070000,
+ 0x38072000,
+ 0x38074000,
+ 0x38076000,
+ 0x38078000,
+ 0x3807a000,
+ 0x3807c000,
+ 0x3807e000,
+ 0x38080000,
+ 0x38082000,
+ 0x38084000,
+ 0x38086000,
+ 0x38088000,
+ 0x3808a000,
+ 0x3808c000,
+ 0x3808e000,
+ 0x38090000,
+ 0x38092000,
+ 0x38094000,
+ 0x38096000,
+ 0x38098000,
+ 0x3809a000,
+ 0x3809c000,
+ 0x3809e000,
+ 0x380a0000,
+ 0x380a2000,
+ 0x380a4000,
+ 0x380a6000,
+ 0x380a8000,
+ 0x380aa000,
+ 0x380ac000,
+ 0x380ae000,
+ 0x380b0000,
+ 0x380b2000,
+ 0x380b4000,
+ 0x380b6000,
+ 0x380b8000,
+ 0x380ba000,
+ 0x380bc000,
+ 0x380be000,
+ 0x380c0000,
+ 0x380c2000,
+ 0x380c4000,
+ 0x380c6000,
+ 0x380c8000,
+ 0x380ca000,
+ 0x380cc000,
+ 0x380ce000,
+ 0x380d0000,
+ 0x380d2000,
+ 0x380d4000,
+ 0x380d6000,
+ 0x380d8000,
+ 0x380da000,
+ 0x380dc000,
+ 0x380de000,
+ 0x380e0000,
+ 0x380e2000,
+ 0x380e4000,
+ 0x380e6000,
+ 0x380e8000,
+ 0x380ea000,
+ 0x380ec000,
+ 0x380ee000,
+ 0x380f0000,
+ 0x380f2000,
+ 0x380f4000,
+ 0x380f6000,
+ 0x380f8000,
+ 0x380fa000,
+ 0x380fc000,
+ 0x380fe000,
+ 0x38100000,
+ 0x38102000,
+ 0x38104000,
+ 0x38106000,
+ 0x38108000,
+ 0x3810a000,
+ 0x3810c000,
+ 0x3810e000,
+ 0x38110000,
+ 0x38112000,
+ 0x38114000,
+ 0x38116000,
+ 0x38118000,
+ 0x3811a000,
+ 0x3811c000,
+ 0x3811e000,
+ 0x38120000,
+ 0x38122000,
+ 0x38124000,
+ 0x38126000,
+ 0x38128000,
+ 0x3812a000,
+ 0x3812c000,
+ 0x3812e000,
+ 0x38130000,
+ 0x38132000,
+ 0x38134000,
+ 0x38136000,
+ 0x38138000,
+ 0x3813a000,
+ 0x3813c000,
+ 0x3813e000,
+ 0x38140000,
+ 0x38142000,
+ 0x38144000,
+ 0x38146000,
+ 0x38148000,
+ 0x3814a000,
+ 0x3814c000,
+ 0x3814e000,
+ 0x38150000,
+ 0x38152000,
+ 0x38154000,
+ 0x38156000,
+ 0x38158000,
+ 0x3815a000,
+ 0x3815c000,
+ 0x3815e000,
+ 0x38160000,
+ 0x38162000,
+ 0x38164000,
+ 0x38166000,
+ 0x38168000,
+ 0x3816a000,
+ 0x3816c000,
+ 0x3816e000,
+ 0x38170000,
+ 0x38172000,
+ 0x38174000,
+ 0x38176000,
+ 0x38178000,
+ 0x3817a000,
+ 0x3817c000,
+ 0x3817e000,
+ 0x38180000,
+ 0x38182000,
+ 0x38184000,
+ 0x38186000,
+ 0x38188000,
+ 0x3818a000,
+ 0x3818c000,
+ 0x3818e000,
+ 0x38190000,
+ 0x38192000,
+ 0x38194000,
+ 0x38196000,
+ 0x38198000,
+ 0x3819a000,
+ 0x3819c000,
+ 0x3819e000,
+ 0x381a0000,
+ 0x381a2000,
+ 0x381a4000,
+ 0x381a6000,
+ 0x381a8000,
+ 0x381aa000,
+ 0x381ac000,
+ 0x381ae000,
+ 0x381b0000,
+ 0x381b2000,
+ 0x381b4000,
+ 0x381b6000,
+ 0x381b8000,
+ 0x381ba000,
+ 0x381bc000,
+ 0x381be000,
+ 0x381c0000,
+ 0x381c2000,
+ 0x381c4000,
+ 0x381c6000,
+ 0x381c8000,
+ 0x381ca000,
+ 0x381cc000,
+ 0x381ce000,
+ 0x381d0000,
+ 0x381d2000,
+ 0x381d4000,
+ 0x381d6000,
+ 0x381d8000,
+ 0x381da000,
+ 0x381dc000,
+ 0x381de000,
+ 0x381e0000,
+ 0x381e2000,
+ 0x381e4000,
+ 0x381e6000,
+ 0x381e8000,
+ 0x381ea000,
+ 0x381ec000,
+ 0x381ee000,
+ 0x381f0000,
+ 0x381f2000,
+ 0x381f4000,
+ 0x381f6000,
+ 0x381f8000,
+ 0x381fa000,
+ 0x381fc000,
+ 0x381fe000,
+ 0x38200000,
+ 0x38202000,
+ 0x38204000,
+ 0x38206000,
+ 0x38208000,
+ 0x3820a000,
+ 0x3820c000,
+ 0x3820e000,
+ 0x38210000,
+ 0x38212000,
+ 0x38214000,
+ 0x38216000,
+ 0x38218000,
+ 0x3821a000,
+ 0x3821c000,
+ 0x3821e000,
+ 0x38220000,
+ 0x38222000,
+ 0x38224000,
+ 0x38226000,
+ 0x38228000,
+ 0x3822a000,
+ 0x3822c000,
+ 0x3822e000,
+ 0x38230000,
+ 0x38232000,
+ 0x38234000,
+ 0x38236000,
+ 0x38238000,
+ 0x3823a000,
+ 0x3823c000,
+ 0x3823e000,
+ 0x38240000,
+ 0x38242000,
+ 0x38244000,
+ 0x38246000,
+ 0x38248000,
+ 0x3824a000,
+ 0x3824c000,
+ 0x3824e000,
+ 0x38250000,
+ 0x38252000,
+ 0x38254000,
+ 0x38256000,
+ 0x38258000,
+ 0x3825a000,
+ 0x3825c000,
+ 0x3825e000,
+ 0x38260000,
+ 0x38262000,
+ 0x38264000,
+ 0x38266000,
+ 0x38268000,
+ 0x3826a000,
+ 0x3826c000,
+ 0x3826e000,
+ 0x38270000,
+ 0x38272000,
+ 0x38274000,
+ 0x38276000,
+ 0x38278000,
+ 0x3827a000,
+ 0x3827c000,
+ 0x3827e000,
+ 0x38280000,
+ 0x38282000,
+ 0x38284000,
+ 0x38286000,
+ 0x38288000,
+ 0x3828a000,
+ 0x3828c000,
+ 0x3828e000,
+ 0x38290000,
+ 0x38292000,
+ 0x38294000,
+ 0x38296000,
+ 0x38298000,
+ 0x3829a000,
+ 0x3829c000,
+ 0x3829e000,
+ 0x382a0000,
+ 0x382a2000,
+ 0x382a4000,
+ 0x382a6000,
+ 0x382a8000,
+ 0x382aa000,
+ 0x382ac000,
+ 0x382ae000,
+ 0x382b0000,
+ 0x382b2000,
+ 0x382b4000,
+ 0x382b6000,
+ 0x382b8000,
+ 0x382ba000,
+ 0x382bc000,
+ 0x382be000,
+ 0x382c0000,
+ 0x382c2000,
+ 0x382c4000,
+ 0x382c6000,
+ 0x382c8000,
+ 0x382ca000,
+ 0x382cc000,
+ 0x382ce000,
+ 0x382d0000,
+ 0x382d2000,
+ 0x382d4000,
+ 0x382d6000,
+ 0x382d8000,
+ 0x382da000,
+ 0x382dc000,
+ 0x382de000,
+ 0x382e0000,
+ 0x382e2000,
+ 0x382e4000,
+ 0x382e6000,
+ 0x382e8000,
+ 0x382ea000,
+ 0x382ec000,
+ 0x382ee000,
+ 0x382f0000,
+ 0x382f2000,
+ 0x382f4000,
+ 0x382f6000,
+ 0x382f8000,
+ 0x382fa000,
+ 0x382fc000,
+ 0x382fe000,
+ 0x38300000,
+ 0x38302000,
+ 0x38304000,
+ 0x38306000,
+ 0x38308000,
+ 0x3830a000,
+ 0x3830c000,
+ 0x3830e000,
+ 0x38310000,
+ 0x38312000,
+ 0x38314000,
+ 0x38316000,
+ 0x38318000,
+ 0x3831a000,
+ 0x3831c000,
+ 0x3831e000,
+ 0x38320000,
+ 0x38322000,
+ 0x38324000,
+ 0x38326000,
+ 0x38328000,
+ 0x3832a000,
+ 0x3832c000,
+ 0x3832e000,
+ 0x38330000,
+ 0x38332000,
+ 0x38334000,
+ 0x38336000,
+ 0x38338000,
+ 0x3833a000,
+ 0x3833c000,
+ 0x3833e000,
+ 0x38340000,
+ 0x38342000,
+ 0x38344000,
+ 0x38346000,
+ 0x38348000,
+ 0x3834a000,
+ 0x3834c000,
+ 0x3834e000,
+ 0x38350000,
+ 0x38352000,
+ 0x38354000,
+ 0x38356000,
+ 0x38358000,
+ 0x3835a000,
+ 0x3835c000,
+ 0x3835e000,
+ 0x38360000,
+ 0x38362000,
+ 0x38364000,
+ 0x38366000,
+ 0x38368000,
+ 0x3836a000,
+ 0x3836c000,
+ 0x3836e000,
+ 0x38370000,
+ 0x38372000,
+ 0x38374000,
+ 0x38376000,
+ 0x38378000,
+ 0x3837a000,
+ 0x3837c000,
+ 0x3837e000,
+ 0x38380000,
+ 0x38382000,
+ 0x38384000,
+ 0x38386000,
+ 0x38388000,
+ 0x3838a000,
+ 0x3838c000,
+ 0x3838e000,
+ 0x38390000,
+ 0x38392000,
+ 0x38394000,
+ 0x38396000,
+ 0x38398000,
+ 0x3839a000,
+ 0x3839c000,
+ 0x3839e000,
+ 0x383a0000,
+ 0x383a2000,
+ 0x383a4000,
+ 0x383a6000,
+ 0x383a8000,
+ 0x383aa000,
+ 0x383ac000,
+ 0x383ae000,
+ 0x383b0000,
+ 0x383b2000,
+ 0x383b4000,
+ 0x383b6000,
+ 0x383b8000,
+ 0x383ba000,
+ 0x383bc000,
+ 0x383be000,
+ 0x383c0000,
+ 0x383c2000,
+ 0x383c4000,
+ 0x383c6000,
+ 0x383c8000,
+ 0x383ca000,
+ 0x383cc000,
+ 0x383ce000,
+ 0x383d0000,
+ 0x383d2000,
+ 0x383d4000,
+ 0x383d6000,
+ 0x383d8000,
+ 0x383da000,
+ 0x383dc000,
+ 0x383de000,
+ 0x383e0000,
+ 0x383e2000,
+ 0x383e4000,
+ 0x383e6000,
+ 0x383e8000,
+ 0x383ea000,
+ 0x383ec000,
+ 0x383ee000,
+ 0x383f0000,
+ 0x383f2000,
+ 0x383f4000,
+ 0x383f6000,
+ 0x383f8000,
+ 0x383fa000,
+ 0x383fc000,
+ 0x383fe000,
+ 0x38400000,
+ 0x38402000,
+ 0x38404000,
+ 0x38406000,
+ 0x38408000,
+ 0x3840a000,
+ 0x3840c000,
+ 0x3840e000,
+ 0x38410000,
+ 0x38412000,
+ 0x38414000,
+ 0x38416000,
+ 0x38418000,
+ 0x3841a000,
+ 0x3841c000,
+ 0x3841e000,
+ 0x38420000,
+ 0x38422000,
+ 0x38424000,
+ 0x38426000,
+ 0x38428000,
+ 0x3842a000,
+ 0x3842c000,
+ 0x3842e000,
+ 0x38430000,
+ 0x38432000,
+ 0x38434000,
+ 0x38436000,
+ 0x38438000,
+ 0x3843a000,
+ 0x3843c000,
+ 0x3843e000,
+ 0x38440000,
+ 0x38442000,
+ 0x38444000,
+ 0x38446000,
+ 0x38448000,
+ 0x3844a000,
+ 0x3844c000,
+ 0x3844e000,
+ 0x38450000,
+ 0x38452000,
+ 0x38454000,
+ 0x38456000,
+ 0x38458000,
+ 0x3845a000,
+ 0x3845c000,
+ 0x3845e000,
+ 0x38460000,
+ 0x38462000,
+ 0x38464000,
+ 0x38466000,
+ 0x38468000,
+ 0x3846a000,
+ 0x3846c000,
+ 0x3846e000,
+ 0x38470000,
+ 0x38472000,
+ 0x38474000,
+ 0x38476000,
+ 0x38478000,
+ 0x3847a000,
+ 0x3847c000,
+ 0x3847e000,
+ 0x38480000,
+ 0x38482000,
+ 0x38484000,
+ 0x38486000,
+ 0x38488000,
+ 0x3848a000,
+ 0x3848c000,
+ 0x3848e000,
+ 0x38490000,
+ 0x38492000,
+ 0x38494000,
+ 0x38496000,
+ 0x38498000,
+ 0x3849a000,
+ 0x3849c000,
+ 0x3849e000,
+ 0x384a0000,
+ 0x384a2000,
+ 0x384a4000,
+ 0x384a6000,
+ 0x384a8000,
+ 0x384aa000,
+ 0x384ac000,
+ 0x384ae000,
+ 0x384b0000,
+ 0x384b2000,
+ 0x384b4000,
+ 0x384b6000,
+ 0x384b8000,
+ 0x384ba000,
+ 0x384bc000,
+ 0x384be000,
+ 0x384c0000,
+ 0x384c2000,
+ 0x384c4000,
+ 0x384c6000,
+ 0x384c8000,
+ 0x384ca000,
+ 0x384cc000,
+ 0x384ce000,
+ 0x384d0000,
+ 0x384d2000,
+ 0x384d4000,
+ 0x384d6000,
+ 0x384d8000,
+ 0x384da000,
+ 0x384dc000,
+ 0x384de000,
+ 0x384e0000,
+ 0x384e2000,
+ 0x384e4000,
+ 0x384e6000,
+ 0x384e8000,
+ 0x384ea000,
+ 0x384ec000,
+ 0x384ee000,
+ 0x384f0000,
+ 0x384f2000,
+ 0x384f4000,
+ 0x384f6000,
+ 0x384f8000,
+ 0x384fa000,
+ 0x384fc000,
+ 0x384fe000,
+ 0x38500000,
+ 0x38502000,
+ 0x38504000,
+ 0x38506000,
+ 0x38508000,
+ 0x3850a000,
+ 0x3850c000,
+ 0x3850e000,
+ 0x38510000,
+ 0x38512000,
+ 0x38514000,
+ 0x38516000,
+ 0x38518000,
+ 0x3851a000,
+ 0x3851c000,
+ 0x3851e000,
+ 0x38520000,
+ 0x38522000,
+ 0x38524000,
+ 0x38526000,
+ 0x38528000,
+ 0x3852a000,
+ 0x3852c000,
+ 0x3852e000,
+ 0x38530000,
+ 0x38532000,
+ 0x38534000,
+ 0x38536000,
+ 0x38538000,
+ 0x3853a000,
+ 0x3853c000,
+ 0x3853e000,
+ 0x38540000,
+ 0x38542000,
+ 0x38544000,
+ 0x38546000,
+ 0x38548000,
+ 0x3854a000,
+ 0x3854c000,
+ 0x3854e000,
+ 0x38550000,
+ 0x38552000,
+ 0x38554000,
+ 0x38556000,
+ 0x38558000,
+ 0x3855a000,
+ 0x3855c000,
+ 0x3855e000,
+ 0x38560000,
+ 0x38562000,
+ 0x38564000,
+ 0x38566000,
+ 0x38568000,
+ 0x3856a000,
+ 0x3856c000,
+ 0x3856e000,
+ 0x38570000,
+ 0x38572000,
+ 0x38574000,
+ 0x38576000,
+ 0x38578000,
+ 0x3857a000,
+ 0x3857c000,
+ 0x3857e000,
+ 0x38580000,
+ 0x38582000,
+ 0x38584000,
+ 0x38586000,
+ 0x38588000,
+ 0x3858a000,
+ 0x3858c000,
+ 0x3858e000,
+ 0x38590000,
+ 0x38592000,
+ 0x38594000,
+ 0x38596000,
+ 0x38598000,
+ 0x3859a000,
+ 0x3859c000,
+ 0x3859e000,
+ 0x385a0000,
+ 0x385a2000,
+ 0x385a4000,
+ 0x385a6000,
+ 0x385a8000,
+ 0x385aa000,
+ 0x385ac000,
+ 0x385ae000,
+ 0x385b0000,
+ 0x385b2000,
+ 0x385b4000,
+ 0x385b6000,
+ 0x385b8000,
+ 0x385ba000,
+ 0x385bc000,
+ 0x385be000,
+ 0x385c0000,
+ 0x385c2000,
+ 0x385c4000,
+ 0x385c6000,
+ 0x385c8000,
+ 0x385ca000,
+ 0x385cc000,
+ 0x385ce000,
+ 0x385d0000,
+ 0x385d2000,
+ 0x385d4000,
+ 0x385d6000,
+ 0x385d8000,
+ 0x385da000,
+ 0x385dc000,
+ 0x385de000,
+ 0x385e0000,
+ 0x385e2000,
+ 0x385e4000,
+ 0x385e6000,
+ 0x385e8000,
+ 0x385ea000,
+ 0x385ec000,
+ 0x385ee000,
+ 0x385f0000,
+ 0x385f2000,
+ 0x385f4000,
+ 0x385f6000,
+ 0x385f8000,
+ 0x385fa000,
+ 0x385fc000,
+ 0x385fe000,
+ 0x38600000,
+ 0x38602000,
+ 0x38604000,
+ 0x38606000,
+ 0x38608000,
+ 0x3860a000,
+ 0x3860c000,
+ 0x3860e000,
+ 0x38610000,
+ 0x38612000,
+ 0x38614000,
+ 0x38616000,
+ 0x38618000,
+ 0x3861a000,
+ 0x3861c000,
+ 0x3861e000,
+ 0x38620000,
+ 0x38622000,
+ 0x38624000,
+ 0x38626000,
+ 0x38628000,
+ 0x3862a000,
+ 0x3862c000,
+ 0x3862e000,
+ 0x38630000,
+ 0x38632000,
+ 0x38634000,
+ 0x38636000,
+ 0x38638000,
+ 0x3863a000,
+ 0x3863c000,
+ 0x3863e000,
+ 0x38640000,
+ 0x38642000,
+ 0x38644000,
+ 0x38646000,
+ 0x38648000,
+ 0x3864a000,
+ 0x3864c000,
+ 0x3864e000,
+ 0x38650000,
+ 0x38652000,
+ 0x38654000,
+ 0x38656000,
+ 0x38658000,
+ 0x3865a000,
+ 0x3865c000,
+ 0x3865e000,
+ 0x38660000,
+ 0x38662000,
+ 0x38664000,
+ 0x38666000,
+ 0x38668000,
+ 0x3866a000,
+ 0x3866c000,
+ 0x3866e000,
+ 0x38670000,
+ 0x38672000,
+ 0x38674000,
+ 0x38676000,
+ 0x38678000,
+ 0x3867a000,
+ 0x3867c000,
+ 0x3867e000,
+ 0x38680000,
+ 0x38682000,
+ 0x38684000,
+ 0x38686000,
+ 0x38688000,
+ 0x3868a000,
+ 0x3868c000,
+ 0x3868e000,
+ 0x38690000,
+ 0x38692000,
+ 0x38694000,
+ 0x38696000,
+ 0x38698000,
+ 0x3869a000,
+ 0x3869c000,
+ 0x3869e000,
+ 0x386a0000,
+ 0x386a2000,
+ 0x386a4000,
+ 0x386a6000,
+ 0x386a8000,
+ 0x386aa000,
+ 0x386ac000,
+ 0x386ae000,
+ 0x386b0000,
+ 0x386b2000,
+ 0x386b4000,
+ 0x386b6000,
+ 0x386b8000,
+ 0x386ba000,
+ 0x386bc000,
+ 0x386be000,
+ 0x386c0000,
+ 0x386c2000,
+ 0x386c4000,
+ 0x386c6000,
+ 0x386c8000,
+ 0x386ca000,
+ 0x386cc000,
+ 0x386ce000,
+ 0x386d0000,
+ 0x386d2000,
+ 0x386d4000,
+ 0x386d6000,
+ 0x386d8000,
+ 0x386da000,
+ 0x386dc000,
+ 0x386de000,
+ 0x386e0000,
+ 0x386e2000,
+ 0x386e4000,
+ 0x386e6000,
+ 0x386e8000,
+ 0x386ea000,
+ 0x386ec000,
+ 0x386ee000,
+ 0x386f0000,
+ 0x386f2000,
+ 0x386f4000,
+ 0x386f6000,
+ 0x386f8000,
+ 0x386fa000,
+ 0x386fc000,
+ 0x386fe000,
+ 0x38700000,
+ 0x38702000,
+ 0x38704000,
+ 0x38706000,
+ 0x38708000,
+ 0x3870a000,
+ 0x3870c000,
+ 0x3870e000,
+ 0x38710000,
+ 0x38712000,
+ 0x38714000,
+ 0x38716000,
+ 0x38718000,
+ 0x3871a000,
+ 0x3871c000,
+ 0x3871e000,
+ 0x38720000,
+ 0x38722000,
+ 0x38724000,
+ 0x38726000,
+ 0x38728000,
+ 0x3872a000,
+ 0x3872c000,
+ 0x3872e000,
+ 0x38730000,
+ 0x38732000,
+ 0x38734000,
+ 0x38736000,
+ 0x38738000,
+ 0x3873a000,
+ 0x3873c000,
+ 0x3873e000,
+ 0x38740000,
+ 0x38742000,
+ 0x38744000,
+ 0x38746000,
+ 0x38748000,
+ 0x3874a000,
+ 0x3874c000,
+ 0x3874e000,
+ 0x38750000,
+ 0x38752000,
+ 0x38754000,
+ 0x38756000,
+ 0x38758000,
+ 0x3875a000,
+ 0x3875c000,
+ 0x3875e000,
+ 0x38760000,
+ 0x38762000,
+ 0x38764000,
+ 0x38766000,
+ 0x38768000,
+ 0x3876a000,
+ 0x3876c000,
+ 0x3876e000,
+ 0x38770000,
+ 0x38772000,
+ 0x38774000,
+ 0x38776000,
+ 0x38778000,
+ 0x3877a000,
+ 0x3877c000,
+ 0x3877e000,
+ 0x38780000,
+ 0x38782000,
+ 0x38784000,
+ 0x38786000,
+ 0x38788000,
+ 0x3878a000,
+ 0x3878c000,
+ 0x3878e000,
+ 0x38790000,
+ 0x38792000,
+ 0x38794000,
+ 0x38796000,
+ 0x38798000,
+ 0x3879a000,
+ 0x3879c000,
+ 0x3879e000,
+ 0x387a0000,
+ 0x387a2000,
+ 0x387a4000,
+ 0x387a6000,
+ 0x387a8000,
+ 0x387aa000,
+ 0x387ac000,
+ 0x387ae000,
+ 0x387b0000,
+ 0x387b2000,
+ 0x387b4000,
+ 0x387b6000,
+ 0x387b8000,
+ 0x387ba000,
+ 0x387bc000,
+ 0x387be000,
+ 0x387c0000,
+ 0x387c2000,
+ 0x387c4000,
+ 0x387c6000,
+ 0x387c8000,
+ 0x387ca000,
+ 0x387cc000,
+ 0x387ce000,
+ 0x387d0000,
+ 0x387d2000,
+ 0x387d4000,
+ 0x387d6000,
+ 0x387d8000,
+ 0x387da000,
+ 0x387dc000,
+ 0x387de000,
+ 0x387e0000,
+ 0x387e2000,
+ 0x387e4000,
+ 0x387e6000,
+ 0x387e8000,
+ 0x387ea000,
+ 0x387ec000,
+ 0x387ee000,
+ 0x387f0000,
+ 0x387f2000,
+ 0x387f4000,
+ 0x387f6000,
+ 0x387f8000,
+ 0x387fa000,
+ 0x387fc000,
+ 0x387fe000,
+};
+
+const static unsigned g_exponent[64] = {
+ 0x00000000,
+ 0x00800000,
+ 0x01000000,
+ 0x01800000,
+ 0x02000000,
+ 0x02800000,
+ 0x03000000,
+ 0x03800000,
+ 0x04000000,
+ 0x04800000,
+ 0x05000000,
+ 0x05800000,
+ 0x06000000,
+ 0x06800000,
+ 0x07000000,
+ 0x07800000,
+ 0x08000000,
+ 0x08800000,
+ 0x09000000,
+ 0x09800000,
+ 0x0a000000,
+ 0x0a800000,
+ 0x0b000000,
+ 0x0b800000,
+ 0x0c000000,
+ 0x0c800000,
+ 0x0d000000,
+ 0x0d800000,
+ 0x0e000000,
+ 0x0e800000,
+ 0x0f000000,
+ 0x47800000,
+ 0x80000000,
+ 0x80800000,
+ 0x81000000,
+ 0x81800000,
+ 0x82000000,
+ 0x82800000,
+ 0x83000000,
+ 0x83800000,
+ 0x84000000,
+ 0x84800000,
+ 0x85000000,
+ 0x85800000,
+ 0x86000000,
+ 0x86800000,
+ 0x87000000,
+ 0x87800000,
+ 0x88000000,
+ 0x88800000,
+ 0x89000000,
+ 0x89800000,
+ 0x8a000000,
+ 0x8a800000,
+ 0x8b000000,
+ 0x8b800000,
+ 0x8c000000,
+ 0x8c800000,
+ 0x8d000000,
+ 0x8d800000,
+ 0x8e000000,
+ 0x8e800000,
+ 0x8f000000,
+ 0xc7800000,
+};
+
+const static unsigned g_offset[64] = {
+ 0x00000000,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000000,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+ 0x00000400,
+};
+
+float float16ToFloat32(unsigned short h)
+{
+ unsigned i32 = g_mantissa[g_offset[h >> 10] + (h & 0x3ff)] + g_exponent[h >> 10];
+ return bitCast<float>(i32);
+}
+}
+
diff --git a/gfx/angle/src/common/Float16ToFloat32.py b/gfx/angle/src/common/Float16ToFloat32.py
new file mode 100755
index 000000000..7705f7b61
--- /dev/null
+++ b/gfx/angle/src/common/Float16ToFloat32.py
@@ -0,0 +1,80 @@
+# Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+
+# This script generates a function that converts 16-bit precision floating
+# point numbers to 32-bit.
+# It is based on ftp://ftp.fox-toolkit.org/pub/fasthalffloatconversion.pdf.
+
+#include "common/mathutil.h"
+
+def convertMantissa(i):
+ if i == 0:
+ return 0
+ elif i < 1024:
+ m = i << 13
+ e = 0
+ while not (m & 0x00800000):
+ e -= 0x00800000
+ m = m << 1
+ m &= ~0x00800000
+ e += 0x38800000
+ return m | e
+ else:
+ return 0x38000000 + ((i - 1024) << 13)
+
+def convertExponent(i):
+ if i == 0:
+ return 0
+ elif i in range(1, 31):
+ return i << 23
+ elif i == 31:
+ return 0x47800000
+ elif i == 32:
+ return 0x80000000
+ elif i in range(33, 63):
+ return 0x80000000 + ((i - 32) << 23)
+ else:
+ return 0xC7800000
+
+def convertOffset(i):
+ if i == 0 or i == 32:
+ return 0
+ else:
+ return 1024
+
+print """//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// This file is automatically generated.
+
+namespace gl
+{
+"""
+
+print "const static unsigned g_mantissa[2048] = {"
+for i in range(0, 2048):
+ print " %#010x," % convertMantissa(i)
+print "};\n"
+
+print "const static unsigned g_exponent[64] = {"
+for i in range(0, 64):
+ print " %#010x," % convertExponent(i)
+print "};\n"
+
+print "const static unsigned g_offset[64] = {"
+for i in range(0, 64):
+ print " %#010x," % convertOffset(i)
+print "};\n"
+
+print """float float16ToFloat32(unsigned short h)
+{
+ unsigned i32 = g_mantissa[g_offset[h >> 10] + (h & 0x3ff)] + g_exponent[h >> 10];
+ return bitCast<float>(i32);
+}
+}
+"""
diff --git a/gfx/angle/src/common/MemoryBuffer.cpp b/gfx/angle/src/common/MemoryBuffer.cpp
new file mode 100755
index 000000000..e7a3fb4a2
--- /dev/null
+++ b/gfx/angle/src/common/MemoryBuffer.cpp
@@ -0,0 +1,80 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "common/MemoryBuffer.h"
+
+#include <algorithm>
+#include <cstdlib>
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+MemoryBuffer::MemoryBuffer()
+ : mSize(0),
+ mData(NULL)
+{
+}
+
+MemoryBuffer::~MemoryBuffer()
+{
+ free(mData);
+ mData = NULL;
+}
+
+bool MemoryBuffer::resize(size_t size)
+{
+ if (size == 0)
+ {
+ free(mData);
+ mData = NULL;
+ mSize = 0;
+ return true;
+ }
+
+ if (size == mSize)
+ {
+ return true;
+ }
+
+ // Only reallocate if the size has changed.
+ uint8_t *newMemory = reinterpret_cast<uint8_t*>(malloc(sizeof(uint8_t) * size));
+ if (newMemory == NULL)
+ {
+ return false;
+ }
+
+ if (mData)
+ {
+ // Copy the intersection of the old data and the new data
+ std::copy(mData, mData + std::min(mSize, size), newMemory);
+ free(mData);
+ }
+
+ mData = newMemory;
+ mSize = size;
+
+ return true;
+}
+
+size_t MemoryBuffer::size() const
+{
+ return mSize;
+}
+
+const uint8_t *MemoryBuffer::data() const
+{
+ return mData;
+}
+
+uint8_t *MemoryBuffer::data()
+{
+ ASSERT(mData);
+ return mData;
+}
+
+}
diff --git a/gfx/angle/src/common/MemoryBuffer.h b/gfx/angle/src/common/MemoryBuffer.h
new file mode 100755
index 000000000..ec621cbca
--- /dev/null
+++ b/gfx/angle/src/common/MemoryBuffer.h
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMMON_MEMORYBUFFER_H_
+#define COMMON_MEMORYBUFFER_H_
+
+#include "common/angleutils.h"
+
+#include <cstddef>
+#include <stdint.h>
+
+namespace rx
+{
+
+class MemoryBuffer : angle::NonCopyable
+{
+ public:
+ MemoryBuffer();
+ ~MemoryBuffer();
+
+ bool resize(size_t size);
+ size_t size() const;
+ bool empty() const { return mSize == 0; }
+
+ const uint8_t *data() const;
+ uint8_t *data();
+
+ private:
+ size_t mSize;
+ uint8_t *mData;
+};
+
+}
+
+#endif // COMMON_MEMORYBUFFER_H_
diff --git a/gfx/angle/src/common/Optional.h b/gfx/angle/src/common/Optional.h
new file mode 100755
index 000000000..5a79048d6
--- /dev/null
+++ b/gfx/angle/src/common/Optional.h
@@ -0,0 +1,74 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Optional.h:
+// Represents a type that may be invalid, similar to std::optional.
+//
+
+#ifndef COMMON_OPTIONAL_H_
+#define COMMON_OPTIONAL_H_
+
+template <class T>
+struct Optional
+{
+ Optional()
+ : mValid(false),
+ mValue(T())
+ {}
+
+ Optional(const T &valueIn) : mValid(true), mValue(valueIn) {}
+
+ Optional(const Optional &other)
+ : mValid(other.mValid),
+ mValue(other.mValue)
+ {}
+
+ Optional &operator=(const Optional &other)
+ {
+ this->mValid = other.mValid;
+ this->mValue = other.mValue;
+ return *this;
+ }
+
+ Optional &operator=(const T &value)
+ {
+ mValue = value;
+ mValid = true;
+ return *this;
+ }
+
+ Optional &operator=(T &&value)
+ {
+ mValue = std::move(value);
+ mValid = true;
+ return *this;
+ }
+
+ void reset()
+ {
+ mValid = false;
+ }
+
+ static Optional Invalid() { return Optional(); }
+
+ bool valid() const { return mValid; }
+ const T &value() const { return mValue; }
+
+ bool operator==(const Optional &other) const
+ {
+ return ((mValid == other.mValid) && (!mValid || (mValue == other.mValue)));
+ }
+
+ bool operator!=(const Optional &other) const
+ {
+ return !(*this == other);
+ }
+
+ private:
+ bool mValid;
+ T mValue;
+};
+
+#endif // COMMON_OPTIONAL_H_
diff --git a/gfx/angle/src/common/Optional_unittest.cpp b/gfx/angle/src/common/Optional_unittest.cpp
new file mode 100755
index 000000000..810046184
--- /dev/null
+++ b/gfx/angle/src/common/Optional_unittest.cpp
@@ -0,0 +1,47 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Unit tests for ANGLE's Optional helper class.
+//
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "common/Optional.h"
+
+namespace
+{
+
+TEST(OptionalTest, BasicInvalid)
+{
+ Optional<int> testInvalid;
+ ASSERT_FALSE(testInvalid.valid());
+ ASSERT_EQ(Optional<int>::Invalid(), testInvalid);
+}
+
+TEST(OptionalTest, BasicValid)
+{
+ Optional<int> testValid(3);
+ ASSERT_TRUE(testValid.valid());
+ ASSERT_EQ(3, testValid.value());
+ ASSERT_NE(Optional<int>::Invalid(), testValid);
+}
+
+TEST(OptionalTest, Copies)
+{
+ Optional<int> testValid(3);
+ Optional<int> testInvalid;
+
+ Optional<int> testCopy = testInvalid;
+ ASSERT_FALSE(testCopy.valid());
+ ASSERT_EQ(testInvalid, testCopy);
+
+ testCopy = testValid;
+ ASSERT_TRUE(testCopy.valid());
+ ASSERT_EQ(3, testCopy.value());
+ ASSERT_EQ(testValid, testCopy);
+}
+
+} // namespace
diff --git a/gfx/angle/src/common/angleutils.cpp b/gfx/angle/src/common/angleutils.cpp
new file mode 100755
index 000000000..7099c2173
--- /dev/null
+++ b/gfx/angle/src/common/angleutils.cpp
@@ -0,0 +1,52 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "common/angleutils.h"
+#include "common/debug.h"
+
+#include <stdio.h>
+
+#include <limits>
+#include <vector>
+
+namespace angle
+{
+const uintptr_t DirtyPointer = std::numeric_limits<uintptr_t>::max();
+}
+
+size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char>& outBuffer)
+{
+ // Attempt to just print to the current buffer
+ int len = vsnprintf(&(outBuffer.front()), outBuffer.size(), fmt, vararg);
+ if (len < 0 || static_cast<size_t>(len) >= outBuffer.size())
+ {
+ // Buffer was not large enough, calculate the required size and resize the buffer
+ len = vsnprintf(NULL, 0, fmt, vararg);
+ outBuffer.resize(len + 1);
+
+ // Print again
+ len = vsnprintf(&(outBuffer.front()), outBuffer.size(), fmt, vararg);
+ }
+ ASSERT(len >= 0);
+ return static_cast<size_t>(len);
+}
+
+std::string FormatString(const char *fmt, va_list vararg)
+{
+ static std::vector<char> buffer(512);
+
+ size_t len = FormatStringIntoVector(fmt, vararg, buffer);
+ return std::string(&buffer[0], len);
+}
+
+std::string FormatString(const char *fmt, ...)
+{
+ va_list vararg;
+ va_start(vararg, fmt);
+ std::string result = FormatString(fmt, vararg);
+ va_end(vararg);
+ return result;
+}
diff --git a/gfx/angle/src/common/angleutils.h b/gfx/angle/src/common/angleutils.h
new file mode 100755
index 000000000..f5ef7bdc1
--- /dev/null
+++ b/gfx/angle/src/common/angleutils.h
@@ -0,0 +1,187 @@
+//
+// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// angleutils.h: Common ANGLE utilities.
+
+#ifndef COMMON_ANGLEUTILS_H_
+#define COMMON_ANGLEUTILS_H_
+
+#include "common/platform.h"
+
+#include <climits>
+#include <cstdarg>
+#include <cstddef>
+#include <string>
+#include <set>
+#include <sstream>
+#include <vector>
+
+// A helper class to disallow copy and assignment operators
+namespace angle
+{
+
+class NonCopyable
+{
+ public:
+ NonCopyable() = default;
+ ~NonCopyable() = default;
+ protected:
+ NonCopyable(const NonCopyable&) = delete;
+ void operator=(const NonCopyable&) = delete;
+};
+
+extern const uintptr_t DirtyPointer;
+} // namespace angle
+
+template <typename T, size_t N>
+constexpr inline size_t ArraySize(T (&)[N])
+{
+ return N;
+}
+
+template <typename T, unsigned int N>
+void SafeRelease(T (&resourceBlock)[N])
+{
+ for (unsigned int i = 0; i < N; i++)
+ {
+ SafeRelease(resourceBlock[i]);
+ }
+}
+
+template <typename T>
+void SafeRelease(T& resource)
+{
+ if (resource)
+ {
+ resource->Release();
+ resource = NULL;
+ }
+}
+
+template <typename T>
+void SafeDelete(T *&resource)
+{
+ delete resource;
+ resource = NULL;
+}
+
+template <typename T>
+void SafeDeleteContainer(T& resource)
+{
+ for (auto &element : resource)
+ {
+ SafeDelete(element);
+ }
+ resource.clear();
+}
+
+template <typename T>
+void SafeDeleteArray(T*& resource)
+{
+ delete[] resource;
+ resource = NULL;
+}
+
+// Provide a less-than function for comparing structs
+// Note: struct memory must be initialized to zero, because of packing gaps
+template <typename T>
+inline bool StructLessThan(const T &a, const T &b)
+{
+ return (memcmp(&a, &b, sizeof(T)) < 0);
+}
+
+// Provide a less-than function for comparing structs
+// Note: struct memory must be initialized to zero, because of packing gaps
+template <typename T>
+inline bool StructEquals(const T &a, const T &b)
+{
+ return (memcmp(&a, &b, sizeof(T)) == 0);
+}
+
+template <typename T>
+inline void StructZero(T *obj)
+{
+ memset(obj, 0, sizeof(T));
+}
+
+template <typename T>
+inline bool IsMaskFlagSet(T mask, T flag)
+{
+ // Handles multibit flags as well
+ return (mask & flag) == flag;
+}
+
+inline const char* MakeStaticString(const std::string &str)
+{
+ static std::set<std::string> strings;
+ std::set<std::string>::iterator it = strings.find(str);
+ if (it != strings.end())
+ {
+ return it->c_str();
+ }
+
+ return strings.insert(str).first->c_str();
+}
+
+inline std::string ArrayString(unsigned int i)
+{
+ // We assume UINT_MAX and GL_INVALID_INDEX are equal
+ // See DynamicHLSL.cpp
+ if (i == UINT_MAX)
+ {
+ return "";
+ }
+
+ std::stringstream strstr;
+
+ strstr << "[";
+ strstr << i;
+ strstr << "]";
+
+ return strstr.str();
+}
+
+inline std::string Str(int i)
+{
+ std::stringstream strstr;
+ strstr << i;
+ return strstr.str();
+}
+
+size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char>& buffer);
+
+std::string FormatString(const char *fmt, va_list vararg);
+std::string FormatString(const char *fmt, ...);
+
+template <typename T>
+std::string ToString(const T &value)
+{
+ std::ostringstream o;
+ o << value;
+ return o.str();
+}
+
+// snprintf is not defined with MSVC prior to to msvc14
+#if defined(_MSC_VER) && _MSC_VER < 1900
+#define snprintf _snprintf
+#endif
+
+#define GL_BGR565_ANGLEX 0x6ABB
+#define GL_BGRA4_ANGLEX 0x6ABC
+#define GL_BGR5_A1_ANGLEX 0x6ABD
+#define GL_INT_64_ANGLEX 0x6ABE
+#define GL_STRUCT_ANGLEX 0x6ABF
+
+// Hidden enum for the NULL D3D device type.
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE 0x6AC0
+
+#define ANGLE_TRY_CHECKED_MATH(result) \
+ if (!result.IsValid()) \
+ { \
+ return gl::Error(GL_INVALID_OPERATION, "Integer overflow."); \
+ }
+
+#endif // COMMON_ANGLEUTILS_H_
diff --git a/gfx/angle/src/common/debug.cpp b/gfx/angle/src/common/debug.cpp
new file mode 100755
index 000000000..f64d9322f
--- /dev/null
+++ b/gfx/angle/src/common/debug.cpp
@@ -0,0 +1,179 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// debug.cpp: Debugging utilities.
+
+#include "common/debug.h"
+
+#include <stdarg.h>
+
+#include <cstdio>
+#include <fstream>
+#include <iostream>
+#include <vector>
+
+#include "common/angleutils.h"
+#include "common/platform.h"
+#include "common/Optional.h"
+
+namespace gl
+{
+
+namespace
+{
+
+class FormattedString final : angle::NonCopyable
+{
+ public:
+ FormattedString(const char *format, va_list vararg) : mFormat(format)
+ {
+ va_copy(mVarArg, vararg);
+ }
+
+ const char *c_str() { return str().c_str(); }
+
+ const std::string &str()
+ {
+ if (!mMessage.valid())
+ {
+ mMessage = FormatString(mFormat, mVarArg);
+ }
+ return mMessage.value();
+ }
+
+ size_t length()
+ {
+ c_str();
+ return mMessage.value().length();
+ }
+
+ private:
+ const char *mFormat;
+ va_list mVarArg;
+ Optional<std::string> mMessage;
+};
+enum DebugTraceOutputType
+{
+ DebugTraceOutputTypeNone,
+ DebugTraceOutputTypeSetMarker,
+ DebugTraceOutputTypeBeginEvent
+};
+
+DebugAnnotator *g_debugAnnotator = nullptr;
+
+void output(bool traceInDebugOnly, MessageType messageType, DebugTraceOutputType outputType,
+ const char *format, va_list vararg)
+{
+ if (DebugAnnotationsActive())
+ {
+ static std::vector<char> buffer(512);
+ size_t len = FormatStringIntoVector(format, vararg, buffer);
+ std::wstring formattedWideMessage(buffer.begin(), buffer.begin() + len);
+
+ ASSERT(g_debugAnnotator != nullptr);
+ switch (outputType)
+ {
+ case DebugTraceOutputTypeNone:
+ break;
+ case DebugTraceOutputTypeBeginEvent:
+ g_debugAnnotator->beginEvent(formattedWideMessage.c_str());
+ break;
+ case DebugTraceOutputTypeSetMarker:
+ g_debugAnnotator->setMarker(formattedWideMessage.c_str());
+ break;
+ }
+ }
+
+ FormattedString formattedMessage(format, vararg);
+
+ if (messageType == MESSAGE_ERR)
+ {
+ std::cerr << formattedMessage.c_str();
+#if !defined(NDEBUG) && defined(_MSC_VER)
+ OutputDebugStringA(formattedMessage.c_str());
+#endif // !defined(NDEBUG) && defined(_MSC_VER)
+ }
+
+#if defined(ANGLE_ENABLE_DEBUG_TRACE)
+#if defined(NDEBUG)
+ if (traceInDebugOnly)
+ {
+ return;
+ }
+#endif // NDEBUG
+ static std::ofstream file(TRACE_OUTPUT_FILE, std::ofstream::app);
+ if (file)
+ {
+ file.write(formattedMessage.c_str(), formattedMessage.length());
+ file.flush();
+ }
+
+#if defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER)
+ OutputDebugStringA(formattedMessage.c_str());
+#endif // ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER
+
+#endif // ANGLE_ENABLE_DEBUG_TRACE
+}
+
+} // namespace
+
+bool DebugAnnotationsActive()
+{
+#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
+ return g_debugAnnotator != nullptr && g_debugAnnotator->getStatus();
+#else
+ return false;
+#endif
+}
+
+void InitializeDebugAnnotations(DebugAnnotator *debugAnnotator)
+{
+ UninitializeDebugAnnotations();
+ g_debugAnnotator = debugAnnotator;
+}
+
+void UninitializeDebugAnnotations()
+{
+ // Pointer is not managed.
+ g_debugAnnotator = nullptr;
+}
+
+void trace(bool traceInDebugOnly, MessageType messageType, const char *format, ...)
+{
+ va_list vararg;
+ va_start(vararg, format);
+ output(traceInDebugOnly, messageType, DebugTraceOutputTypeSetMarker, format, vararg);
+ va_end(vararg);
+}
+
+ScopedPerfEventHelper::ScopedPerfEventHelper(const char* format, ...)
+{
+#if !defined(ANGLE_ENABLE_DEBUG_TRACE)
+ if (!DebugAnnotationsActive())
+ {
+ return;
+ }
+#endif // !ANGLE_ENABLE_DEBUG_TRACE
+ va_list vararg;
+ va_start(vararg, format);
+ output(true, MESSAGE_EVENT, DebugTraceOutputTypeBeginEvent, format, vararg);
+ va_end(vararg);
+}
+
+ScopedPerfEventHelper::~ScopedPerfEventHelper()
+{
+ if (DebugAnnotationsActive())
+ {
+ g_debugAnnotator->endEvent();
+ }
+}
+
+std::ostream &DummyStream()
+{
+ return std::cout;
+}
+
+} // namespace gl
diff --git a/gfx/angle/src/common/debug.h b/gfx/angle/src/common/debug.h
new file mode 100755
index 000000000..9356090ae
--- /dev/null
+++ b/gfx/angle/src/common/debug.h
@@ -0,0 +1,174 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// debug.h: Debugging utilities.
+
+#ifndef COMMON_DEBUG_H_
+#define COMMON_DEBUG_H_
+
+#include <assert.h>
+#include <stdio.h>
+#include <string>
+
+#include "common/angleutils.h"
+
+#if !defined(TRACE_OUTPUT_FILE)
+#define TRACE_OUTPUT_FILE "angle_debug.txt"
+#endif
+
+namespace gl
+{
+
+enum MessageType
+{
+ MESSAGE_TRACE,
+ MESSAGE_FIXME,
+ MESSAGE_ERR,
+ MESSAGE_EVENT,
+};
+
+// Outputs text to the debugging log, or the debugging window
+void trace(bool traceInDebugOnly, MessageType messageType, const char *format, ...);
+
+// Pairs a D3D begin event with an end event.
+class ScopedPerfEventHelper : angle::NonCopyable
+{
+ public:
+ ScopedPerfEventHelper(const char* format, ...);
+ ~ScopedPerfEventHelper();
+};
+
+// Wraps the D3D9/D3D11 debug annotation functions.
+class DebugAnnotator : angle::NonCopyable
+{
+ public:
+ DebugAnnotator() { };
+ virtual ~DebugAnnotator() { };
+ virtual void beginEvent(const wchar_t *eventName) = 0;
+ virtual void endEvent() = 0;
+ virtual void setMarker(const wchar_t *markerName) = 0;
+ virtual bool getStatus() = 0;
+};
+
+void InitializeDebugAnnotations(DebugAnnotator *debugAnnotator);
+void UninitializeDebugAnnotations();
+bool DebugAnnotationsActive();
+
+// This class is used to explicitly ignore values in the conditional logging macros. This avoids
+// compiler warnings like "value computed is not used" and "statement has no effect".
+class LogMessageVoidify
+{
+ public:
+ LogMessageVoidify() {}
+ // This has to be an operator with a precedence lower than << but higher than ?:
+ void operator&(std::ostream &) {}
+};
+
+// This can be any ostream, it is unused, but needs to be a valid reference.
+std::ostream &DummyStream();
+
+} // namespace gl
+
+#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
+#define ANGLE_TRACE_ENABLED
+#endif
+
+#define ANGLE_EMPTY_STATEMENT for (;;) break
+#if !defined(NDEBUG) || defined(ANGLE_ENABLE_RELEASE_ASSERTS)
+#define ANGLE_ENABLE_ASSERTS
+#endif
+
+// A macro to output a trace of a function call and its arguments to the debugging log
+#if defined(ANGLE_TRACE_ENABLED)
+#define TRACE(message, ...) gl::trace(true, gl::MESSAGE_TRACE, "trace: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#else
+#define TRACE(message, ...) (void(0))
+#endif
+
+// A macro to output a function call and its arguments to the debugging log, to denote an item in need of fixing.
+#if defined(ANGLE_TRACE_ENABLED)
+#define FIXME(message, ...) gl::trace(false, gl::MESSAGE_FIXME, "fixme: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#else
+#define FIXME(message, ...) (void(0))
+#endif
+
+// A macro to output a function call and its arguments to the debugging log, in case of error.
+#if defined(ANGLE_TRACE_ENABLED) || defined(ANGLE_ENABLE_ASSERTS)
+#define ERR(message, ...) gl::trace(false, gl::MESSAGE_ERR, "err: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#else
+#define ERR(message, ...) (void(0))
+#endif
+
+// A macro to log a performance event around a scope.
+#if defined(ANGLE_TRACE_ENABLED)
+#if defined(_MSC_VER)
+#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__("%s" message "\n", __FUNCTION__, __VA_ARGS__);
+#else
+#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper("%s" message "\n", __FUNCTION__, ##__VA_ARGS__);
+#endif // _MSC_VER
+#else
+#define EVENT(message, ...) (void(0))
+#endif
+
+#if defined(ANGLE_TRACE_ENABLED)
+#undef ANGLE_TRACE_ENABLED
+#endif
+
+#if defined(COMPILER_GCC) || defined(__clang__)
+#define ANGLE_CRASH() __builtin_trap()
+#else
+#define ANGLE_CRASH() ((void)(*(volatile char *)0 = 0))
+#endif
+
+#if !defined(NDEBUG)
+#define ANGLE_ASSERT_IMPL(expression) assert(expression)
+#else
+// TODO(jmadill): Detect if debugger is attached and break.
+#define ANGLE_ASSERT_IMPL(expression) ANGLE_CRASH()
+#endif // !defined(NDEBUG)
+
+// Helper macro which avoids evaluating the arguments to a stream if the condition doesn't hold.
+// Condition is evaluated once and only once.
+#define ANGLE_LAZY_STREAM(stream, condition) \
+ !(condition) ? static_cast<void>(0) : ::gl::LogMessageVoidify() & (stream)
+
+#if defined(NDEBUG) && !defined(ANGLE_ENABLE_ASSERTS)
+#define ANGLE_ASSERTS_ON 0
+#else
+#define ANGLE_ASSERTS_ON 1
+#endif
+
+// A macro asserting a condition and outputting failures to the debug log
+#if ANGLE_ASSERTS_ON
+#define ASSERT(expression) \
+ (expression ? static_cast<void>(0) \
+ : (ERR("\t! Assert failed in %s(%d): %s\n", __FUNCTION__, __LINE__, #expression), \
+ ANGLE_ASSERT_IMPL(expression)))
+#else
+#define ASSERT(condition) \
+ ANGLE_LAZY_STREAM(::gl::DummyStream(), ANGLE_ASSERTS_ON ? !(condition) : false) \
+ << "Check failed: " #condition ". "
+#endif // ANGLE_ASSERTS_ON
+
+#define UNUSED_VARIABLE(variable) ((void)variable)
+
+// A macro to indicate unimplemented functionality
+#ifndef NOASSERT_UNIMPLEMENTED
+#define NOASSERT_UNIMPLEMENTED 1
+#endif
+
+#define UNIMPLEMENTED() \
+ { \
+ ERR("\t! Unimplemented: %s(%d)\n", __FUNCTION__, __LINE__); \
+ ASSERT(NOASSERT_UNIMPLEMENTED); \
+ } \
+ ANGLE_EMPTY_STATEMENT
+
+// A macro for code which is not expected to be reached under valid assumptions
+#define UNREACHABLE() \
+ (ERR("\t! Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__), ASSERT(false))
+
+#endif // COMMON_DEBUG_H_
diff --git a/gfx/angle/src/common/event_tracer.cpp b/gfx/angle/src/common/event_tracer.cpp
new file mode 100755
index 000000000..c9eb5e307
--- /dev/null
+++ b/gfx/angle/src/common/event_tracer.cpp
@@ -0,0 +1,56 @@
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "common/event_tracer.h"
+
+#include "common/debug.h"
+
+namespace angle
+{
+
+const unsigned char *GetTraceCategoryEnabledFlag(const char *name)
+{
+ angle::Platform *platform = ANGLEPlatformCurrent();
+ ASSERT(platform);
+
+ const unsigned char *categoryEnabledFlag = platform->getTraceCategoryEnabledFlag(name);
+ if (categoryEnabledFlag != nullptr)
+ {
+ return categoryEnabledFlag;
+ }
+
+ static unsigned char disabled = 0;
+ return &disabled;
+}
+
+Platform::TraceEventHandle AddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id,
+ int numArgs, const char** argNames, const unsigned char* argTypes,
+ const unsigned long long* argValues, unsigned char flags)
+{
+ angle::Platform *platform = ANGLEPlatformCurrent();
+ ASSERT(platform);
+
+ double timestamp = platform->monotonicallyIncreasingTime();
+
+ if (timestamp != 0)
+ {
+ angle::Platform::TraceEventHandle handle =
+ platform->addTraceEvent(phase,
+ categoryGroupEnabled,
+ name,
+ id,
+ timestamp,
+ numArgs,
+ argNames,
+ argTypes,
+ argValues,
+ flags);
+ ASSERT(handle != 0);
+ return handle;
+ }
+
+ return static_cast<Platform::TraceEventHandle>(0);
+}
+
+} // namespace angle
diff --git a/gfx/angle/src/common/event_tracer.h b/gfx/angle/src/common/event_tracer.h
new file mode 100755
index 000000000..ed70f249d
--- /dev/null
+++ b/gfx/angle/src/common/event_tracer.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_EVENT_TRACER_H_
+#define COMMON_EVENT_TRACER_H_
+
+#include "common/platform.h"
+#include "platform/Platform.h"
+
+namespace angle
+{
+
+const unsigned char *GetTraceCategoryEnabledFlag(const char* name);
+Platform::TraceEventHandle AddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name,
+ unsigned long long id, int numArgs, const char** argNames,
+ const unsigned char* argTypes, const unsigned long long* argValues,
+ unsigned char flags);
+
+}
+
+#endif // COMMON_EVENT_TRACER_H_
diff --git a/gfx/angle/src/common/mathutil.cpp b/gfx/angle/src/common/mathutil.cpp
new file mode 100755
index 000000000..5db997c66
--- /dev/null
+++ b/gfx/angle/src/common/mathutil.cpp
@@ -0,0 +1,73 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// mathutil.cpp: Math and bit manipulation functions.
+
+#include "common/mathutil.h"
+
+#include <algorithm>
+#include <math.h>
+
+namespace gl
+{
+
+namespace
+{
+
+struct RGB9E5Data
+{
+ unsigned int R : 9;
+ unsigned int G : 9;
+ unsigned int B : 9;
+ unsigned int E : 5;
+};
+
+// B is the exponent bias (15)
+constexpr int g_sharedexp_bias = 15;
+
+// N is the number of mantissa bits per component (9)
+constexpr int g_sharedexp_mantissabits = 9;
+
+// Emax is the maximum allowed biased exponent value (31)
+constexpr int g_sharedexp_maxexponent = 31;
+
+constexpr float g_sharedexp_max =
+ ((static_cast<float>(1 << g_sharedexp_mantissabits) - 1) /
+ static_cast<float>(1 << g_sharedexp_mantissabits)) *
+ static_cast<float>(1 << (g_sharedexp_maxexponent - g_sharedexp_bias));
+
+} // anonymous namespace
+
+unsigned int convertRGBFloatsTo999E5(float red, float green, float blue)
+{
+ const float red_c = std::max<float>(0, std::min(g_sharedexp_max, red));
+ const float green_c = std::max<float>(0, std::min(g_sharedexp_max, green));
+ const float blue_c = std::max<float>(0, std::min(g_sharedexp_max, blue));
+
+ const float max_c = std::max<float>(std::max<float>(red_c, green_c), blue_c);
+ const float exp_p = std::max<float>(-g_sharedexp_bias - 1, floor(log(max_c))) + 1 + g_sharedexp_bias;
+ const int max_s = static_cast<int>(floor((max_c / (pow(2.0f, exp_p - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f));
+ const int exp_s = static_cast<int>((max_s < pow(2.0f, g_sharedexp_mantissabits)) ? exp_p : exp_p + 1);
+
+ RGB9E5Data output;
+ output.R = static_cast<unsigned int>(floor((red_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f));
+ output.G = static_cast<unsigned int>(floor((green_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f));
+ output.B = static_cast<unsigned int>(floor((blue_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f));
+ output.E = exp_s;
+
+ return bitCast<unsigned int>(output);
+}
+
+void convert999E5toRGBFloats(unsigned int input, float *red, float *green, float *blue)
+{
+ const RGB9E5Data *inputData = reinterpret_cast<const RGB9E5Data*>(&input);
+
+ *red = inputData->R * pow(2.0f, (int)inputData->E - g_sharedexp_bias - g_sharedexp_mantissabits);
+ *green = inputData->G * pow(2.0f, (int)inputData->E - g_sharedexp_bias - g_sharedexp_mantissabits);
+ *blue = inputData->B * pow(2.0f, (int)inputData->E - g_sharedexp_bias - g_sharedexp_mantissabits);
+}
+
+} // namespace gl
diff --git a/gfx/angle/src/common/mathutil.h b/gfx/angle/src/common/mathutil.h
new file mode 100755
index 000000000..630b6c088
--- /dev/null
+++ b/gfx/angle/src/common/mathutil.h
@@ -0,0 +1,852 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// mathutil.h: Math and bit manipulation functions.
+
+#ifndef COMMON_MATHUTIL_H_
+#define COMMON_MATHUTIL_H_
+
+#include <limits>
+#include <algorithm>
+#include <math.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <base/numerics/safe_math.h>
+
+#include "common/debug.h"
+#include "common/platform.h"
+
+namespace angle
+{
+using base::CheckedNumeric;
+using base::IsValueInRangeForNumericType;
+}
+
+namespace gl
+{
+
+const unsigned int Float32One = 0x3F800000;
+const unsigned short Float16One = 0x3C00;
+
+struct Vector4
+{
+ Vector4() {}
+ Vector4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
+
+ float x;
+ float y;
+ float z;
+ float w;
+};
+
+struct Vector2
+{
+ Vector2() {}
+ Vector2(float x, float y) : x(x), y(y) {}
+
+ float x;
+ float y;
+};
+
+inline bool isPow2(int x)
+{
+ return (x & (x - 1)) == 0 && (x != 0);
+}
+
+inline int log2(int x)
+{
+ int r = 0;
+ while ((x >> r) > 1) r++;
+ return r;
+}
+
+inline unsigned int ceilPow2(unsigned int x)
+{
+ if (x != 0) x--;
+ x |= x >> 1;
+ x |= x >> 2;
+ x |= x >> 4;
+ x |= x >> 8;
+ x |= x >> 16;
+ x++;
+
+ return x;
+}
+
+inline int clampToInt(unsigned int x)
+{
+ return static_cast<int>(std::min(x, static_cast<unsigned int>(std::numeric_limits<int>::max())));
+}
+
+template <typename DestT, typename SrcT>
+inline DestT clampCast(SrcT value)
+{
+ static const DestT destLo = std::numeric_limits<DestT>::min();
+ static const DestT destHi = std::numeric_limits<DestT>::max();
+ static const SrcT srcLo = static_cast<SrcT>(destLo);
+ static const SrcT srcHi = static_cast<SrcT>(destHi);
+
+ // When value is outside of or equal to the limits for DestT we use the DestT limit directly.
+ // This avoids undefined behaviors due to loss of precision when converting from floats to
+ // integers:
+ // destHi for ints is 2147483647 but the closest float number is around 2147483648, so when
+ // doing a conversion from float to int we run into an UB because the float is outside of the
+ // range representable by the int.
+ if (value <= srcLo)
+ {
+ return destLo;
+ }
+ else if (value >= srcHi)
+ {
+ return destHi;
+ }
+ else
+ {
+ return static_cast<DestT>(value);
+ }
+}
+
+template<typename T, typename MIN, typename MAX>
+inline T clamp(T x, MIN min, MAX max)
+{
+ // Since NaNs fail all comparison tests, a NaN value will default to min
+ return x > min ? (x > max ? max : x) : min;
+}
+
+inline float clamp01(float x)
+{
+ return clamp(x, 0.0f, 1.0f);
+}
+
+template<const int n>
+inline unsigned int unorm(float x)
+{
+ const unsigned int max = 0xFFFFFFFF >> (32 - n);
+
+ if (x > 1)
+ {
+ return max;
+ }
+ else if (x < 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return (unsigned int)(max * x + 0.5f);
+ }
+}
+
+inline bool supportsSSE2()
+{
+#if defined(ANGLE_USE_SSE)
+ static bool checked = false;
+ static bool supports = false;
+
+ if (checked)
+ {
+ return supports;
+ }
+
+#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(_M_ARM)
+ {
+ int info[4];
+ __cpuid(info, 0);
+
+ if (info[0] >= 1)
+ {
+ __cpuid(info, 1);
+
+ supports = (info[3] >> 26) & 1;
+ }
+ }
+#endif // defined(ANGLE_PLATFORM_WINDOWS) && !defined(_M_ARM)
+ checked = true;
+ return supports;
+#else // defined(ANGLE_USE_SSE)
+ return false;
+#endif
+}
+
+template <typename destType, typename sourceType>
+destType bitCast(const sourceType &source)
+{
+ size_t copySize = std::min(sizeof(destType), sizeof(sourceType));
+ destType output;
+ memcpy(&output, &source, copySize);
+ return output;
+}
+
+inline unsigned short float32ToFloat16(float fp32)
+{
+ unsigned int fp32i = bitCast<unsigned int>(fp32);
+ unsigned int sign = (fp32i & 0x80000000) >> 16;
+ unsigned int abs = fp32i & 0x7FFFFFFF;
+
+ if(abs > 0x47FFEFFF) // Infinity
+ {
+ return static_cast<unsigned short>(sign | 0x7FFF);
+ }
+ else if(abs < 0x38800000) // Denormal
+ {
+ unsigned int mantissa = (abs & 0x007FFFFF) | 0x00800000;
+ int e = 113 - (abs >> 23);
+
+ if(e < 24)
+ {
+ abs = mantissa >> e;
+ }
+ else
+ {
+ abs = 0;
+ }
+
+ return static_cast<unsigned short>(sign | (abs + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
+ }
+ else
+ {
+ return static_cast<unsigned short>(sign | (abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
+ }
+}
+
+float float16ToFloat32(unsigned short h);
+
+unsigned int convertRGBFloatsTo999E5(float red, float green, float blue);
+void convert999E5toRGBFloats(unsigned int input, float *red, float *green, float *blue);
+
+inline unsigned short float32ToFloat11(float fp32)
+{
+ const unsigned int float32MantissaMask = 0x7FFFFF;
+ const unsigned int float32ExponentMask = 0x7F800000;
+ const unsigned int float32SignMask = 0x80000000;
+ const unsigned int float32ValueMask = ~float32SignMask;
+ const unsigned int float32ExponentFirstBit = 23;
+ const unsigned int float32ExponentBias = 127;
+
+ const unsigned short float11Max = 0x7BF;
+ const unsigned short float11MantissaMask = 0x3F;
+ const unsigned short float11ExponentMask = 0x7C0;
+ const unsigned short float11BitMask = 0x7FF;
+ const unsigned int float11ExponentBias = 14;
+
+ const unsigned int float32Maxfloat11 = 0x477E0000;
+ const unsigned int float32Minfloat11 = 0x38800000;
+
+ const unsigned int float32Bits = bitCast<unsigned int>(fp32);
+ const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;
+
+ unsigned int float32Val = float32Bits & float32ValueMask;
+
+ if ((float32Val & float32ExponentMask) == float32ExponentMask)
+ {
+ // INF or NAN
+ if ((float32Val & float32MantissaMask) != 0)
+ {
+ return float11ExponentMask | (((float32Val >> 17) | (float32Val >> 11) | (float32Val >> 6) | (float32Val)) & float11MantissaMask);
+ }
+ else if (float32Sign)
+ {
+ // -INF is clamped to 0 since float11 is positive only
+ return 0;
+ }
+ else
+ {
+ return float11ExponentMask;
+ }
+ }
+ else if (float32Sign)
+ {
+ // float11 is positive only, so clamp to zero
+ return 0;
+ }
+ else if (float32Val > float32Maxfloat11)
+ {
+ // The number is too large to be represented as a float11, set to max
+ return float11Max;
+ }
+ else
+ {
+ if (float32Val < float32Minfloat11)
+ {
+ // The number is too small to be represented as a normalized float11
+ // Convert it to a denormalized value.
+ const unsigned int shift = (float32ExponentBias - float11ExponentBias) - (float32Val >> float32ExponentFirstBit);
+ float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
+ }
+ else
+ {
+ // Rebias the exponent to represent the value as a normalized float11
+ float32Val += 0xC8000000;
+ }
+
+ return ((float32Val + 0xFFFF + ((float32Val >> 17) & 1)) >> 17) & float11BitMask;
+ }
+}
+
+inline unsigned short float32ToFloat10(float fp32)
+{
+ const unsigned int float32MantissaMask = 0x7FFFFF;
+ const unsigned int float32ExponentMask = 0x7F800000;
+ const unsigned int float32SignMask = 0x80000000;
+ const unsigned int float32ValueMask = ~float32SignMask;
+ const unsigned int float32ExponentFirstBit = 23;
+ const unsigned int float32ExponentBias = 127;
+
+ const unsigned short float10Max = 0x3DF;
+ const unsigned short float10MantissaMask = 0x1F;
+ const unsigned short float10ExponentMask = 0x3E0;
+ const unsigned short float10BitMask = 0x3FF;
+ const unsigned int float10ExponentBias = 14;
+
+ const unsigned int float32Maxfloat10 = 0x477C0000;
+ const unsigned int float32Minfloat10 = 0x38800000;
+
+ const unsigned int float32Bits = bitCast<unsigned int>(fp32);
+ const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;
+
+ unsigned int float32Val = float32Bits & float32ValueMask;
+
+ if ((float32Val & float32ExponentMask) == float32ExponentMask)
+ {
+ // INF or NAN
+ if ((float32Val & float32MantissaMask) != 0)
+ {
+ return float10ExponentMask | (((float32Val >> 18) | (float32Val >> 13) | (float32Val >> 3) | (float32Val)) & float10MantissaMask);
+ }
+ else if (float32Sign)
+ {
+ // -INF is clamped to 0 since float11 is positive only
+ return 0;
+ }
+ else
+ {
+ return float10ExponentMask;
+ }
+ }
+ else if (float32Sign)
+ {
+ // float10 is positive only, so clamp to zero
+ return 0;
+ }
+ else if (float32Val > float32Maxfloat10)
+ {
+ // The number is too large to be represented as a float11, set to max
+ return float10Max;
+ }
+ else
+ {
+ if (float32Val < float32Minfloat10)
+ {
+ // The number is too small to be represented as a normalized float11
+ // Convert it to a denormalized value.
+ const unsigned int shift = (float32ExponentBias - float10ExponentBias) - (float32Val >> float32ExponentFirstBit);
+ float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
+ }
+ else
+ {
+ // Rebias the exponent to represent the value as a normalized float11
+ float32Val += 0xC8000000;
+ }
+
+ return ((float32Val + 0x1FFFF + ((float32Val >> 18) & 1)) >> 18) & float10BitMask;
+ }
+}
+
+inline float float11ToFloat32(unsigned short fp11)
+{
+ unsigned short exponent = (fp11 >> 6) & 0x1F;
+ unsigned short mantissa = fp11 & 0x3F;
+
+ if (exponent == 0x1F)
+ {
+ // INF or NAN
+ return bitCast<float>(0x7f800000 | (mantissa << 17));
+ }
+ else
+ {
+ if (exponent != 0)
+ {
+ // normalized
+ }
+ else if (mantissa != 0)
+ {
+ // The value is denormalized
+ exponent = 1;
+
+ do
+ {
+ exponent--;
+ mantissa <<= 1;
+ }
+ while ((mantissa & 0x40) == 0);
+
+ mantissa = mantissa & 0x3F;
+ }
+ else // The value is zero
+ {
+ exponent = static_cast<unsigned short>(-112);
+ }
+
+ return bitCast<float>(((exponent + 112) << 23) | (mantissa << 17));
+ }
+}
+
+inline float float10ToFloat32(unsigned short fp11)
+{
+ unsigned short exponent = (fp11 >> 5) & 0x1F;
+ unsigned short mantissa = fp11 & 0x1F;
+
+ if (exponent == 0x1F)
+ {
+ // INF or NAN
+ return bitCast<float>(0x7f800000 | (mantissa << 17));
+ }
+ else
+ {
+ if (exponent != 0)
+ {
+ // normalized
+ }
+ else if (mantissa != 0)
+ {
+ // The value is denormalized
+ exponent = 1;
+
+ do
+ {
+ exponent--;
+ mantissa <<= 1;
+ }
+ while ((mantissa & 0x20) == 0);
+
+ mantissa = mantissa & 0x1F;
+ }
+ else // The value is zero
+ {
+ exponent = static_cast<unsigned short>(-112);
+ }
+
+ return bitCast<float>(((exponent + 112) << 23) | (mantissa << 18));
+ }
+}
+
+template <typename T>
+inline float normalizedToFloat(T input)
+{
+ static_assert(std::numeric_limits<T>::is_integer, "T must be an integer.");
+
+ const float inverseMax = 1.0f / std::numeric_limits<T>::max();
+ return input * inverseMax;
+}
+
+template <unsigned int inputBitCount, typename T>
+inline float normalizedToFloat(T input)
+{
+ static_assert(std::numeric_limits<T>::is_integer, "T must be an integer.");
+ static_assert(inputBitCount < (sizeof(T) * 8), "T must have more bits than inputBitCount.");
+
+ const float inverseMax = 1.0f / ((1 << inputBitCount) - 1);
+ return input * inverseMax;
+}
+
+template <typename T>
+inline T floatToNormalized(float input)
+{
+ return static_cast<T>(std::numeric_limits<T>::max() * input + 0.5f);
+}
+
+template <unsigned int outputBitCount, typename T>
+inline T floatToNormalized(float input)
+{
+ static_assert(outputBitCount < (sizeof(T) * 8), "T must have more bits than outputBitCount.");
+ return static_cast<T>(((1 << outputBitCount) - 1) * input + 0.5f);
+}
+
+template <unsigned int inputBitCount, unsigned int inputBitStart, typename T>
+inline T getShiftedData(T input)
+{
+ static_assert(inputBitCount + inputBitStart <= (sizeof(T) * 8),
+ "T must have at least as many bits as inputBitCount + inputBitStart.");
+ const T mask = (1 << inputBitCount) - 1;
+ return (input >> inputBitStart) & mask;
+}
+
+template <unsigned int inputBitCount, unsigned int inputBitStart, typename T>
+inline T shiftData(T input)
+{
+ static_assert(inputBitCount + inputBitStart <= (sizeof(T) * 8),
+ "T must have at least as many bits as inputBitCount + inputBitStart.");
+ const T mask = (1 << inputBitCount) - 1;
+ return (input & mask) << inputBitStart;
+}
+
+inline unsigned int CountLeadingZeros(uint32_t x)
+{
+ // Use binary search to find the amount of leading zeros.
+ unsigned int zeros = 32u;
+ uint32_t y;
+
+ y = x >> 16u;
+ if (y != 0)
+ {
+ zeros = zeros - 16u;
+ x = y;
+ }
+ y = x >> 8u;
+ if (y != 0)
+ {
+ zeros = zeros - 8u;
+ x = y;
+ }
+ y = x >> 4u;
+ if (y != 0)
+ {
+ zeros = zeros - 4u;
+ x = y;
+ }
+ y = x >> 2u;
+ if (y != 0)
+ {
+ zeros = zeros - 2u;
+ x = y;
+ }
+ y = x >> 1u;
+ if (y != 0)
+ {
+ return zeros - 2u;
+ }
+ return zeros - x;
+}
+
+inline unsigned char average(unsigned char a, unsigned char b)
+{
+ return ((a ^ b) >> 1) + (a & b);
+}
+
+inline signed char average(signed char a, signed char b)
+{
+ return ((short)a + (short)b) / 2;
+}
+
+inline unsigned short average(unsigned short a, unsigned short b)
+{
+ return ((a ^ b) >> 1) + (a & b);
+}
+
+inline signed short average(signed short a, signed short b)
+{
+ return ((int)a + (int)b) / 2;
+}
+
+inline unsigned int average(unsigned int a, unsigned int b)
+{
+ return ((a ^ b) >> 1) + (a & b);
+}
+
+inline int average(int a, int b)
+{
+ long long average = (static_cast<long long>(a) + static_cast<long long>(b)) / 2ll;
+ return static_cast<int>(average);
+}
+
+inline float average(float a, float b)
+{
+ return (a + b) * 0.5f;
+}
+
+inline unsigned short averageHalfFloat(unsigned short a, unsigned short b)
+{
+ return float32ToFloat16((float16ToFloat32(a) + float16ToFloat32(b)) * 0.5f);
+}
+
+inline unsigned int averageFloat11(unsigned int a, unsigned int b)
+{
+ return float32ToFloat11((float11ToFloat32(static_cast<unsigned short>(a)) + float11ToFloat32(static_cast<unsigned short>(b))) * 0.5f);
+}
+
+inline unsigned int averageFloat10(unsigned int a, unsigned int b)
+{
+ return float32ToFloat10((float10ToFloat32(static_cast<unsigned short>(a)) + float10ToFloat32(static_cast<unsigned short>(b))) * 0.5f);
+}
+
+template <typename T>
+struct Range
+{
+ Range() {}
+ Range(T lo, T hi) : start(lo), end(hi) { ASSERT(lo <= hi); }
+
+ T start;
+ T end;
+
+ T length() const { return end - start; }
+
+ bool intersects(Range<T> other)
+ {
+ if (start <= other.start)
+ {
+ return other.start < end;
+ }
+ else
+ {
+ return start < other.end;
+ }
+ }
+
+ void extend(T value)
+ {
+ start = value > start ? value : start;
+ end = value < end ? value : end;
+ }
+
+ bool empty() const
+ {
+ return end <= start;
+ }
+};
+
+typedef Range<int> RangeI;
+typedef Range<unsigned int> RangeUI;
+
+struct IndexRange
+{
+ IndexRange() : IndexRange(0, 0, 0) {}
+ IndexRange(size_t start_, size_t end_, size_t vertexIndexCount_)
+ : start(start_), end(end_), vertexIndexCount(vertexIndexCount_)
+ {
+ ASSERT(start <= end);
+ }
+
+ // Number of vertices in the range.
+ size_t vertexCount() const { return (end - start) + 1; }
+
+ // Inclusive range of indices that are not primitive restart
+ size_t start;
+ size_t end;
+
+ // Number of non-primitive restart indices
+ size_t vertexIndexCount;
+};
+
+// First, both normalized floating-point values are converted into 16-bit integer values.
+// Then, the results are packed into the returned 32-bit unsigned integer.
+// The first float value will be written to the least significant bits of the output;
+// the last float value will be written to the most significant bits.
+// The conversion of each value to fixed point is done as follows :
+// packSnorm2x16 : round(clamp(c, -1, +1) * 32767.0)
+inline uint32_t packSnorm2x16(float f1, float f2)
+{
+ int16_t leastSignificantBits = static_cast<int16_t>(roundf(clamp(f1, -1.0f, 1.0f) * 32767.0f));
+ int16_t mostSignificantBits = static_cast<int16_t>(roundf(clamp(f2, -1.0f, 1.0f) * 32767.0f));
+ return static_cast<uint32_t>(mostSignificantBits) << 16 |
+ (static_cast<uint32_t>(leastSignificantBits) & 0xFFFF);
+}
+
+// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then, each
+// component is converted to a normalized floating-point value to generate the returned two float values.
+// The first float value will be extracted from the least significant bits of the input;
+// the last float value will be extracted from the most-significant bits.
+// The conversion for unpacked fixed-point value to floating point is done as follows:
+// unpackSnorm2x16 : clamp(f / 32767.0, -1, +1)
+inline void unpackSnorm2x16(uint32_t u, float *f1, float *f2)
+{
+ int16_t leastSignificantBits = static_cast<int16_t>(u & 0xFFFF);
+ int16_t mostSignificantBits = static_cast<int16_t>(u >> 16);
+ *f1 = clamp(static_cast<float>(leastSignificantBits) / 32767.0f, -1.0f, 1.0f);
+ *f2 = clamp(static_cast<float>(mostSignificantBits) / 32767.0f, -1.0f, 1.0f);
+}
+
+// First, both normalized floating-point values are converted into 16-bit integer values.
+// Then, the results are packed into the returned 32-bit unsigned integer.
+// The first float value will be written to the least significant bits of the output;
+// the last float value will be written to the most significant bits.
+// The conversion of each value to fixed point is done as follows:
+// packUnorm2x16 : round(clamp(c, 0, +1) * 65535.0)
+inline uint32_t packUnorm2x16(float f1, float f2)
+{
+ uint16_t leastSignificantBits = static_cast<uint16_t>(roundf(clamp(f1, 0.0f, 1.0f) * 65535.0f));
+ uint16_t mostSignificantBits = static_cast<uint16_t>(roundf(clamp(f2, 0.0f, 1.0f) * 65535.0f));
+ return static_cast<uint32_t>(mostSignificantBits) << 16 | static_cast<uint32_t>(leastSignificantBits);
+}
+
+// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then, each
+// component is converted to a normalized floating-point value to generate the returned two float values.
+// The first float value will be extracted from the least significant bits of the input;
+// the last float value will be extracted from the most-significant bits.
+// The conversion for unpacked fixed-point value to floating point is done as follows:
+// unpackUnorm2x16 : f / 65535.0
+inline void unpackUnorm2x16(uint32_t u, float *f1, float *f2)
+{
+ uint16_t leastSignificantBits = static_cast<uint16_t>(u & 0xFFFF);
+ uint16_t mostSignificantBits = static_cast<uint16_t>(u >> 16);
+ *f1 = static_cast<float>(leastSignificantBits) / 65535.0f;
+ *f2 = static_cast<float>(mostSignificantBits) / 65535.0f;
+}
+
+// Returns an unsigned integer obtained by converting the two floating-point values to the 16-bit
+// floating-point representation found in the OpenGL ES Specification, and then packing these
+// two 16-bit integers into a 32-bit unsigned integer.
+// f1: The 16 least-significant bits of the result;
+// f2: The 16 most-significant bits.
+inline uint32_t packHalf2x16(float f1, float f2)
+{
+ uint16_t leastSignificantBits = static_cast<uint16_t>(float32ToFloat16(f1));
+ uint16_t mostSignificantBits = static_cast<uint16_t>(float32ToFloat16(f2));
+ return static_cast<uint32_t>(mostSignificantBits) << 16 | static_cast<uint32_t>(leastSignificantBits);
+}
+
+// Returns two floating-point values obtained by unpacking a 32-bit unsigned integer into a pair of 16-bit values,
+// interpreting those values as 16-bit floating-point numbers according to the OpenGL ES Specification,
+// and converting them to 32-bit floating-point values.
+// The first float value is obtained from the 16 least-significant bits of u;
+// the second component is obtained from the 16 most-significant bits of u.
+inline void unpackHalf2x16(uint32_t u, float *f1, float *f2)
+{
+ uint16_t leastSignificantBits = static_cast<uint16_t>(u & 0xFFFF);
+ uint16_t mostSignificantBits = static_cast<uint16_t>(u >> 16);
+
+ *f1 = float16ToFloat32(leastSignificantBits);
+ *f2 = float16ToFloat32(mostSignificantBits);
+}
+
+// Returns whether the argument is Not a Number.
+// IEEE 754 single precision NaN representation: Exponent(8 bits) - 255, Mantissa(23 bits) - non-zero.
+inline bool isNaN(float f)
+{
+ // Exponent mask: ((1u << 8) - 1u) << 23 = 0x7f800000u
+ // Mantissa mask: ((1u << 23) - 1u) = 0x7fffffu
+ return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) && (bitCast<uint32_t>(f) & 0x7fffffu);
+}
+
+// Returns whether the argument is infinity.
+// IEEE 754 single precision infinity representation: Exponent(8 bits) - 255, Mantissa(23 bits) - zero.
+inline bool isInf(float f)
+{
+ // Exponent mask: ((1u << 8) - 1u) << 23 = 0x7f800000u
+ // Mantissa mask: ((1u << 23) - 1u) = 0x7fffffu
+ return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) && !(bitCast<uint32_t>(f) & 0x7fffffu);
+}
+
+namespace priv
+{
+template <unsigned int N, unsigned int R>
+struct iSquareRoot
+{
+ static constexpr unsigned int solve()
+ {
+ return (R * R > N)
+ ? 0
+ : ((R * R == N) ? R : static_cast<unsigned int>(iSquareRoot<N, R + 1>::value));
+ }
+ enum Result
+ {
+ value = iSquareRoot::solve()
+ };
+};
+
+template <unsigned int N>
+struct iSquareRoot<N, N>
+{
+ enum result
+ {
+ value = N
+ };
+};
+
+} // namespace priv
+
+template <unsigned int N>
+constexpr unsigned int iSquareRoot()
+{
+ return priv::iSquareRoot<N, 1>::value;
+}
+
+// Sum, difference and multiplication operations for signed ints that wrap on 32-bit overflow.
+//
+// Unsigned types are defined to do arithmetic modulo 2^n in C++. For signed types, overflow
+// behavior is undefined.
+
+template <typename T>
+inline T WrappingSum(T lhs, T rhs)
+{
+ uint32_t lhsUnsigned = static_cast<uint32_t>(lhs);
+ uint32_t rhsUnsigned = static_cast<uint32_t>(rhs);
+ return static_cast<T>(lhsUnsigned + rhsUnsigned);
+}
+
+template <typename T>
+inline T WrappingDiff(T lhs, T rhs)
+{
+ uint32_t lhsUnsigned = static_cast<uint32_t>(lhs);
+ uint32_t rhsUnsigned = static_cast<uint32_t>(rhs);
+ return static_cast<T>(lhsUnsigned - rhsUnsigned);
+}
+
+inline int32_t WrappingMul(int32_t lhs, int32_t rhs)
+{
+ int64_t lhsWide = static_cast<int64_t>(lhs);
+ int64_t rhsWide = static_cast<int64_t>(rhs);
+ // The multiplication is guaranteed not to overflow.
+ int64_t resultWide = lhsWide * rhsWide;
+ // Implement the desired wrapping behavior by masking out the high-order 32 bits.
+ resultWide = resultWide & 0xffffffffll;
+ // Casting to a narrower signed type is fine since the casted value is representable in the
+ // narrower type.
+ return static_cast<int32_t>(resultWide);
+}
+
+} // namespace gl
+
+namespace rx
+{
+
+template <typename T>
+T roundUp(const T value, const T alignment)
+{
+ auto temp = value + alignment - static_cast<T>(1);
+ return temp - temp % alignment;
+}
+
+template <typename T>
+angle::CheckedNumeric<T> CheckedRoundUp(const T value, const T alignment)
+{
+ angle::CheckedNumeric<T> checkedValue(value);
+ angle::CheckedNumeric<T> checkedAlignment(alignment);
+ return roundUp(checkedValue, checkedAlignment);
+}
+
+inline unsigned int UnsignedCeilDivide(unsigned int value, unsigned int divisor)
+{
+ unsigned int divided = value / divisor;
+ return (divided + ((value % divisor == 0) ? 0 : 1));
+}
+
+#if defined(_MSC_VER)
+
+#define ANGLE_ROTL(x,y) _rotl(x,y)
+#define ANGLE_ROTR16(x,y) _rotr16(x,y)
+
+#else
+
+inline uint32_t RotL(uint32_t x, int8_t r)
+{
+ return (x << r) | (x >> (32 - r));
+}
+
+inline uint16_t RotR16(uint16_t x, int8_t r)
+{
+ return (x >> r) | (x << (16 - r));
+}
+
+#define ANGLE_ROTL(x, y) ::rx::RotL(x, y)
+#define ANGLE_ROTR16(x, y) ::rx::RotR16(x, y)
+
+#endif // namespace rx
+
+}
+
+#endif // COMMON_MATHUTIL_H_
diff --git a/gfx/angle/src/common/mathutil_unittest.cpp b/gfx/angle/src/common/mathutil_unittest.cpp
new file mode 100755
index 000000000..bf443b72b
--- /dev/null
+++ b/gfx/angle/src/common/mathutil_unittest.cpp
@@ -0,0 +1,210 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// mathutil_unittest:
+// Unit tests for the utils defined in mathutil.h
+//
+
+#include "mathutil.h"
+
+#include <gtest/gtest.h>
+
+using namespace gl;
+
+namespace
+{
+
+// Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions.
+// For floats f1 and f2, unpackSnorm2x16(packSnorm2x16(f1, f2)) should be same as f1 and f2.
+TEST(MathUtilTest, packAndUnpackSnorm2x16)
+{
+ const float input[8][2] =
+ {
+ { 0.0f, 0.0f },
+ { 1.0f, 1.0f },
+ { -1.0f, 1.0f },
+ { -1.0f, -1.0f },
+ { 0.875f, 0.75f },
+ { 0.00392f, -0.99215f },
+ { -0.000675f, 0.004954f },
+ { -0.6937f, -0.02146f }
+ };
+ const float floatFaultTolerance = 0.0001f;
+ float outputVal1, outputVal2;
+
+ for (size_t i = 0; i < 8; i++)
+ {
+ unpackSnorm2x16(packSnorm2x16(input[i][0], input[i][1]), &outputVal1, &outputVal2);
+ EXPECT_NEAR(input[i][0], outputVal1, floatFaultTolerance);
+ EXPECT_NEAR(input[i][1], outputVal2, floatFaultTolerance);
+ }
+}
+
+// Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions with infinity values,
+// result should be clamped to [-1, 1].
+TEST(MathUtilTest, packAndUnpackSnorm2x16Infinity)
+{
+ const float floatFaultTolerance = 0.0001f;
+ float outputVal1, outputVal2;
+
+ unpackSnorm2x16(packSnorm2x16(std::numeric_limits<float>::infinity(),
+ std::numeric_limits<float>::infinity()), &outputVal1, &outputVal2);
+ EXPECT_NEAR(1.0f, outputVal1, floatFaultTolerance);
+ EXPECT_NEAR(1.0f, outputVal2, floatFaultTolerance);
+
+ unpackSnorm2x16(packSnorm2x16(std::numeric_limits<float>::infinity(),
+ -std::numeric_limits<float>::infinity()), &outputVal1, &outputVal2);
+ EXPECT_NEAR(1.0f, outputVal1, floatFaultTolerance);
+ EXPECT_NEAR(-1.0f, outputVal2, floatFaultTolerance);
+
+ unpackSnorm2x16(packSnorm2x16(-std::numeric_limits<float>::infinity(),
+ -std::numeric_limits<float>::infinity()), &outputVal1, &outputVal2);
+ EXPECT_NEAR(-1.0f, outputVal1, floatFaultTolerance);
+ EXPECT_NEAR(-1.0f, outputVal2, floatFaultTolerance);
+}
+
+// Test the correctness of packUnorm2x16 and unpackUnorm2x16 functions.
+// For floats f1 and f2, unpackUnorm2x16(packUnorm2x16(f1, f2)) should be same as f1 and f2.
+TEST(MathUtilTest, packAndUnpackUnorm2x16)
+{
+ const float input[8][2] =
+ {
+ { 0.0f, 0.0f },
+ { 1.0f, 1.0f },
+ { -1.0f, 1.0f },
+ { -1.0f, -1.0f },
+ { 0.875f, 0.75f },
+ { 0.00392f, -0.99215f },
+ { -0.000675f, 0.004954f },
+ { -0.6937f, -0.02146f }
+ };
+ const float floatFaultTolerance = 0.0001f;
+ float outputVal1, outputVal2;
+
+ for (size_t i = 0; i < 8; i++)
+ {
+ unpackUnorm2x16(packUnorm2x16(input[i][0], input[i][1]), &outputVal1, &outputVal2);
+ float expected = input[i][0] < 0.0f ? 0.0f : input[i][0];
+ EXPECT_NEAR(expected, outputVal1, floatFaultTolerance);
+ expected = input[i][1] < 0.0f ? 0.0f : input[i][1];
+ EXPECT_NEAR(expected, outputVal2, floatFaultTolerance);
+ }
+}
+
+// Test the correctness of packUnorm2x16 and unpackUnorm2x16 functions with infinity values,
+// result should be clamped to [0, 1].
+TEST(MathUtilTest, packAndUnpackUnorm2x16Infinity)
+{
+ const float floatFaultTolerance = 0.0001f;
+ float outputVal1, outputVal2;
+
+ unpackUnorm2x16(packUnorm2x16(std::numeric_limits<float>::infinity(),
+ std::numeric_limits<float>::infinity()), &outputVal1, &outputVal2);
+ EXPECT_NEAR(1.0f, outputVal1, floatFaultTolerance);
+ EXPECT_NEAR(1.0f, outputVal2, floatFaultTolerance);
+
+ unpackUnorm2x16(packUnorm2x16(std::numeric_limits<float>::infinity(),
+ -std::numeric_limits<float>::infinity()), &outputVal1, &outputVal2);
+ EXPECT_NEAR(1.0f, outputVal1, floatFaultTolerance);
+ EXPECT_NEAR(0.0f, outputVal2, floatFaultTolerance);
+
+ unpackUnorm2x16(packUnorm2x16(-std::numeric_limits<float>::infinity(),
+ -std::numeric_limits<float>::infinity()), &outputVal1, &outputVal2);
+ EXPECT_NEAR(0.0f, outputVal1, floatFaultTolerance);
+ EXPECT_NEAR(0.0f, outputVal2, floatFaultTolerance);
+}
+
+// Test the correctness of packHalf2x16 and unpackHalf2x16 functions.
+// For floats f1 and f2, unpackHalf2x16(packHalf2x16(f1, f2)) should be same as f1 and f2.
+TEST(MathUtilTest, packAndUnpackHalf2x16)
+{
+ const float input[8][2] =
+ {
+ { 0.0f, 0.0f },
+ { 1.0f, 1.0f },
+ { -1.0f, 1.0f },
+ { -1.0f, -1.0f },
+ { 0.875f, 0.75f },
+ { 0.00392f, -0.99215f },
+ { -0.000675f, 0.004954f },
+ { -0.6937f, -0.02146f },
+ };
+ const float floatFaultTolerance = 0.0005f;
+ float outputVal1, outputVal2;
+
+ for (size_t i = 0; i < 8; i++)
+ {
+ unpackHalf2x16(packHalf2x16(input[i][0], input[i][1]), &outputVal1, &outputVal2);
+ EXPECT_NEAR(input[i][0], outputVal1, floatFaultTolerance);
+ EXPECT_NEAR(input[i][1], outputVal2, floatFaultTolerance);
+ }
+}
+
+// Test the correctness of gl::isNaN function.
+TEST(MathUtilTest, isNaN)
+{
+ EXPECT_TRUE(isNaN(bitCast<float>(0xffu << 23 | 1u)));
+ EXPECT_TRUE(isNaN(bitCast<float>(1u << 31 | 0xffu << 23 | 1u)));
+ EXPECT_TRUE(isNaN(bitCast<float>(1u << 31 | 0xffu << 23 | 0x400000u)));
+ EXPECT_TRUE(isNaN(bitCast<float>(1u << 31 | 0xffu << 23 | 0x7fffffu)));
+ EXPECT_FALSE(isNaN(0.0f));
+ EXPECT_FALSE(isNaN(bitCast<float>(1u << 31 | 0xffu << 23)));
+ EXPECT_FALSE(isNaN(bitCast<float>(0xffu << 23)));
+}
+
+// Test the correctness of gl::isInf function.
+TEST(MathUtilTest, isInf)
+{
+ EXPECT_TRUE(isInf(bitCast<float>(0xffu << 23)));
+ EXPECT_TRUE(isInf(bitCast<float>(1u << 31 | 0xffu << 23)));
+ EXPECT_FALSE(isInf(0.0f));
+ EXPECT_FALSE(isInf(bitCast<float>(0xffu << 23 | 1u)));
+ EXPECT_FALSE(isInf(bitCast<float>(1u << 31 | 0xffu << 23 | 1u)));
+ EXPECT_FALSE(isInf(bitCast<float>(1u << 31 | 0xffu << 23 | 0x400000u)));
+ EXPECT_FALSE(isInf(bitCast<float>(1u << 31 | 0xffu << 23 | 0x7fffffu)));
+ EXPECT_FALSE(isInf(bitCast<float>(0xfeu << 23 | 0x7fffffu)));
+ EXPECT_FALSE(isInf(bitCast<float>(1u << 31 | 0xfeu << 23 | 0x7fffffu)));
+}
+
+TEST(MathUtilTest, CountLeadingZeros)
+{
+ for (unsigned int i = 0; i < 32u; ++i)
+ {
+ uint32_t iLeadingZeros = 1u << (31u - i);
+ EXPECT_EQ(i, CountLeadingZeros(iLeadingZeros));
+ }
+ EXPECT_EQ(32u, CountLeadingZeros(0));
+}
+
+// Some basic tests. Tests that rounding up zero produces zero.
+TEST(MathUtilTest, BasicRoundUp)
+{
+ EXPECT_EQ(0u, rx::roundUp(0u, 4u));
+ EXPECT_EQ(4u, rx::roundUp(1u, 4u));
+ EXPECT_EQ(4u, rx::roundUp(4u, 4u));
+}
+
+// Test that rounding up zero produces zero for checked ints.
+TEST(MathUtilTest, CheckedRoundUpZero)
+{
+ auto checkedValue = rx::CheckedRoundUp(0u, 4u);
+ ASSERT_TRUE(checkedValue.IsValid());
+ ASSERT_EQ(0u, checkedValue.ValueOrDie());
+}
+
+// Test out-of-bounds with CheckedRoundUp
+TEST(MathUtilTest, CheckedRoundUpInvalid)
+{
+ // The answer to this query is out of bounds.
+ auto limit = std::numeric_limits<unsigned int>::max();
+ auto checkedValue = rx::CheckedRoundUp(limit, limit - 1);
+ ASSERT_FALSE(checkedValue.IsValid());
+
+ // Our implementation can't handle this query, despite the parameters being in range.
+ auto checkedLimit = rx::CheckedRoundUp(limit - 1, limit);
+ ASSERT_FALSE(checkedLimit.IsValid());
+}
+
+} // anonymous namespace
diff --git a/gfx/angle/src/common/matrix_utils.h b/gfx/angle/src/common/matrix_utils.h
new file mode 100755
index 000000000..aa3f89536
--- /dev/null
+++ b/gfx/angle/src/common/matrix_utils.h
@@ -0,0 +1,386 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Matrix:
+// Utility class implementing various matrix operations.
+// Supports matrices with minimum 2 and maximum 4 number of rows/columns.
+//
+// TODO: Check if we can merge Matrix.h in sample_util with this and replace it with this implementation.
+// TODO: Rename this file to Matrix.h once we remove Matrix.h in sample_util.
+
+#ifndef COMMON_MATRIX_UTILS_H_
+#define COMMON_MATRIX_UTILS_H_
+
+#include <vector>
+
+#include "common/debug.h"
+#include "common/mathutil.h"
+
+namespace angle
+{
+
+template<typename T>
+class Matrix
+{
+ public:
+ Matrix(const std::vector<T> &elements, const unsigned int &numRows, const unsigned int &numCols)
+ : mElements(elements),
+ mRows(numRows),
+ mCols(numCols)
+ {
+ ASSERT(rows() >= 1 && rows() <= 4);
+ ASSERT(columns() >= 1 && columns() <= 4);
+ }
+
+ Matrix(const std::vector<T> &elements, const unsigned int &size)
+ : mElements(elements),
+ mRows(size),
+ mCols(size)
+ {
+ ASSERT(rows() >= 1 && rows() <= 4);
+ ASSERT(columns() >= 1 && columns() <= 4);
+ }
+
+ Matrix(const T *elements, const unsigned int &size)
+ : mRows(size),
+ mCols(size)
+ {
+ ASSERT(rows() >= 1 && rows() <= 4);
+ ASSERT(columns() >= 1 && columns() <= 4);
+ for (size_t i = 0; i < size * size; i++)
+ mElements.push_back(elements[i]);
+ }
+
+ const T &operator()(const unsigned int &rowIndex, const unsigned int &columnIndex) const
+ {
+ return mElements[rowIndex * columns() + columnIndex];
+ }
+
+ T &operator()(const unsigned int &rowIndex, const unsigned int &columnIndex)
+ {
+ return mElements[rowIndex * columns() + columnIndex];
+ }
+
+ const T &at(const unsigned int &rowIndex, const unsigned int &columnIndex) const
+ {
+ return operator()(rowIndex, columnIndex);
+ }
+
+ Matrix<T> operator*(const Matrix<T> &m)
+ {
+ ASSERT(columns() == m.rows());
+
+ unsigned int resultRows = rows();
+ unsigned int resultCols = m.columns();
+ Matrix<T> result(std::vector<T>(resultRows * resultCols), resultRows, resultCols);
+ for (unsigned int i = 0; i < resultRows; i++)
+ {
+ for (unsigned int j = 0; j < resultCols; j++)
+ {
+ T tmp = 0.0f;
+ for (unsigned int k = 0; k < columns(); k++)
+ tmp += at(i, k) * m(k, j);
+ result(i, j) = tmp;
+ }
+ }
+
+ return result;
+ }
+
+ unsigned int size() const
+ {
+ ASSERT(rows() == columns());
+ return rows();
+ }
+
+ unsigned int rows() const { return mRows; }
+
+ unsigned int columns() const { return mCols; }
+
+ std::vector<T> elements() const { return mElements; }
+
+ Matrix<T> compMult(const Matrix<T> &mat1) const
+ {
+ Matrix result(std::vector<T>(mElements.size()), size());
+ for (unsigned int i = 0; i < columns(); i++)
+ for (unsigned int j = 0; j < rows(); j++)
+ result(i, j) = at(i, j) * mat1(i, j);
+
+ return result;
+ }
+
+ Matrix<T> outerProduct(const Matrix<T> &mat1) const
+ {
+ unsigned int cols = mat1.columns();
+ Matrix result(std::vector<T>(rows() * cols), rows(), cols);
+ for (unsigned int i = 0; i < rows(); i++)
+ for (unsigned int j = 0; j < cols; j++)
+ result(i, j) = at(i, 0) * mat1(0, j);
+
+ return result;
+ }
+
+ Matrix<T> transpose() const
+ {
+ Matrix result(std::vector<T>(mElements.size()), columns(), rows());
+ for (unsigned int i = 0; i < columns(); i++)
+ for (unsigned int j = 0; j < rows(); j++)
+ result(i, j) = at(j, i);
+
+ return result;
+ }
+
+ T determinant() const
+ {
+ ASSERT(rows() == columns());
+
+ switch (size())
+ {
+ case 2:
+ return at(0, 0) * at(1, 1) - at(0, 1) * at(1, 0);
+
+ case 3:
+ return at(0, 0) * at(1, 1) * at(2, 2) +
+ at(0, 1) * at(1, 2) * at(2, 0) +
+ at(0, 2) * at(1, 0) * at(2, 1) -
+ at(0, 2) * at(1, 1) * at(2, 0) -
+ at(0, 1) * at(1, 0) * at(2, 2) -
+ at(0, 0) * at(1, 2) * at(2, 1);
+
+ case 4:
+ {
+ const float minorMatrices[4][3 * 3] =
+ {
+ {
+ at(1, 1), at(2, 1), at(3, 1),
+ at(1, 2), at(2, 2), at(3, 2),
+ at(1, 3), at(2, 3), at(3, 3),
+ },
+ {
+ at(1, 0), at(2, 0), at(3, 0),
+ at(1, 2), at(2, 2), at(3, 2),
+ at(1, 3), at(2, 3), at(3, 3),
+ },
+ {
+ at(1, 0), at(2, 0), at(3, 0),
+ at(1, 1), at(2, 1), at(3, 1),
+ at(1, 3), at(2, 3), at(3, 3),
+ },
+ {
+ at(1, 0), at(2, 0), at(3, 0),
+ at(1, 1), at(2, 1), at(3, 1),
+ at(1, 2), at(2, 2), at(3, 2),
+ }
+ };
+ return at(0, 0) * Matrix<T>(minorMatrices[0], 3).determinant() -
+ at(0, 1) * Matrix<T>(minorMatrices[1], 3).determinant() +
+ at(0, 2) * Matrix<T>(minorMatrices[2], 3).determinant() -
+ at(0, 3) * Matrix<T>(minorMatrices[3], 3).determinant();
+ }
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ return T();
+ }
+
+ Matrix<T> inverse() const
+ {
+ ASSERT(rows() == columns());
+
+ Matrix<T> cof(std::vector<T>(mElements.size()), rows(), columns());
+ switch (size())
+ {
+ case 2:
+ cof(0, 0) = at(1, 1);
+ cof(0, 1) = -at(1, 0);
+ cof(1, 0) = -at(0, 1);
+ cof(1, 1) = at(0, 0);
+ break;
+
+ case 3:
+ cof(0, 0) = at(1, 1) * at(2, 2) -
+ at(2, 1) * at(1, 2);
+ cof(0, 1) = -(at(1, 0) * at(2, 2) -
+ at(2, 0) * at(1, 2));
+ cof(0, 2) = at(1, 0) * at(2, 1) -
+ at(2, 0) * at(1, 1);
+ cof(1, 0) = -(at(0, 1) * at(2, 2) -
+ at(2, 1) * at(0, 2));
+ cof(1, 1) = at(0, 0) * at(2, 2) -
+ at(2, 0) * at(0, 2);
+ cof(1, 2) = -(at(0, 0) * at(2, 1) -
+ at(2, 0) * at(0, 1));
+ cof(2, 0) = at(0, 1) * at(1, 2) -
+ at(1, 1) * at(0, 2);
+ cof(2, 1) = -(at(0, 0) * at(1, 2) -
+ at(1, 0) * at(0, 2));
+ cof(2, 2) = at(0, 0) * at(1, 1) -
+ at(1, 0) * at(0, 1);
+ break;
+
+ case 4:
+ cof(0, 0) = at(1, 1) * at(2, 2) * at(3, 3) +
+ at(2, 1) * at(3, 2) * at(1, 3) +
+ at(3, 1) * at(1, 2) * at(2, 3) -
+ at(1, 1) * at(3, 2) * at(2, 3) -
+ at(2, 1) * at(1, 2) * at(3, 3) -
+ at(3, 1) * at(2, 2) * at(1, 3);
+ cof(0, 1) = -(at(1, 0) * at(2, 2) * at(3, 3) +
+ at(2, 0) * at(3, 2) * at(1, 3) +
+ at(3, 0) * at(1, 2) * at(2, 3) -
+ at(1, 0) * at(3, 2) * at(2, 3) -
+ at(2, 0) * at(1, 2) * at(3, 3) -
+ at(3, 0) * at(2, 2) * at(1, 3));
+ cof(0, 2) = at(1, 0) * at(2, 1) * at(3, 3) +
+ at(2, 0) * at(3, 1) * at(1, 3) +
+ at(3, 0) * at(1, 1) * at(2, 3) -
+ at(1, 0) * at(3, 1) * at(2, 3) -
+ at(2, 0) * at(1, 1) * at(3, 3) -
+ at(3, 0) * at(2, 1) * at(1, 3);
+ cof(0, 3) = -(at(1, 0) * at(2, 1) * at(3, 2) +
+ at(2, 0) * at(3, 1) * at(1, 2) +
+ at(3, 0) * at(1, 1) * at(2, 2) -
+ at(1, 0) * at(3, 1) * at(2, 2) -
+ at(2, 0) * at(1, 1) * at(3, 2) -
+ at(3, 0) * at(2, 1) * at(1, 2));
+ cof(1, 0) = -(at(0, 1) * at(2, 2) * at(3, 3) +
+ at(2, 1) * at(3, 2) * at(0, 3) +
+ at(3, 1) * at(0, 2) * at(2, 3) -
+ at(0, 1) * at(3, 2) * at(2, 3) -
+ at(2, 1) * at(0, 2) * at(3, 3) -
+ at(3, 1) * at(2, 2) * at(0, 3));
+ cof(1, 1) = at(0, 0) * at(2, 2) * at(3, 3) +
+ at(2, 0) * at(3, 2) * at(0, 3) +
+ at(3, 0) * at(0, 2) * at(2, 3) -
+ at(0, 0) * at(3, 2) * at(2, 3) -
+ at(2, 0) * at(0, 2) * at(3, 3) -
+ at(3, 0) * at(2, 2) * at(0, 3);
+ cof(1, 2) = -(at(0, 0) * at(2, 1) * at(3, 3) +
+ at(2, 0) * at(3, 1) * at(0, 3) +
+ at(3, 0) * at(0, 1) * at(2, 3) -
+ at(0, 0) * at(3, 1) * at(2, 3) -
+ at(2, 0) * at(0, 1) * at(3, 3) -
+ at(3, 0) * at(2, 1) * at(0, 3));
+ cof(1, 3) = at(0, 0) * at(2, 1) * at(3, 2) +
+ at(2, 0) * at(3, 1) * at(0, 2) +
+ at(3, 0) * at(0, 1) * at(2, 2) -
+ at(0, 0) * at(3, 1) * at(2, 2) -
+ at(2, 0) * at(0, 1) * at(3, 2) -
+ at(3, 0) * at(2, 1) * at(0, 2);
+ cof(2, 0) = at(0, 1) * at(1, 2) * at(3, 3) +
+ at(1, 1) * at(3, 2) * at(0, 3) +
+ at(3, 1) * at(0, 2) * at(1, 3) -
+ at(0, 1) * at(3, 2) * at(1, 3) -
+ at(1, 1) * at(0, 2) * at(3, 3) -
+ at(3, 1) * at(1, 2) * at(0, 3);
+ cof(2, 1) = -(at(0, 0) * at(1, 2) * at(3, 3) +
+ at(1, 0) * at(3, 2) * at(0, 3) +
+ at(3, 0) * at(0, 2) * at(1, 3) -
+ at(0, 0) * at(3, 2) * at(1, 3) -
+ at(1, 0) * at(0, 2) * at(3, 3) -
+ at(3, 0) * at(1, 2) * at(0, 3));
+ cof(2, 2) = at(0, 0) * at(1, 1) * at(3, 3) +
+ at(1, 0) * at(3, 1) * at(0, 3) +
+ at(3, 0) * at(0, 1) * at(1, 3) -
+ at(0, 0) * at(3, 1) * at(1, 3) -
+ at(1, 0) * at(0, 1) * at(3, 3) -
+ at(3, 0) * at(1, 1) * at(0, 3);
+ cof(2, 3) = -(at(0, 0) * at(1, 1) * at(3, 2) +
+ at(1, 0) * at(3, 1) * at(0, 2) +
+ at(3, 0) * at(0, 1) * at(1, 2) -
+ at(0, 0) * at(3, 1) * at(1, 2) -
+ at(1, 0) * at(0, 1) * at(3, 2) -
+ at(3, 0) * at(1, 1) * at(0, 2));
+ cof(3, 0) = -(at(0, 1) * at(1, 2) * at(2, 3) +
+ at(1, 1) * at(2, 2) * at(0, 3) +
+ at(2, 1) * at(0, 2) * at(1, 3) -
+ at(0, 1) * at(2, 2) * at(1, 3) -
+ at(1, 1) * at(0, 2) * at(2, 3) -
+ at(2, 1) * at(1, 2) * at(0, 3));
+ cof(3, 1) = at(0, 0) * at(1, 2) * at(2, 3) +
+ at(1, 0) * at(2, 2) * at(0, 3) +
+ at(2, 0) * at(0, 2) * at(1, 3) -
+ at(0, 0) * at(2, 2) * at(1, 3) -
+ at(1, 0) * at(0, 2) * at(2, 3) -
+ at(2, 0) * at(1, 2) * at(0, 3);
+ cof(3, 2) = -(at(0, 0) * at(1, 1) * at(2, 3) +
+ at(1, 0) * at(2, 1) * at(0, 3) +
+ at(2, 0) * at(0, 1) * at(1, 3) -
+ at(0, 0) * at(2, 1) * at(1, 3) -
+ at(1, 0) * at(0, 1) * at(2, 3) -
+ at(2, 0) * at(1, 1) * at(0, 3));
+ cof(3, 3) = at(0, 0) * at(1, 1) * at(2, 2) +
+ at(1, 0) * at(2, 1) * at(0, 2) +
+ at(2, 0) * at(0, 1) * at(1, 2) -
+ at(0, 0) * at(2, 1) * at(1, 2) -
+ at(1, 0) * at(0, 1) * at(2, 2) -
+ at(2, 0) * at(1, 1) * at(0, 2);
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ // The inverse of A is the transpose of the cofactor matrix times the reciprocal of the determinant of A.
+ Matrix<T> adjugateMatrix(cof.transpose());
+ T det = determinant();
+ Matrix<T> result(std::vector<T>(mElements.size()), rows(), columns());
+ for (unsigned int i = 0; i < rows(); i++)
+ for (unsigned int j = 0; j < columns(); j++)
+ result(i, j) = det ? adjugateMatrix(i, j) / det : T();
+
+ return result;
+ }
+
+ void setToIdentity()
+ {
+ ASSERT(rows() == columns());
+
+ const auto one = T(1);
+ const auto zero = T(0);
+
+ for (auto &e : mElements)
+ e = zero;
+
+ for (unsigned int i = 0; i < rows(); ++i)
+ {
+ const auto pos = i * columns() + (i % columns());
+ mElements[pos] = one;
+ }
+ }
+
+ template <unsigned int Size>
+ static void setToIdentity(T(&matrix)[Size])
+ {
+ static_assert(gl::iSquareRoot<Size>() != 0, "Matrix is not square.");
+
+ const auto cols = gl::iSquareRoot<Size>();
+ const auto one = T(1);
+ const auto zero = T(0);
+
+ for (auto &e : matrix)
+ e = zero;
+
+ for (unsigned int i = 0; i < cols; ++i)
+ {
+ const auto pos = i * cols + (i % cols);
+ matrix[pos] = one;
+ }
+ }
+
+ private:
+ std::vector<T> mElements;
+ unsigned int mRows;
+ unsigned int mCols;
+};
+
+} // namespace angle
+
+#endif // COMMON_MATRIX_UTILS_H_
+
diff --git a/gfx/angle/src/common/matrix_utils_unittest.cpp b/gfx/angle/src/common/matrix_utils_unittest.cpp
new file mode 100755
index 000000000..6e9f92d9a
--- /dev/null
+++ b/gfx/angle/src/common/matrix_utils_unittest.cpp
@@ -0,0 +1,184 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// matrix_utils_unittests:
+// Unit tests for the matrix utils.
+//
+
+#include "matrix_utils.h"
+
+#include <gtest/gtest.h>
+
+using namespace angle;
+
+namespace
+{
+
+const unsigned int minDimensions = 2;
+const unsigned int maxDimensions = 4;
+
+TEST(MatrixUtilsTest, MatrixConstructorTest)
+{
+ for (unsigned int i = minDimensions; i <= maxDimensions; i++)
+ {
+ for (unsigned int j = minDimensions; j <= maxDimensions; j++)
+ {
+ unsigned int numElements = i * j;
+ Matrix<float> m(std::vector<float>(numElements, 1.0f), i, j);
+ EXPECT_EQ(m.rows(), i);
+ EXPECT_EQ(m.columns(), j);
+ EXPECT_EQ(m.elements(), std::vector<float>(numElements, 1.0f));
+ }
+ }
+
+ for (unsigned int i = minDimensions; i <= maxDimensions; i++)
+ {
+ unsigned int numElements = i * i;
+ Matrix<float> m(std::vector<float>(numElements, 1.0f), i);
+ EXPECT_EQ(m.size(), i);
+ EXPECT_EQ(m.columns(), m.columns());
+ EXPECT_EQ(m.elements(), std::vector<float>(numElements, 1.0f));
+ }
+}
+
+TEST(MatrixUtilsTest, MatrixCompMultTest)
+{
+ for (unsigned int i = minDimensions; i <= maxDimensions; i++)
+ {
+ unsigned int numElements = i * i;
+ Matrix<float> m1(std::vector<float>(numElements, 2.0f), i);
+ Matrix<float> actualResult = m1.compMult(m1);
+ std::vector<float> actualResultElements = actualResult.elements();
+ std::vector<float> expectedResultElements(numElements, 4.0f);
+ EXPECT_EQ(expectedResultElements, actualResultElements);
+ }
+}
+
+TEST(MatrixUtilsTest, MatrixOuterProductTest)
+{
+ for (unsigned int i = minDimensions; i <= maxDimensions; i++)
+ {
+ for (unsigned int j = minDimensions; j <= maxDimensions; j++)
+ {
+ unsigned int numElements = i * j;
+ Matrix<float> m1(std::vector<float>(numElements, 2.0f), i, 1);
+ Matrix<float> m2(std::vector<float>(numElements, 2.0f), 1, j);
+ Matrix<float> actualResult = m1.outerProduct(m2);
+ EXPECT_EQ(actualResult.rows(), i);
+ EXPECT_EQ(actualResult.columns(), j);
+ std::vector<float> actualResultElements = actualResult.elements();
+ std::vector<float> expectedResultElements(numElements, 4.0f);
+ EXPECT_EQ(expectedResultElements, actualResultElements);
+ }
+ }
+}
+
+TEST(MatrixUtilsTest, MatrixTransposeTest)
+{
+ for (unsigned int i = minDimensions; i <= maxDimensions; i++)
+ {
+ for (unsigned int j = minDimensions; j <= maxDimensions; j++)
+ {
+ unsigned int numElements = i * j;
+ Matrix<float> m1(std::vector<float>(numElements, 2.0f), i, j);
+ Matrix<float> expectedResult = Matrix<float>(std::vector<float>(numElements, 2.0f), j, i);
+ Matrix<float> actualResult = m1.transpose();
+ EXPECT_EQ(expectedResult.elements(), actualResult.elements());
+ EXPECT_EQ(actualResult.rows(), expectedResult.rows());
+ EXPECT_EQ(actualResult.columns(), expectedResult.columns());
+ // transpose(transpose(A)) = A
+ Matrix<float> m2 = actualResult.transpose();
+ EXPECT_EQ(m1.elements(), m2.elements());
+ }
+ }
+}
+
+TEST(MatrixUtilsTest, MatrixDeterminantTest)
+{
+ for (unsigned int i = minDimensions; i <= maxDimensions; i++)
+ {
+ unsigned int numElements = i * i;
+ Matrix<float> m(std::vector<float>(numElements, 2.0f), i);
+ EXPECT_EQ(m.determinant(), 0.0f);
+ }
+}
+
+TEST(MatrixUtilsTest, 2x2MatrixInverseTest)
+{
+ float inputElements[] =
+ {
+ 2.0f, 5.0f,
+ 3.0f, 7.0f
+ };
+ unsigned int numElements = 4;
+ std::vector<float> input(inputElements, inputElements + numElements);
+ Matrix<float> inputMatrix(input, 2);
+ float identityElements[] =
+ {
+ 1.0f, 0.0f,
+ 0.0f, 1.0f
+ };
+ std::vector<float> identityMatrix(identityElements, identityElements + numElements);
+ // A * inverse(A) = I, where I is identity matrix.
+ Matrix<float> result = inputMatrix * inputMatrix.inverse();
+ EXPECT_EQ(identityMatrix, result.elements());
+}
+
+TEST(MatrixUtilsTest, 3x3MatrixInverseTest)
+{
+ float inputElements[] =
+ {
+ 11.0f, 23.0f, 37.0f,
+ 13.0f, 29.0f, 41.0f,
+ 19.0f, 31.0f, 43.0f
+ };
+ unsigned int numElements = 9;
+ std::vector<float> input(inputElements, inputElements + numElements);
+ Matrix<float> inputMatrix(input, 3);
+ float identityElements[] =
+ {
+ 1.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f
+ };
+ std::vector<float> identityMatrix(identityElements, identityElements + numElements);
+ // A * inverse(A) = I, where I is identity matrix.
+ Matrix<float> result = inputMatrix * inputMatrix.inverse();
+ std::vector<float> resultElements = result.elements();
+ const float floatFaultTolarance = 0.000001f;
+ for (size_t i = 0; i < numElements; i++)
+ EXPECT_NEAR(resultElements[i], identityMatrix[i], floatFaultTolarance);
+}
+
+TEST(MatrixUtilsTest, 4x4MatrixInverseTest)
+{
+ float inputElements[] =
+ {
+ 29.0f, 43.0f, 61.0f, 79.0f,
+ 31.0f, 47.0f, 67.0f, 83.0f,
+ 37.0f, 53.0f, 71.0f, 89.0f,
+ 41.0f, 59.0f, 73.0f, 97.0f
+ };
+ unsigned int numElements = 16;
+ std::vector<float> input(inputElements, inputElements + numElements);
+ Matrix<float> inputMatrix(input, 4);
+ float identityElements[] =
+ {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f,
+ };
+ std::vector<float> identityMatrix(identityElements, identityElements + numElements);
+ // A * inverse(A) = I, where I is identity matrix.
+ Matrix<float> result = inputMatrix * inputMatrix.inverse();
+ std::vector<float> resultElements = result.elements();
+ const float floatFaultTolarance = 0.00001f;
+ for (unsigned int i = 0; i < numElements; i++)
+ EXPECT_NEAR(resultElements[i], identityMatrix[i], floatFaultTolarance);
+}
+
+}
+
diff --git a/gfx/angle/src/common/platform.h b/gfx/angle/src/common/platform.h
new file mode 100755
index 000000000..15dac456c
--- /dev/null
+++ b/gfx/angle/src/common/platform.h
@@ -0,0 +1,92 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// platform.h: Operating system specific includes and defines.
+
+#ifndef COMMON_PLATFORM_H_
+#define COMMON_PLATFORM_H_
+
+#if defined(_WIN32) || defined(_WIN64)
+# define ANGLE_PLATFORM_WINDOWS 1
+#elif defined(__APPLE__)
+# define ANGLE_PLATFORM_APPLE 1
+# define ANGLE_PLATFORM_POSIX 1
+#elif defined(ANDROID)
+# define ANGLE_PLATFORM_ANDROID 1
+# define ANGLE_PLATFORM_POSIX 1
+#elif defined(__linux__) || defined(EMSCRIPTEN)
+# define ANGLE_PLATFORM_LINUX 1
+# define ANGLE_PLATFORM_POSIX 1
+#elif defined(__FreeBSD__) || \
+ defined(__OpenBSD__) || \
+ defined(__NetBSD__) || \
+ defined(__DragonFly__) || \
+ defined(__sun) || \
+ defined(__GLIBC__) || \
+ defined(__GNU__) || \
+ defined(__QNX__)
+# define ANGLE_PLATFORM_POSIX 1
+#else
+# error Unsupported platform.
+#endif
+
+#ifdef ANGLE_PLATFORM_WINDOWS
+# ifndef STRICT
+# define STRICT 1
+# endif
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN 1
+# endif
+# ifndef NOMINMAX
+# define NOMINMAX 1
+# endif
+
+# include <windows.h>
+# include <intrin.h>
+
+# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
+# define ANGLE_ENABLE_WINDOWS_STORE 1
+# endif
+
+# if defined(ANGLE_ENABLE_D3D9)
+# include <d3d9.h>
+# include <d3dcompiler.h>
+# endif
+
+# if defined(ANGLE_ENABLE_D3D11)
+# include <d3d10_1.h>
+# include <d3d11.h>
+# include <d3d11_1.h>
+# include <dxgi.h>
+# include <dxgi1_2.h>
+# include <d3dcompiler.h>
+# endif
+
+# if defined(ANGLE_ENABLE_WINDOWS_STORE)
+# include <dxgi1_3.h>
+# if defined(_DEBUG)
+# include <DXProgrammableCapture.h>
+# include <dxgidebug.h>
+# endif
+# endif
+
+# undef near
+# undef far
+#endif
+
+#if defined(_MSC_VER) && !defined(_M_ARM)
+#include <intrin.h>
+#define ANGLE_USE_SSE
+#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))
+#include <x86intrin.h>
+#define ANGLE_USE_SSE
+#endif
+
+// The MemoryBarrier function name collides with a macro under Windows
+// We will undef the macro so that the function name does not get replaced
+#undef MemoryBarrier
+
+#endif // COMMON_PLATFORM_H_
diff --git a/gfx/angle/src/common/string_utils.cpp b/gfx/angle/src/common/string_utils.cpp
new file mode 100755
index 000000000..bb1edd245
--- /dev/null
+++ b/gfx/angle/src/common/string_utils.cpp
@@ -0,0 +1,182 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// string_utils:
+// String helper functions.
+//
+
+#include "string_utils.h"
+
+#include <algorithm>
+#include <stdlib.h>
+#include <string.h>
+#include <fstream>
+#include <sstream>
+
+#include "common/platform.h"
+
+namespace angle
+{
+
+const char kWhitespaceASCII[] = " \f\n\r\t\v";
+
+std::vector<std::string> SplitString(const std::string &input,
+ const std::string &delimiters,
+ WhitespaceHandling whitespace,
+ SplitResult resultType)
+{
+ std::vector<std::string> result;
+ if (input.empty())
+ {
+ return result;
+ }
+
+ std::string::size_type start = 0;
+ while (start != std::string::npos)
+ {
+ auto end = input.find_first_of(delimiters, start);
+
+ std::string piece;
+ if (end == std::string::npos)
+ {
+ piece = input.substr(start);
+ start = std::string::npos;
+ }
+ else
+ {
+ piece = input.substr(start, end - start);
+ start = end + 1;
+ }
+
+ if (whitespace == TRIM_WHITESPACE)
+ {
+ piece = TrimString(piece, kWhitespaceASCII);
+ }
+
+ if (resultType == SPLIT_WANT_ALL || !piece.empty())
+ {
+ result.push_back(piece);
+ }
+ }
+
+ return result;
+}
+
+void SplitStringAlongWhitespace(const std::string &input,
+ std::vector<std::string> *tokensOut)
+{
+
+ std::istringstream stream(input);
+ std::string line;
+
+ while (std::getline(stream, line))
+ {
+ size_t prev = 0, pos;
+ while ((pos = line.find_first_of(kWhitespaceASCII, prev)) != std::string::npos)
+ {
+ if (pos > prev)
+ tokensOut->push_back(line.substr(prev, pos - prev));
+ prev = pos + 1;
+ }
+ if (prev < line.length())
+ tokensOut->push_back(line.substr(prev, std::string::npos));
+ }
+}
+
+std::string TrimString(const std::string &input, const std::string &trimChars)
+{
+ auto begin = input.find_first_not_of(trimChars);
+ if (begin == std::string::npos)
+ {
+ return "";
+ }
+
+ std::string::size_type end = input.find_last_not_of(trimChars);
+ if (end == std::string::npos)
+ {
+ return input.substr(begin);
+ }
+
+ return input.substr(begin, end - begin + 1);
+}
+
+bool HexStringToUInt(const std::string &input, unsigned int *uintOut)
+{
+ unsigned int offset = 0;
+
+ if (input.size() >= 2 && input[0] == '0' && input[1] == 'x')
+ {
+ offset = 2u;
+ }
+
+ // Simple validity check
+ if (input.find_first_not_of("0123456789ABCDEFabcdef", offset) != std::string::npos)
+ {
+ return false;
+ }
+
+ std::stringstream inStream(input);
+ inStream >> std::hex >> *uintOut;
+ return !inStream.fail();
+}
+
+bool ReadFileToString(const std::string &path, std::string *stringOut)
+{
+ std::ifstream inFile(path.c_str());
+ if (inFile.fail())
+ {
+ return false;
+ }
+
+ inFile.seekg(0, std::ios::end);
+ stringOut->reserve(static_cast<std::string::size_type>(inFile.tellg()));
+ inFile.seekg(0, std::ios::beg);
+
+ stringOut->assign(std::istreambuf_iterator<char>(inFile), std::istreambuf_iterator<char>());
+ return !inFile.fail();
+}
+
+Optional<std::vector<wchar_t>> WidenString(size_t length, const char *cString)
+{
+ std::vector<wchar_t> wcstring(length + 1);
+#if !defined(ANGLE_PLATFORM_WINDOWS)
+ size_t written = mbstowcs(wcstring.data(), cString, length + 1);
+ if (written == 0)
+ {
+ return Optional<std::vector<wchar_t>>::Invalid();
+ }
+#else
+ size_t convertedChars = 0;
+ errno_t err = mbstowcs_s(&convertedChars, wcstring.data(), length + 1, cString, _TRUNCATE);
+ if (err != 0)
+ {
+ return Optional<std::vector<wchar_t>>::Invalid();
+ }
+#endif
+ return Optional<std::vector<wchar_t>>(wcstring);
+}
+
+bool BeginsWith(const std::string &str, const char *prefix)
+{
+ return strncmp(str.c_str(), prefix, strlen(prefix)) == 0;
+}
+
+bool BeginsWith(const char *str, const char *prefix)
+{
+ return strncmp(str, prefix, strlen(prefix)) == 0;
+}
+
+bool EndsWith(const std::string &str, const char *suffix)
+{
+ const auto len = strlen(suffix);
+ if (len > str.size())
+ return false;
+
+ const char *end = str.c_str() + str.size() - len;
+
+ return memcmp(end, suffix, len) == 0;
+}
+
+} // namespace angle
diff --git a/gfx/angle/src/common/string_utils.h b/gfx/angle/src/common/string_utils.h
new file mode 100755
index 000000000..c649c64d6
--- /dev/null
+++ b/gfx/angle/src/common/string_utils.h
@@ -0,0 +1,67 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// string_utils:
+// String helper functions.
+//
+
+#ifndef LIBANGLE_STRING_UTILS_H_
+#define LIBANGLE_STRING_UTILS_H_
+
+#include <string>
+#include <vector>
+
+#include "common/Optional.h"
+
+namespace angle
+{
+
+extern const char kWhitespaceASCII[];
+
+enum WhitespaceHandling
+{
+ KEEP_WHITESPACE,
+ TRIM_WHITESPACE,
+};
+
+enum SplitResult
+{
+ SPLIT_WANT_ALL,
+ SPLIT_WANT_NONEMPTY,
+};
+
+std::vector<std::string> SplitString(const std::string &input,
+ const std::string &delimiters,
+ WhitespaceHandling whitespace,
+ SplitResult resultType);
+
+void SplitStringAlongWhitespace(const std::string &input,
+ std::vector<std::string> *tokensOut);
+
+std::string TrimString(const std::string &input, const std::string &trimChars);
+
+bool HexStringToUInt(const std::string &input, unsigned int *uintOut);
+
+bool ReadFileToString(const std::string &path, std::string *stringOut);
+
+Optional<std::vector<wchar_t>> WidenString(size_t length, const char *cString);
+
+// Check if the string str begins with the given prefix.
+// Prefix may not be NULL and needs to be NULL terminated.
+// The comparison is case sensitive.
+bool BeginsWith(const std::string &str, const char *prefix);
+
+// Check if the string str begins with the given prefix.
+// str and prefix may not be NULL and need to be NULL terminated.
+// The comparison is case sensitive.
+bool BeginsWith(const char *str, const char *prefix);
+
+// Check if the string str ends with the given suffix.
+// Suffix may not be NUL and needs to be NULL terminated.
+// The comparison is case sensitive.
+bool EndsWith(const std::string& str, const char* suffix);
+}
+
+#endif // LIBANGLE_STRING_UTILS_H_
diff --git a/gfx/angle/src/common/string_utils_unittest.cpp b/gfx/angle/src/common/string_utils_unittest.cpp
new file mode 100755
index 000000000..e7ce8a62d
--- /dev/null
+++ b/gfx/angle/src/common/string_utils_unittest.cpp
@@ -0,0 +1,163 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// string_utils_unittests:
+// Unit tests for the string utils.
+//
+
+#include "string_utils.h"
+
+#include <gtest/gtest.h>
+
+using namespace angle;
+
+namespace
+{
+
+// Basic SplitString tests
+TEST(StringUtilsTest, SplitString_Basics)
+{
+ std::vector<std::string> r;
+
+ r = SplitString(std::string(), ",:;", KEEP_WHITESPACE, SPLIT_WANT_ALL);
+ EXPECT_TRUE(r.empty());
+
+ // Empty separator list
+ r = SplitString("hello, world", "", KEEP_WHITESPACE, SPLIT_WANT_ALL);
+ ASSERT_EQ(1u, r.size());
+ EXPECT_EQ("hello, world", r[0]);
+
+ // Should split on any of the separators.
+ r = SplitString("::,,;;", ",:;", KEEP_WHITESPACE, SPLIT_WANT_ALL);
+ ASSERT_EQ(7u, r.size());
+ for (auto str : r)
+ ASSERT_TRUE(str.empty());
+
+ r = SplitString("red, green; blue:", ",:;", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
+ ASSERT_EQ(3u, r.size());
+ EXPECT_EQ("red", r[0]);
+ EXPECT_EQ("green", r[1]);
+ EXPECT_EQ("blue", r[2]);
+
+ // Want to split a string along whitespace sequences.
+ r = SplitString(" red green \tblue\n", " \t\n", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
+ ASSERT_EQ(3u, r.size());
+ EXPECT_EQ("red", r[0]);
+ EXPECT_EQ("green", r[1]);
+ EXPECT_EQ("blue", r[2]);
+
+ // Weird case of splitting on spaces but not trimming.
+ r = SplitString(" red ", " ", TRIM_WHITESPACE, SPLIT_WANT_ALL);
+ ASSERT_EQ(3u, r.size());
+ EXPECT_EQ("", r[0]); // Before the first space.
+ EXPECT_EQ("red", r[1]);
+ EXPECT_EQ("", r[2]); // After the last space.
+}
+
+// Check different whitespace and result types for SplitString
+TEST(StringUtilsTest, SplitString_WhitespaceAndResultType)
+{
+ std::vector<std::string> r;
+
+ // Empty input handling.
+ r = SplitString(std::string(), ",", KEEP_WHITESPACE, SPLIT_WANT_ALL);
+ EXPECT_TRUE(r.empty());
+ r = SplitString(std::string(), ",", KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY);
+ EXPECT_TRUE(r.empty());
+
+ // Input string is space and we're trimming.
+ r = SplitString(" ", ",", TRIM_WHITESPACE, SPLIT_WANT_ALL);
+ ASSERT_EQ(1u, r.size());
+ EXPECT_EQ("", r[0]);
+ r = SplitString(" ", ",", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
+ EXPECT_TRUE(r.empty());
+
+ // Test all 4 combinations of flags on ", ,".
+ r = SplitString(", ,", ",", KEEP_WHITESPACE, SPLIT_WANT_ALL);
+ ASSERT_EQ(3u, r.size());
+ EXPECT_EQ("", r[0]);
+ EXPECT_EQ(" ", r[1]);
+ EXPECT_EQ("", r[2]);
+ r = SplitString(", ,", ",", KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY);
+ ASSERT_EQ(1u, r.size());
+ ASSERT_EQ(" ", r[0]);
+ r = SplitString(", ,", ",", TRIM_WHITESPACE, SPLIT_WANT_ALL);
+ ASSERT_EQ(3u, r.size());
+ EXPECT_EQ("", r[0]);
+ EXPECT_EQ("", r[1]);
+ EXPECT_EQ("", r[2]);
+ r = SplitString(", ,", ",", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
+ ASSERT_TRUE(r.empty());
+}
+
+// Tests for TrimString
+TEST(StringUtilsTest, TrimString)
+{
+ // Basic tests
+ EXPECT_EQ("a", TrimString("a", kWhitespaceASCII));
+ EXPECT_EQ("a", TrimString(" a", kWhitespaceASCII));
+ EXPECT_EQ("a", TrimString("a ", kWhitespaceASCII));
+ EXPECT_EQ("a", TrimString(" a ", kWhitespaceASCII));
+
+ // Tests with empty strings
+ EXPECT_EQ("", TrimString("", kWhitespaceASCII));
+ EXPECT_EQ("", TrimString(" \n\r\t", kWhitespaceASCII));
+ EXPECT_EQ(" foo ", TrimString(" foo ", ""));
+
+ // Tests it doesn't removes characters in the middle
+ EXPECT_EQ("foo bar", TrimString(" foo bar ", kWhitespaceASCII));
+
+ // Test with non-whitespace trimChars
+ EXPECT_EQ(" ", TrimString("foo bar", "abcdefghijklmnopqrstuvwxyz"));
+}
+
+// Basic functionality tests for HexStringToUInt
+TEST(StringUtilsTest, HexStringToUIntBasic)
+{
+ unsigned int uintValue;
+
+ std::string emptyString;
+ ASSERT_FALSE(HexStringToUInt(emptyString, &uintValue));
+
+ std::string testStringA("0xBADF00D");
+ ASSERT_TRUE(HexStringToUInt(testStringA, &uintValue));
+ EXPECT_EQ(0xBADF00Du, uintValue);
+
+ std::string testStringB("0xBADFOOD");
+ EXPECT_FALSE(HexStringToUInt(testStringB, &uintValue));
+
+ std::string testStringC("BADF00D");
+ EXPECT_TRUE(HexStringToUInt(testStringC, &uintValue));
+ EXPECT_EQ(0xBADF00Du, uintValue);
+
+ std::string testStringD("0x BADF00D");
+ EXPECT_FALSE(HexStringToUInt(testStringD, &uintValue));
+}
+
+// Note: ReadFileToString is harder to test
+
+
+TEST(StringUtilsTest, BeginsEndsWith)
+{
+ ASSERT_FALSE(BeginsWith("foo", "bar"));
+ ASSERT_FALSE(BeginsWith("", "foo"));
+ ASSERT_FALSE(BeginsWith("foo", "foobar"));
+
+ ASSERT_TRUE(BeginsWith("foobar", "foo"));
+ ASSERT_TRUE(BeginsWith("foobar", ""));
+ ASSERT_TRUE(BeginsWith("foo", "foo"));
+ ASSERT_TRUE(BeginsWith("", ""));
+
+ ASSERT_FALSE(EndsWith("foo", "bar"));
+ ASSERT_FALSE(EndsWith("", "bar"));
+ ASSERT_FALSE(EndsWith("foo", "foobar"));
+
+ ASSERT_TRUE(EndsWith("foobar", "bar"));
+ ASSERT_TRUE(EndsWith("foobar", ""));
+ ASSERT_TRUE(EndsWith("bar", "bar"));
+ ASSERT_TRUE(EndsWith("", ""));
+}
+
+} \ No newline at end of file
diff --git a/gfx/angle/src/common/third_party/numerics/README.angle b/gfx/angle/src/common/third_party/numerics/README.angle
new file mode 100755
index 000000000..c7df1a849
--- /dev/null
+++ b/gfx/angle/src/common/third_party/numerics/README.angle
@@ -0,0 +1,16 @@
+Name: Chromium: base/numerics
+Short Name: base::numerics
+Version:
+URL: https://chromium.googlesource.com/chromium/src.git/+/lkcr/base/numerics/
+SOURCE CODE: Copy the Chromium folder manually into this folder and run git cl format.
+Date: 30/05/2016
+Revision: 28b5bbb227d331c01e6ff9b2f8729732135aadc7 (Chromium)
+Security Critical: no
+License: Chromium
+License File: LICENSE in Chromium/src
+
+Description:
+base::numerics is a library for doing some simple safe math and conversions. To update the checkout, simply
+overwrite the base/numerics folder with Chromium's latest. The only modifications are to the base/logging.h
+file which defines CHECK to be ASSERT to be compatible with ANGLE.
+
diff --git a/gfx/angle/src/common/third_party/numerics/base/logging.h b/gfx/angle/src/common/third_party/numerics/base/logging.h
new file mode 100755
index 000000000..6cf05b4e6
--- /dev/null
+++ b/gfx/angle/src/common/third_party/numerics/base/logging.h
@@ -0,0 +1,22 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// logging.h: Compatiblity hacks for importing Chromium's base/numerics.
+
+#ifndef BASE_LOGGING_H_
+#define BASE_LOGGING_H_
+
+#include "common/debug.h"
+
+#ifndef CHECK
+#define CHECK(X) ASSERT(X)
+#endif
+
+// Unfortunately ANGLE relies on ASSERT being an empty statement, which these libs don't respect.
+#ifndef NOTREACHED
+#define NOTREACHED() UNREACHABLE()
+#endif
+
+#endif // BASE_LOGGING_H_
diff --git a/gfx/angle/src/common/third_party/numerics/base/numerics/OWNERS b/gfx/angle/src/common/third_party/numerics/base/numerics/OWNERS
new file mode 100755
index 000000000..41f35fc79
--- /dev/null
+++ b/gfx/angle/src/common/third_party/numerics/base/numerics/OWNERS
@@ -0,0 +1,3 @@
+jschuh@chromium.org
+tsepez@chromium.org
+
diff --git a/gfx/angle/src/common/third_party/numerics/base/numerics/safe_conversions.h b/gfx/angle/src/common/third_party/numerics/base/numerics/safe_conversions.h
new file mode 100755
index 000000000..3fe496c21
--- /dev/null
+++ b/gfx/angle/src/common/third_party/numerics/base/numerics/safe_conversions.h
@@ -0,0 +1,174 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_NUMERICS_SAFE_CONVERSIONS_H_
+#define BASE_NUMERICS_SAFE_CONVERSIONS_H_
+
+#include <stddef.h>
+
+#include <limits>
+#include <type_traits>
+
+#include "base/logging.h"
+#include "base/numerics/safe_conversions_impl.h"
+
+namespace base
+{
+
+// Convenience function that returns true if the supplied value is in range
+// for the destination type.
+template <typename Dst, typename Src>
+constexpr bool IsValueInRangeForNumericType(Src value)
+{
+ return internal::DstRangeRelationToSrcRange<Dst>(value) == internal::RANGE_VALID;
+}
+
+// Convenience function for determining if a numeric value is negative without
+// throwing compiler warnings on: unsigned(value) < 0.
+template <typename T>
+constexpr typename std::enable_if<std::numeric_limits<T>::is_signed, bool>::type IsValueNegative(
+ T value)
+{
+ static_assert(std::numeric_limits<T>::is_specialized, "Argument must be numeric.");
+ return value < 0;
+}
+
+template <typename T>
+constexpr typename std::enable_if<!std::numeric_limits<T>::is_signed, bool>::type IsValueNegative(T)
+{
+ static_assert(std::numeric_limits<T>::is_specialized, "Argument must be numeric.");
+ return false;
+}
+
+// checked_cast<> is analogous to static_cast<> for numeric types,
+// except that it CHECKs that the specified numeric conversion will not
+// overflow or underflow. NaN source will always trigger a CHECK.
+template <typename Dst, typename Src>
+inline Dst checked_cast(Src value)
+{
+ CHECK(IsValueInRangeForNumericType<Dst>(value));
+ return static_cast<Dst>(value);
+}
+
+// HandleNaN will cause this class to CHECK(false).
+struct SaturatedCastNaNBehaviorCheck
+{
+ template <typename T>
+ static T HandleNaN()
+ {
+ CHECK(false);
+ return T();
+ }
+};
+
+// HandleNaN will return 0 in this case.
+struct SaturatedCastNaNBehaviorReturnZero
+{
+ template <typename T>
+ static constexpr T HandleNaN()
+ {
+ return T();
+ }
+};
+
+namespace internal
+{
+// This wrapper is used for C++11 constexpr support by avoiding the declaration
+// of local variables in the saturated_cast template function.
+template <typename Dst, class NaNHandler, typename Src>
+constexpr Dst saturated_cast_impl(const Src value, const RangeConstraint constraint)
+{
+ return constraint == RANGE_VALID
+ ? static_cast<Dst>(value)
+ : (constraint == RANGE_UNDERFLOW
+ ? std::numeric_limits<Dst>::min()
+ : (constraint == RANGE_OVERFLOW
+ ? std::numeric_limits<Dst>::max()
+ : (constraint == RANGE_INVALID
+ ? NaNHandler::template HandleNaN<Dst>()
+ : (NOTREACHED(), static_cast<Dst>(value)))));
+}
+} // namespace internal
+
+// saturated_cast<> is analogous to static_cast<> for numeric types, except
+// that the specified numeric conversion will saturate rather than overflow or
+// underflow. NaN assignment to an integral will defer the behavior to a
+// specified class. By default, it will return 0.
+template <typename Dst, class NaNHandler = SaturatedCastNaNBehaviorReturnZero, typename Src>
+constexpr Dst saturated_cast(Src value)
+{
+ return std::numeric_limits<Dst>::is_iec559
+ ? static_cast<Dst>(value) // Floating point optimization.
+ : internal::saturated_cast_impl<Dst, NaNHandler>(
+ value, internal::DstRangeRelationToSrcRange<Dst>(value));
+}
+
+// strict_cast<> is analogous to static_cast<> for numeric types, except that
+// it will cause a compile failure if the destination type is not large enough
+// to contain any value in the source type. It performs no runtime checking.
+template <typename Dst, typename Src>
+constexpr Dst strict_cast(Src value)
+{
+ static_assert(std::numeric_limits<Src>::is_specialized, "Argument must be numeric.");
+ static_assert(std::numeric_limits<Dst>::is_specialized, "Result must be numeric.");
+ static_assert((internal::StaticDstRangeRelationToSrcRange<Dst, Src>::value ==
+ internal::NUMERIC_RANGE_CONTAINED),
+ "The numeric conversion is out of range for this type. You "
+ "should probably use one of the following conversion "
+ "mechanisms on the value you want to pass:\n"
+ "- base::checked_cast\n"
+ "- base::saturated_cast\n"
+ "- base::CheckedNumeric");
+
+ return static_cast<Dst>(value);
+}
+
+// StrictNumeric implements compile time range checking between numeric types by
+// wrapping assignment operations in a strict_cast. This class is intended to be
+// used for function arguments and return types, to ensure the destination type
+// can always contain the source type. This is essentially the same as enforcing
+// -Wconversion in gcc and C4302 warnings on MSVC, but it can be applied
+// incrementally at API boundaries, making it easier to convert code so that it
+// compiles cleanly with truncation warnings enabled.
+// This template should introduce no runtime overhead, but it also provides no
+// runtime checking of any of the associated mathematical operations. Use
+// CheckedNumeric for runtime range checks of the actual value being assigned.
+template <typename T>
+class StrictNumeric
+{
+ public:
+ typedef T type;
+
+ constexpr StrictNumeric() : value_(0) {}
+
+ // Copy constructor.
+ template <typename Src>
+ constexpr StrictNumeric(const StrictNumeric<Src> &rhs) : value_(strict_cast<T>(rhs.value_))
+ {
+ }
+
+ // This is not an explicit constructor because we implicitly upgrade regular
+ // numerics to StrictNumerics to make them easier to use.
+ template <typename Src>
+ constexpr StrictNumeric(Src value) : value_(strict_cast<T>(value))
+ {
+ }
+
+ // The numeric cast operator basically handles all the magic.
+ template <typename Dst>
+ constexpr operator Dst() const
+ {
+ return strict_cast<Dst>(value_);
+ }
+
+ private:
+ const T value_;
+};
+
+// Explicitly make a shorter size_t typedef for convenience.
+typedef StrictNumeric<size_t> SizeT;
+
+} // namespace base
+
+#endif // BASE_NUMERICS_SAFE_CONVERSIONS_H_
diff --git a/gfx/angle/src/common/third_party/numerics/base/numerics/safe_conversions_impl.h b/gfx/angle/src/common/third_party/numerics/base/numerics/safe_conversions_impl.h
new file mode 100755
index 000000000..1591b9c8c
--- /dev/null
+++ b/gfx/angle/src/common/third_party/numerics/base/numerics/safe_conversions_impl.h
@@ -0,0 +1,269 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_
+#define BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_
+
+#include <limits.h>
+#include <stdint.h>
+
+#include <climits>
+#include <limits>
+
+namespace base
+{
+namespace internal
+{
+
+// The std library doesn't provide a binary max_exponent for integers, however
+// we can compute one by adding one to the number of non-sign bits. This allows
+// for accurate range comparisons between floating point and integer types.
+template <typename NumericType>
+struct MaxExponent
+{
+ static_assert(std::is_arithmetic<NumericType>::value, "Argument must be numeric.");
+ static const int value =
+ std::numeric_limits<NumericType>::is_iec559
+ ? std::numeric_limits<NumericType>::max_exponent
+ : (sizeof(NumericType) * CHAR_BIT + 1 - std::numeric_limits<NumericType>::is_signed);
+};
+
+enum IntegerRepresentation
+{
+ INTEGER_REPRESENTATION_UNSIGNED,
+ INTEGER_REPRESENTATION_SIGNED
+};
+
+// A range for a given nunmeric Src type is contained for a given numeric Dst
+// type if both numeric_limits<Src>::max() <= numeric_limits<Dst>::max() and
+// numeric_limits<Src>::min() >= numeric_limits<Dst>::min() are true.
+// We implement this as template specializations rather than simple static
+// comparisons to ensure type correctness in our comparisons.
+enum NumericRangeRepresentation
+{
+ NUMERIC_RANGE_NOT_CONTAINED,
+ NUMERIC_RANGE_CONTAINED
+};
+
+// Helper templates to statically determine if our destination type can contain
+// maximum and minimum values represented by the source type.
+
+template <typename Dst,
+ typename Src,
+ IntegerRepresentation DstSign = std::numeric_limits<Dst>::is_signed
+ ? INTEGER_REPRESENTATION_SIGNED
+ : INTEGER_REPRESENTATION_UNSIGNED,
+ IntegerRepresentation SrcSign = std::numeric_limits<Src>::is_signed
+ ? INTEGER_REPRESENTATION_SIGNED
+ : INTEGER_REPRESENTATION_UNSIGNED>
+struct StaticDstRangeRelationToSrcRange;
+
+// Same sign: Dst is guaranteed to contain Src only if its range is equal or
+// larger.
+template <typename Dst, typename Src, IntegerRepresentation Sign>
+struct StaticDstRangeRelationToSrcRange<Dst, Src, Sign, Sign>
+{
+ static const NumericRangeRepresentation value =
+ MaxExponent<Dst>::value >= MaxExponent<Src>::value ? NUMERIC_RANGE_CONTAINED
+ : NUMERIC_RANGE_NOT_CONTAINED;
+};
+
+// Unsigned to signed: Dst is guaranteed to contain source only if its range is
+// larger.
+template <typename Dst, typename Src>
+struct StaticDstRangeRelationToSrcRange<Dst,
+ Src,
+ INTEGER_REPRESENTATION_SIGNED,
+ INTEGER_REPRESENTATION_UNSIGNED>
+{
+ static const NumericRangeRepresentation value =
+ MaxExponent<Dst>::value > MaxExponent<Src>::value ? NUMERIC_RANGE_CONTAINED
+ : NUMERIC_RANGE_NOT_CONTAINED;
+};
+
+// Signed to unsigned: Dst cannot be statically determined to contain Src.
+template <typename Dst, typename Src>
+struct StaticDstRangeRelationToSrcRange<Dst,
+ Src,
+ INTEGER_REPRESENTATION_UNSIGNED,
+ INTEGER_REPRESENTATION_SIGNED>
+{
+ static const NumericRangeRepresentation value = NUMERIC_RANGE_NOT_CONTAINED;
+};
+
+enum RangeConstraint : unsigned char
+{
+ RANGE_VALID = 0x0, // Value can be represented by the destination type.
+ RANGE_UNDERFLOW = 0x1, // Value would overflow.
+ RANGE_OVERFLOW = 0x2, // Value would underflow.
+ RANGE_INVALID = RANGE_UNDERFLOW | RANGE_OVERFLOW // Invalid (i.e. NaN).
+};
+
+// Helper function for coercing an int back to a RangeContraint.
+constexpr RangeConstraint GetRangeConstraint(int integer_range_constraint)
+{
+ // TODO(jschuh): Once we get full C++14 support we want this
+ // assert(integer_range_constraint >= RANGE_VALID &&
+ // integer_range_constraint <= RANGE_INVALID)
+ return static_cast<RangeConstraint>(integer_range_constraint);
+}
+
+// This function creates a RangeConstraint from an upper and lower bound
+// check by taking advantage of the fact that only NaN can be out of range in
+// both directions at once.
+constexpr inline RangeConstraint GetRangeConstraint(bool is_in_upper_bound, bool is_in_lower_bound)
+{
+ return GetRangeConstraint((is_in_upper_bound ? 0 : RANGE_OVERFLOW) |
+ (is_in_lower_bound ? 0 : RANGE_UNDERFLOW));
+}
+
+// The following helper template addresses a corner case in range checks for
+// conversion from a floating-point type to an integral type of smaller range
+// but larger precision (e.g. float -> unsigned). The problem is as follows:
+// 1. Integral maximum is always one less than a power of two, so it must be
+// truncated to fit the mantissa of the floating point. The direction of
+// rounding is implementation defined, but by default it's always IEEE
+// floats, which round to nearest and thus result in a value of larger
+// magnitude than the integral value.
+// Example: float f = UINT_MAX; // f is 4294967296f but UINT_MAX
+// // is 4294967295u.
+// 2. If the floating point value is equal to the promoted integral maximum
+// value, a range check will erroneously pass.
+// Example: (4294967296f <= 4294967295u) // This is true due to a precision
+// // loss in rounding up to float.
+// 3. When the floating point value is then converted to an integral, the
+// resulting value is out of range for the target integral type and
+// thus is implementation defined.
+// Example: unsigned u = (float)INT_MAX; // u will typically overflow to 0.
+// To fix this bug we manually truncate the maximum value when the destination
+// type is an integral of larger precision than the source floating-point type,
+// such that the resulting maximum is represented exactly as a floating point.
+template <typename Dst, typename Src>
+struct NarrowingRange
+{
+ typedef typename std::numeric_limits<Src> SrcLimits;
+ typedef typename std::numeric_limits<Dst> DstLimits;
+ // The following logic avoids warnings where the max function is
+ // instantiated with invalid values for a bit shift (even though
+ // such a function can never be called).
+ static const int shift = (MaxExponent<Src>::value > MaxExponent<Dst>::value &&
+ SrcLimits::digits < DstLimits::digits &&
+ SrcLimits::is_iec559 &&
+ DstLimits::is_integer)
+ ? (DstLimits::digits - SrcLimits::digits)
+ : 0;
+
+ static constexpr Dst max()
+ {
+ // We use UINTMAX_C below to avoid compiler warnings about shifting floating
+ // points. Since it's a compile time calculation, it shouldn't have any
+ // performance impact.
+ return DstLimits::max() - static_cast<Dst>((UINTMAX_C(1) << shift) - 1);
+ }
+
+ static constexpr Dst min()
+ {
+ return std::numeric_limits<Dst>::is_iec559 ? -DstLimits::max() : DstLimits::min();
+ }
+};
+
+template <typename Dst,
+ typename Src,
+ IntegerRepresentation DstSign = std::numeric_limits<Dst>::is_signed
+ ? INTEGER_REPRESENTATION_SIGNED
+ : INTEGER_REPRESENTATION_UNSIGNED,
+ IntegerRepresentation SrcSign = std::numeric_limits<Src>::is_signed
+ ? INTEGER_REPRESENTATION_SIGNED
+ : INTEGER_REPRESENTATION_UNSIGNED,
+ NumericRangeRepresentation DstRange = StaticDstRangeRelationToSrcRange<Dst, Src>::value>
+struct DstRangeRelationToSrcRangeImpl;
+
+// The following templates are for ranges that must be verified at runtime. We
+// split it into checks based on signedness to avoid confusing casts and
+// compiler warnings on signed an unsigned comparisons.
+
+// Dst range is statically determined to contain Src: Nothing to check.
+template <typename Dst, typename Src, IntegerRepresentation DstSign, IntegerRepresentation SrcSign>
+struct DstRangeRelationToSrcRangeImpl<Dst, Src, DstSign, SrcSign, NUMERIC_RANGE_CONTAINED>
+{
+ static constexpr RangeConstraint Check(Src value) { return RANGE_VALID; }
+};
+
+// Signed to signed narrowing: Both the upper and lower boundaries may be
+// exceeded.
+template <typename Dst, typename Src>
+struct DstRangeRelationToSrcRangeImpl<Dst,
+ Src,
+ INTEGER_REPRESENTATION_SIGNED,
+ INTEGER_REPRESENTATION_SIGNED,
+ NUMERIC_RANGE_NOT_CONTAINED>
+{
+ static constexpr RangeConstraint Check(Src value)
+ {
+ return GetRangeConstraint((value <= NarrowingRange<Dst, Src>::max()),
+ (value >= NarrowingRange<Dst, Src>::min()));
+ }
+};
+
+// Unsigned to unsigned narrowing: Only the upper boundary can be exceeded.
+template <typename Dst, typename Src>
+struct DstRangeRelationToSrcRangeImpl<Dst,
+ Src,
+ INTEGER_REPRESENTATION_UNSIGNED,
+ INTEGER_REPRESENTATION_UNSIGNED,
+ NUMERIC_RANGE_NOT_CONTAINED>
+{
+ static constexpr RangeConstraint Check(Src value)
+ {
+ return GetRangeConstraint(value <= NarrowingRange<Dst, Src>::max(), true);
+ }
+};
+
+// Unsigned to signed: The upper boundary may be exceeded.
+template <typename Dst, typename Src>
+struct DstRangeRelationToSrcRangeImpl<Dst,
+ Src,
+ INTEGER_REPRESENTATION_SIGNED,
+ INTEGER_REPRESENTATION_UNSIGNED,
+ NUMERIC_RANGE_NOT_CONTAINED>
+{
+ static constexpr RangeConstraint Check(Src value)
+ {
+ return sizeof(Dst) > sizeof(Src)
+ ? RANGE_VALID
+ : GetRangeConstraint(value <= static_cast<Src>(NarrowingRange<Dst, Src>::max()),
+ true);
+ }
+};
+
+// Signed to unsigned: The upper boundary may be exceeded for a narrower Dst,
+// and any negative value exceeds the lower boundary.
+template <typename Dst, typename Src>
+struct DstRangeRelationToSrcRangeImpl<Dst,
+ Src,
+ INTEGER_REPRESENTATION_UNSIGNED,
+ INTEGER_REPRESENTATION_SIGNED,
+ NUMERIC_RANGE_NOT_CONTAINED>
+{
+ static constexpr RangeConstraint Check(Src value)
+ {
+ return (MaxExponent<Dst>::value >= MaxExponent<Src>::value)
+ ? GetRangeConstraint(true, value >= static_cast<Src>(0))
+ : GetRangeConstraint(value <= static_cast<Src>(NarrowingRange<Dst, Src>::max()),
+ value >= static_cast<Src>(0));
+ }
+};
+
+template <typename Dst, typename Src>
+constexpr RangeConstraint DstRangeRelationToSrcRange(Src value)
+{
+ static_assert(std::numeric_limits<Src>::is_specialized, "Argument must be numeric.");
+ static_assert(std::numeric_limits<Dst>::is_specialized, "Result must be numeric.");
+ return DstRangeRelationToSrcRangeImpl<Dst, Src>::Check(value);
+}
+
+} // namespace internal
+} // namespace base
+
+#endif // BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_
diff --git a/gfx/angle/src/common/third_party/numerics/base/numerics/safe_math.h b/gfx/angle/src/common/third_party/numerics/base/numerics/safe_math.h
new file mode 100755
index 000000000..505efde38
--- /dev/null
+++ b/gfx/angle/src/common/third_party/numerics/base/numerics/safe_math.h
@@ -0,0 +1,324 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_NUMERICS_SAFE_MATH_H_
+#define BASE_NUMERICS_SAFE_MATH_H_
+
+#include <stddef.h>
+
+#include <limits>
+#include <type_traits>
+
+#include "base/logging.h"
+#include "base/numerics/safe_math_impl.h"
+
+namespace base
+{
+
+namespace internal
+{
+
+// CheckedNumeric implements all the logic and operators for detecting integer
+// boundary conditions such as overflow, underflow, and invalid conversions.
+// The CheckedNumeric type implicitly converts from floating point and integer
+// data types, and contains overloads for basic arithmetic operations (i.e.: +,
+// -, *, /, %).
+//
+// The following methods convert from CheckedNumeric to standard numeric values:
+// IsValid() - Returns true if the underlying numeric value is valid (i.e. has
+// has not wrapped and is not the result of an invalid conversion).
+// ValueOrDie() - Returns the underlying value. If the state is not valid this
+// call will crash on a CHECK.
+// ValueOrDefault() - Returns the current value, or the supplied default if the
+// state is not valid.
+// ValueFloating() - Returns the underlying floating point value (valid only
+// only for floating point CheckedNumeric types).
+//
+// Bitwise operations are explicitly not supported, because correct
+// handling of some cases (e.g. sign manipulation) is ambiguous. Comparison
+// operations are explicitly not supported because they could result in a crash
+// on a CHECK condition. You should use patterns like the following for these
+// operations:
+// Bitwise operation:
+// CheckedNumeric<int> checked_int = untrusted_input_value;
+// int x = checked_int.ValueOrDefault(0) | kFlagValues;
+// Comparison:
+// CheckedNumeric<size_t> checked_size = untrusted_input_value;
+// checked_size += HEADER LENGTH;
+// if (checked_size.IsValid() && checked_size.ValueOrDie() < buffer_size)
+// Do stuff...
+template <typename T>
+class CheckedNumeric
+{
+ static_assert(std::is_arithmetic<T>::value, "CheckedNumeric<T>: T must be a numeric type.");
+
+ public:
+ typedef T type;
+
+ CheckedNumeric() {}
+
+ // Copy constructor.
+ template <typename Src>
+ CheckedNumeric(const CheckedNumeric<Src> &rhs) : state_(rhs.ValueUnsafe(), rhs.validity())
+ {
+ }
+
+ template <typename Src>
+ CheckedNumeric(Src value, RangeConstraint validity) : state_(value, validity)
+ {
+ }
+
+ // This is not an explicit constructor because we implicitly upgrade regular
+ // numerics to CheckedNumerics to make them easier to use.
+ template <typename Src>
+ CheckedNumeric(Src value) // NOLINT(runtime/explicit)
+ : state_(value)
+ {
+ static_assert(std::numeric_limits<Src>::is_specialized, "Argument must be numeric.");
+ }
+
+ // This is not an explicit constructor because we want a seamless conversion
+ // from StrictNumeric types.
+ template <typename Src>
+ CheckedNumeric(StrictNumeric<Src> value) // NOLINT(runtime/explicit)
+ : state_(static_cast<Src>(value))
+ {
+ }
+
+ // IsValid() is the public API to test if a CheckedNumeric is currently valid.
+ bool IsValid() const { return validity() == RANGE_VALID; }
+
+ // ValueOrDie() The primary accessor for the underlying value. If the current
+ // state is not valid it will CHECK and crash.
+ T ValueOrDie() const
+ {
+ CHECK(IsValid());
+ return state_.value();
+ }
+
+ // ValueOrDefault(T default_value) A convenience method that returns the
+ // current value if the state is valid, and the supplied default_value for
+ // any other state.
+ T ValueOrDefault(T default_value) const { return IsValid() ? state_.value() : default_value; }
+
+ // ValueFloating() - Since floating point values include their validity state,
+ // we provide an easy method for extracting them directly, without a risk of
+ // crashing on a CHECK.
+ T ValueFloating() const
+ {
+ static_assert(std::numeric_limits<T>::is_iec559, "Argument must be float.");
+ return CheckedNumeric<T>::cast(*this).ValueUnsafe();
+ }
+
+ // validity() - DO NOT USE THIS IN EXTERNAL CODE - It is public right now for
+ // tests and to avoid a big matrix of friend operator overloads. But the
+ // values it returns are likely to change in the future.
+ // Returns: current validity state (i.e. valid, overflow, underflow, nan).
+ // TODO(jschuh): crbug.com/332611 Figure out and implement semantics for
+ // saturation/wrapping so we can expose this state consistently and implement
+ // saturated arithmetic.
+ RangeConstraint validity() const { return state_.validity(); }
+
+ // ValueUnsafe() - DO NOT USE THIS IN EXTERNAL CODE - It is public right now
+ // for tests and to avoid a big matrix of friend operator overloads. But the
+ // values it returns are likely to change in the future.
+ // Returns: the raw numeric value, regardless of the current state.
+ // TODO(jschuh): crbug.com/332611 Figure out and implement semantics for
+ // saturation/wrapping so we can expose this state consistently and implement
+ // saturated arithmetic.
+ T ValueUnsafe() const { return state_.value(); }
+
+ // Prototypes for the supported arithmetic operator overloads.
+ template <typename Src>
+ CheckedNumeric &operator+=(Src rhs);
+ template <typename Src>
+ CheckedNumeric &operator-=(Src rhs);
+ template <typename Src>
+ CheckedNumeric &operator*=(Src rhs);
+ template <typename Src>
+ CheckedNumeric &operator/=(Src rhs);
+ template <typename Src>
+ CheckedNumeric &operator%=(Src rhs);
+
+ CheckedNumeric operator-() const
+ {
+ RangeConstraint validity;
+ T value = CheckedNeg(state_.value(), &validity);
+ // Negation is always valid for floating point.
+ if (std::numeric_limits<T>::is_iec559)
+ return CheckedNumeric<T>(value);
+
+ validity = GetRangeConstraint(state_.validity() | validity);
+ return CheckedNumeric<T>(value, validity);
+ }
+
+ CheckedNumeric Abs() const
+ {
+ RangeConstraint validity;
+ T value = CheckedAbs(state_.value(), &validity);
+ // Absolute value is always valid for floating point.
+ if (std::numeric_limits<T>::is_iec559)
+ return CheckedNumeric<T>(value);
+
+ validity = GetRangeConstraint(state_.validity() | validity);
+ return CheckedNumeric<T>(value, validity);
+ }
+
+ // This function is available only for integral types. It returns an unsigned
+ // integer of the same width as the source type, containing the absolute value
+ // of the source, and properly handling signed min.
+ CheckedNumeric<typename UnsignedOrFloatForSize<T>::type> UnsignedAbs() const
+ {
+ return CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>(
+ CheckedUnsignedAbs(state_.value()), state_.validity());
+ }
+
+ CheckedNumeric &operator++()
+ {
+ *this += 1;
+ return *this;
+ }
+
+ CheckedNumeric operator++(int)
+ {
+ CheckedNumeric value = *this;
+ *this += 1;
+ return value;
+ }
+
+ CheckedNumeric &operator--()
+ {
+ *this -= 1;
+ return *this;
+ }
+
+ CheckedNumeric operator--(int)
+ {
+ CheckedNumeric value = *this;
+ *this -= 1;
+ return value;
+ }
+
+ // These static methods behave like a convenience cast operator targeting
+ // the desired CheckedNumeric type. As an optimization, a reference is
+ // returned when Src is the same type as T.
+ template <typename Src>
+ static CheckedNumeric<T> cast(
+ Src u,
+ typename std::enable_if<std::numeric_limits<Src>::is_specialized, int>::type = 0)
+ {
+ return u;
+ }
+
+ template <typename Src>
+ static CheckedNumeric<T> cast(
+ const CheckedNumeric<Src> &u,
+ typename std::enable_if<!std::is_same<Src, T>::value, int>::type = 0)
+ {
+ return u;
+ }
+
+ static const CheckedNumeric<T> &cast(const CheckedNumeric<T> &u) { return u; }
+
+ private:
+ template <typename NumericType>
+ struct UnderlyingType
+ {
+ using type = NumericType;
+ };
+
+ template <typename NumericType>
+ struct UnderlyingType<CheckedNumeric<NumericType>>
+ {
+ using type = NumericType;
+ };
+
+ CheckedNumericState<T> state_;
+};
+
+// This is the boilerplate for the standard arithmetic operator overloads. A
+// macro isn't the prettiest solution, but it beats rewriting these five times.
+// Some details worth noting are:
+// * We apply the standard arithmetic promotions.
+// * We skip range checks for floating points.
+// * We skip range checks for destination integers with sufficient range.
+// TODO(jschuh): extract these out into templates.
+#define BASE_NUMERIC_ARITHMETIC_OPERATORS(NAME, OP, COMPOUND_OP) \
+ /* Binary arithmetic operator for CheckedNumerics of the same type. */ \
+ template <typename T> \
+ CheckedNumeric<typename ArithmeticPromotion<T>::type> operator OP( \
+ const CheckedNumeric<T> &lhs, const CheckedNumeric<T> &rhs) \
+ { \
+ typedef typename ArithmeticPromotion<T>::type Promotion; \
+ /* Floating point always takes the fast path */ \
+ if (std::numeric_limits<T>::is_iec559) \
+ return CheckedNumeric<T>(lhs.ValueUnsafe() OP rhs.ValueUnsafe()); \
+ if (IsIntegerArithmeticSafe<Promotion, T, T>::value) \
+ return CheckedNumeric<Promotion>(lhs.ValueUnsafe() OP rhs.ValueUnsafe(), \
+ GetRangeConstraint(rhs.validity() | lhs.validity())); \
+ RangeConstraint validity = RANGE_VALID; \
+ T result = \
+ static_cast<T>(Checked##NAME(static_cast<Promotion>(lhs.ValueUnsafe()), \
+ static_cast<Promotion>(rhs.ValueUnsafe()), &validity)); \
+ return CheckedNumeric<Promotion>( \
+ result, GetRangeConstraint(validity | lhs.validity() | rhs.validity())); \
+ } \
+ /* Assignment arithmetic operator implementation from CheckedNumeric. */ \
+ template <typename T> \
+ template <typename Src> \
+ CheckedNumeric<T> &CheckedNumeric<T>::operator COMPOUND_OP(Src rhs) \
+ { \
+ *this = CheckedNumeric<T>::cast(*this) \
+ OP CheckedNumeric<typename UnderlyingType<Src>::type>::cast(rhs); \
+ return *this; \
+ } \
+ /* Binary arithmetic operator for CheckedNumeric of different type. */ \
+ template <typename T, typename Src> \
+ CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \
+ const CheckedNumeric<Src> &lhs, const CheckedNumeric<T> &rhs) \
+ { \
+ typedef typename ArithmeticPromotion<T, Src>::type Promotion; \
+ if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \
+ return CheckedNumeric<Promotion>(lhs.ValueUnsafe() OP rhs.ValueUnsafe(), \
+ GetRangeConstraint(rhs.validity() | lhs.validity())); \
+ return CheckedNumeric<Promotion>::cast(lhs) OP CheckedNumeric<Promotion>::cast(rhs); \
+ } \
+ /* Binary arithmetic operator for left CheckedNumeric and right numeric. */ \
+ template <typename T, typename Src, \
+ typename std::enable_if<std::is_arithmetic<Src>::value>::type * = nullptr> \
+ CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \
+ const CheckedNumeric<T> &lhs, Src rhs) \
+ { \
+ typedef typename ArithmeticPromotion<T, Src>::type Promotion; \
+ if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \
+ return CheckedNumeric<Promotion>(lhs.ValueUnsafe() OP rhs, lhs.validity()); \
+ return CheckedNumeric<Promotion>::cast(lhs) OP CheckedNumeric<Promotion>::cast(rhs); \
+ } \
+ /* Binary arithmetic operator for left numeric and right CheckedNumeric. */ \
+ template <typename T, typename Src, \
+ typename std::enable_if<std::is_arithmetic<Src>::value>::type * = nullptr> \
+ CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \
+ Src lhs, const CheckedNumeric<T> &rhs) \
+ { \
+ typedef typename ArithmeticPromotion<T, Src>::type Promotion; \
+ if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \
+ return CheckedNumeric<Promotion>(lhs OP rhs.ValueUnsafe(), rhs.validity()); \
+ return CheckedNumeric<Promotion>::cast(lhs) OP CheckedNumeric<Promotion>::cast(rhs); \
+ }
+
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Add, +, +=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Sub, -, -=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Mul, *, *=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Div, /, /=)
+BASE_NUMERIC_ARITHMETIC_OPERATORS(Mod, %, %=)
+
+#undef BASE_NUMERIC_ARITHMETIC_OPERATORS
+
+} // namespace internal
+
+using internal::CheckedNumeric;
+
+} // namespace base
+
+#endif // BASE_NUMERICS_SAFE_MATH_H_
diff --git a/gfx/angle/src/common/third_party/numerics/base/numerics/safe_math_impl.h b/gfx/angle/src/common/third_party/numerics/base/numerics/safe_math_impl.h
new file mode 100755
index 000000000..341cdbc2b
--- /dev/null
+++ b/gfx/angle/src/common/third_party/numerics/base/numerics/safe_math_impl.h
@@ -0,0 +1,570 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_NUMERICS_SAFE_MATH_IMPL_H_
+#define BASE_NUMERICS_SAFE_MATH_IMPL_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <climits>
+#include <cmath>
+#include <cstdlib>
+#include <limits>
+#include <type_traits>
+
+#include "base/numerics/safe_conversions.h"
+
+namespace base
+{
+namespace internal
+{
+
+// Everything from here up to the floating point operations is portable C++,
+// but it may not be fast. This code could be split based on
+// platform/architecture and replaced with potentially faster implementations.
+
+// Integer promotion templates used by the portable checked integer arithmetic.
+template <size_t Size, bool IsSigned>
+struct IntegerForSizeAndSign;
+template <>
+struct IntegerForSizeAndSign<1, true>
+{
+ typedef int8_t type;
+};
+template <>
+struct IntegerForSizeAndSign<1, false>
+{
+ typedef uint8_t type;
+};
+template <>
+struct IntegerForSizeAndSign<2, true>
+{
+ typedef int16_t type;
+};
+template <>
+struct IntegerForSizeAndSign<2, false>
+{
+ typedef uint16_t type;
+};
+template <>
+struct IntegerForSizeAndSign<4, true>
+{
+ typedef int32_t type;
+};
+template <>
+struct IntegerForSizeAndSign<4, false>
+{
+ typedef uint32_t type;
+};
+template <>
+struct IntegerForSizeAndSign<8, true>
+{
+ typedef int64_t type;
+};
+template <>
+struct IntegerForSizeAndSign<8, false>
+{
+ typedef uint64_t type;
+};
+
+// WARNING: We have no IntegerForSizeAndSign<16, *>. If we ever add one to
+// support 128-bit math, then the ArithmeticPromotion template below will need
+// to be updated (or more likely replaced with a decltype expression).
+
+template <typename Integer>
+struct UnsignedIntegerForSize
+{
+ typedef
+ typename std::enable_if<std::numeric_limits<Integer>::is_integer,
+ typename IntegerForSizeAndSign<sizeof(Integer), false>::type>::type
+ type;
+};
+
+template <typename Integer>
+struct SignedIntegerForSize
+{
+ typedef
+ typename std::enable_if<std::numeric_limits<Integer>::is_integer,
+ typename IntegerForSizeAndSign<sizeof(Integer), true>::type>::type
+ type;
+};
+
+template <typename Integer>
+struct TwiceWiderInteger
+{
+ typedef typename std::enable_if<
+ std::numeric_limits<Integer>::is_integer,
+ typename IntegerForSizeAndSign<sizeof(Integer) * 2,
+ std::numeric_limits<Integer>::is_signed>::type>::type type;
+};
+
+template <typename Integer>
+struct PositionOfSignBit
+{
+ static const typename std::enable_if<std::numeric_limits<Integer>::is_integer, size_t>::type
+ value = CHAR_BIT * sizeof(Integer) - 1;
+};
+
+// This is used for UnsignedAbs, where we need to support floating-point
+// template instantiations even though we don't actually support the operations.
+// However, there is no corresponding implementation of e.g. CheckedUnsignedAbs,
+// so the float versions will not compile.
+template <typename Numeric,
+ bool IsInteger = std::numeric_limits<Numeric>::is_integer,
+ bool IsFloat = std::numeric_limits<Numeric>::is_iec559>
+struct UnsignedOrFloatForSize;
+
+template <typename Numeric>
+struct UnsignedOrFloatForSize<Numeric, true, false>
+{
+ typedef typename UnsignedIntegerForSize<Numeric>::type type;
+};
+
+template <typename Numeric>
+struct UnsignedOrFloatForSize<Numeric, false, true>
+{
+ typedef Numeric type;
+};
+
+// Helper templates for integer manipulations.
+
+template <typename T>
+constexpr bool HasSignBit(T x)
+{
+ // Cast to unsigned since right shift on signed is undefined.
+ return !!(static_cast<typename UnsignedIntegerForSize<T>::type>(x) >>
+ PositionOfSignBit<T>::value);
+}
+
+// This wrapper undoes the standard integer promotions.
+template <typename T>
+constexpr T BinaryComplement(T x)
+{
+ return static_cast<T>(~x);
+}
+
+// Here are the actual portable checked integer math implementations.
+// TODO(jschuh): Break this code out from the enable_if pattern and find a clean
+// way to coalesce things into the CheckedNumericState specializations below.
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer, T>::type
+CheckedAdd(T x, T y, RangeConstraint *validity)
+{
+ // Since the value of x+y is undefined if we have a signed type, we compute
+ // it using the unsigned type of the same size.
+ typedef typename UnsignedIntegerForSize<T>::type UnsignedDst;
+ UnsignedDst ux = static_cast<UnsignedDst>(x);
+ UnsignedDst uy = static_cast<UnsignedDst>(y);
+ UnsignedDst uresult = static_cast<UnsignedDst>(ux + uy);
+ // Addition is valid if the sign of (x + y) is equal to either that of x or
+ // that of y.
+ if (std::numeric_limits<T>::is_signed)
+ {
+ if (HasSignBit(BinaryComplement(static_cast<UnsignedDst>((uresult ^ ux) & (uresult ^ uy)))))
+ {
+ *validity = RANGE_VALID;
+ }
+ else
+ { // Direction of wrap is inverse of result sign.
+ *validity = HasSignBit(uresult) ? RANGE_OVERFLOW : RANGE_UNDERFLOW;
+ }
+ }
+ else
+ { // Unsigned is either valid or overflow.
+ *validity = BinaryComplement(x) >= y ? RANGE_VALID : RANGE_OVERFLOW;
+ }
+ return static_cast<T>(uresult);
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer, T>::type
+CheckedSub(T x, T y, RangeConstraint *validity)
+{
+ // Since the value of x+y is undefined if we have a signed type, we compute
+ // it using the unsigned type of the same size.
+ typedef typename UnsignedIntegerForSize<T>::type UnsignedDst;
+ UnsignedDst ux = static_cast<UnsignedDst>(x);
+ UnsignedDst uy = static_cast<UnsignedDst>(y);
+ UnsignedDst uresult = static_cast<UnsignedDst>(ux - uy);
+ // Subtraction is valid if either x and y have same sign, or (x-y) and x have
+ // the same sign.
+ if (std::numeric_limits<T>::is_signed)
+ {
+ if (HasSignBit(BinaryComplement(static_cast<UnsignedDst>((uresult ^ ux) & (ux ^ uy)))))
+ {
+ *validity = RANGE_VALID;
+ }
+ else
+ { // Direction of wrap is inverse of result sign.
+ *validity = HasSignBit(uresult) ? RANGE_OVERFLOW : RANGE_UNDERFLOW;
+ }
+ }
+ else
+ { // Unsigned is either valid or underflow.
+ *validity = x >= y ? RANGE_VALID : RANGE_UNDERFLOW;
+ }
+ return static_cast<T>(uresult);
+}
+
+// Integer multiplication is a bit complicated. In the fast case we just
+// we just promote to a twice wider type, and range check the result. In the
+// slow case we need to manually check that the result won't be truncated by
+// checking with division against the appropriate bound.
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && sizeof(T) * 2 <= sizeof(uintmax_t),
+ T>::type
+CheckedMul(T x, T y, RangeConstraint *validity)
+{
+ typedef typename TwiceWiderInteger<T>::type IntermediateType;
+ IntermediateType tmp = static_cast<IntermediateType>(x) * static_cast<IntermediateType>(y);
+ *validity = DstRangeRelationToSrcRange<T>(tmp);
+ return static_cast<T>(tmp);
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed &&
+ (sizeof(T) * 2 > sizeof(uintmax_t)),
+ T>::type
+CheckedMul(T x, T y, RangeConstraint *validity)
+{
+ // If either side is zero then the result will be zero.
+ if (!x || !y)
+ {
+ *validity = RANGE_VALID;
+ return static_cast<T>(0);
+ }
+ else if (x > 0)
+ {
+ if (y > 0)
+ *validity = x <= std::numeric_limits<T>::max() / y ? RANGE_VALID : RANGE_OVERFLOW;
+ else
+ *validity = y >= std::numeric_limits<T>::min() / x ? RANGE_VALID : RANGE_UNDERFLOW;
+ }
+ else
+ {
+ if (y > 0)
+ *validity = x >= std::numeric_limits<T>::min() / y ? RANGE_VALID : RANGE_UNDERFLOW;
+ else
+ *validity = y >= std::numeric_limits<T>::max() / x ? RANGE_VALID : RANGE_OVERFLOW;
+ }
+
+ return static_cast<T>(x * y);
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed &&
+ (sizeof(T) * 2 > sizeof(uintmax_t)),
+ T>::type
+CheckedMul(T x, T y, RangeConstraint *validity)
+{
+ *validity = (y == 0 || x <= std::numeric_limits<T>::max() / y) ? RANGE_VALID : RANGE_OVERFLOW;
+ return static_cast<T>(x * y);
+}
+
+// Division just requires a check for an invalid negation on signed min/-1.
+template <typename T>
+T CheckedDiv(T x,
+ T y,
+ RangeConstraint *validity,
+ typename std::enable_if<std::numeric_limits<T>::is_integer, int>::type = 0)
+{
+ if (std::numeric_limits<T>::is_signed && x == std::numeric_limits<T>::min() &&
+ y == static_cast<T>(-1))
+ {
+ *validity = RANGE_OVERFLOW;
+ return std::numeric_limits<T>::min();
+ }
+
+ *validity = RANGE_VALID;
+ return static_cast<T>(x / y);
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed,
+ T>::type
+CheckedMod(T x, T y, RangeConstraint *validity)
+{
+ *validity = y > 0 ? RANGE_VALID : RANGE_INVALID;
+ return static_cast<T>(x % y);
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed,
+ T>::type
+CheckedMod(T x, T y, RangeConstraint *validity)
+{
+ *validity = RANGE_VALID;
+ return static_cast<T>(x % y);
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed,
+ T>::type
+CheckedNeg(T value, RangeConstraint *validity)
+{
+ *validity = value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW;
+ // The negation of signed min is min, so catch that one.
+ return static_cast<T>(-value);
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed,
+ T>::type
+CheckedNeg(T value, RangeConstraint *validity)
+{
+ // The only legal unsigned negation is zero.
+ *validity = value ? RANGE_UNDERFLOW : RANGE_VALID;
+ return static_cast<T>(-static_cast<typename SignedIntegerForSize<T>::type>(value));
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed,
+ T>::type
+CheckedAbs(T value, RangeConstraint *validity)
+{
+ *validity = value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW;
+ return static_cast<T>(std::abs(value));
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed,
+ T>::type
+CheckedAbs(T value, RangeConstraint *validity)
+{
+ // T is unsigned, so |value| must already be positive.
+ *validity = RANGE_VALID;
+ return value;
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed,
+ typename UnsignedIntegerForSize<T>::type>::type
+CheckedUnsignedAbs(T value)
+{
+ typedef typename UnsignedIntegerForSize<T>::type UnsignedT;
+ return value == std::numeric_limits<T>::min()
+ ? static_cast<UnsignedT>(std::numeric_limits<T>::max()) + 1
+ : static_cast<UnsignedT>(std::abs(value));
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed,
+ T>::type
+CheckedUnsignedAbs(T value)
+{
+ // T is unsigned, so |value| must already be positive.
+ return static_cast<T>(value);
+}
+
+// These are the floating point stubs that the compiler needs to see. Only the
+// negation operation is ever called.
+#define BASE_FLOAT_ARITHMETIC_STUBS(NAME) \
+ template <typename T> \
+ typename std::enable_if<std::numeric_limits<T>::is_iec559, T>::type Checked##NAME( \
+ T, T, RangeConstraint *) \
+ { \
+ NOTREACHED(); \
+ return static_cast<T>(0); \
+ }
+
+BASE_FLOAT_ARITHMETIC_STUBS(Add)
+BASE_FLOAT_ARITHMETIC_STUBS(Sub)
+BASE_FLOAT_ARITHMETIC_STUBS(Mul)
+BASE_FLOAT_ARITHMETIC_STUBS(Div)
+BASE_FLOAT_ARITHMETIC_STUBS(Mod)
+
+#undef BASE_FLOAT_ARITHMETIC_STUBS
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_iec559, T>::type CheckedNeg(T value,
+ RangeConstraint *)
+{
+ return static_cast<T>(-value);
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_iec559, T>::type CheckedAbs(T value,
+ RangeConstraint *)
+{
+ return static_cast<T>(std::abs(value));
+}
+
+// Floats carry around their validity state with them, but integers do not. So,
+// we wrap the underlying value in a specialization in order to hide that detail
+// and expose an interface via accessors.
+enum NumericRepresentation
+{
+ NUMERIC_INTEGER,
+ NUMERIC_FLOATING,
+ NUMERIC_UNKNOWN
+};
+
+template <typename NumericType>
+struct GetNumericRepresentation
+{
+ static const NumericRepresentation value =
+ std::numeric_limits<NumericType>::is_integer
+ ? NUMERIC_INTEGER
+ : (std::numeric_limits<NumericType>::is_iec559 ? NUMERIC_FLOATING : NUMERIC_UNKNOWN);
+};
+
+template <typename T, NumericRepresentation type = GetNumericRepresentation<T>::value>
+class CheckedNumericState
+{
+};
+
+// Integrals require quite a bit of additional housekeeping to manage state.
+template <typename T>
+class CheckedNumericState<T, NUMERIC_INTEGER>
+{
+ private:
+ T value_;
+ RangeConstraint validity_ : CHAR_BIT; // Actually requires only two bits.
+
+ public:
+ template <typename Src, NumericRepresentation type>
+ friend class CheckedNumericState;
+
+ CheckedNumericState() : value_(0), validity_(RANGE_VALID) {}
+
+ template <typename Src>
+ CheckedNumericState(Src value, RangeConstraint validity)
+ : value_(static_cast<T>(value)),
+ validity_(GetRangeConstraint(validity | DstRangeRelationToSrcRange<T>(value)))
+ {
+ static_assert(std::numeric_limits<Src>::is_specialized, "Argument must be numeric.");
+ }
+
+ // Copy constructor.
+ template <typename Src>
+ CheckedNumericState(const CheckedNumericState<Src> &rhs)
+ : value_(static_cast<T>(rhs.value())),
+ validity_(GetRangeConstraint(rhs.validity() | DstRangeRelationToSrcRange<T>(rhs.value())))
+ {
+ }
+
+ template <typename Src>
+ explicit CheckedNumericState(
+ Src value,
+ typename std::enable_if<std::numeric_limits<Src>::is_specialized, int>::type = 0)
+ : value_(static_cast<T>(value)), validity_(DstRangeRelationToSrcRange<T>(value))
+ {
+ }
+
+ RangeConstraint validity() const { return validity_; }
+ T value() const { return value_; }
+};
+
+// Floating points maintain their own validity, but need translation wrappers.
+template <typename T>
+class CheckedNumericState<T, NUMERIC_FLOATING>
+{
+ private:
+ T value_;
+
+ public:
+ template <typename Src, NumericRepresentation type>
+ friend class CheckedNumericState;
+
+ CheckedNumericState() : value_(0.0) {}
+
+ template <typename Src>
+ CheckedNumericState(
+ Src value,
+ RangeConstraint validity,
+ typename std::enable_if<std::numeric_limits<Src>::is_integer, int>::type = 0)
+ {
+ switch (DstRangeRelationToSrcRange<T>(value))
+ {
+ case RANGE_VALID:
+ value_ = static_cast<T>(value);
+ break;
+
+ case RANGE_UNDERFLOW:
+ value_ = -std::numeric_limits<T>::infinity();
+ break;
+
+ case RANGE_OVERFLOW:
+ value_ = std::numeric_limits<T>::infinity();
+ break;
+
+ case RANGE_INVALID:
+ value_ = std::numeric_limits<T>::quiet_NaN();
+ break;
+
+ default:
+ NOTREACHED();
+ }
+ }
+
+ template <typename Src>
+ explicit CheckedNumericState(
+ Src value,
+ typename std::enable_if<std::numeric_limits<Src>::is_specialized, int>::type = 0)
+ : value_(static_cast<T>(value))
+ {
+ }
+
+ // Copy constructor.
+ template <typename Src>
+ CheckedNumericState(const CheckedNumericState<Src> &rhs) : value_(static_cast<T>(rhs.value()))
+ {
+ }
+
+ RangeConstraint validity() const
+ {
+ return GetRangeConstraint(value_ <= std::numeric_limits<T>::max(),
+ value_ >= -std::numeric_limits<T>::max());
+ }
+ T value() const { return value_; }
+};
+
+// For integers less than 128-bit and floats 32-bit or larger, we have the type
+// with the larger maximum exponent take precedence.
+enum ArithmeticPromotionCategory
+{
+ LEFT_PROMOTION,
+ RIGHT_PROMOTION
+};
+
+template <typename Lhs,
+ typename Rhs = Lhs,
+ ArithmeticPromotionCategory Promotion =
+ (MaxExponent<Lhs>::value > MaxExponent<Rhs>::value) ? LEFT_PROMOTION
+ : RIGHT_PROMOTION>
+struct ArithmeticPromotion;
+
+template <typename Lhs, typename Rhs>
+struct ArithmeticPromotion<Lhs, Rhs, LEFT_PROMOTION>
+{
+ typedef Lhs type;
+};
+
+template <typename Lhs, typename Rhs>
+struct ArithmeticPromotion<Lhs, Rhs, RIGHT_PROMOTION>
+{
+ typedef Rhs type;
+};
+
+// We can statically check if operations on the provided types can wrap, so we
+// can skip the checked operations if they're not needed. So, for an integer we
+// care if the destination type preserves the sign and is twice the width of
+// the source.
+template <typename T, typename Lhs, typename Rhs>
+struct IsIntegerArithmeticSafe
+{
+ static const bool value =
+ !std::numeric_limits<T>::is_iec559 &&
+ StaticDstRangeRelationToSrcRange<T, Lhs>::value == NUMERIC_RANGE_CONTAINED &&
+ sizeof(T) >= (2 * sizeof(Lhs)) &&
+ StaticDstRangeRelationToSrcRange<T, Rhs>::value != NUMERIC_RANGE_CONTAINED &&
+ sizeof(T) >= (2 * sizeof(Rhs));
+};
+
+} // namespace internal
+} // namespace base
+
+#endif // BASE_NUMERICS_SAFE_MATH_IMPL_H_
diff --git a/gfx/angle/src/common/third_party/numerics/base/numerics/safe_numerics_unittest.cc b/gfx/angle/src/common/third_party/numerics/base/numerics/safe_numerics_unittest.cc
new file mode 100755
index 000000000..052d85042
--- /dev/null
+++ b/gfx/angle/src/common/third_party/numerics/base/numerics/safe_numerics_unittest.cc
@@ -0,0 +1,771 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <limits>
+#include <type_traits>
+
+#include "base/compiler_specific.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/numerics/safe_math.h"
+#include "build/build_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS)
+#include <mmintrin.h>
+#endif
+
+using std::numeric_limits;
+using base::CheckedNumeric;
+using base::checked_cast;
+using base::IsValueInRangeForNumericType;
+using base::IsValueNegative;
+using base::SizeT;
+using base::StrictNumeric;
+using base::saturated_cast;
+using base::strict_cast;
+using base::internal::MaxExponent;
+using base::internal::RANGE_VALID;
+using base::internal::RANGE_INVALID;
+using base::internal::RANGE_OVERFLOW;
+using base::internal::RANGE_UNDERFLOW;
+using base::internal::SignedIntegerForSize;
+
+// These tests deliberately cause arithmetic overflows. If the compiler is
+// aggressive enough, it can const fold these overflows. Disable warnings about
+// overflows for const expressions.
+#if defined(OS_WIN)
+#pragma warning(disable : 4756)
+#endif
+
+// This is a helper function for finding the maximum value in Src that can be
+// wholy represented as the destination floating-point type.
+template <typename Dst, typename Src>
+Dst GetMaxConvertibleToFloat()
+{
+ typedef numeric_limits<Dst> DstLimits;
+ typedef numeric_limits<Src> SrcLimits;
+ static_assert(SrcLimits::is_specialized, "Source must be numeric.");
+ static_assert(DstLimits::is_specialized, "Destination must be numeric.");
+ CHECK(DstLimits::is_iec559);
+
+ if (SrcLimits::digits <= DstLimits::digits &&
+ MaxExponent<Src>::value <= MaxExponent<Dst>::value)
+ return SrcLimits::max();
+ Src max = SrcLimits::max() / 2 + (SrcLimits::is_integer ? 1 : 0);
+ while (max != static_cast<Src>(static_cast<Dst>(max)))
+ {
+ max /= 2;
+ }
+ return static_cast<Dst>(max);
+}
+
+// Helper macros to wrap displaying the conversion types and line numbers.
+#define TEST_EXPECTED_VALIDITY(expected, actual) \
+ EXPECT_EQ(expected, CheckedNumeric<Dst>(actual).IsValid()) \
+ << "Result test: Value " << +(actual).ValueUnsafe() << " as " << dst << " on line " \
+ << line;
+
+#define TEST_EXPECTED_SUCCESS(actual) TEST_EXPECTED_VALIDITY(true, actual)
+#define TEST_EXPECTED_FAILURE(actual) TEST_EXPECTED_VALIDITY(false, actual)
+
+#define TEST_EXPECTED_VALUE(expected, actual) \
+ EXPECT_EQ(static_cast<Dst>(expected), CheckedNumeric<Dst>(actual).ValueUnsafe()) \
+ << "Result test: Value " << +((actual).ValueUnsafe()) << " as " << dst << " on line " \
+ << line;
+
+// Signed integer arithmetic.
+template <typename Dst>
+static void TestSpecializedArithmetic(
+ const char *dst,
+ int line,
+ typename std::enable_if<numeric_limits<Dst>::is_integer && numeric_limits<Dst>::is_signed,
+ int>::type = 0)
+{
+ typedef numeric_limits<Dst> DstLimits;
+ TEST_EXPECTED_FAILURE(-CheckedNumeric<Dst>(DstLimits::min()));
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()).Abs());
+ TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
+
+ TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + -1);
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) + -1);
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) + -DstLimits::max());
+
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) - 1);
+ TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) - -1);
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - -DstLimits::max());
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) - DstLimits::max());
+
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) * 2);
+
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) / -1);
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) / 2);
+
+ // Modulus is legal only for integers.
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
+ TEST_EXPECTED_VALUE(-1, CheckedNumeric<Dst>(-1) % 2);
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-1) % -2);
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) % 2);
+ TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
+ // Test all the different modulus combinations.
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
+ CheckedNumeric<Dst> checked_dst = 1;
+ TEST_EXPECTED_VALUE(0, checked_dst %= 1);
+}
+
+// Unsigned integer arithmetic.
+template <typename Dst>
+static void TestSpecializedArithmetic(
+ const char *dst,
+ int line,
+ typename std::enable_if<numeric_limits<Dst>::is_integer && !numeric_limits<Dst>::is_signed,
+ int>::type = 0)
+{
+ typedef numeric_limits<Dst> DstLimits;
+ TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::min()));
+ TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()).Abs());
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) + -1);
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) - 1);
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) * 2);
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) / 2);
+ TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()).UnsignedAbs());
+ TEST_EXPECTED_SUCCESS(CheckedNumeric<typename SignedIntegerForSize<Dst>::type>(
+ std::numeric_limits<typename SignedIntegerForSize<Dst>::type>::min())
+ .UnsignedAbs());
+
+ // Modulus is legal only for integers.
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
+ TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % 2);
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) % 2);
+ TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
+ // Test all the different modulus combinations.
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
+ CheckedNumeric<Dst> checked_dst = 1;
+ TEST_EXPECTED_VALUE(0, checked_dst %= 1);
+}
+
+// Floating point arithmetic.
+template <typename Dst>
+void TestSpecializedArithmetic(
+ const char *dst,
+ int line,
+ typename std::enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0)
+{
+ typedef numeric_limits<Dst> DstLimits;
+ TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::min()));
+
+ TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()).Abs());
+ TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
+
+ TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) + -1);
+ TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + 1);
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) + -DstLimits::max());
+
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - -DstLimits::max());
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) - DstLimits::max());
+
+ TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) * 2);
+
+ TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2);
+ EXPECT_EQ(static_cast<Dst>(1.0), CheckedNumeric<Dst>(1.0).ValueFloating());
+}
+
+// Generic arithmetic tests.
+template <typename Dst>
+static void TestArithmetic(const char *dst, int line)
+{
+ typedef numeric_limits<Dst> DstLimits;
+
+ EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid());
+ EXPECT_EQ(
+ false,
+ CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) * DstLimits::max()).IsValid());
+ EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDie());
+ EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDefault(1));
+ EXPECT_EQ(static_cast<Dst>(1),
+ CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) * DstLimits::max())
+ .ValueOrDefault(1));
+
+ // Test the operator combinations.
+ TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + CheckedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - CheckedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * CheckedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / CheckedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(2, 1 + CheckedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(0, 1 - CheckedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(1, 1 * CheckedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(1, 1 / CheckedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + 1);
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - 1);
+ TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * 1);
+ TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
+ CheckedNumeric<Dst> checked_dst = 1;
+ TEST_EXPECTED_VALUE(2, checked_dst += 1);
+ checked_dst = 1;
+ TEST_EXPECTED_VALUE(0, checked_dst -= 1);
+ checked_dst = 1;
+ TEST_EXPECTED_VALUE(1, checked_dst *= 1);
+ checked_dst = 1;
+ TEST_EXPECTED_VALUE(1, checked_dst /= 1);
+
+ // Generic negation.
+ TEST_EXPECTED_VALUE(0, -CheckedNumeric<Dst>());
+ TEST_EXPECTED_VALUE(-1, -CheckedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(1, -CheckedNumeric<Dst>(-1));
+ TEST_EXPECTED_VALUE(static_cast<Dst>(DstLimits::max() * -1),
+ -CheckedNumeric<Dst>(DstLimits::max()));
+
+ // Generic absolute value.
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>().Abs());
+ TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).Abs());
+ TEST_EXPECTED_VALUE(DstLimits::max(), CheckedNumeric<Dst>(DstLimits::max()).Abs());
+
+ // Generic addition.
+ TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>() + 1));
+ TEST_EXPECTED_VALUE(2, (CheckedNumeric<Dst>(1) + 1));
+ TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) + 1));
+ TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) + 1);
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) + DstLimits::max());
+
+ // Generic subtraction.
+ TEST_EXPECTED_VALUE(-1, (CheckedNumeric<Dst>() - 1));
+ TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(1) - 1));
+ TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) - 1));
+ TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) - 1);
+
+ // Generic multiplication.
+ TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>() * 1));
+ TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>(1) * 1));
+ TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) * 2));
+ TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * 0));
+ TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) * 0));
+ TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * -1));
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) * DstLimits::max());
+
+ // Generic division.
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() / 1);
+ TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
+ TEST_EXPECTED_VALUE(DstLimits::min() / 2, CheckedNumeric<Dst>(DstLimits::min()) / 2);
+ TEST_EXPECTED_VALUE(DstLimits::max() / 2, CheckedNumeric<Dst>(DstLimits::max()) / 2);
+
+ TestSpecializedArithmetic<Dst>(dst, line);
+}
+
+// Helper macro to wrap displaying the conversion types and line numbers.
+#define TEST_ARITHMETIC(Dst) TestArithmetic<Dst>(#Dst, __LINE__)
+
+TEST(SafeNumerics, SignedIntegerMath)
+{
+ TEST_ARITHMETIC(int8_t);
+ TEST_ARITHMETIC(int);
+ TEST_ARITHMETIC(intptr_t);
+ TEST_ARITHMETIC(intmax_t);
+}
+
+TEST(SafeNumerics, UnsignedIntegerMath)
+{
+ TEST_ARITHMETIC(uint8_t);
+ TEST_ARITHMETIC(unsigned int);
+ TEST_ARITHMETIC(uintptr_t);
+ TEST_ARITHMETIC(uintmax_t);
+}
+
+TEST(SafeNumerics, FloatingPointMath)
+{
+ TEST_ARITHMETIC(float);
+ TEST_ARITHMETIC(double);
+}
+
+// Enumerates the five different conversions types we need to test.
+enum NumericConversionType
+{
+ SIGN_PRESERVING_VALUE_PRESERVING,
+ SIGN_PRESERVING_NARROW,
+ SIGN_TO_UNSIGN_WIDEN_OR_EQUAL,
+ SIGN_TO_UNSIGN_NARROW,
+ UNSIGN_TO_SIGN_NARROW_OR_EQUAL,
+};
+
+// Template covering the different conversion tests.
+template <typename Dst, typename Src, NumericConversionType conversion>
+struct TestNumericConversion
+{
+};
+
+// EXPECT_EQ wrappers providing specific detail on test failures.
+#define TEST_EXPECTED_RANGE(expected, actual) \
+ EXPECT_EQ(expected, base::internal::DstRangeRelationToSrcRange<Dst>(actual)) \
+ << "Conversion test: " << src << " value " << actual << " to " << dst << " on line " \
+ << line;
+
+template <typename Dst, typename Src>
+struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING>
+{
+ static void Test(const char *dst, const char *src, int line)
+ {
+ typedef numeric_limits<Src> SrcLimits;
+ typedef numeric_limits<Dst> DstLimits;
+ // Integral to floating.
+ static_assert(
+ (DstLimits::is_iec559 && SrcLimits::is_integer) ||
+ // Not floating to integral and...
+ (!(DstLimits::is_integer && SrcLimits::is_iec559) &&
+ // Same sign, same numeric, source is narrower or same.
+ ((SrcLimits::is_signed == DstLimits::is_signed && sizeof(Dst) >= sizeof(Src)) ||
+ // Or signed destination and source is smaller
+ (DstLimits::is_signed && sizeof(Dst) > sizeof(Src)))),
+ "Comparison must be sign preserving and value preserving");
+
+ const CheckedNumeric<Dst> checked_dst = SrcLimits::max();
+ TEST_EXPECTED_SUCCESS(checked_dst);
+ if (MaxExponent<Dst>::value > MaxExponent<Src>::value)
+ {
+ if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1)
+ {
+ // At least twice larger type.
+ TEST_EXPECTED_SUCCESS(SrcLimits::max() * checked_dst);
+ }
+ else
+ { // Larger, but not at least twice as large.
+ TEST_EXPECTED_FAILURE(SrcLimits::max() * checked_dst);
+ TEST_EXPECTED_SUCCESS(checked_dst + 1);
+ }
+ }
+ else
+ { // Same width type.
+ TEST_EXPECTED_FAILURE(checked_dst + 1);
+ }
+
+ TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
+ if (SrcLimits::is_iec559)
+ {
+ TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max() * static_cast<Src>(-1));
+ TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
+ TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
+ TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
+ }
+ else if (numeric_limits<Src>::is_signed)
+ {
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
+ TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
+ }
+ }
+};
+
+template <typename Dst, typename Src>
+struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW>
+{
+ static void Test(const char *dst, const char *src, int line)
+ {
+ typedef numeric_limits<Src> SrcLimits;
+ typedef numeric_limits<Dst> DstLimits;
+ static_assert(SrcLimits::is_signed == DstLimits::is_signed,
+ "Destination and source sign must be the same");
+ static_assert(sizeof(Dst) < sizeof(Src) || (DstLimits::is_integer && SrcLimits::is_iec559),
+ "Destination must be narrower than source");
+
+ const CheckedNumeric<Dst> checked_dst;
+ TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
+ TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
+ TEST_EXPECTED_FAILURE(checked_dst - SrcLimits::max());
+
+ TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
+ if (SrcLimits::is_iec559)
+ {
+ TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
+ TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
+ TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
+ TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
+ if (DstLimits::is_integer)
+ {
+ if (SrcLimits::digits < DstLimits::digits)
+ {
+ TEST_EXPECTED_RANGE(RANGE_OVERFLOW, static_cast<Src>(DstLimits::max()));
+ }
+ else
+ {
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
+ }
+ TEST_EXPECTED_RANGE(RANGE_VALID,
+ static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::min()));
+ }
+ }
+ else if (SrcLimits::is_signed)
+ {
+ TEST_EXPECTED_VALUE(-1, checked_dst - static_cast<Src>(1));
+ TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
+ }
+ else
+ {
+ TEST_EXPECTED_FAILURE(checked_dst - static_cast<Src>(1));
+ TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
+ }
+ }
+};
+
+template <typename Dst, typename Src>
+struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL>
+{
+ static void Test(const char *dst, const char *src, int line)
+ {
+ typedef numeric_limits<Src> SrcLimits;
+ typedef numeric_limits<Dst> DstLimits;
+ static_assert(sizeof(Dst) >= sizeof(Src),
+ "Destination must be equal or wider than source.");
+ static_assert(SrcLimits::is_signed, "Source must be signed");
+ static_assert(!DstLimits::is_signed, "Destination must be unsigned");
+
+ const CheckedNumeric<Dst> checked_dst;
+ TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max());
+ TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
+ TEST_EXPECTED_FAILURE(checked_dst + -SrcLimits::max());
+
+ TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
+ TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
+ TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
+ }
+};
+
+template <typename Dst, typename Src>
+struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW>
+{
+ static void Test(const char *dst, const char *src, int line)
+ {
+ typedef numeric_limits<Src> SrcLimits;
+ typedef numeric_limits<Dst> DstLimits;
+ static_assert(
+ (DstLimits::is_integer && SrcLimits::is_iec559) || (sizeof(Dst) < sizeof(Src)),
+ "Destination must be narrower than source.");
+ static_assert(SrcLimits::is_signed, "Source must be signed.");
+ static_assert(!DstLimits::is_signed, "Destination must be unsigned.");
+
+ const CheckedNumeric<Dst> checked_dst;
+ TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
+ TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
+ TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
+ TEST_EXPECTED_FAILURE(checked_dst + -SrcLimits::max());
+
+ TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
+ TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
+ if (SrcLimits::is_iec559)
+ {
+ TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
+ TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
+ TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
+ TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
+ if (DstLimits::is_integer)
+ {
+ if (SrcLimits::digits < DstLimits::digits)
+ {
+ TEST_EXPECTED_RANGE(RANGE_OVERFLOW, static_cast<Src>(DstLimits::max()));
+ }
+ else
+ {
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
+ }
+ TEST_EXPECTED_RANGE(RANGE_VALID,
+ static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::min()));
+ }
+ }
+ else
+ {
+ TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
+ }
+ }
+};
+
+template <typename Dst, typename Src>
+struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL>
+{
+ static void Test(const char *dst, const char *src, int line)
+ {
+ typedef numeric_limits<Src> SrcLimits;
+ typedef numeric_limits<Dst> DstLimits;
+ static_assert(sizeof(Dst) <= sizeof(Src),
+ "Destination must be narrower or equal to source.");
+ static_assert(!SrcLimits::is_signed, "Source must be unsigned.");
+ static_assert(DstLimits::is_signed, "Destination must be signed.");
+
+ const CheckedNumeric<Dst> checked_dst;
+ TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
+ TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
+ TEST_EXPECTED_VALUE(SrcLimits::min(), checked_dst + SrcLimits::min());
+
+ TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
+ TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
+ }
+};
+
+// Helper macro to wrap displaying the conversion types and line numbers
+#define TEST_NUMERIC_CONVERSION(d, s, t) TestNumericConversion<d, s, t>::Test(#d, #s, __LINE__)
+
+TEST(SafeNumerics, IntMinOperations)
+{
+ TEST_NUMERIC_CONVERSION(int8_t, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(uint8_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
+
+ TEST_NUMERIC_CONVERSION(int8_t, int, SIGN_PRESERVING_NARROW);
+ TEST_NUMERIC_CONVERSION(uint8_t, unsigned int, SIGN_PRESERVING_NARROW);
+ TEST_NUMERIC_CONVERSION(int8_t, float, SIGN_PRESERVING_NARROW);
+
+ TEST_NUMERIC_CONVERSION(uint8_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
+
+ TEST_NUMERIC_CONVERSION(uint8_t, int, SIGN_TO_UNSIGN_NARROW);
+ TEST_NUMERIC_CONVERSION(uint8_t, intmax_t, SIGN_TO_UNSIGN_NARROW);
+ TEST_NUMERIC_CONVERSION(uint8_t, float, SIGN_TO_UNSIGN_NARROW);
+
+ TEST_NUMERIC_CONVERSION(int8_t, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
+ TEST_NUMERIC_CONVERSION(int8_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
+}
+
+TEST(SafeNumerics, IntOperations)
+{
+ TEST_NUMERIC_CONVERSION(int, int, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(unsigned int, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(int, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(unsigned int, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(int, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
+
+ TEST_NUMERIC_CONVERSION(int, intmax_t, SIGN_PRESERVING_NARROW);
+ TEST_NUMERIC_CONVERSION(unsigned int, uintmax_t, SIGN_PRESERVING_NARROW);
+ TEST_NUMERIC_CONVERSION(int, float, SIGN_PRESERVING_NARROW);
+ TEST_NUMERIC_CONVERSION(int, double, SIGN_PRESERVING_NARROW);
+
+ TEST_NUMERIC_CONVERSION(unsigned int, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
+ TEST_NUMERIC_CONVERSION(unsigned int, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
+
+ TEST_NUMERIC_CONVERSION(unsigned int, intmax_t, SIGN_TO_UNSIGN_NARROW);
+ TEST_NUMERIC_CONVERSION(unsigned int, float, SIGN_TO_UNSIGN_NARROW);
+ TEST_NUMERIC_CONVERSION(unsigned int, double, SIGN_TO_UNSIGN_NARROW);
+
+ TEST_NUMERIC_CONVERSION(int, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
+ TEST_NUMERIC_CONVERSION(int, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
+}
+
+TEST(SafeNumerics, IntMaxOperations)
+{
+ TEST_NUMERIC_CONVERSION(intmax_t, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(uintmax_t, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(intmax_t, int, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(uintmax_t, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(intmax_t, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(intmax_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
+
+ TEST_NUMERIC_CONVERSION(intmax_t, float, SIGN_PRESERVING_NARROW);
+ TEST_NUMERIC_CONVERSION(intmax_t, double, SIGN_PRESERVING_NARROW);
+
+ TEST_NUMERIC_CONVERSION(uintmax_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
+ TEST_NUMERIC_CONVERSION(uintmax_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
+
+ TEST_NUMERIC_CONVERSION(uintmax_t, float, SIGN_TO_UNSIGN_NARROW);
+ TEST_NUMERIC_CONVERSION(uintmax_t, double, SIGN_TO_UNSIGN_NARROW);
+
+ TEST_NUMERIC_CONVERSION(intmax_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
+}
+
+TEST(SafeNumerics, FloatOperations)
+{
+ TEST_NUMERIC_CONVERSION(float, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(float, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(float, int, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(float, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING);
+
+ TEST_NUMERIC_CONVERSION(float, double, SIGN_PRESERVING_NARROW);
+}
+
+TEST(SafeNumerics, DoubleOperations)
+{
+ TEST_NUMERIC_CONVERSION(double, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(double, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(double, int, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(double, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING);
+}
+
+TEST(SafeNumerics, SizeTOperations)
+{
+ TEST_NUMERIC_CONVERSION(size_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
+ TEST_NUMERIC_CONVERSION(int, size_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
+}
+
+TEST(SafeNumerics, CastTests)
+{
+// MSVC catches and warns that we're forcing saturation in these tests.
+// Since that's intentional, we need to shut this warning off.
+#if defined(COMPILER_MSVC)
+#pragma warning(disable : 4756)
+#endif
+
+ int small_positive = 1;
+ int small_negative = -1;
+ double double_small = 1.0;
+ double double_large = numeric_limits<double>::max();
+ double double_infinity = numeric_limits<float>::infinity();
+ double double_large_int = numeric_limits<int>::max();
+ double double_small_int = numeric_limits<int>::min();
+
+ // Just test that the casts compile, since the other tests cover logic.
+ EXPECT_EQ(0, checked_cast<int>(static_cast<size_t>(0)));
+ EXPECT_EQ(0, strict_cast<int>(static_cast<char>(0)));
+ EXPECT_EQ(0, strict_cast<int>(static_cast<unsigned char>(0)));
+ EXPECT_EQ(0U, strict_cast<unsigned>(static_cast<unsigned char>(0)));
+ EXPECT_EQ(1ULL, static_cast<uint64_t>(StrictNumeric<size_t>(1U)));
+ EXPECT_EQ(1ULL, static_cast<uint64_t>(SizeT(1U)));
+ EXPECT_EQ(1U, static_cast<size_t>(StrictNumeric<unsigned>(1U)));
+
+ EXPECT_TRUE(CheckedNumeric<uint64_t>(StrictNumeric<unsigned>(1U)).IsValid());
+ EXPECT_TRUE(CheckedNumeric<int>(StrictNumeric<unsigned>(1U)).IsValid());
+ EXPECT_FALSE(CheckedNumeric<unsigned>(StrictNumeric<int>(-1)).IsValid());
+
+ EXPECT_TRUE(IsValueNegative(-1));
+ EXPECT_TRUE(IsValueNegative(numeric_limits<int>::min()));
+ EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::min()));
+ EXPECT_TRUE(IsValueNegative(-numeric_limits<double>::max()));
+ EXPECT_FALSE(IsValueNegative(0));
+ EXPECT_FALSE(IsValueNegative(1));
+ EXPECT_FALSE(IsValueNegative(0u));
+ EXPECT_FALSE(IsValueNegative(1u));
+ EXPECT_FALSE(IsValueNegative(numeric_limits<int>::max()));
+ EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::max()));
+ EXPECT_FALSE(IsValueNegative(numeric_limits<double>::max()));
+
+ // These casts and coercions will fail to compile:
+ // EXPECT_EQ(0, strict_cast<int>(static_cast<size_t>(0)));
+ // EXPECT_EQ(0, strict_cast<size_t>(static_cast<int>(0)));
+ // EXPECT_EQ(1ULL, StrictNumeric<size_t>(1));
+ // EXPECT_EQ(1, StrictNumeric<size_t>(1U));
+
+ // Test various saturation corner cases.
+ EXPECT_EQ(saturated_cast<int>(small_negative), static_cast<int>(small_negative));
+ EXPECT_EQ(saturated_cast<int>(small_positive), static_cast<int>(small_positive));
+ EXPECT_EQ(saturated_cast<unsigned>(small_negative), static_cast<unsigned>(0));
+ EXPECT_EQ(saturated_cast<int>(double_small), static_cast<int>(double_small));
+ EXPECT_EQ(saturated_cast<int>(double_large), numeric_limits<int>::max());
+ EXPECT_EQ(saturated_cast<float>(double_large), double_infinity);
+ EXPECT_EQ(saturated_cast<float>(-double_large), -double_infinity);
+ EXPECT_EQ(numeric_limits<int>::min(), saturated_cast<int>(double_small_int));
+ EXPECT_EQ(numeric_limits<int>::max(), saturated_cast<int>(double_large_int));
+
+ float not_a_number =
+ std::numeric_limits<float>::infinity() - std::numeric_limits<float>::infinity();
+ EXPECT_TRUE(std::isnan(not_a_number));
+ EXPECT_EQ(0, saturated_cast<int>(not_a_number));
+}
+
+#if GTEST_HAS_DEATH_TEST
+
+TEST(SafeNumerics, SaturatedCastChecks)
+{
+ float not_a_number =
+ std::numeric_limits<float>::infinity() - std::numeric_limits<float>::infinity();
+ EXPECT_TRUE(std::isnan(not_a_number));
+ EXPECT_DEATH((saturated_cast<int, base::SaturatedCastNaNBehaviorCheck>(not_a_number)), "");
+}
+
+#endif // GTEST_HAS_DEATH_TEST
+
+TEST(SafeNumerics, IsValueInRangeForNumericType)
+{
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(1));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(2));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(-1));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0xffffffffu));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0xffffffff)));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000000)));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000001)));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(std::numeric_limits<int32_t>::min()));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(std::numeric_limits<int64_t>::min()));
+
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(1));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(2));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(-1));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffff));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffffu));
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0x80000000u));
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0xffffffffu));
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x80000000)));
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0xffffffff)));
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x100000000)));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(std::numeric_limits<int32_t>::min()));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
+ static_cast<int64_t>(std::numeric_limits<int32_t>::min())));
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
+ static_cast<int64_t>(std::numeric_limits<int32_t>::min()) - 1));
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(std::numeric_limits<int64_t>::min()));
+
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(1));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(2));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(-1));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0xffffffffu));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0xffffffff)));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000000)));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000001)));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(std::numeric_limits<int32_t>::min()));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(INT64_C(-1)));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(std::numeric_limits<int64_t>::min()));
+
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(1));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(2));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(-1));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffff));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffffu));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x80000000u));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0xffffffffu));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x80000000)));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0xffffffff)));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x100000000)));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x7fffffffffffffff)));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(UINT64_C(0x7fffffffffffffff)));
+ EXPECT_FALSE(IsValueInRangeForNumericType<int64_t>(UINT64_C(0x8000000000000000)));
+ EXPECT_FALSE(IsValueInRangeForNumericType<int64_t>(UINT64_C(0xffffffffffffffff)));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(std::numeric_limits<int32_t>::min()));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
+ static_cast<int64_t>(std::numeric_limits<int32_t>::min())));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(std::numeric_limits<int64_t>::min()));
+}
+
+TEST(SafeNumerics, CompoundNumericOperations)
+{
+ CheckedNumeric<int> a = 1;
+ CheckedNumeric<int> b = 2;
+ CheckedNumeric<int> c = 3;
+ CheckedNumeric<int> d = 4;
+ a += b;
+ EXPECT_EQ(3, a.ValueOrDie());
+ a -= c;
+ EXPECT_EQ(0, a.ValueOrDie());
+ d /= b;
+ EXPECT_EQ(2, d.ValueOrDie());
+ d *= d;
+ EXPECT_EQ(4, d.ValueOrDie());
+
+ CheckedNumeric<int> too_large = std::numeric_limits<int>::max();
+ EXPECT_TRUE(too_large.IsValid());
+ too_large += d;
+ EXPECT_FALSE(too_large.IsValid());
+ too_large -= d;
+ EXPECT_FALSE(too_large.IsValid());
+ too_large /= d;
+ EXPECT_FALSE(too_large.IsValid());
+}
diff --git a/gfx/angle/src/common/tls.cpp b/gfx/angle/src/common/tls.cpp
new file mode 100755
index 000000000..cb1b32d32
--- /dev/null
+++ b/gfx/angle/src/common/tls.cpp
@@ -0,0 +1,156 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// tls.cpp: Simple cross-platform interface for thread local storage.
+
+#include "common/tls.h"
+
+#include <assert.h>
+
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+#include <vector>
+#include <set>
+#include <map>
+#include <mutex>
+
+#include <wrl/client.h>
+#include <wrl/async.h>
+#include <Windows.System.Threading.h>
+
+using namespace std;
+using namespace Windows::Foundation;
+using namespace ABI::Windows::System::Threading;
+
+// Thread local storage for Windows Store support
+typedef vector<void*> ThreadLocalData;
+
+static __declspec(thread) ThreadLocalData* currentThreadData = nullptr;
+static set<ThreadLocalData*> allThreadData;
+static DWORD nextTlsIndex = 0;
+static vector<DWORD> freeTlsIndices;
+
+#endif
+
+TLSIndex CreateTLSIndex()
+{
+ TLSIndex index;
+
+#ifdef ANGLE_PLATFORM_WINDOWS
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+ if (!freeTlsIndices.empty())
+ {
+ DWORD result = freeTlsIndices.back();
+ freeTlsIndices.pop_back();
+ index = result;
+ }
+ else
+ {
+ index = nextTlsIndex++;
+ }
+#else
+ index = TlsAlloc();
+#endif
+
+#elif defined(ANGLE_PLATFORM_POSIX)
+ // Create global pool key
+ if ((pthread_key_create(&index, NULL)) != 0)
+ {
+ index = TLS_INVALID_INDEX;
+ }
+#endif
+
+ assert(index != TLS_INVALID_INDEX && "CreateTLSIndex(): Unable to allocate Thread Local Storage");
+ return index;
+}
+
+bool DestroyTLSIndex(TLSIndex index)
+{
+ assert(index != TLS_INVALID_INDEX && "DestroyTLSIndex(): Invalid TLS Index");
+ if (index == TLS_INVALID_INDEX)
+ {
+ return false;
+ }
+
+#ifdef ANGLE_PLATFORM_WINDOWS
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+ assert(index < nextTlsIndex);
+ assert(find(freeTlsIndices.begin(), freeTlsIndices.end(), index) == freeTlsIndices.end());
+
+ freeTlsIndices.push_back(index);
+ for (auto threadData : allThreadData)
+ {
+ if (threadData->size() > index)
+ {
+ threadData->at(index) = nullptr;
+ }
+ }
+ return true;
+#else
+ return (TlsFree(index) == TRUE);
+#endif
+#elif defined(ANGLE_PLATFORM_POSIX)
+ return (pthread_key_delete(index) == 0);
+#endif
+}
+
+bool SetTLSValue(TLSIndex index, void *value)
+{
+ assert(index != TLS_INVALID_INDEX && "SetTLSValue(): Invalid TLS Index");
+ if (index == TLS_INVALID_INDEX)
+ {
+ return false;
+ }
+
+#ifdef ANGLE_PLATFORM_WINDOWS
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+ ThreadLocalData* threadData = currentThreadData;
+ if (!threadData)
+ {
+ threadData = new ThreadLocalData(index + 1, nullptr);
+ allThreadData.insert(threadData);
+ currentThreadData = threadData;
+ }
+ else if (threadData->size() <= index)
+ {
+ threadData->resize(index + 1, nullptr);
+ }
+
+ threadData->at(index) = value;
+ return true;
+#else
+ return (TlsSetValue(index, value) == TRUE);
+#endif
+#elif defined(ANGLE_PLATFORM_POSIX)
+ return (pthread_setspecific(index, value) == 0);
+#endif
+}
+
+void *GetTLSValue(TLSIndex index)
+{
+ assert(index != TLS_INVALID_INDEX && "GetTLSValue(): Invalid TLS Index");
+ if (index == TLS_INVALID_INDEX)
+ {
+ return NULL;
+ }
+
+#ifdef ANGLE_PLATFORM_WINDOWS
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+ ThreadLocalData* threadData = currentThreadData;
+ if (threadData && threadData->size() > index)
+ {
+ return threadData->at(index);
+ }
+ else
+ {
+ return nullptr;
+ }
+#else
+ return TlsGetValue(index);
+#endif
+#elif defined(ANGLE_PLATFORM_POSIX)
+ return pthread_getspecific(index);
+#endif
+}
diff --git a/gfx/angle/src/common/tls.h b/gfx/angle/src/common/tls.h
new file mode 100755
index 000000000..ca9e07ab7
--- /dev/null
+++ b/gfx/angle/src/common/tls.h
@@ -0,0 +1,46 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// tls.h: Simple cross-platform interface for thread local storage.
+
+#ifndef COMMON_TLS_H_
+#define COMMON_TLS_H_
+
+#include "common/platform.h"
+
+#ifdef ANGLE_PLATFORM_WINDOWS
+
+// TLS does not exist for Windows Store and needs to be emulated
+# ifdef ANGLE_ENABLE_WINDOWS_STORE
+# ifndef TLS_OUT_OF_INDEXES
+# define TLS_OUT_OF_INDEXES static_cast<DWORD>(0xFFFFFFFF)
+# endif
+# ifndef CREATE_SUSPENDED
+# define CREATE_SUSPENDED 0x00000004
+# endif
+# endif
+ typedef DWORD TLSIndex;
+# define TLS_INVALID_INDEX (TLS_OUT_OF_INDEXES)
+#elif defined(ANGLE_PLATFORM_POSIX)
+# include <pthread.h>
+# include <semaphore.h>
+# include <errno.h>
+ typedef pthread_key_t TLSIndex;
+# define TLS_INVALID_INDEX (static_cast<TLSIndex>(-1))
+#else
+# error Unsupported platform.
+#endif
+
+// TODO(kbr): for POSIX platforms this will have to be changed to take
+// in a destructor function pointer, to allow the thread-local storage
+// to be properly deallocated upon thread exit.
+TLSIndex CreateTLSIndex();
+bool DestroyTLSIndex(TLSIndex index);
+
+bool SetTLSValue(TLSIndex index, void *value);
+void *GetTLSValue(TLSIndex index);
+
+#endif // COMMON_TLS_H_
diff --git a/gfx/angle/src/common/utilities.cpp b/gfx/angle/src/common/utilities.cpp
new file mode 100755
index 000000000..89e383405
--- /dev/null
+++ b/gfx/angle/src/common/utilities.cpp
@@ -0,0 +1,843 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// utilities.cpp: Conversion functions and other utility routines.
+
+#include "common/utilities.h"
+#include "common/mathutil.h"
+#include "common/platform.h"
+
+#include <set>
+
+#if defined(ANGLE_ENABLE_WINDOWS_STORE)
+# include <wrl.h>
+# include <wrl/wrappers/corewrappers.h>
+# include <windows.applicationmodel.core.h>
+# include <windows.graphics.display.h>
+#endif
+
+namespace
+{
+
+template <class IndexType>
+gl::IndexRange ComputeTypedIndexRange(const IndexType *indices,
+ size_t count,
+ bool primitiveRestartEnabled,
+ GLuint primitiveRestartIndex)
+{
+ ASSERT(count > 0);
+
+ IndexType minIndex = 0;
+ IndexType maxIndex = 0;
+ size_t nonPrimitiveRestartIndices = 0;
+
+ if (primitiveRestartEnabled)
+ {
+ // Find the first non-primitive restart index to initialize the min and max values
+ size_t i = 0;
+ for (; i < count; i++)
+ {
+ if (indices[i] != primitiveRestartIndex)
+ {
+ minIndex = indices[i];
+ maxIndex = indices[i];
+ nonPrimitiveRestartIndices++;
+ break;
+ }
+ }
+
+ // Loop over the rest of the indices
+ for (; i < count; i++)
+ {
+ if (indices[i] != primitiveRestartIndex)
+ {
+ if (minIndex > indices[i])
+ {
+ minIndex = indices[i];
+ }
+ if (maxIndex < indices[i])
+ {
+ maxIndex = indices[i];
+ }
+ nonPrimitiveRestartIndices++;
+ }
+ }
+ }
+ else
+ {
+ minIndex = indices[0];
+ maxIndex = indices[0];
+ nonPrimitiveRestartIndices = count;
+
+ for (size_t i = 1; i < count; i++)
+ {
+ if (minIndex > indices[i])
+ {
+ minIndex = indices[i];
+ }
+ if (maxIndex < indices[i])
+ {
+ maxIndex = indices[i];
+ }
+ }
+ }
+
+ return gl::IndexRange(static_cast<size_t>(minIndex), static_cast<size_t>(maxIndex),
+ nonPrimitiveRestartIndices);
+}
+
+} // anonymous namespace
+
+namespace gl
+{
+
+int VariableComponentCount(GLenum type)
+{
+ return VariableRowCount(type) * VariableColumnCount(type);
+}
+
+GLenum VariableComponentType(GLenum type)
+{
+ switch(type)
+ {
+ case GL_BOOL:
+ case GL_BOOL_VEC2:
+ case GL_BOOL_VEC3:
+ case GL_BOOL_VEC4:
+ return GL_BOOL;
+ case GL_FLOAT:
+ case GL_FLOAT_VEC2:
+ case GL_FLOAT_VEC3:
+ case GL_FLOAT_VEC4:
+ case GL_FLOAT_MAT2:
+ case GL_FLOAT_MAT3:
+ case GL_FLOAT_MAT4:
+ case GL_FLOAT_MAT2x3:
+ case GL_FLOAT_MAT3x2:
+ case GL_FLOAT_MAT2x4:
+ case GL_FLOAT_MAT4x2:
+ case GL_FLOAT_MAT3x4:
+ case GL_FLOAT_MAT4x3:
+ return GL_FLOAT;
+ case GL_INT:
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_3D:
+ case GL_SAMPLER_CUBE:
+ case GL_SAMPLER_2D_ARRAY:
+ case GL_SAMPLER_EXTERNAL_OES:
+ case GL_INT_SAMPLER_2D:
+ case GL_INT_SAMPLER_3D:
+ case GL_INT_SAMPLER_CUBE:
+ case GL_INT_SAMPLER_2D_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_2D:
+ case GL_UNSIGNED_INT_SAMPLER_3D:
+ case GL_UNSIGNED_INT_SAMPLER_CUBE:
+ case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+ case GL_SAMPLER_2D_SHADOW:
+ case GL_SAMPLER_CUBE_SHADOW:
+ case GL_SAMPLER_2D_ARRAY_SHADOW:
+ case GL_INT_VEC2:
+ case GL_INT_VEC3:
+ case GL_INT_VEC4:
+ return GL_INT;
+ case GL_UNSIGNED_INT:
+ case GL_UNSIGNED_INT_VEC2:
+ case GL_UNSIGNED_INT_VEC3:
+ case GL_UNSIGNED_INT_VEC4:
+ return GL_UNSIGNED_INT;
+ default:
+ UNREACHABLE();
+ }
+
+ return GL_NONE;
+}
+
+size_t VariableComponentSize(GLenum type)
+{
+ switch(type)
+ {
+ case GL_BOOL: return sizeof(GLint);
+ case GL_FLOAT: return sizeof(GLfloat);
+ case GL_INT: return sizeof(GLint);
+ case GL_UNSIGNED_INT: return sizeof(GLuint);
+ default: UNREACHABLE();
+ }
+
+ return 0;
+}
+
+size_t VariableInternalSize(GLenum type)
+{
+ // Expanded to 4-element vectors
+ return VariableComponentSize(VariableComponentType(type)) * VariableRowCount(type) * 4;
+}
+
+size_t VariableExternalSize(GLenum type)
+{
+ return VariableComponentSize(VariableComponentType(type)) * VariableComponentCount(type);
+}
+
+GLenum VariableBoolVectorType(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ case GL_INT:
+ case GL_UNSIGNED_INT:
+ return GL_BOOL;
+ case GL_FLOAT_VEC2:
+ case GL_INT_VEC2:
+ case GL_UNSIGNED_INT_VEC2:
+ return GL_BOOL_VEC2;
+ case GL_FLOAT_VEC3:
+ case GL_INT_VEC3:
+ case GL_UNSIGNED_INT_VEC3:
+ return GL_BOOL_VEC3;
+ case GL_FLOAT_VEC4:
+ case GL_INT_VEC4:
+ case GL_UNSIGNED_INT_VEC4:
+ return GL_BOOL_VEC4;
+
+ default:
+ UNREACHABLE();
+ return GL_NONE;
+ }
+}
+
+int VariableRowCount(GLenum type)
+{
+ switch (type)
+ {
+ case GL_NONE:
+ case GL_STRUCT_ANGLEX:
+ return 0;
+ case GL_BOOL:
+ case GL_FLOAT:
+ case GL_INT:
+ case GL_UNSIGNED_INT:
+ case GL_BOOL_VEC2:
+ case GL_FLOAT_VEC2:
+ case GL_INT_VEC2:
+ case GL_UNSIGNED_INT_VEC2:
+ case GL_BOOL_VEC3:
+ case GL_FLOAT_VEC3:
+ case GL_INT_VEC3:
+ case GL_UNSIGNED_INT_VEC3:
+ case GL_BOOL_VEC4:
+ case GL_FLOAT_VEC4:
+ case GL_INT_VEC4:
+ case GL_UNSIGNED_INT_VEC4:
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_3D:
+ case GL_SAMPLER_CUBE:
+ case GL_SAMPLER_2D_ARRAY:
+ case GL_SAMPLER_EXTERNAL_OES:
+ case GL_SAMPLER_2D_RECT_ARB:
+ case GL_INT_SAMPLER_2D:
+ case GL_INT_SAMPLER_3D:
+ case GL_INT_SAMPLER_CUBE:
+ case GL_INT_SAMPLER_2D_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_2D:
+ case GL_UNSIGNED_INT_SAMPLER_3D:
+ case GL_UNSIGNED_INT_SAMPLER_CUBE:
+ case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+ case GL_SAMPLER_2D_SHADOW:
+ case GL_SAMPLER_CUBE_SHADOW:
+ case GL_SAMPLER_2D_ARRAY_SHADOW:
+ case GL_IMAGE_2D:
+ case GL_INT_IMAGE_2D:
+ case GL_UNSIGNED_INT_IMAGE_2D:
+ case GL_IMAGE_2D_ARRAY:
+ case GL_INT_IMAGE_2D_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
+ case GL_IMAGE_3D:
+ case GL_INT_IMAGE_3D:
+ case GL_UNSIGNED_INT_IMAGE_3D:
+ case GL_IMAGE_CUBE:
+ case GL_INT_IMAGE_CUBE:
+ case GL_UNSIGNED_INT_IMAGE_CUBE:
+ return 1;
+ case GL_FLOAT_MAT2:
+ case GL_FLOAT_MAT3x2:
+ case GL_FLOAT_MAT4x2:
+ return 2;
+ case GL_FLOAT_MAT3:
+ case GL_FLOAT_MAT2x3:
+ case GL_FLOAT_MAT4x3:
+ return 3;
+ case GL_FLOAT_MAT4:
+ case GL_FLOAT_MAT2x4:
+ case GL_FLOAT_MAT3x4:
+ return 4;
+ default:
+ UNREACHABLE();
+ }
+
+ return 0;
+}
+
+int VariableColumnCount(GLenum type)
+{
+ switch (type)
+ {
+ case GL_NONE:
+ case GL_STRUCT_ANGLEX:
+ return 0;
+ case GL_BOOL:
+ case GL_FLOAT:
+ case GL_INT:
+ case GL_UNSIGNED_INT:
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_3D:
+ case GL_SAMPLER_CUBE:
+ case GL_SAMPLER_2D_ARRAY:
+ case GL_INT_SAMPLER_2D:
+ case GL_INT_SAMPLER_3D:
+ case GL_INT_SAMPLER_CUBE:
+ case GL_INT_SAMPLER_2D_ARRAY:
+ case GL_SAMPLER_EXTERNAL_OES:
+ case GL_SAMPLER_2D_RECT_ARB:
+ case GL_UNSIGNED_INT_SAMPLER_2D:
+ case GL_UNSIGNED_INT_SAMPLER_3D:
+ case GL_UNSIGNED_INT_SAMPLER_CUBE:
+ case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+ case GL_SAMPLER_2D_SHADOW:
+ case GL_SAMPLER_CUBE_SHADOW:
+ case GL_SAMPLER_2D_ARRAY_SHADOW:
+ return 1;
+ case GL_BOOL_VEC2:
+ case GL_FLOAT_VEC2:
+ case GL_INT_VEC2:
+ case GL_UNSIGNED_INT_VEC2:
+ case GL_FLOAT_MAT2:
+ case GL_FLOAT_MAT2x3:
+ case GL_FLOAT_MAT2x4:
+ return 2;
+ case GL_BOOL_VEC3:
+ case GL_FLOAT_VEC3:
+ case GL_INT_VEC3:
+ case GL_UNSIGNED_INT_VEC3:
+ case GL_FLOAT_MAT3:
+ case GL_FLOAT_MAT3x2:
+ case GL_FLOAT_MAT3x4:
+ return 3;
+ case GL_BOOL_VEC4:
+ case GL_FLOAT_VEC4:
+ case GL_INT_VEC4:
+ case GL_UNSIGNED_INT_VEC4:
+ case GL_FLOAT_MAT4:
+ case GL_FLOAT_MAT4x2:
+ case GL_FLOAT_MAT4x3:
+ return 4;
+ default:
+ UNREACHABLE();
+ }
+
+ return 0;
+}
+
+bool IsSamplerType(GLenum type)
+{
+ switch (type)
+ {
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_3D:
+ case GL_SAMPLER_CUBE:
+ case GL_SAMPLER_2D_ARRAY:
+ case GL_SAMPLER_EXTERNAL_OES:
+ case GL_INT_SAMPLER_2D:
+ case GL_INT_SAMPLER_3D:
+ case GL_INT_SAMPLER_CUBE:
+ case GL_INT_SAMPLER_2D_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_2D:
+ case GL_UNSIGNED_INT_SAMPLER_3D:
+ case GL_UNSIGNED_INT_SAMPLER_CUBE:
+ case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+ case GL_SAMPLER_2D_SHADOW:
+ case GL_SAMPLER_CUBE_SHADOW:
+ case GL_SAMPLER_2D_ARRAY_SHADOW:
+ return true;
+ }
+
+ return false;
+}
+
+GLenum SamplerTypeToTextureType(GLenum samplerType)
+{
+ switch (samplerType)
+ {
+ case GL_SAMPLER_2D:
+ case GL_INT_SAMPLER_2D:
+ case GL_UNSIGNED_INT_SAMPLER_2D:
+ case GL_SAMPLER_2D_SHADOW:
+ return GL_TEXTURE_2D;
+
+ case GL_SAMPLER_EXTERNAL_OES:
+ return GL_TEXTURE_EXTERNAL_OES;
+
+ case GL_SAMPLER_CUBE:
+ case GL_INT_SAMPLER_CUBE:
+ case GL_UNSIGNED_INT_SAMPLER_CUBE:
+ case GL_SAMPLER_CUBE_SHADOW:
+ return GL_TEXTURE_CUBE_MAP;
+
+ case GL_SAMPLER_2D_ARRAY:
+ case GL_INT_SAMPLER_2D_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+ case GL_SAMPLER_2D_ARRAY_SHADOW:
+ return GL_TEXTURE_2D_ARRAY;
+
+ case GL_SAMPLER_3D:
+ case GL_INT_SAMPLER_3D:
+ case GL_UNSIGNED_INT_SAMPLER_3D:
+ return GL_TEXTURE_3D;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+bool IsMatrixType(GLenum type)
+{
+ return VariableRowCount(type) > 1;
+}
+
+GLenum TransposeMatrixType(GLenum type)
+{
+ if (!IsMatrixType(type))
+ {
+ return type;
+ }
+
+ switch (type)
+ {
+ case GL_FLOAT_MAT2: return GL_FLOAT_MAT2;
+ case GL_FLOAT_MAT3: return GL_FLOAT_MAT3;
+ case GL_FLOAT_MAT4: return GL_FLOAT_MAT4;
+ case GL_FLOAT_MAT2x3: return GL_FLOAT_MAT3x2;
+ case GL_FLOAT_MAT3x2: return GL_FLOAT_MAT2x3;
+ case GL_FLOAT_MAT2x4: return GL_FLOAT_MAT4x2;
+ case GL_FLOAT_MAT4x2: return GL_FLOAT_MAT2x4;
+ case GL_FLOAT_MAT3x4: return GL_FLOAT_MAT4x3;
+ case GL_FLOAT_MAT4x3: return GL_FLOAT_MAT3x4;
+ default: UNREACHABLE(); return GL_NONE;
+ }
+}
+
+int MatrixRegisterCount(GLenum type, bool isRowMajorMatrix)
+{
+ ASSERT(IsMatrixType(type));
+ return isRowMajorMatrix ? VariableRowCount(type) : VariableColumnCount(type);
+}
+
+int MatrixComponentCount(GLenum type, bool isRowMajorMatrix)
+{
+ ASSERT(IsMatrixType(type));
+ return isRowMajorMatrix ? VariableColumnCount(type) : VariableRowCount(type);
+}
+
+int VariableRegisterCount(GLenum type)
+{
+ return IsMatrixType(type) ? VariableColumnCount(type) : 1;
+}
+
+int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize)
+{
+ ASSERT(allocationSize <= bitsSize);
+
+ unsigned int mask = std::numeric_limits<unsigned int>::max() >> (std::numeric_limits<unsigned int>::digits - allocationSize);
+
+ for (unsigned int i = 0; i < bitsSize - allocationSize + 1; i++)
+ {
+ if ((*bits & mask) == 0)
+ {
+ *bits |= mask;
+ return i;
+ }
+
+ mask <<= 1;
+ }
+
+ return -1;
+}
+
+static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1, "Unexpected GL cube map enum value.");
+static_assert(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2, "Unexpected GL cube map enum value.");
+static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3, "Unexpected GL cube map enum value.");
+static_assert(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4, "Unexpected GL cube map enum value.");
+static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5, "Unexpected GL cube map enum value.");
+
+bool IsCubeMapTextureTarget(GLenum target)
+{
+ return (target >= FirstCubeMapTextureTarget && target <= LastCubeMapTextureTarget);
+}
+
+size_t CubeMapTextureTargetToLayerIndex(GLenum target)
+{
+ ASSERT(IsCubeMapTextureTarget(target));
+ return target - static_cast<size_t>(FirstCubeMapTextureTarget);
+}
+
+GLenum LayerIndexToCubeMapTextureTarget(size_t index)
+{
+ ASSERT(index <= (LastCubeMapTextureTarget - FirstCubeMapTextureTarget));
+ return FirstCubeMapTextureTarget + static_cast<GLenum>(index);
+}
+
+IndexRange ComputeIndexRange(GLenum indexType,
+ const GLvoid *indices,
+ size_t count,
+ bool primitiveRestartEnabled)
+{
+ switch (indexType)
+ {
+ case GL_UNSIGNED_BYTE:
+ return ComputeTypedIndexRange(static_cast<const GLubyte *>(indices), count,
+ primitiveRestartEnabled,
+ GetPrimitiveRestartIndex(indexType));
+ case GL_UNSIGNED_SHORT:
+ return ComputeTypedIndexRange(static_cast<const GLushort *>(indices), count,
+ primitiveRestartEnabled,
+ GetPrimitiveRestartIndex(indexType));
+ case GL_UNSIGNED_INT:
+ return ComputeTypedIndexRange(static_cast<const GLuint *>(indices), count,
+ primitiveRestartEnabled,
+ GetPrimitiveRestartIndex(indexType));
+ default:
+ UNREACHABLE();
+ return IndexRange();
+ }
+}
+
+GLuint GetPrimitiveRestartIndex(GLenum indexType)
+{
+ switch (indexType)
+ {
+ case GL_UNSIGNED_BYTE:
+ return 0xFF;
+ case GL_UNSIGNED_SHORT:
+ return 0xFFFF;
+ case GL_UNSIGNED_INT:
+ return 0xFFFFFFFF;
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+bool IsTriangleMode(GLenum drawMode)
+{
+ switch (drawMode)
+ {
+ case GL_TRIANGLES:
+ case GL_TRIANGLE_FAN:
+ case GL_TRIANGLE_STRIP:
+ return true;
+ case GL_POINTS:
+ case GL_LINES:
+ case GL_LINE_LOOP:
+ case GL_LINE_STRIP:
+ return false;
+ default: UNREACHABLE();
+ }
+
+ return false;
+}
+
+// [OpenGL ES SL 3.00.4] Section 11 p. 120
+// Vertex Outs/Fragment Ins packing priorities
+int VariableSortOrder(GLenum type)
+{
+ switch (type)
+ {
+ // 1. Arrays of mat4 and mat4
+ // Non-square matrices of type matCxR consume the same space as a square
+ // matrix of type matN where N is the greater of C and R
+ case GL_FLOAT_MAT4:
+ case GL_FLOAT_MAT2x4:
+ case GL_FLOAT_MAT3x4:
+ case GL_FLOAT_MAT4x2:
+ case GL_FLOAT_MAT4x3:
+ return 0;
+
+ // 2. Arrays of mat2 and mat2 (since they occupy full rows)
+ case GL_FLOAT_MAT2:
+ return 1;
+
+ // 3. Arrays of vec4 and vec4
+ case GL_FLOAT_VEC4:
+ case GL_INT_VEC4:
+ case GL_BOOL_VEC4:
+ case GL_UNSIGNED_INT_VEC4:
+ return 2;
+
+ // 4. Arrays of mat3 and mat3
+ case GL_FLOAT_MAT3:
+ case GL_FLOAT_MAT2x3:
+ case GL_FLOAT_MAT3x2:
+ return 3;
+
+ // 5. Arrays of vec3 and vec3
+ case GL_FLOAT_VEC3:
+ case GL_INT_VEC3:
+ case GL_BOOL_VEC3:
+ case GL_UNSIGNED_INT_VEC3:
+ return 4;
+
+ // 6. Arrays of vec2 and vec2
+ case GL_FLOAT_VEC2:
+ case GL_INT_VEC2:
+ case GL_BOOL_VEC2:
+ case GL_UNSIGNED_INT_VEC2:
+ return 5;
+
+ // 7. Single component types
+ case GL_FLOAT:
+ case GL_INT:
+ case GL_BOOL:
+ case GL_UNSIGNED_INT:
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_CUBE:
+ case GL_SAMPLER_EXTERNAL_OES:
+ case GL_SAMPLER_2D_RECT_ARB:
+ case GL_SAMPLER_2D_ARRAY:
+ case GL_SAMPLER_3D:
+ case GL_INT_SAMPLER_2D:
+ case GL_INT_SAMPLER_3D:
+ case GL_INT_SAMPLER_CUBE:
+ case GL_INT_SAMPLER_2D_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_2D:
+ case GL_UNSIGNED_INT_SAMPLER_3D:
+ case GL_UNSIGNED_INT_SAMPLER_CUBE:
+ case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+ case GL_SAMPLER_2D_SHADOW:
+ case GL_SAMPLER_2D_ARRAY_SHADOW:
+ case GL_SAMPLER_CUBE_SHADOW:
+ return 6;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+std::string ParseUniformName(const std::string &name, size_t *outSubscript)
+{
+ // Strip any trailing array operator and retrieve the subscript
+ size_t open = name.find_last_of('[');
+ size_t close = name.find_last_of(']');
+ bool hasIndex = (open != std::string::npos) && (close == name.length() - 1);
+ if (!hasIndex)
+ {
+ if (outSubscript)
+ {
+ *outSubscript = GL_INVALID_INDEX;
+ }
+ return name;
+ }
+
+ if (outSubscript)
+ {
+ int index = atoi(name.substr(open + 1).c_str());
+ if (index >= 0)
+ {
+ *outSubscript = index;
+ }
+ else
+ {
+ *outSubscript = GL_INVALID_INDEX;
+ }
+ }
+
+ return name.substr(0, open);
+}
+
+template <>
+GLuint ConvertToGLuint(GLfloat param)
+{
+ return uiround<GLuint>(param);
+}
+
+template <>
+GLint ConvertToGLint(GLfloat param)
+{
+ return iround<GLint>(param);
+}
+
+template <>
+GLint ConvertFromGLfloat(GLfloat param)
+{
+ return iround<GLint>(param);
+}
+template <>
+GLuint ConvertFromGLfloat(GLfloat param)
+{
+ return uiround<GLuint>(param);
+}
+
+unsigned int ParseAndStripArrayIndex(std::string *name)
+{
+ unsigned int subscript = GL_INVALID_INDEX;
+
+ // Strip any trailing array operator and retrieve the subscript
+ size_t open = name->find_last_of('[');
+ size_t close = name->find_last_of(']');
+ if (open != std::string::npos && close == name->length() - 1)
+ {
+ subscript = atoi(name->c_str() + open + 1);
+ name->erase(open);
+ }
+
+ return subscript;
+}
+
+} // namespace gl
+
+namespace egl
+{
+static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 1,
+ "Unexpected EGL cube map enum value.");
+static_assert(EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 2,
+ "Unexpected EGL cube map enum value.");
+static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 3,
+ "Unexpected EGL cube map enum value.");
+static_assert(EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 4,
+ "Unexpected EGL cube map enum value.");
+static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 5,
+ "Unexpected EGL cube map enum value.");
+
+bool IsCubeMapTextureTarget(EGLenum target)
+{
+ return (target >= FirstCubeMapTextureTarget && target <= LastCubeMapTextureTarget);
+}
+
+size_t CubeMapTextureTargetToLayerIndex(EGLenum target)
+{
+ ASSERT(IsCubeMapTextureTarget(target));
+ return target - static_cast<size_t>(FirstCubeMapTextureTarget);
+}
+
+EGLenum LayerIndexToCubeMapTextureTarget(size_t index)
+{
+ ASSERT(index <= (LastCubeMapTextureTarget - FirstCubeMapTextureTarget));
+ return FirstCubeMapTextureTarget + static_cast<GLenum>(index);
+}
+
+bool IsTextureTarget(EGLenum target)
+{
+ switch (target)
+ {
+ case EGL_GL_TEXTURE_2D_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
+ case EGL_GL_TEXTURE_3D_KHR:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool IsRenderbufferTarget(EGLenum target)
+{
+ return target == EGL_GL_RENDERBUFFER_KHR;
+}
+} // namespace egl
+
+namespace egl_gl
+{
+GLenum EGLCubeMapTargetToGLCubeMapTarget(EGLenum eglTarget)
+{
+ ASSERT(egl::IsCubeMapTextureTarget(eglTarget));
+ return gl::LayerIndexToCubeMapTextureTarget(egl::CubeMapTextureTargetToLayerIndex(eglTarget));
+}
+
+GLenum EGLImageTargetToGLTextureTarget(EGLenum eglTarget)
+{
+ switch (eglTarget)
+ {
+ case EGL_GL_TEXTURE_2D_KHR:
+ return GL_TEXTURE_2D;
+
+ case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
+ case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
+ return EGLCubeMapTargetToGLCubeMapTarget(eglTarget);
+
+ case EGL_GL_TEXTURE_3D_KHR:
+ return GL_TEXTURE_3D;
+
+ default:
+ UNREACHABLE();
+ return GL_NONE;
+ }
+}
+
+GLuint EGLClientBufferToGLObjectHandle(EGLClientBuffer buffer)
+{
+ return static_cast<GLuint>(reinterpret_cast<uintptr_t>(buffer));
+}
+} // namespace egl_gl
+
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+std::string getTempPath()
+{
+#ifdef ANGLE_PLATFORM_WINDOWS
+ char path[MAX_PATH];
+ DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path);
+ if (pathLen == 0)
+ {
+ UNREACHABLE();
+ return std::string();
+ }
+
+ UINT unique = GetTempFileNameA(path, "sh", 0, path);
+ if (unique == 0)
+ {
+ UNREACHABLE();
+ return std::string();
+ }
+
+ return path;
+#else
+ UNIMPLEMENTED();
+ return "";
+#endif
+}
+
+void writeFile(const char* path, const void* content, size_t size)
+{
+ FILE* file = fopen(path, "w");
+ if (!file)
+ {
+ UNREACHABLE();
+ return;
+ }
+
+ fwrite(content, sizeof(char), size, file);
+ fclose(file);
+}
+#endif // !ANGLE_ENABLE_WINDOWS_STORE
+
+#if defined (ANGLE_PLATFORM_WINDOWS)
+
+// Causes the thread to relinquish the remainder of its time slice to any
+// other thread that is ready to run.If there are no other threads ready
+// to run, the function returns immediately, and the thread continues execution.
+void ScheduleYield()
+{
+ Sleep(0);
+}
+
+#endif
diff --git a/gfx/angle/src/common/utilities.h b/gfx/angle/src/common/utilities.h
new file mode 100755
index 000000000..16d6560a7
--- /dev/null
+++ b/gfx/angle/src/common/utilities.h
@@ -0,0 +1,172 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// utilities.h: Conversion functions and other utility routines.
+
+#ifndef COMMON_UTILITIES_H_
+#define COMMON_UTILITIES_H_
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "angle_gl.h"
+#include <string>
+#include <math.h>
+
+#include "common/mathutil.h"
+
+namespace gl
+{
+
+int VariableComponentCount(GLenum type);
+GLenum VariableComponentType(GLenum type);
+size_t VariableComponentSize(GLenum type);
+size_t VariableInternalSize(GLenum type);
+size_t VariableExternalSize(GLenum type);
+GLenum VariableBoolVectorType(GLenum type);
+int VariableRowCount(GLenum type);
+int VariableColumnCount(GLenum type);
+bool IsSamplerType(GLenum type);
+GLenum SamplerTypeToTextureType(GLenum samplerType);
+bool IsMatrixType(GLenum type);
+GLenum TransposeMatrixType(GLenum type);
+int VariableRegisterCount(GLenum type);
+int MatrixRegisterCount(GLenum type, bool isRowMajorMatrix);
+int MatrixComponentCount(GLenum type, bool isRowMajorMatrix);
+int VariableSortOrder(GLenum type);
+
+int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize);
+
+static const GLenum FirstCubeMapTextureTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+static const GLenum LastCubeMapTextureTarget = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
+bool IsCubeMapTextureTarget(GLenum target);
+size_t CubeMapTextureTargetToLayerIndex(GLenum target);
+GLenum LayerIndexToCubeMapTextureTarget(size_t index);
+
+// Parse the base uniform name and array index. Returns the base name of the uniform. outSubscript is
+// set to GL_INVALID_INDEX if the provided name is not an array or the array index is invalid.
+std::string ParseUniformName(const std::string &name, size_t *outSubscript);
+
+// Find the range of index values in the provided indices pointer. Primitive restart indices are
+// only counted in the range if primitive restart is disabled.
+IndexRange ComputeIndexRange(GLenum indexType,
+ const GLvoid *indices,
+ size_t count,
+ bool primitiveRestartEnabled);
+
+// Get the primitive restart index value for the given index type.
+GLuint GetPrimitiveRestartIndex(GLenum indexType);
+
+bool IsTriangleMode(GLenum drawMode);
+
+// [OpenGL ES 3.0.2] Section 2.3.1 page 14
+// Data Conversion For State-Setting Commands
+// Floating-point values are rounded to the nearest integer, instead of truncated, as done by static_cast.
+template <typename outT> outT iround(GLfloat value) { return static_cast<outT>(value > 0.0f ? floor(value + 0.5f) : ceil(value - 0.5f)); }
+template <typename outT> outT uiround(GLfloat value) { return static_cast<outT>(value + 0.5f); }
+
+// Helper for converting arbitrary GL types to other GL types used in queries and state setting
+template <typename ParamType>
+GLuint ConvertToGLuint(ParamType param)
+{
+ return static_cast<GLuint>(param);
+}
+template <>
+GLuint ConvertToGLuint(GLfloat param);
+
+template <typename ParamType>
+GLint ConvertToGLint(ParamType param)
+{
+ return static_cast<GLint>(param);
+}
+template <>
+GLint ConvertToGLint(GLfloat param);
+
+// Same conversion as uint
+template <typename ParamType>
+GLenum ConvertToGLenum(ParamType param)
+{
+ return static_cast<GLenum>(ConvertToGLuint(param));
+}
+
+template <typename ParamType>
+GLfloat ConvertToGLfloat(ParamType param)
+{
+ return static_cast<GLfloat>(param);
+}
+
+template <typename ParamType>
+ParamType ConvertFromGLfloat(GLfloat param)
+{
+ return static_cast<ParamType>(param);
+}
+template <>
+GLint ConvertFromGLfloat(GLfloat param);
+template <>
+GLuint ConvertFromGLfloat(GLfloat param);
+
+template <typename ParamType>
+ParamType ConvertFromGLenum(GLenum param)
+{
+ return static_cast<ParamType>(param);
+}
+
+template <typename ParamType>
+ParamType ConvertFromGLuint(GLuint param)
+{
+ return static_cast<ParamType>(param);
+}
+
+template <typename ParamType>
+ParamType ConvertFromGLint(GLint param)
+{
+ return static_cast<ParamType>(param);
+}
+
+template <typename ParamType>
+ParamType ConvertFromGLboolean(GLboolean param)
+{
+ return static_cast<ParamType>(param ? GL_TRUE : GL_FALSE);
+}
+
+template <typename ParamType>
+ParamType ConvertFromGLint64(GLint64 param)
+{
+ return clampCast<ParamType>(param);
+}
+
+unsigned int ParseAndStripArrayIndex(std::string *name);
+
+} // namespace gl
+
+namespace egl
+{
+static const EGLenum FirstCubeMapTextureTarget = EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR;
+static const EGLenum LastCubeMapTextureTarget = EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR;
+bool IsCubeMapTextureTarget(EGLenum target);
+size_t CubeMapTextureTargetToLayerIndex(EGLenum target);
+EGLenum LayerIndexToCubeMapTextureTarget(size_t index);
+bool IsTextureTarget(EGLenum target);
+bool IsRenderbufferTarget(EGLenum target);
+}
+
+namespace egl_gl
+{
+GLenum EGLCubeMapTargetToGLCubeMapTarget(EGLenum eglTarget);
+GLenum EGLImageTargetToGLTextureTarget(EGLenum eglTarget);
+GLuint EGLClientBufferToGLObjectHandle(EGLClientBuffer buffer);
+}
+
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+std::string getTempPath();
+void writeFile(const char* path, const void* data, size_t size);
+#endif
+
+#if defined (ANGLE_PLATFORM_WINDOWS)
+void ScheduleYield();
+#endif
+
+#endif // COMMON_UTILITIES_H_
diff --git a/gfx/angle/src/common/utilities_unittest.cpp b/gfx/angle/src/common/utilities_unittest.cpp
new file mode 100755
index 000000000..447bfc6eb
--- /dev/null
+++ b/gfx/angle/src/common/utilities_unittest.cpp
@@ -0,0 +1,55 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// utilities_unittest.cpp: Unit tests for ANGLE's GL utility functions
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "common/utilities.h"
+
+namespace
+{
+
+TEST(ParseUniformName, ArrayIndex)
+{
+ size_t index;
+ EXPECT_EQ("foo", gl::ParseUniformName("foo[123]", &index));
+ EXPECT_EQ(123u, index);
+
+ EXPECT_EQ("bar", gl::ParseUniformName("bar[0]", &index));
+ EXPECT_EQ(0u, index);
+}
+
+TEST(ParseUniformName, NegativeArrayIndex)
+{
+ size_t index;
+ EXPECT_EQ("foo", gl::ParseUniformName("foo[-1]", &index));
+ EXPECT_EQ(GL_INVALID_INDEX, index);
+}
+
+TEST(ParseUniformName, NoArrayIndex)
+{
+ size_t index;
+ EXPECT_EQ("foo", gl::ParseUniformName("foo", &index));
+ EXPECT_EQ(GL_INVALID_INDEX, index);
+}
+
+TEST(ParseUniformName, NULLArrayIndex)
+{
+ EXPECT_EQ("foo", gl::ParseUniformName("foo[10]", nullptr));
+}
+
+TEST(ParseUniformName, TrailingWhitespace)
+{
+ size_t index;
+ EXPECT_EQ("foo ", gl::ParseUniformName("foo ", &index));
+ EXPECT_EQ(GL_INVALID_INDEX, index);
+
+ EXPECT_EQ("foo[10] ", gl::ParseUniformName("foo[10] ", &index));
+ EXPECT_EQ(GL_INVALID_INDEX, index);
+}
+
+}
diff --git a/gfx/angle/src/common/version.h b/gfx/angle/src/common/version.h
new file mode 100755
index 000000000..b653ae39c
--- /dev/null
+++ b/gfx/angle/src/common/version.h
@@ -0,0 +1,28 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMMON_VERSION_H_
+#define COMMON_VERSION_H_
+
+#include "commit.h"
+
+#define ANGLE_MAJOR_VERSION 2
+#define ANGLE_MINOR_VERSION 1
+
+#ifndef ANGLE_REVISION
+#define ANGLE_REVISION 0
+#endif
+
+#define ANGLE_STRINGIFY(x) #x
+#define ANGLE_MACRO_STRINGIFY(x) ANGLE_STRINGIFY(x)
+
+#define ANGLE_VERSION_STRING \
+ ANGLE_MACRO_STRINGIFY(ANGLE_MAJOR_VERSION) "." \
+ ANGLE_MACRO_STRINGIFY(ANGLE_MINOR_VERSION) "." \
+ ANGLE_MACRO_STRINGIFY(ANGLE_REVISION) "." \
+ ANGLE_COMMIT_HASH
+
+#endif // COMMON_VERSION_H_