Chromium Code Reviews| Index: src/core/Sk4x.h |
| diff --git a/src/core/Sk4x.h b/src/core/Sk4x.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..c1933a14dfff1c19199d96c4bae82b0497ff9001 |
| --- /dev/null |
| +++ b/src/core/Sk4x.h |
| @@ -0,0 +1,96 @@ |
| +#ifndef Sk4x_DEFINED |
| +#define Sk4x_DEFINED |
| + |
| +// Sk4x.h brings the fun of GCC vector extensions* to platforms without them (MSVC). |
| +// We also paper over some of the differences between GCC and Clang's flavors. |
| +// |
| +// * https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html |
| +// http://clang.llvm.org/docs/LanguageExtensions.html#vectors-and-extended-vectors |
| + |
| +// First code common to both Clang and GCC. |
| +#if defined(__GNUC__) |
| + typedef float Sk4f __attribute__((vector_size(16))); |
| + typedef int Sk4i __attribute__((vector_size(16))); |
| +#endif |
| + |
| +// Now code specialized for Clang xor GCC. |
| +#if defined(__clang__) |
| + #define Sk4Shuffle(x,y, m,a,s,k) __builtin_shufflevector(x,y, m,a,s,k) |
| + |
| + #if __has_builtin(__builtin_convertvector) |
| + template<typename D, typename S> |
| + D Sk4Convert(S src) { return __builtin_convertvector(src, D); } |
| + #else |
| + template<typename D, typename S> |
| + D Sk4Convert(S src) { |
| + D dst = { (D)src[0], (D)src[1], (D)src[2], (D)src[3] }; |
| + return dst; |
| + } |
| + #endif |
| + |
| +#elif defined(__GNUC__) |
| + template <typename V> |
| + V Sk4Shuffle(V x, V y, int m, int a, int s, int k) { |
| + Sk4i mask = { m, a, s, k }; |
| + return __builtin_shuffle(x, y, mask); |
| + } |
| + |
| + template<typename D, typename S> |
| + D Sk4Convert(S src) { |
| + D dst = { (D)src[0], (D)src[1], (D)src[2], (D)src[3] }; |
| + return dst; |
| + } |
| + |
| +#endif |
| + |
| +#if !defined(__GNUC__) |
| + #error "Need to implement scalar versions." |
| +#endif |
| + |
| + |
| +// Finally code that will work no matter the implementation. |
| +inline Sk4f SkLoad4f(float a, float b, float c, float d) { |
| + Sk4f v = { a, b, c, d }; |
| + return v; |
| +} |
| + |
| +inline Sk4i SkLoad4i(int a, int b, int c, int d) { |
| + Sk4i v = { a, b, c, d }; |
| + return v; |
| +} |
| + |
| +inline Sk4f SkLoad4f(const float fs[4]) { |
| + Sk4f v = { fs[0], fs[1], fs[2], fs[3] }; |
| + return v; |
| +} |
| + |
| +inline Sk4i SkLoad4i(const int is[4]) { |
| + Sk4i v = { is[0], is[1], is[2], is[3] }; |
| + return v; |
| +} |
| + |
| +inline void SkStore4(Sk4f v, float fs[4]) { |
| + *reinterpret_cast<Sk4f*>(fs) = v; |
| +} |
| + |
| +inline void SkStore4(Sk4i v, int is[4]) { |
| + *reinterpret_cast<Sk4i*>(is) = v; |
| +} |
| + |
| +inline bool Sk4All(Sk4i v) { |
|
reed1
2014/10/10 16:06:11
as we start to actually use these, we might discus
mtklein
2014/10/10 21:26:07
See what you think of the API at PS 20?
|
| + return v[0] & v[1] & v[2] & v[3]; |
| +} |
| + |
| +template <typename V> |
| +V Sk4Min(V a, V b) { |
| + Sk4i less = a < b; |
| + return ((Sk4i)a & less) | ((Sk4i)b & ~less); |
| +} |
| + |
| +template <typename V> |
| +V Sk4Max(V a, V b) { |
| + Sk4i less = a < b; |
| + return ((Sk4i)b & less) | ((Sk4i)a & ~less); |
| +} |
| + |
| +#endif//Sk4x_DEFINED |