// Copyright 2013 The Flutter 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 FLUTTER_IMPELLER_GEOMETRY_HALF_H_ #define FLUTTER_IMPELLER_GEOMETRY_HALF_H_ #include #include "flutter/fml/build_config.h" #include "impeller/geometry/color.h" #include "impeller/geometry/point.h" #include "impeller/geometry/scalar.h" #include "impeller/geometry/vector.h" // NOLINTBEGIN(google-explicit-constructor) #if defined(FML_OS_MACOSX) || defined(FML_OS_IOS) || \ defined(FML_OS_IOS_SIMULATOR) using InternalHalf = _Float16; #else using InternalHalf = uint16_t; #endif namespace impeller { /// @brief Convert a scalar to a half precision float. /// /// See also: https://clang.llvm.org/docs/LanguageExtensions.html /// This is not currently supported on Windows toolchains. inline constexpr InternalHalf ScalarToHalf(Scalar f) { #ifdef FML_OS_WIN return static_cast(0); #else return static_cast(f); #endif } /// @brief A storage only class for half precision floating point. struct Half { InternalHalf x = 0; constexpr Half() {} constexpr Half(double value) : x(ScalarToHalf(static_cast(value))) {} constexpr Half(Scalar value) : x(ScalarToHalf(value)) {} constexpr Half(int value) : x(ScalarToHalf(static_cast(value))) {} constexpr Half(InternalHalf x) : x(x) {} constexpr bool operator==(const Half& v) const { return v.x == x; } constexpr bool operator!=(const Half& v) const { return v.x != x; } }; /// @brief A storage only class for half precision floating point vector 4. struct HalfVector4 { union { struct { InternalHalf x = 0; InternalHalf y = 0; InternalHalf z = 0; InternalHalf w = 0; }; InternalHalf e[4]; }; constexpr HalfVector4() {} constexpr HalfVector4(const Color& a) : x(ScalarToHalf(a.red)), y(ScalarToHalf(a.green)), z(ScalarToHalf(a.blue)), w(ScalarToHalf(a.alpha)) {} constexpr HalfVector4(const Vector4& a) : x(ScalarToHalf(a.x)), y(ScalarToHalf(a.y)), z(ScalarToHalf(a.z)), w(ScalarToHalf(a.w)) {} constexpr HalfVector4(InternalHalf x, InternalHalf y, InternalHalf z, InternalHalf w) : x(x), y(y), z(z), w(w) {} constexpr bool operator==(const HalfVector4& v) const { return v.x == x && v.y == y && v.z == z && v.w == w; } constexpr bool operator!=(const HalfVector4& v) const { return v.x != x || v.y != y || v.z != z || v.w != w; } }; /// @brief A storage only class for half precision floating point vector 3. struct HalfVector3 { union { struct { InternalHalf x = 0; InternalHalf y = 0; InternalHalf z = 0; }; InternalHalf e[3]; }; constexpr HalfVector3() {} constexpr HalfVector3(const Vector3& a) : x(ScalarToHalf(a.x)), y(ScalarToHalf(a.y)), z(ScalarToHalf(a.z)) {} constexpr HalfVector3(InternalHalf x, InternalHalf y, InternalHalf z) : x(x), y(y), z(z) {} constexpr bool operator==(const HalfVector3& v) const { return v.x == x && v.y == y && v.z == z; } constexpr bool operator!=(const HalfVector3& v) const { return v.x != x || v.y != y || v.z != z; } }; /// @brief A storage only class for half precision floating point vector 2. struct HalfVector2 { union { struct { InternalHalf x = 0; InternalHalf y = 0; }; InternalHalf e[2]; }; constexpr HalfVector2() {} constexpr HalfVector2(const Vector2& a) : x(ScalarToHalf(a.x)), y(ScalarToHalf(a.y)) {} constexpr HalfVector2(InternalHalf x, InternalHalf y) : x(x), y(y){}; constexpr bool operator==(const HalfVector2& v) const { return v.x == x && v.y == y; } constexpr bool operator!=(const HalfVector2& v) const { return v.x != x || v.y != y; } }; static_assert(sizeof(Half) == sizeof(uint16_t)); static_assert(sizeof(HalfVector2) == 2 * sizeof(Half)); static_assert(sizeof(HalfVector3) == 3 * sizeof(Half)); static_assert(sizeof(HalfVector4) == 4 * sizeof(Half)); } // namespace impeller namespace std { inline std::ostream& operator<<(std::ostream& out, const impeller::Half& p) { out << "(" << static_cast(p.x) << ")"; return out; } inline std::ostream& operator<<(std::ostream& out, const impeller::HalfVector2& p) { out << "(" << static_cast(p.x) << ", " << static_cast(p.y) << ")"; return out; } inline std::ostream& operator<<(std::ostream& out, const impeller::HalfVector3& p) { out << "(" << static_cast(p.x) << ", " << static_cast(p.y) << ", " << static_cast(p.z) << ")"; return out; } inline std::ostream& operator<<(std::ostream& out, const impeller::HalfVector4& p) { out << "(" << static_cast(p.x) << ", " << static_cast(p.y) << ", " << static_cast(p.z) << ", " << static_cast(p.w) << ")"; return out; } // NOLINTEND(google-explicit-constructor) } // namespace std #endif // FLUTTER_IMPELLER_GEOMETRY_HALF_H_