Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(115)

Side by Side Diff: src/core/SkNx.h

Issue 1812233003: SkNx refresh (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: typo Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/effects/gradients/SkRadialGradient.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2015 Google Inc. 2 * Copyright 2015 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #ifndef SkNx_DEFINED 8 #ifndef SkNx_DEFINED
9 #define SkNx_DEFINED 9 #define SkNx_DEFINED
10 10
11 //#define SKNX_NO_SIMD 11 //#define SKNX_NO_SIMD
12 12
13 #include "SkScalar.h" 13 #include "SkScalar.h"
14 #include "SkTypes.h" 14 #include "SkTypes.h"
15 #include <limits>
15 #include <math.h> 16 #include <math.h>
17 #include <type_traits>
16 18
17 // The default implementations just fall back on a pair of size N/2. 19 #define SI static inline
18 // These support the union of operations we might do to ints and floats, but 20
19 // platform specializations might support fewer (e.g. no float <<, no int /). 21 // The default SkNx<N,T> just proxies down to a pair of SkNx<N/2, T>.
20 template <int N, typename T> 22 template <int N, typename T>
21 class SkNx { 23 struct SkNx {
22 public: 24 typedef SkNx<N/2, T> Half;
23 SkNx() {}
24 SkNx(T val) : fLo(val), fHi(val) {}
25 25
26 typedef SkNx<N/2, T> Half; 26 Half fLo, fHi;
27
28 SkNx() = default;
27 SkNx(const Half& lo, const Half& hi) : fLo(lo), fHi(hi) {} 29 SkNx(const Half& lo, const Half& hi) : fLo(lo), fHi(hi) {}
28 30
29 SkNx(T a, T b) : fLo(a), fHi(b) { } 31 SkNx(T v) : fLo(v), fHi(v) {}
30 SkNx(T a, T b, T c, T d) : fLo(a,b), fHi(c,d) { } 32
31 SkNx(T a, T b, T c, T d, T e, T f, T g, T h) : fLo(a,b,c,d), fHi(e,f,g,h) { } 33 SkNx(T a, T b) : fLo(a) , fHi(b) { static_assert(N==2, ""); }
34 SkNx(T a, T b, T c, T d) : fLo(a,b), fHi(c,d) { static_assert(N==4, ""); }
35 SkNx(T a, T b, T c, T d, T e, T f, T g, T h) : fLo(a,b,c,d), fHi(e,f,g,h) {
36 static_assert(N==8, "");
37 }
32 SkNx(T a, T b, T c, T d, T e, T f, T g, T h, 38 SkNx(T a, T b, T c, T d, T e, T f, T g, T h,
33 T i, T j, T k, T l, T m, T n, T o, T p) : fLo(a,b,c,d, e,f,g,h), fHi(i ,j,k,l, m,n,o,p) {} 39 T i, T j, T k, T l, T m, T n, T o, T p) : fLo(a,b,c,d, e,f,g,h), fHi(i ,j,k,l, m,n,o,p) {
34 40 static_assert(N==16, "");
35 static SkNx Load(const void* ptr) {
36 auto vals = (const T*)ptr;
37 return SkNx(Half::Load(vals), Half::Load(vals+N/2));
38 }
39
40 void store(void* ptr) const {
41 auto vals = (T*)ptr;
42 fLo.store(vals);
43 fHi.store(vals+N/2);
44 }
45
46 #define OP(op) SkNx operator op(const SkNx& o) const { return {fLo op o.fLo, fHi op o.fHi}; }
47 OP(+) OP(-) OP(*) OP(/)
48 OP(&) OP(|) OP(^)
49 OP(==) OP(!=) OP(<) OP(>) OP(<=) OP(>=)
50 #undef OP
51
52 #define OP(op) SkNx op() const { return {fLo.op(), fHi.op()}; }
53 OP(abs) OP(floor)
54 OP(sqrt) OP(rsqrt0) OP(rsqrt1) OP(rsqrt2)
55 OP(invert) OP(approxInvert)
56 #undef OP
57
58 SkNx operator << (int bits) const { return SkNx(fLo << bits, fHi << bits); }
59 SkNx operator >> (int bits) const { return SkNx(fLo >> bits, fHi >> bits); }
60
61 SkNx saturatedAdd(const SkNx& o) const {
62 return {fLo.saturatedAdd(o.fLo), fHi.saturatedAdd(o.fHi)};
63 }
64
65 static SkNx Min(const SkNx& a, const SkNx& b) {
66 return {Half::Min(a.fLo, b.fLo), Half::Min(a.fHi, b.fHi)};
67 }
68 static SkNx Max(const SkNx& a, const SkNx& b) {
69 return {Half::Max(a.fLo, b.fLo), Half::Max(a.fHi, b.fHi)};
70 } 41 }
71 42
72 T operator[](int k) const { 43 T operator[](int k) const {
73 SkASSERT(0 <= k && k < N); 44 SkASSERT(0 <= k && k < N);
74 return k < N/2 ? fLo[k] : fHi[k-N/2]; 45 return k < N/2 ? fLo[k] : fHi[k-N/2];
75 } 46 }
76 47
48 static SkNx Load(const void* vptr) {
49 auto ptr = (const char*)vptr;
50 return { Half::Load(ptr), Half::Load(ptr + N/2*sizeof(T)) };
51 }
52 void store(void* vptr) const {
53 auto ptr = (char*)vptr;
54 fLo.store(ptr);
55 fHi.store(ptr + N/2*sizeof(T));
56 }
57
58 bool anyTrue() const { return fLo.anyTrue() || fHi.anyTrue(); }
77 bool allTrue() const { return fLo.allTrue() && fHi.allTrue(); } 59 bool allTrue() const { return fLo.allTrue() && fHi.allTrue(); }
78 bool anyTrue() const { return fLo.anyTrue() || fHi.anyTrue(); } 60
61 SkNx abs() const { return { fLo. abs(), fHi. abs() }; }
62 SkNx sqrt() const { return { fLo. sqrt(), fHi. sqrt() }; }
63 SkNx rsqrt() const { return { fLo. rsqrt(), fHi. rsqrt() }; }
64 SkNx floor() const { return { fLo. floor(), fHi. floor() }; }
65 SkNx invert() const { return { fLo.invert(), fHi.invert() }; }
66
67 SkNx operator!() const { return { !fLo, !fHi }; }
68 SkNx operator-() const { return { -fLo, -fHi }; }
69 SkNx operator~() const { return { ~fLo, ~fHi }; }
70
71 SkNx operator<<(int bits) const { return { fLo << bits, fHi << bits }; }
72 SkNx operator>>(int bits) const { return { fLo >> bits, fHi >> bits }; }
73
74 SkNx operator+(const SkNx& y) const { return { fLo + y.fLo, fHi + y.fHi }; }
75 SkNx operator-(const SkNx& y) const { return { fLo - y.fLo, fHi - y.fHi }; }
76 SkNx operator*(const SkNx& y) const { return { fLo * y.fLo, fHi * y.fHi }; }
77 SkNx operator/(const SkNx& y) const { return { fLo / y.fLo, fHi / y.fHi }; }
78
79 SkNx operator&(const SkNx& y) const { return { fLo & y.fLo, fHi & y.fHi }; }
80 SkNx operator|(const SkNx& y) const { return { fLo | y.fLo, fHi | y.fHi }; }
81 SkNx operator^(const SkNx& y) const { return { fLo ^ y.fLo, fHi ^ y.fHi }; }
82
83 SkNx operator==(const SkNx& y) const { return { fLo == y.fLo, fHi == y.fHi } ; }
84 SkNx operator!=(const SkNx& y) const { return { fLo != y.fLo, fHi != y.fHi } ; }
85 SkNx operator<=(const SkNx& y) const { return { fLo <= y.fLo, fHi <= y.fHi } ; }
86 SkNx operator>=(const SkNx& y) const { return { fLo >= y.fLo, fHi >= y.fHi } ; }
87 SkNx operator< (const SkNx& y) const { return { fLo < y.fLo, fHi < y.fHi } ; }
88 SkNx operator> (const SkNx& y) const { return { fLo > y.fLo, fHi > y.fHi } ; }
89
90 SkNx saturatedAdd(const SkNx& y) const {
91 return { fLo.saturatedAdd(y.fLo), fHi.saturatedAdd(y.fHi) };
92 }
79 SkNx thenElse(const SkNx& t, const SkNx& e) const { 93 SkNx thenElse(const SkNx& t, const SkNx& e) const {
80 return SkNx(fLo.thenElse(t.fLo, e.fLo), fHi.thenElse(t.fHi, e.fHi)); 94 return { fLo.thenElse(t.fLo, e.fLo), fHi.thenElse(t.fHi, e.fHi) };
81 } 95 }
82 96
83 protected: 97 static SkNx Min(const SkNx& x, const SkNx& y) {
84 static_assert(0 == (N & (N-1)), "N must be a power of 2."); 98 return { Half::Min(x.fLo, y.fLo), Half::Min(x.fHi, y.fHi) };
85 99 }
86 Half fLo, fHi; 100 static SkNx Max(const SkNx& x, const SkNx& y) {
101 return { Half::Max(x.fLo, y.fLo), Half::Max(x.fHi, y.fHi) };
102 }
87 }; 103 };
88 104
89 // Bottom out the default implementations with scalars when nothing's been speci alized. 105 // The N -> N/2 recursion bottoms out at N == 1, a scalar value.
90 template <typename T> 106 template <typename T>
91 class SkNx<1, T> { 107 struct SkNx<1,T> {
92 public: 108 T fVal;
93 SkNx() {} 109
94 SkNx(T val) : fVal(val) {} 110 SkNx() = default;
111 SkNx(T v) : fVal(v) {}
112
113 T operator[](int k) const {
114 SkASSERT(k == 0);
115 return fVal;
116 }
95 117
96 static SkNx Load(const void* ptr) { 118 static SkNx Load(const void* ptr) {
97 auto vals = (const T*)ptr; 119 SkNx v;
98 return SkNx(vals[0]); 120 memcpy(&v, ptr, sizeof(T));
99 } 121 return v;
100 122 }
101 void store(void* ptr) const { 123 void store(void* ptr) const { memcpy(ptr, &fVal, sizeof(T)); }
102 auto vals = (T*) ptr; 124
103 vals[0] = fVal; 125 bool anyTrue() const { return fVal != 0; }
104 }
105
106 #define OP(op) SkNx operator op(const SkNx& o) const { return fVal op o.fVal; }
107 OP(+) OP(-) OP(*) OP(/)
108 OP(&) OP(|) OP(^)
109 OP(==) OP(!=) OP(<) OP(>) OP(<=) OP(>=)
110 #undef OP
111
112 SkNx operator << (int bits) const { return fVal << bits; }
113 SkNx operator >> (int bits) const { return fVal >> bits; }
114
115 SkNx saturatedAdd(const SkNx& o) const {
116 SkASSERT((T)(~0) > 0); // TODO: support signed T?
117 T sum = fVal + o.fVal;
118 return sum < fVal ? (T)(~0) : sum;
119 }
120
121 static SkNx Min(const SkNx& a, const SkNx& b) { return SkTMin(a.fVal, b.fVal ); }
122 static SkNx Max(const SkNx& a, const SkNx& b) { return SkTMax(a.fVal, b.fVal ); }
123
124 SkNx abs() const { return SkTAbs(fVal); }
125 SkNx floor() const { return Floor(fVal); }
126
127 SkNx sqrt () const { return Sqrt(fVal); }
128 SkNx rsqrt0() const { return this->sqrt().invert(); }
129 SkNx rsqrt1() const { return this->rsqrt0(); }
130 SkNx rsqrt2() const { return this->rsqrt1(); }
131
132 SkNx invert() const { return 1 / fVal; }
133 SkNx approxInvert() const { return this->invert(); }
134
135 T operator[](int k) const {
136 SkASSERT(0 == k);
137 return fVal;
138 }
139
140 bool allTrue() const { return fVal != 0; } 126 bool allTrue() const { return fVal != 0; }
141 bool anyTrue() const { return fVal != 0; } 127
128 SkNx abs() const { return Abs(fVal); }
129 SkNx sqrt() const { return Sqrt(fVal); }
130 SkNx rsqrt() const { return T(1) / this->sqrt(); }
131 SkNx floor() const { return Floor(fVal); }
132 SkNx invert() const { return T(1) / *this; }
133
134 SkNx operator!() const { return !fVal; }
135 SkNx operator-() const { return -fVal; }
136 SkNx operator~() const { return FromBits(~ToBits(fVal)); }
137
138 SkNx operator<<(int bits) const { return fVal << bits; }
139 SkNx operator>>(int bits) const { return fVal >> bits; }
140
141 SkNx operator+(const SkNx& y) const { return fVal + y.fVal; }
142 SkNx operator-(const SkNx& y) const { return fVal - y.fVal; }
143 SkNx operator*(const SkNx& y) const { return fVal * y.fVal; }
144 SkNx operator/(const SkNx& y) const { return fVal / y.fVal; }
145
146 SkNx operator&(const SkNx& y) const { return FromBits(ToBits(fVal) & ToBits( y.fVal)); }
147 SkNx operator|(const SkNx& y) const { return FromBits(ToBits(fVal) | ToBits( y.fVal)); }
148 SkNx operator^(const SkNx& y) const { return FromBits(ToBits(fVal) ^ ToBits( y.fVal)); }
149
150 SkNx operator==(const SkNx& y) const { return FromBits(fVal == y.fVal ? ~0 : 0); }
151 SkNx operator!=(const SkNx& y) const { return FromBits(fVal != y.fVal ? ~0 : 0); }
152 SkNx operator<=(const SkNx& y) const { return FromBits(fVal <= y.fVal ? ~0 : 0); }
153 SkNx operator>=(const SkNx& y) const { return FromBits(fVal >= y.fVal ? ~0 : 0); }
154 SkNx operator< (const SkNx& y) const { return FromBits(fVal < y.fVal ? ~0 : 0); }
155 SkNx operator> (const SkNx& y) const { return FromBits(fVal > y.fVal ? ~0 : 0); }
156
157 static SkNx Min(const SkNx& x, const SkNx& y) { return x.fVal < y.fVal ? x : y; }
158 static SkNx Max(const SkNx& x, const SkNx& y) { return x.fVal > y.fVal ? x : y; }
159
160 SkNx saturatedAdd(const SkNx& y) const {
161 static_assert(std::is_unsigned<T>::value, "");
162 T sum = fVal + y.fVal;
163 return sum < fVal ? std::numeric_limits<T>::max() : sum;
164 }
165
142 SkNx thenElse(const SkNx& t, const SkNx& e) const { return fVal != 0 ? t : e ; } 166 SkNx thenElse(const SkNx& t, const SkNx& e) const { return fVal != 0 ? t : e ; }
143 167
144 protected: 168 private:
145 static double Floor(double val) { return ::floor (val); } 169 // Helper functions to choose the right float/double methods. (In <cmath> m adness lies...)
146 static float Floor(float val) { return ::floorf(val); } 170 static float Abs(float val) { return ::fabsf(val); }
147 static double Sqrt(double val) { return ::sqrt (val); } 171 static float Sqrt(float val) { return ::sqrtf(val); }
148 static float Sqrt(float val) { return ::sqrtf(val); } 172 static float Floor(float val) { return ::floorf(val); }
149 173
150 T fVal; 174 static double Abs(double val) { return ::fabs(val); }
175 static double Sqrt(double val) { return ::sqrt(val); }
176 static double Floor(double val) { return ::floor(val); }
177
178 // Helper functions for working with floats/doubles as bit patterns.
179 template <typename U> static U ToBits(U v) { return v; }
180 static int32_t ToBits(float v) { int32_t bits; memcpy(&bits, &v, sizeof(v)) ; return bits; }
181 static int64_t ToBits(double v) { int64_t bits; memcpy(&bits, &v, sizeof(v)) ; return bits; }
182
183 template <typename Bits> static T FromBits(Bits bits) {
184 static_assert(std::is_pod<T >::value &&
185 std::is_pod<Bits>::value &&
186 sizeof(T) <= sizeof(Bits), "");
187 T val;
188 memcpy(&val, &bits, sizeof(T));
189 return val;
190 }
151 }; 191 };
152 192
153 // This generic shuffle can be called to create any valid SkNx<N,T>. 193 // Allow scalars on the left or right of binary operators, and things like +=, & =, etc.
154 // Sk4f f(a,b,c,d); 194 #define V template <int N, typename T> SI SkNx<N,T>
155 // Sk2f t = SkNx_shuffle<2,1>(f); // ~~~> Sk2f(c,b) 195 V operator+ (T x, const SkNx<N,T>& y) { return SkNx<N,T>(x) + y; }
156 // f = SkNx_shuffle<0,1,1,0>(t); // ~~~> Sk4f(c,b,b,c) 196 V operator- (T x, const SkNx<N,T>& y) { return SkNx<N,T>(x) - y; }
197 V operator* (T x, const SkNx<N,T>& y) { return SkNx<N,T>(x) * y; }
198 V operator/ (T x, const SkNx<N,T>& y) { return SkNx<N,T>(x) / y; }
199 V operator& (T x, const SkNx<N,T>& y) { return SkNx<N,T>(x) & y; }
200 V operator| (T x, const SkNx<N,T>& y) { return SkNx<N,T>(x) | y; }
201 V operator^ (T x, const SkNx<N,T>& y) { return SkNx<N,T>(x) ^ y; }
202 V operator==(T x, const SkNx<N,T>& y) { return SkNx<N,T>(x) == y; }
203 V operator!=(T x, const SkNx<N,T>& y) { return SkNx<N,T>(x) != y; }
204 V operator<=(T x, const SkNx<N,T>& y) { return SkNx<N,T>(x) <= y; }
205 V operator>=(T x, const SkNx<N,T>& y) { return SkNx<N,T>(x) >= y; }
206 V operator< (T x, const SkNx<N,T>& y) { return SkNx<N,T>(x) < y; }
207 V operator> (T x, const SkNx<N,T>& y) { return SkNx<N,T>(x) > y; }
208
209 V operator+ (const SkNx<N,T>& x, T y) { return x + SkNx<N,T>(y); }
210 V operator- (const SkNx<N,T>& x, T y) { return x - SkNx<N,T>(y); }
211 V operator* (const SkNx<N,T>& x, T y) { return x * SkNx<N,T>(y); }
212 V operator/ (const SkNx<N,T>& x, T y) { return x / SkNx<N,T>(y); }
213 V operator& (const SkNx<N,T>& x, T y) { return x & SkNx<N,T>(y); }
214 V operator| (const SkNx<N,T>& x, T y) { return x | SkNx<N,T>(y); }
215 V operator^ (const SkNx<N,T>& x, T y) { return x ^ SkNx<N,T>(y); }
216 V operator==(const SkNx<N,T>& x, T y) { return x == SkNx<N,T>(y); }
217 V operator!=(const SkNx<N,T>& x, T y) { return x != SkNx<N,T>(y); }
218 V operator<=(const SkNx<N,T>& x, T y) { return x <= SkNx<N,T>(y); }
219 V operator>=(const SkNx<N,T>& x, T y) { return x >= SkNx<N,T>(y); }
220 V operator< (const SkNx<N,T>& x, T y) { return x < SkNx<N,T>(y); }
221 V operator> (const SkNx<N,T>& x, T y) { return x > SkNx<N,T>(y); }
222
223 V& operator<<=(SkNx<N,T>& x, int bits) { return (x = x << bits); }
224 V& operator>>=(SkNx<N,T>& x, int bits) { return (x = x >> bits); }
225
226 V& operator +=(SkNx<N,T>& x, const SkNx<N,T>& y) { return (x = x + y); }
227 V& operator -=(SkNx<N,T>& x, const SkNx<N,T>& y) { return (x = x - y); }
228 V& operator *=(SkNx<N,T>& x, const SkNx<N,T>& y) { return (x = x * y); }
229 V& operator /=(SkNx<N,T>& x, const SkNx<N,T>& y) { return (x = x / y); }
230 V& operator &=(SkNx<N,T>& x, const SkNx<N,T>& y) { return (x = x & y); }
231 V& operator |=(SkNx<N,T>& x, const SkNx<N,T>& y) { return (x = x | y); }
232 V& operator ^=(SkNx<N,T>& x, const SkNx<N,T>& y) { return (x = x ^ y); }
233
234 V& operator +=(SkNx<N,T>& x, T y) { return (x = x + SkNx<N,T>(y)); }
235 V& operator -=(SkNx<N,T>& x, T y) { return (x = x - SkNx<N,T>(y)); }
236 V& operator *=(SkNx<N,T>& x, T y) { return (x = x * SkNx<N,T>(y)); }
237 V& operator /=(SkNx<N,T>& x, T y) { return (x = x / SkNx<N,T>(y)); }
238 V& operator &=(SkNx<N,T>& x, T y) { return (x = x & SkNx<N,T>(y)); }
239 V& operator |=(SkNx<N,T>& x, T y) { return (x = x | SkNx<N,T>(y)); }
240 V& operator ^=(SkNx<N,T>& x, T y) { return (x = x ^ SkNx<N,T>(y)); }
241 #undef V
242
243 // SkNx<N,T> ~~> SkNx<N/2,T> + SkNx<N/2,T>
244 template <int N, typename T>
245 SI void SkNx_split(const SkNx<N,T>& v, SkNx<N/2,T>* lo, SkNx<N/2,T>* hi) {
246 *lo = v.fLo;
247 *hi = v.fHi;
248 }
249
250 // SkNx<N/2,T> + SkNx<N/2,T> ~~> SkNx<N,T>
251 template <int N, typename T>
252 SI SkNx<N*2,T> SkNx_join(const SkNx<N,T>& lo, const SkNx<N,T>& hi) {
253 return { lo, hi };
254 }
255
256 // A very generic shuffle. Can reorder, duplicate, contract, expand...
257 // Sk4f v = { R,G,B,A };
258 // SkNx_shuffle<2,1,0,3>(v) ~~> {B,G,R,A}
259 // SkNx_shuffle<2,1>(v) ~~> {B,G}
260 // SkNx_shuffle<2,1,2,1,2,1,2,1>(v) ~~> {B,G,B,G,B,G,B,G}
261 // SkNx_shuffle<3,3,3,3>(v) ~~> {A,A,A,A}
157 template <int... Ix, int N, typename T> 262 template <int... Ix, int N, typename T>
158 static inline SkNx<sizeof...(Ix), T> SkNx_shuffle(const SkNx<N,T>& src) { return { src[Ix]... }; } 263 SI SkNx<sizeof...(Ix),T> SkNx_shuffle(const SkNx<N,T>& v) {
159 264 return { v[Ix]... };
160 // This is a generic cast between two SkNx with the same number of elements N. E.g. 265 }
161 // Sk4b bs = ...; // Load 4 bytes. 266
162 // Sk4f fs = SkNx_cast<float>(bs); // Cast each byte to a float. 267 // Cast from SkNx<N, Src> to SkNx<N, Dst>, as if you called static_cast<Dst>(Src ).
163 // Sk4h hs = SkNx_cast<uint16_t>(fs); // Cast each float to uint16_t. 268 template <typename Dst, typename Src, int N>
164 template <typename D, typename S> 269 SI SkNx<N,Dst> SkNx_cast(const SkNx<N,Src>& v) {
165 static inline SkNx<2,D> SkNx_cast(const SkNx<2,S>& src) { 270 return { SkNx_cast<Dst>(v.fLo), SkNx_cast<Dst>(v.fHi) };
166 return { (D)src[0], (D)src[1] }; 271 }
167 } 272 template <typename Dst, typename Src>
168 273 SI SkNx<1,Dst> SkNx_cast(const SkNx<1,Src>& v) {
169 template <typename D, typename S> 274 return static_cast<Dst>(v.fVal);
170 static inline SkNx<4,D> SkNx_cast(const SkNx<4,S>& src) {
171 return { (D)src[0], (D)src[1], (D)src[2], (D)src[3] };
172 }
173
174 template <typename D, typename S>
175 static inline SkNx<8,D> SkNx_cast(const SkNx<8,S>& src) {
176 return { (D)src[0], (D)src[1], (D)src[2], (D)src[3],
177 (D)src[4], (D)src[5], (D)src[6], (D)src[7] };
178 }
179
180 template <typename D, typename S>
181 static inline SkNx<16,D> SkNx_cast(const SkNx<16,S>& src) {
182 return { (D)src[ 0], (D)src[ 1], (D)src[ 2], (D)src[ 3],
183 (D)src[ 4], (D)src[ 5], (D)src[ 6], (D)src[ 7],
184 (D)src[ 8], (D)src[ 9], (D)src[10], (D)src[11],
185 (D)src[12], (D)src[13], (D)src[14], (D)src[15] };
186 } 275 }
187 276
188 typedef SkNx<2, float> Sk2f; 277 typedef SkNx<2, float> Sk2f;
189 typedef SkNx<4, float> Sk4f; 278 typedef SkNx<4, float> Sk4f;
279 typedef SkNx<8, float> Sk8f;
280 typedef SkNx<16, float> Sk16f;
281
190 typedef SkNx<2, SkScalar> Sk2s; 282 typedef SkNx<2, SkScalar> Sk2s;
191 typedef SkNx<4, SkScalar> Sk4s; 283 typedef SkNx<4, SkScalar> Sk4s;
284 typedef SkNx<8, SkScalar> Sk8s;
285 typedef SkNx<16, SkScalar> Sk16s;
192 286
193 typedef SkNx<4, uint8_t> Sk4b; 287 typedef SkNx<4, uint8_t> Sk4b;
288 typedef SkNx<8, uint8_t> Sk8b;
194 typedef SkNx<16, uint8_t> Sk16b; 289 typedef SkNx<16, uint8_t> Sk16b;
290
195 typedef SkNx<4, uint16_t> Sk4h; 291 typedef SkNx<4, uint16_t> Sk4h;
292 typedef SkNx<8, uint16_t> Sk8h;
196 typedef SkNx<16, uint16_t> Sk16h; 293 typedef SkNx<16, uint16_t> Sk16h;
294
197 typedef SkNx<4, int> Sk4i; 295 typedef SkNx<4, int> Sk4i;
198 296
199 typedef SkNx<4, int> Sk4i;
200
201 // Include platform specific specializations if available. 297 // Include platform specific specializations if available.
202 #if !defined(SKNX_NO_SIMD) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 298 #if !defined(SKNX_NO_SIMD) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
203 #include "../opts/SkNx_sse.h" 299 #include "../opts/SkNx_sse.h"
204 #elif !defined(SKNX_NO_SIMD) && defined(SK_ARM_HAS_NEON) 300 #elif !defined(SKNX_NO_SIMD) && defined(SK_ARM_HAS_NEON)
205 #include "../opts/SkNx_neon.h" 301 #include "../opts/SkNx_neon.h"
206 #else
207 static inline
208 void Sk4f_ToBytes(uint8_t p[16], const Sk4f& a, const Sk4f& b, const Sk4f& c , const Sk4f& d) {
209 SkNx_cast<uint8_t>(a).store(p+ 0);
210 SkNx_cast<uint8_t>(b).store(p+ 4);
211 SkNx_cast<uint8_t>(c).store(p+ 8);
212 SkNx_cast<uint8_t>(d).store(p+12);
213 }
214 #endif 302 #endif
215 303
304 SI void Sk4f_ToBytes(uint8_t p[16], const Sk4f& a, const Sk4f& b, const Sk4f& c, const Sk4f& d) {
305 SkNx_cast<uint8_t>(SkNx_join(SkNx_join(a,b), SkNx_join(c,d))).store(p);
306 }
307
308 #undef SI
309
216 #endif//SkNx_DEFINED 310 #endif//SkNx_DEFINED
OLDNEW
« no previous file with comments | « no previous file | src/effects/gradients/SkRadialGradient.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698