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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 SkNi thenElse(const SkNi& t, const SkNi& e) const { | 74 SkNi thenElse(const SkNi& t, const SkNi& e) const { |
75 return SkNi(fLo.thenElse(t.fLo, e.fLo), fHi.thenElse(t.fHi, e.fHi)); | 75 return SkNi(fLo.thenElse(t.fLo, e.fLo), fHi.thenElse(t.fHi, e.fHi)); |
76 } | 76 } |
77 | 77 |
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, typename T> | 84 template <int N> |
85 class SkNf { | 85 class SkNf { |
86 static int32_t MyNi(float); | |
87 static int64_t MyNi(double); | |
88 typedef decltype(MyNi(T())) I; | |
89 public: | 86 public: |
90 SkNf() {} | 87 SkNf() {} |
91 explicit SkNf(T val) : fLo(val), fHi(val) {} | 88 explicit SkNf(float val) : fLo(val), fHi(val) {} |
92 static SkNf Load(const T vals[N]) { | 89 static SkNf Load(const float vals[N]) { |
93 return SkNf(SkNf<N/2,T>::Load(vals), SkNf<N/2,T>::Load(vals+N/2)); | 90 return SkNf(SkNf<N/2>::Load(vals), SkNf<N/2>::Load(vals+N/2)); |
94 } | 91 } |
95 // 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. |
96 // 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. |
97 // Converts [0,255] bytes to [0.0, 255.0] floats. | 94 // Converts [0,255] bytes to [0.0, 255.0] floats. |
98 static SkNf FromBytes(const uint8_t bytes[N]) { | 95 static SkNf FromBytes(const uint8_t bytes[N]) { |
99 return SkNf(SkNf<N/2,T>::FromBytes(bytes), SkNf<N/2,T>::FromBytes(bytes+
N/2)); | 96 return SkNf(SkNf<N/2>::FromBytes(bytes), SkNf<N/2>::FromBytes(bytes+N/2)
); |
100 } | 97 } |
101 | 98 |
102 SkNf(T a, T b) : fLo(a), fHi(b) {
REQUIRE(N==2); } | 99 SkNf(float a, float b) : fLo(a), fHi(b) { REQUIRE(N==2
); } |
103 SkNf(T a, T b, T c, T d) : fLo(a,b), fHi(c,d) {
REQUIRE(N==4); } | 100 SkNf(float a, float b, float c, float d) : fLo(a,b), fHi(c,d) { REQUIRE(N==4
); } |
104 SkNf(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); } | 101 SkNf(float a, float b, float c, float d, float e, float f, float g, float h) |
| 102 : fLo(a,b,c,d) |
| 103 , fHi(e,f,g,h) { REQUIRE(N==8); } |
105 | 104 |
106 void store(T vals[N]) const { | 105 void store(float vals[N]) const { |
107 fLo.store(vals); | 106 fLo.store(vals); |
108 fHi.store(vals+N/2); | 107 fHi.store(vals+N/2); |
109 } | 108 } |
110 // Please see note on FromBytes(). | 109 // Please see note on FromBytes(). |
111 // Clamps to [0.0,255.0] floats and truncates to [0,255] bytes. | 110 // Clamps to [0.0,255.0] floats and truncates to [0,255] bytes. |
112 void toBytes(uint8_t bytes[N]) const { | 111 void toBytes(uint8_t bytes[N]) const { |
113 fLo.toBytes(bytes); | 112 fLo.toBytes(bytes); |
114 fHi.toBytes(bytes+N/2); | 113 fHi.toBytes(bytes+N/2); |
115 } | 114 } |
116 | 115 |
117 SkNi<N,I> castTrunc() const { return SkNi<N,I>(fLo.castTrunc(), fHi.castTrun
c()); } | |
118 | |
119 SkNf operator + (const SkNf& o) const { return SkNf(fLo + o.fLo, fHi + o.fHi
); } | 116 SkNf operator + (const SkNf& o) const { return SkNf(fLo + o.fLo, fHi + o.fHi
); } |
120 SkNf operator - (const SkNf& o) const { return SkNf(fLo - o.fLo, fHi - o.fHi
); } | 117 SkNf operator - (const SkNf& o) const { return SkNf(fLo - o.fLo, fHi - o.fHi
); } |
121 SkNf operator * (const SkNf& o) const { return SkNf(fLo * o.fLo, fHi * o.fHi
); } | 118 SkNf operator * (const SkNf& o) const { return SkNf(fLo * o.fLo, fHi * o.fHi
); } |
122 SkNf operator / (const SkNf& o) const { return SkNf(fLo / o.fLo, fHi / o.fHi
); } | 119 SkNf operator / (const SkNf& o) const { return SkNf(fLo / o.fLo, fHi / o.fHi
); } |
123 | 120 |
124 SkNf operator == (const SkNf& o) const { return SkNf(fLo == o.fLo, fHi == o.
fHi); } | 121 SkNf operator == (const SkNf& o) const { return SkNf(fLo == o.fLo, fHi == o.
fHi); } |
125 SkNf operator != (const SkNf& o) const { return SkNf(fLo != o.fLo, fHi != o.
fHi); } | 122 SkNf operator != (const SkNf& o) const { return SkNf(fLo != o.fLo, fHi != o.
fHi); } |
126 SkNf operator < (const SkNf& o) const { return SkNf(fLo < o.fLo, fHi < o.
fHi); } | 123 SkNf operator < (const SkNf& o) const { return SkNf(fLo < o.fLo, fHi < o.
fHi); } |
127 SkNf operator > (const SkNf& o) const { return SkNf(fLo > o.fLo, fHi > o.
fHi); } | 124 SkNf operator > (const SkNf& o) const { return SkNf(fLo > o.fLo, fHi > o.
fHi); } |
128 SkNf operator <= (const SkNf& o) const { return SkNf(fLo <= o.fLo, fHi <= o.
fHi); } | 125 SkNf operator <= (const SkNf& o) const { return SkNf(fLo <= o.fLo, fHi <= o.
fHi); } |
129 SkNf operator >= (const SkNf& o) const { return SkNf(fLo >= o.fLo, fHi >= o.
fHi); } | 126 SkNf operator >= (const SkNf& o) const { return SkNf(fLo >= o.fLo, fHi >= o.
fHi); } |
130 | 127 |
131 static SkNf Min(const SkNf& l, const SkNf& r) { | 128 static SkNf Min(const SkNf& l, const SkNf& r) { |
132 return SkNf(SkNf<N/2,T>::Min(l.fLo, r.fLo), SkNf<N/2,T>::Min(l.fHi, r.fH
i)); | 129 return SkNf(SkNf<N/2>::Min(l.fLo, r.fLo), SkNf<N/2>::Min(l.fHi, r.fHi)); |
133 } | 130 } |
134 static SkNf Max(const SkNf& l, const SkNf& r) { | 131 static SkNf Max(const SkNf& l, const SkNf& r) { |
135 return SkNf(SkNf<N/2,T>::Max(l.fLo, r.fLo), SkNf<N/2,T>::Max(l.fHi, r.fH
i)); | 132 return SkNf(SkNf<N/2>::Max(l.fLo, r.fLo), SkNf<N/2>::Max(l.fHi, r.fHi)); |
136 } | 133 } |
137 | 134 |
138 SkNf sqrt() const { return SkNf(fLo. sqrt(), fHi. sqrt()); } | 135 SkNf sqrt() const { return SkNf(fLo. sqrt(), fHi. sqrt()); } |
139 | 136 |
140 // Generally, increasing precision, increasing cost. | 137 // Generally, increasing precision, increasing cost. |
141 SkNf rsqrt0() const { return SkNf(fLo.rsqrt0(), fHi.rsqrt0()); } | 138 SkNf rsqrt0() const { return SkNf(fLo.rsqrt0(), fHi.rsqrt0()); } |
142 SkNf rsqrt1() const { return SkNf(fLo.rsqrt1(), fHi.rsqrt1()); } | 139 SkNf rsqrt1() const { return SkNf(fLo.rsqrt1(), fHi.rsqrt1()); } |
143 SkNf rsqrt2() const { return SkNf(fLo.rsqrt2(), fHi.rsqrt2()); } | 140 SkNf rsqrt2() const { return SkNf(fLo.rsqrt2(), fHi.rsqrt2()); } |
144 | 141 |
145 SkNf invert() const { return SkNf(fLo. invert(), fHi. invert
()); } | 142 SkNf invert() const { return SkNf(fLo. invert(), fHi. invert
()); } |
146 SkNf approxInvert() const { return SkNf(fLo.approxInvert(), fHi.approxInvert
()); } | 143 SkNf approxInvert() const { return SkNf(fLo.approxInvert(), fHi.approxInvert
()); } |
147 | 144 |
148 template <int k> T kth() const { | 145 template <int k> float kth() const { |
149 SkASSERT(0 <= k && k < N); | 146 SkASSERT(0 <= k && k < N); |
150 return k < N/2 ? fLo.template kth<k>() : fHi.template kth<k-N/2>(); | 147 return k < N/2 ? fLo.template kth<k>() : fHi.template kth<k-N/2>(); |
151 } | 148 } |
152 | 149 |
153 bool allTrue() const { return fLo.allTrue() && fHi.allTrue(); } | 150 bool allTrue() const { return fLo.allTrue() && fHi.allTrue(); } |
154 bool anyTrue() const { return fLo.anyTrue() || fHi.anyTrue(); } | 151 bool anyTrue() const { return fLo.anyTrue() || fHi.anyTrue(); } |
155 SkNf thenElse(const SkNf& t, const SkNf& e) const { | 152 SkNf thenElse(const SkNf& t, const SkNf& e) const { |
156 return SkNf(fLo.thenElse(t.fLo, e.fLo), fHi.thenElse(t.fHi, e.fHi)); | 153 return SkNf(fLo.thenElse(t.fLo, e.fLo), fHi.thenElse(t.fHi, e.fHi)); |
157 } | 154 } |
158 | 155 |
159 protected: | 156 protected: |
160 REQUIRE(0 == (N & (N-1))); | 157 REQUIRE(0 == (N & (N-1))); |
161 SkNf(const SkNf<N/2, T>& lo, const SkNf<N/2, T>& hi) : fLo(lo), fHi(hi) {} | 158 SkNf(const SkNf<N/2>& lo, const SkNf<N/2>& hi) : fLo(lo), fHi(hi) {} |
162 | 159 |
163 SkNf<N/2, T> fLo, fHi; | 160 SkNf<N/2> fLo, fHi; |
164 }; | 161 }; |
165 | 162 |
166 | 163 |
167 // 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. |
168 | 165 |
169 template <typename T> | 166 template <typename T> |
170 class SkNi<1,T> { | 167 class SkNi<1,T> { |
171 public: | 168 public: |
172 SkNi() {} | 169 SkNi() {} |
173 explicit SkNi(T val) : fVal(val) {} | 170 explicit SkNi(T val) : fVal(val) {} |
(...skipping 23 matching lines...) Expand all Loading... |
197 } | 194 } |
198 | 195 |
199 bool allTrue() const { return fVal; } | 196 bool allTrue() const { return fVal; } |
200 bool anyTrue() const { return fVal; } | 197 bool anyTrue() const { return fVal; } |
201 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; } |
202 | 199 |
203 protected: | 200 protected: |
204 T fVal; | 201 T fVal; |
205 }; | 202 }; |
206 | 203 |
207 template <typename T> | 204 template <> |
208 class SkNf<1,T> { | 205 class SkNf<1> { |
209 static int32_t MyNi(float); | |
210 static int64_t MyNi(double); | |
211 typedef decltype(MyNi(T())) I; | |
212 public: | 206 public: |
213 SkNf() {} | 207 SkNf() {} |
214 explicit SkNf(T val) : fVal(val) {} | 208 explicit SkNf(float val) : fVal(val) {} |
215 static SkNf Load(const T vals[1]) { return SkNf(vals[0]); } | 209 static SkNf Load(const float vals[1]) { return SkNf(vals[0]); } |
216 static SkNf FromBytes(const uint8_t bytes[1]) { return SkNf((T)bytes[0]); } | 210 static SkNf FromBytes(const uint8_t bytes[1]) { return SkNf((float)bytes[0])
; } |
217 | 211 |
218 void store(T vals[1]) const { vals[0] = fVal; } | 212 void store(float vals[1]) const { vals[0] = fVal; } |
219 void toBytes(uint8_t bytes[1]) const { bytes[0] = (uint8_t)(SkTMin(fVal, (T)
255.0)); } | 213 void toBytes(uint8_t bytes[1]) const { bytes[0] = (uint8_t)(SkTMin(fVal, 255
.0f)); } |
220 | |
221 SkNi<1,I> castTrunc() const { return SkNi<1,I>(fVal); } | |
222 | 214 |
223 SkNf operator + (const SkNf& o) const { return SkNf(fVal + o.fVal); } | 215 SkNf operator + (const SkNf& o) const { return SkNf(fVal + o.fVal); } |
224 SkNf operator - (const SkNf& o) const { return SkNf(fVal - o.fVal); } | 216 SkNf operator - (const SkNf& o) const { return SkNf(fVal - o.fVal); } |
225 SkNf operator * (const SkNf& o) const { return SkNf(fVal * o.fVal); } | 217 SkNf operator * (const SkNf& o) const { return SkNf(fVal * o.fVal); } |
226 SkNf operator / (const SkNf& o) const { return SkNf(fVal / o.fVal); } | 218 SkNf operator / (const SkNf& o) const { return SkNf(fVal / o.fVal); } |
227 | 219 |
228 SkNf operator == (const SkNf& o) const { return SkNf(fVal == o.fVal); } | 220 SkNf operator == (const SkNf& o) const { return SkNf(fVal == o.fVal); } |
229 SkNf operator != (const SkNf& o) const { return SkNf(fVal != o.fVal); } | 221 SkNf operator != (const SkNf& o) const { return SkNf(fVal != o.fVal); } |
230 SkNf operator < (const SkNf& o) const { return SkNf(fVal < o.fVal); } | 222 SkNf operator < (const SkNf& o) const { return SkNf(fVal < o.fVal); } |
231 SkNf operator > (const SkNf& o) const { return SkNf(fVal > o.fVal); } | 223 SkNf operator > (const SkNf& o) const { return SkNf(fVal > o.fVal); } |
232 SkNf operator <= (const SkNf& o) const { return SkNf(fVal <= o.fVal); } | 224 SkNf operator <= (const SkNf& o) const { return SkNf(fVal <= o.fVal); } |
233 SkNf operator >= (const SkNf& o) const { return SkNf(fVal >= o.fVal); } | 225 SkNf operator >= (const SkNf& o) const { return SkNf(fVal >= o.fVal); } |
234 | 226 |
235 static SkNf Min(const SkNf& l, const SkNf& r) { return SkNf(SkTMin(l.fVal, r
.fVal)); } | 227 static SkNf Min(const SkNf& l, const SkNf& r) { return SkNf(SkTMin(l.fVal, r
.fVal)); } |
236 static SkNf Max(const SkNf& l, const SkNf& r) { return SkNf(SkTMax(l.fVal, r
.fVal)); } | 228 static SkNf Max(const SkNf& l, const SkNf& r) { return SkNf(SkTMax(l.fVal, r
.fVal)); } |
237 | 229 |
238 SkNf sqrt() const { return SkNf(Sqrt(fVal)); } | 230 SkNf sqrt() const { return SkNf(sqrtf(fVal)); } |
239 SkNf rsqrt0() const { return SkNf((T)1 / Sqrt(fVal)); } | 231 SkNf rsqrt0() const { return SkNf(1.0f / sqrtf(fVal)); } |
240 SkNf rsqrt1() const { return this->rsqrt0(); } | 232 SkNf rsqrt1() const { return this->rsqrt0(); } |
241 SkNf rsqrt2() const { return this->rsqrt1(); } | 233 SkNf rsqrt2() const { return this->rsqrt1(); } |
242 | 234 |
243 SkNf invert() const { return SkNf((T)1 / fVal); } | 235 SkNf invert() const { return SkNf(1.0f / fVal); } |
244 SkNf approxInvert() const { return this->invert(); } | 236 SkNf approxInvert() const { return this->invert(); } |
245 | 237 |
246 template <int k> T kth() const { | 238 template <int k> float kth() const { |
247 SkASSERT(k == 0); | 239 SkASSERT(k == 0); |
248 return fVal; | 240 return fVal; |
249 } | 241 } |
250 | 242 |
251 bool allTrue() const { return this->pun(); } | 243 bool allTrue() const { return this->pun() != 0; } |
252 bool anyTrue() const { return this->pun(); } | 244 bool anyTrue() const { return this->pun() != 0; } |
253 SkNf thenElse(const SkNf& t, const SkNf& e) const { return this->pun() ? t :
e; } | 245 SkNf thenElse(const SkNf& t, const SkNf& e) const { return this->pun() ? t :
e; } |
254 | 246 |
255 protected: | 247 protected: |
256 // We do double sqrts natively, or via floats for any other type. | 248 uint32_t pun() const { |
257 template <typename U> | 249 union { float f; uint32_t i; } pun = { fVal }; |
258 static U Sqrt(U val) { return (U) ::sqrtf((float)val); } | |
259 static double Sqrt(double val) { return ::sqrt ( val); } | |
260 | |
261 I pun() const { | |
262 union { T f; I i; } pun = { fVal }; | |
263 return pun.i; | 250 return pun.i; |
264 } | 251 } |
265 | 252 |
266 T fVal; | 253 float fVal; |
267 }; | 254 }; |
268 | 255 |
269 // This default implementation can be specialized by ../opts/SkNx_foo.h | 256 // This default implementation can be specialized by ../opts/SkNx_foo.h |
270 // if there's a better platform-specific shuffle strategy. | 257 // if there's a better platform-specific shuffle strategy. |
271 template <typename SkNx, int... Ix> | 258 template <typename SkNx, int... Ix> |
272 inline SkNx SkNx_shuffle_impl(const SkNx& src) { return SkNx( src.template kth<I
x>()... ); } | 259 inline SkNx SkNx_shuffle_impl(const SkNx& src) { return SkNx( src.template kth<I
x>()... ); } |
273 | 260 |
274 // This generic shuffle can be called on either SkNi or SkNf with 1 or N indices
: | 261 // This generic shuffle can be called on either SkNi or SkNf with 1 or N indices
: |
275 // Sk4f f(a,b,c,d); | 262 // Sk4f f(a,b,c,d); |
276 // SkNx_shuffle<3>(f); // ~~~> Sk4f(d,d,d,d) | 263 // SkNx_shuffle<3>(f); // ~~~> Sk4f(d,d,d,d) |
277 // SkNx_shuffle<2,1,0,3>(f); // ~~~> Sk4f(c,b,a,d) | 264 // SkNx_shuffle<2,1,0,3>(f); // ~~~> Sk4f(c,b,a,d) |
278 template <int... Ix, typename SkNx> | 265 template <int... Ix, typename SkNx> |
279 inline SkNx SkNx_shuffle(const SkNx& src) { return SkNx_shuffle_impl<SkNx, Ix...
>(src); } | 266 inline SkNx SkNx_shuffle(const SkNx& src) { return SkNx_shuffle_impl<SkNx, Ix...
>(src); } |
280 | 267 |
281 // 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. |
282 template <int Ix, typename SkNx> | 269 template <int Ix, typename SkNx> |
283 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); } |
284 | 271 |
285 } // namespace | 272 } // namespace |
286 | 273 |
287 | 274 |
288 | |
289 | |
290 // Include platform specific specializations if available. | 275 // Include platform specific specializations if available. |
291 #ifndef SKNX_NO_SIMD | 276 #ifndef SKNX_NO_SIMD |
292 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 | 277 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 |
293 #include "../opts/SkNx_sse.h" | 278 #include "../opts/SkNx_sse.h" |
294 #elif defined(SK_ARM_HAS_NEON) | 279 #elif defined(SK_ARM_HAS_NEON) |
295 #include "../opts/SkNx_neon.h" | 280 #include "../opts/SkNx_neon.h" |
296 #endif | 281 #endif |
297 #endif | 282 #endif |
298 | 283 |
299 #undef REQUIRE | 284 #undef REQUIRE |
300 | 285 |
301 typedef SkNf<2, float> Sk2f; | 286 typedef SkNf<2> Sk2f; |
302 typedef SkNf<2, double> Sk2d; | 287 typedef SkNf<2> Sk2s; |
303 typedef SkNf<2, SkScalar> Sk2s; | |
304 | 288 |
305 typedef SkNf<4, float> Sk4f; | 289 typedef SkNf<4> Sk4f; |
306 typedef SkNf<4, double> Sk4d; | 290 typedef SkNf<4> Sk4s; |
307 typedef SkNf<4, SkScalar> Sk4s; | |
308 | 291 |
309 typedef SkNi<4, uint16_t> Sk4h; | |
310 typedef SkNi<8, uint16_t> Sk8h; | 292 typedef SkNi<8, uint16_t> Sk8h; |
311 typedef SkNi<16, uint16_t> Sk16h; | 293 typedef SkNi<16, uint16_t> Sk16h; |
312 | 294 typedef SkNi<16, uint8_t> Sk16b; |
313 typedef SkNi<16, uint8_t> Sk16b; | |
314 | |
315 typedef SkNi<4, int32_t> Sk4i; | |
316 typedef SkNi<4, uint32_t> Sk4u; | |
317 | 295 |
318 #endif//SkNx_DEFINED | 296 #endif//SkNx_DEFINED |
OLD | NEW |