OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright 2016 Google Inc. |
| 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. |
| 6 */ |
| 7 |
| 8 #ifndef Sk4x4f_DEFINED |
| 9 #define Sk4x4f_DEFINED |
| 10 |
| 11 #include "SkNx.h" |
| 12 |
| 13 struct Sk4x4f { |
| 14 Sk4f r,g,b,a; |
| 15 |
| 16 static Sk4x4f Transpose(const Sk4f&, const Sk4f&, const Sk4f&, const Sk4f&); |
| 17 static Sk4x4f Transpose(const float[16]); |
| 18 static Sk4x4f Transpose(const uint8_t[16]); |
| 19 |
| 20 void transpose(Sk4f*, Sk4f*, Sk4f*, Sk4f*) const; |
| 21 void transpose( float[16]) const; |
| 22 void transpose(uint8_t[16]) const; |
| 23 }; |
| 24 |
| 25 // TODO: SSE2, NEON |
| 26 |
| 27 #if 1 && !defined(SKNX_NO_SIMD) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSSE3 |
| 28 |
| 29 inline Sk4x4f Sk4x4f::Transpose(const Sk4f& x, const Sk4f& y, const Sk4f& z, con
st Sk4f& w) { |
| 30 auto r = x.fVec, |
| 31 g = y.fVec, |
| 32 b = z.fVec, |
| 33 a = w.fVec; |
| 34 _MM_TRANSPOSE4_PS(r,g,b,a); |
| 35 return { r,g,b,a }; |
| 36 } |
| 37 |
| 38 inline Sk4x4f Sk4x4f::Transpose(const float fs[16]) { |
| 39 return Transpose(Sk4f::Load(fs+0), Sk4f::Load(fs+4), Sk4f::Load(fs+8), Sk4f:
:Load(fs+12)); |
| 40 } |
| 41 |
| 42 inline Sk4x4f Sk4x4f::Transpose(const uint8_t bs[16]) { |
| 43 auto b16 = _mm_loadu_si128((const __m128i*)bs); |
| 44 auto _ = ~0; // Shuffles in a zero byte. |
| 45 auto r = _mm_cvtepi32_ps( |
| 46 _mm_shuffle_epi8(b16, _mm_setr_epi8(0,_,_,_,4,_,_,_, 8,_,_,_,12,_,_,
_))); |
| 47 auto g = _mm_cvtepi32_ps( |
| 48 _mm_shuffle_epi8(b16, _mm_setr_epi8(1,_,_,_,5,_,_,_, 9,_,_,_,13,_,_,
_))); |
| 49 auto b = _mm_cvtepi32_ps( |
| 50 _mm_shuffle_epi8(b16, _mm_setr_epi8(2,_,_,_,6,_,_,_,10,_,_,_,14,_,_,
_))); |
| 51 auto a = _mm_cvtepi32_ps( |
| 52 _mm_shuffle_epi8(b16, _mm_setr_epi8(3,_,_,_,7,_,_,_,11,_,_,_,15,_,_,
_))); |
| 53 return { r,g,b,a }; |
| 54 } |
| 55 |
| 56 inline void Sk4x4f::transpose(Sk4f* x, Sk4f* y, Sk4f* z, Sk4f* w) const { |
| 57 auto R = r.fVec, |
| 58 G = g.fVec, |
| 59 B = b.fVec, |
| 60 A = a.fVec; |
| 61 _MM_TRANSPOSE4_PS(R,G,B,A); |
| 62 *x = R; |
| 63 *y = G; |
| 64 *z = B; |
| 65 *w = A; |
| 66 } |
| 67 |
| 68 inline void Sk4x4f::transpose(float fs[16]) const { |
| 69 Sk4f x,y,z,w; |
| 70 this->transpose(&x,&y,&z,&w); |
| 71 x.store(fs+ 0); |
| 72 y.store(fs+ 4); |
| 73 z.store(fs+ 8); |
| 74 w.store(fs+12); |
| 75 } |
| 76 |
| 77 inline void Sk4x4f::transpose(uint8_t bs[16]) const { |
| 78 auto packed = _mm_packus_epi16(_mm_packus_epi16(_mm_cvttps_epi32(r.fVec), |
| 79 _mm_cvttps_epi32(g.fVec)), |
| 80 _mm_packus_epi16(_mm_cvttps_epi32(b.fVec), |
| 81 _mm_cvttps_epi32(a.fVec))); |
| 82 _mm_storeu_si128((__m128i*)bs, _mm_shuffle_epi8(packed, _mm_setr_epi8(0, 4,
8, 12, |
| 83 1, 5,
9, 13, |
| 84 2, 6,
10, 14, |
| 85 3, 7,
11, 15))); |
| 86 } |
| 87 |
| 88 #else |
| 89 |
| 90 inline Sk4x4f Sk4x4f::Transpose(const Sk4f& x, const Sk4f& y, const Sk4f& z, con
st Sk4f& w) { |
| 91 return { |
| 92 { x[0], y[0], z[0], w[0] }, |
| 93 { x[1], y[1], z[1], w[1] }, |
| 94 { x[2], y[2], z[2], w[2] }, |
| 95 { x[3], y[3], z[3], w[3] }, |
| 96 }; |
| 97 } |
| 98 |
| 99 inline Sk4x4f Sk4x4f::Transpose(const float fs[16]) { |
| 100 return Transpose(Sk4f::Load(fs+0), Sk4f::Load(fs+4), Sk4f::Load(fs+8), Sk4f:
:Load(fs+12)); |
| 101 } |
| 102 |
| 103 inline Sk4x4f Sk4x4f::Transpose(const uint8_t bs[16]) { |
| 104 return { |
| 105 { (float)bs[0], (float)bs[4], (float)bs[ 8], (float)bs[12] }, |
| 106 { (float)bs[1], (float)bs[5], (float)bs[ 9], (float)bs[13] }, |
| 107 { (float)bs[2], (float)bs[6], (float)bs[10], (float)bs[14] }, |
| 108 { (float)bs[3], (float)bs[7], (float)bs[11], (float)bs[15] }, |
| 109 }; |
| 110 } |
| 111 |
| 112 inline void Sk4x4f::transpose(Sk4f* x, Sk4f* y, Sk4f* z, Sk4f* w) const { |
| 113 *x = { r[0], g[0], b[0], a[0] }; |
| 114 *y = { r[1], g[1], b[1], a[1] }; |
| 115 *z = { r[2], g[2], b[2], a[2] }; |
| 116 *w = { r[3], g[3], b[3], a[3] }; |
| 117 } |
| 118 |
| 119 inline void Sk4x4f::transpose(float fs[16]) const { |
| 120 Sk4f x,y,z,w; |
| 121 this->transpose(&x,&y,&z,&w); |
| 122 x.store(fs+ 0); |
| 123 y.store(fs+ 4); |
| 124 z.store(fs+ 8); |
| 125 w.store(fs+12); |
| 126 } |
| 127 |
| 128 inline void Sk4x4f::transpose(uint8_t bs[16]) const { |
| 129 bs[ 0] = (uint8_t)r[0]; bs[ 1] = (uint8_t)g[0]; bs[ 2] = (uint8_t)b[0]; bs[
3] = (uint8_t)a[0]; |
| 130 bs[ 4] = (uint8_t)r[1]; bs[ 5] = (uint8_t)g[1]; bs[ 6] = (uint8_t)b[1]; bs[
7] = (uint8_t)a[1]; |
| 131 bs[ 8] = (uint8_t)r[2]; bs[ 9] = (uint8_t)g[2]; bs[10] = (uint8_t)b[2]; bs[1
1] = (uint8_t)a[2]; |
| 132 bs[12] = (uint8_t)r[3]; bs[13] = (uint8_t)g[3]; bs[14] = (uint8_t)b[3]; bs[1
5] = (uint8_t)a[3]; |
| 133 } |
| 134 |
| 135 #endif |
| 136 |
| 137 #endif//Sk4x4f_DEFINED |
OLD | NEW |