OLD | NEW |
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 |
(...skipping 13 matching lines...) Expand all Loading... |
24 // will probably pick one randomly for us, which is rarely correct). | 24 // will probably pick one randomly for us, which is rarely correct). |
25 namespace { | 25 namespace { |
26 | 26 |
27 // The default implementations just fall back on a pair of size N/2. | 27 // The default implementations just fall back on a pair of size N/2. |
28 | 28 |
29 template <int N, typename T> | 29 template <int N, typename T> |
30 class SkNi { | 30 class SkNi { |
31 public: | 31 public: |
32 SkNi() {} | 32 SkNi() {} |
33 SkNi(const SkNi<N/2, T>& lo, const SkNi<N/2, T>& hi) : fLo(lo), fHi(hi) {} | 33 SkNi(const SkNi<N/2, T>& lo, const SkNi<N/2, T>& hi) : fLo(lo), fHi(hi) {} |
34 explicit SkNi(T val) : fLo(val), fHi(val) {} | 34 SkNi(T val) : fLo(val), fHi(val) {} |
35 static SkNi Load(const T vals[N]) { | 35 static SkNi Load(const T vals[N]) { |
36 return SkNi(SkNi<N/2,T>::Load(vals), SkNi<N/2,T>::Load(vals+N/2)); | 36 return SkNi(SkNi<N/2,T>::Load(vals), SkNi<N/2,T>::Load(vals+N/2)); |
37 } | 37 } |
38 | 38 |
39 SkNi(T a, T b) : fLo(a), fHi(b) {
REQUIRE(N==2); } | 39 SkNi(T a, T b) : fLo(a), fHi(b) {
REQUIRE(N==2); } |
40 SkNi(T a, T b, T c, T d) : fLo(a,b), fHi(c,d) {
REQUIRE(N==4); } | 40 SkNi(T a, T b, T c, T d) : fLo(a,b), fHi(c,d) {
REQUIRE(N==4); } |
41 SkNi(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) {
REQUIRE(N==8); } | 41 SkNi(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) {
REQUIRE(N==8); } |
42 SkNi(T a, T b, T c, T d, T e, T f, T g, T h, | 42 SkNi(T a, T b, T c, T d, T e, T f, T g, T h, |
43 T i, T j, T k, T l, T m, T n, T o, T p) | 43 T i, T j, T k, T l, T m, T n, T o, T p) |
44 : fLo(a,b,c,d, e,f,g,h), fHi(i,j,k,l, m,n,o,p) { REQUIRE(N==16); } | 44 : fLo(a,b,c,d, e,f,g,h), fHi(i,j,k,l, m,n,o,p) { REQUIRE(N==16); } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 protected: | 78 protected: |
79 REQUIRE(0 == (N & (N-1))); | 79 REQUIRE(0 == (N & (N-1))); |
80 | 80 |
81 SkNi<N/2, T> fLo, fHi; | 81 SkNi<N/2, T> fLo, fHi; |
82 }; | 82 }; |
83 | 83 |
84 template <int N> | 84 template <int N> |
85 class SkNf { | 85 class SkNf { |
86 public: | 86 public: |
87 SkNf() {} | 87 SkNf() {} |
88 explicit SkNf(float val) : fLo(val), fHi(val) {} | 88 SkNf(float val) : fLo(val), fHi(val) {} |
89 static SkNf Load(const float vals[N]) { | 89 static SkNf Load(const float vals[N]) { |
90 return SkNf(SkNf<N/2>::Load(vals), SkNf<N/2>::Load(vals+N/2)); | 90 return SkNf(SkNf<N/2>::Load(vals), SkNf<N/2>::Load(vals+N/2)); |
91 } | 91 } |
92 // FromBytes() and toBytes() specializations may assume their argument is N-
byte aligned. | 92 // FromBytes() and toBytes() specializations may assume their argument is N-
byte aligned. |
93 // E.g. Sk4f::FromBytes() may assume it's reading from a 4-byte-aligned poin
ter. | 93 // E.g. Sk4f::FromBytes() may assume it's reading from a 4-byte-aligned poin
ter. |
94 // Converts [0,255] bytes to [0.0, 255.0] floats. | 94 // Converts [0,255] bytes to [0.0, 255.0] floats. |
95 static SkNf FromBytes(const uint8_t bytes[N]) { | 95 static SkNf FromBytes(const uint8_t bytes[N]) { |
96 return SkNf(SkNf<N/2>::FromBytes(bytes), SkNf<N/2>::FromBytes(bytes+N/2)
); | 96 return SkNf(SkNf<N/2>::FromBytes(bytes), SkNf<N/2>::FromBytes(bytes+N/2)
); |
97 } | 97 } |
98 | 98 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 SkNf<N/2> fLo, fHi; | 160 SkNf<N/2> fLo, fHi; |
161 }; | 161 }; |
162 | 162 |
163 | 163 |
164 // Bottom out the default implementations with scalars when nothing's been speci
alized. | 164 // Bottom out the default implementations with scalars when nothing's been speci
alized. |
165 | 165 |
166 template <typename T> | 166 template <typename T> |
167 class SkNi<1,T> { | 167 class SkNi<1,T> { |
168 public: | 168 public: |
169 SkNi() {} | 169 SkNi() {} |
170 explicit SkNi(T val) : fVal(val) {} | 170 SkNi(T val) : fVal(val) {} |
171 static SkNi Load(const T vals[1]) { return SkNi(vals[0]); } | 171 static SkNi Load(const T vals[1]) { return SkNi(vals[0]); } |
172 | 172 |
173 void store(T vals[1]) const { vals[0] = fVal; } | 173 void store(T vals[1]) const { vals[0] = fVal; } |
174 | 174 |
175 SkNi saturatedAdd(const SkNi& o) const { | 175 SkNi saturatedAdd(const SkNi& o) const { |
176 SkASSERT((T)(~0) > 0); // TODO: support signed T | 176 SkASSERT((T)(~0) > 0); // TODO: support signed T |
177 T sum = fVal + o.fVal; | 177 T sum = fVal + o.fVal; |
178 return SkNi(sum < fVal ? (T)(~0) : sum); | 178 return SkNi(sum < fVal ? (T)(~0) : sum); |
179 } | 179 } |
180 | 180 |
(...skipping 17 matching lines...) Expand all Loading... |
198 SkNi thenElse(const SkNi& t, const SkNi& e) const { return fVal ? t : e; } | 198 SkNi thenElse(const SkNi& t, const SkNi& e) const { return fVal ? t : e; } |
199 | 199 |
200 protected: | 200 protected: |
201 T fVal; | 201 T fVal; |
202 }; | 202 }; |
203 | 203 |
204 template <> | 204 template <> |
205 class SkNf<1> { | 205 class SkNf<1> { |
206 public: | 206 public: |
207 SkNf() {} | 207 SkNf() {} |
208 explicit SkNf(float val) : fVal(val) {} | 208 SkNf(float val) : fVal(val) {} |
209 static SkNf Load(const float vals[1]) { return SkNf(vals[0]); } | 209 static SkNf Load(const float vals[1]) { return SkNf(vals[0]); } |
210 static SkNf FromBytes(const uint8_t bytes[1]) { return SkNf((float)bytes[0])
; } | 210 static SkNf FromBytes(const uint8_t bytes[1]) { return SkNf((float)bytes[0])
; } |
211 | 211 |
212 void store(float vals[1]) const { vals[0] = fVal; } | 212 void store(float vals[1]) const { vals[0] = fVal; } |
213 void toBytes(uint8_t bytes[1]) const { bytes[0] = (uint8_t)(SkTMin(fVal, 255
.0f)); } | 213 void toBytes(uint8_t bytes[1]) const { bytes[0] = (uint8_t)(SkTMin(fVal, 255
.0f)); } |
214 | 214 |
215 SkNf operator + (const SkNf& o) const { return SkNf(fVal + o.fVal); } | 215 SkNf operator + (const SkNf& o) const { return SkNf(fVal + o.fVal); } |
216 SkNf operator - (const SkNf& o) const { return SkNf(fVal - o.fVal); } | 216 SkNf operator - (const SkNf& o) const { return SkNf(fVal - o.fVal); } |
217 SkNf operator * (const SkNf& o) const { return SkNf(fVal * o.fVal); } | 217 SkNf operator * (const SkNf& o) const { return SkNf(fVal * o.fVal); } |
218 SkNf operator / (const SkNf& o) const { return SkNf(fVal / o.fVal); } | 218 SkNf operator / (const SkNf& o) const { return SkNf(fVal / o.fVal); } |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 | 267 |
268 // A reminder alias that shuffles can be used to duplicate a single index across
a vector. | 268 // A reminder alias that shuffles can be used to duplicate a single index across
a vector. |
269 template <int Ix, typename SkNx> | 269 template <int Ix, typename SkNx> |
270 inline SkNx SkNx_dup(const SkNx& src) { return SkNx_shuffle<Ix>(src); } | 270 inline SkNx SkNx_dup(const SkNx& src) { return SkNx_shuffle<Ix>(src); } |
271 | 271 |
272 } // namespace | 272 } // namespace |
273 | 273 |
274 | 274 |
275 // Include platform specific specializations if available. | 275 // Include platform specific specializations if available. |
276 #ifndef SKNX_NO_SIMD | 276 #ifndef SKNX_NO_SIMD |
277 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 | 277 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_AVX |
| 278 #include "../opts/SkNx_avx.h" |
| 279 #elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 |
278 #include "../opts/SkNx_sse.h" | 280 #include "../opts/SkNx_sse.h" |
279 #elif defined(SK_ARM_HAS_NEON) | 281 #elif defined(SK_ARM_HAS_NEON) |
280 #include "../opts/SkNx_neon.h" | 282 #include "../opts/SkNx_neon.h" |
281 #endif | 283 #endif |
282 #endif | 284 #endif |
283 | 285 |
284 #undef REQUIRE | 286 #undef REQUIRE |
285 | 287 |
286 typedef SkNf<2> Sk2f; | 288 typedef SkNf<2> Sk2f; |
287 typedef SkNf<2> Sk2s; | 289 typedef SkNf<2> Sk2s; |
288 | |
289 typedef SkNf<4> Sk4f; | 290 typedef SkNf<4> Sk4f; |
290 typedef SkNf<4> Sk4s; | 291 typedef SkNf<4> Sk4s; |
| 292 typedef SkNf<8> Sk8f; |
| 293 typedef SkNf<8> Sk8s; |
291 | 294 |
292 typedef SkNi<8, uint16_t> Sk8h; | 295 typedef SkNi<8, uint16_t> Sk8h; |
293 typedef SkNi<16, uint16_t> Sk16h; | 296 typedef SkNi<16, uint16_t> Sk16h; |
294 typedef SkNi<16, uint8_t> Sk16b; | 297 typedef SkNi<16, uint8_t> Sk16b; |
295 | 298 |
296 #endif//SkNx_DEFINED | 299 #endif//SkNx_DEFINED |
OLD | NEW |