OLD | NEW |
---|---|
(Empty) | |
1 #ifndef Sk4x_DEFINED | |
2 #define Sk4x_DEFINED | |
3 | |
4 // Sk4x.h brings the fun of GCC vector extensions* to platforms without them (MS VC). | |
5 // We also paper over some of the differences between GCC and Clang's flavors. | |
6 // | |
7 // * https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html | |
8 // http://clang.llvm.org/docs/LanguageExtensions.html#vectors-and-extended-vec tors | |
9 | |
10 // First code common to both Clang and GCC. | |
11 #if defined(__GNUC__) | |
12 typedef float Sk4f __attribute__((vector_size(16))); | |
13 typedef int Sk4i __attribute__((vector_size(16))); | |
14 #endif | |
15 | |
16 // Now code specialized for Clang xor GCC. | |
17 #if defined(__clang__) | |
18 #define Sk4Shuffle(x,y, m,a,s,k) __builtin_shufflevector(x,y, m,a,s,k) | |
19 | |
20 #if __has_builtin(__builtin_convertvector) | |
21 template<typename D, typename S> | |
22 D Sk4Convert(S src) { return __builtin_convertvector(src, D); } | |
23 #else | |
24 template<typename D, typename S> | |
25 D Sk4Convert(S src) { | |
26 D dst = { (D)src[0], (D)src[1], (D)src[2], (D)src[3] }; | |
27 return dst; | |
28 } | |
29 #endif | |
30 | |
31 #elif defined(__GNUC__) | |
32 template <typename V> | |
33 V Sk4Shuffle(V x, V y, int m, int a, int s, int k) { | |
34 Sk4i mask = { m, a, s, k }; | |
35 return __builtin_shuffle(x, y, mask); | |
36 } | |
37 | |
38 template<typename D, typename S> | |
39 D Sk4Convert(S src) { | |
40 D dst = { (D)src[0], (D)src[1], (D)src[2], (D)src[3] }; | |
41 return dst; | |
42 } | |
43 | |
44 #endif | |
45 | |
46 #if !defined(__GNUC__) | |
47 #error "Need to implement scalar versions." | |
48 #endif | |
49 | |
50 | |
51 // Finally code that will work no matter the implementation. | |
52 inline Sk4f SkLoad4f(float a, float b, float c, float d) { | |
53 Sk4f v = { a, b, c, d }; | |
54 return v; | |
55 } | |
56 | |
57 inline Sk4i SkLoad4i(int a, int b, int c, int d) { | |
58 Sk4i v = { a, b, c, d }; | |
59 return v; | |
60 } | |
61 | |
62 inline Sk4f SkLoad4f(const float fs[4]) { | |
63 Sk4f v = { fs[0], fs[1], fs[2], fs[3] }; | |
64 return v; | |
65 } | |
66 | |
67 inline Sk4i SkLoad4i(const int is[4]) { | |
68 Sk4i v = { is[0], is[1], is[2], is[3] }; | |
69 return v; | |
70 } | |
71 | |
72 inline void SkStore4(Sk4f v, float fs[4]) { | |
73 *reinterpret_cast<Sk4f*>(fs) = v; | |
74 } | |
75 | |
76 inline void SkStore4(Sk4i v, int is[4]) { | |
77 *reinterpret_cast<Sk4i*>(is) = v; | |
78 } | |
79 | |
80 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?
| |
81 return v[0] & v[1] & v[2] & v[3]; | |
82 } | |
83 | |
84 template <typename V> | |
85 V Sk4Min(V a, V b) { | |
86 Sk4i less = a < b; | |
87 return ((Sk4i)a & less) | ((Sk4i)b & ~less); | |
88 } | |
89 | |
90 template <typename V> | |
91 V Sk4Max(V a, V b) { | |
92 Sk4i less = a < b; | |
93 return ((Sk4i)b & less) | ((Sk4i)a & ~less); | |
94 } | |
95 | |
96 #endif//Sk4x_DEFINED | |
OLD | NEW |