mtklein | 0e05f38 | 2016-03-22 17:17:44 -0700 | [diff] [blame] | 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 | |
Mike Klein | 1e76464 | 2016-10-14 17:09:03 -0400 | [diff] [blame^] | 13 | namespace { |
| 14 | |
mtklein | 0e05f38 | 2016-03-22 17:17:44 -0700 | [diff] [blame] | 15 | struct Sk4x4f { |
| 16 | Sk4f r,g,b,a; |
| 17 | |
| 18 | static Sk4x4f Transpose(const Sk4f&, const Sk4f&, const Sk4f&, const Sk4f&); |
| 19 | static Sk4x4f Transpose(const float[16]); |
| 20 | static Sk4x4f Transpose(const uint8_t[16]); |
| 21 | |
mtklein | 1fd50ac | 2016-03-24 10:12:37 -0700 | [diff] [blame] | 22 | void transpose(Sk4f* x, Sk4f* y, Sk4f* z, Sk4f* w) const { |
| 23 | auto t = Transpose(r,g,b,a); |
| 24 | *x = t.r; |
| 25 | *y = t.g; |
| 26 | *z = t.b; |
| 27 | *w = t.a; |
| 28 | } |
mtklein | 0e05f38 | 2016-03-22 17:17:44 -0700 | [diff] [blame] | 29 | void transpose( float[16]) const; |
| 30 | void transpose(uint8_t[16]) const; |
| 31 | }; |
| 32 | |
mtklein | 1443c69 | 2016-03-23 09:52:13 -0700 | [diff] [blame] | 33 | #if 1 && !defined(SKNX_NO_SIMD) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 |
mtklein | 0e05f38 | 2016-03-22 17:17:44 -0700 | [diff] [blame] | 34 | |
| 35 | inline Sk4x4f Sk4x4f::Transpose(const Sk4f& x, const Sk4f& y, const Sk4f& z, const Sk4f& w) { |
| 36 | auto r = x.fVec, |
| 37 | g = y.fVec, |
| 38 | b = z.fVec, |
| 39 | a = w.fVec; |
| 40 | _MM_TRANSPOSE4_PS(r,g,b,a); |
| 41 | return { r,g,b,a }; |
| 42 | } |
| 43 | |
| 44 | inline Sk4x4f Sk4x4f::Transpose(const float fs[16]) { |
| 45 | return Transpose(Sk4f::Load(fs+0), Sk4f::Load(fs+4), Sk4f::Load(fs+8), Sk4f::Load(fs+12)); |
| 46 | } |
| 47 | |
| 48 | inline Sk4x4f Sk4x4f::Transpose(const uint8_t bs[16]) { |
| 49 | auto b16 = _mm_loadu_si128((const __m128i*)bs); |
mtklein | 1443c69 | 2016-03-23 09:52:13 -0700 | [diff] [blame] | 50 | |
| 51 | auto mask = _mm_set1_epi32(0xFF); |
| 52 | auto r = _mm_cvtepi32_ps(_mm_and_si128(mask, (b16 ))), |
| 53 | g = _mm_cvtepi32_ps(_mm_and_si128(mask, _mm_srli_epi32(b16, 8))), |
| 54 | b = _mm_cvtepi32_ps(_mm_and_si128(mask, _mm_srli_epi32(b16, 16))), |
| 55 | a = _mm_cvtepi32_ps( _mm_srli_epi32(b16, 24)); |
mtklein | 0e05f38 | 2016-03-22 17:17:44 -0700 | [diff] [blame] | 56 | return { r,g,b,a }; |
| 57 | } |
| 58 | |
mtklein | 0e05f38 | 2016-03-22 17:17:44 -0700 | [diff] [blame] | 59 | inline void Sk4x4f::transpose(float fs[16]) const { |
| 60 | Sk4f x,y,z,w; |
| 61 | this->transpose(&x,&y,&z,&w); |
| 62 | x.store(fs+ 0); |
| 63 | y.store(fs+ 4); |
| 64 | z.store(fs+ 8); |
| 65 | w.store(fs+12); |
| 66 | } |
| 67 | |
| 68 | inline void Sk4x4f::transpose(uint8_t bs[16]) const { |
mtklein | 1443c69 | 2016-03-23 09:52:13 -0700 | [diff] [blame] | 69 | auto R = _mm_cvttps_epi32(r.fVec), |
| 70 | G = _mm_slli_epi32(_mm_cvttps_epi32(g.fVec), 8), |
| 71 | B = _mm_slli_epi32(_mm_cvttps_epi32(b.fVec), 16), |
| 72 | A = _mm_slli_epi32(_mm_cvttps_epi32(a.fVec), 24); |
| 73 | _mm_storeu_si128((__m128i*)bs, _mm_or_si128(A, _mm_or_si128(B, _mm_or_si128(G, R)))); |
mtklein | 0e05f38 | 2016-03-22 17:17:44 -0700 | [diff] [blame] | 74 | } |
| 75 | |
mtklein | 1fd50ac | 2016-03-24 10:12:37 -0700 | [diff] [blame] | 76 | #elif defined(SK_ARM_HAS_NEON) |
| 77 | |
| 78 | inline Sk4x4f Sk4x4f::Transpose(const Sk4f& x, const Sk4f& y, const Sk4f& z, const Sk4f& w) { |
| 79 | float32x4x2_t xy = vuzpq_f32(x.fVec, y.fVec), |
| 80 | zw = vuzpq_f32(z.fVec, w.fVec), |
| 81 | rb = vuzpq_f32(xy.val[0], zw.val[0]), |
| 82 | ga = vuzpq_f32(xy.val[1], zw.val[1]); |
| 83 | return { rb.val[0], ga.val[0], rb.val[1], ga.val[1] }; |
| 84 | } |
| 85 | |
| 86 | inline Sk4x4f Sk4x4f::Transpose(const float fs[16]) { |
| 87 | float32x4x4_t v = vld4q_f32(fs); |
| 88 | return { v.val[0], v.val[1], v.val[2], v.val[3] }; |
| 89 | } |
| 90 | |
| 91 | inline Sk4x4f Sk4x4f::Transpose(const uint8_t bs[16]) { |
| 92 | auto b16 = vreinterpretq_u32_u8(vld1q_u8(bs)); |
| 93 | auto r = vcvtq_f32_u32(vandq_u32(vdupq_n_u32(0x000000FF), b16) ), |
| 94 | g = vcvtq_n_f32_u32(vandq_u32(vdupq_n_u32(0x0000FF00), b16), 8), |
| 95 | b = vcvtq_n_f32_u32(vandq_u32(vdupq_n_u32(0x00FF0000), b16), 16), |
| 96 | a = vcvtq_n_f32_u32(vandq_u32(vdupq_n_u32(0xFF000000), b16), 24); |
| 97 | return { r,g,b,a }; |
| 98 | } |
| 99 | |
| 100 | inline void Sk4x4f::transpose(float fs[16]) const { |
| 101 | float32x4x4_t v = {{ r.fVec, g.fVec, b.fVec, a.fVec }}; |
| 102 | vst4q_f32(fs, v); |
| 103 | } |
| 104 | |
| 105 | inline void Sk4x4f::transpose(uint8_t bs[16]) const { |
| 106 | auto R = vandq_u32(vdupq_n_u32(0x000000FF), vcvtq_u32_f32(r.fVec )), |
| 107 | G = vandq_u32(vdupq_n_u32(0x0000FF00), vcvtq_n_u32_f32(g.fVec, 8)), |
| 108 | B = vandq_u32(vdupq_n_u32(0x00FF0000), vcvtq_n_u32_f32(b.fVec, 16)), |
| 109 | A = vandq_u32(vdupq_n_u32(0xFF000000), vcvtq_n_u32_f32(a.fVec, 24)); |
| 110 | vst1q_u8(bs, vreinterpretq_u8_u32(vorrq_u32(A, vorrq_u32(B, vorrq_u32(G, R))))); |
| 111 | } |
| 112 | |
mtklein | 0e05f38 | 2016-03-22 17:17:44 -0700 | [diff] [blame] | 113 | #else |
| 114 | |
| 115 | inline Sk4x4f Sk4x4f::Transpose(const Sk4f& x, const Sk4f& y, const Sk4f& z, const Sk4f& w) { |
| 116 | return { |
| 117 | { x[0], y[0], z[0], w[0] }, |
| 118 | { x[1], y[1], z[1], w[1] }, |
| 119 | { x[2], y[2], z[2], w[2] }, |
| 120 | { x[3], y[3], z[3], w[3] }, |
| 121 | }; |
| 122 | } |
| 123 | |
| 124 | inline Sk4x4f Sk4x4f::Transpose(const float fs[16]) { |
| 125 | return Transpose(Sk4f::Load(fs+0), Sk4f::Load(fs+4), Sk4f::Load(fs+8), Sk4f::Load(fs+12)); |
| 126 | } |
| 127 | |
| 128 | inline Sk4x4f Sk4x4f::Transpose(const uint8_t bs[16]) { |
| 129 | return { |
| 130 | { (float)bs[0], (float)bs[4], (float)bs[ 8], (float)bs[12] }, |
| 131 | { (float)bs[1], (float)bs[5], (float)bs[ 9], (float)bs[13] }, |
| 132 | { (float)bs[2], (float)bs[6], (float)bs[10], (float)bs[14] }, |
| 133 | { (float)bs[3], (float)bs[7], (float)bs[11], (float)bs[15] }, |
| 134 | }; |
| 135 | } |
| 136 | |
mtklein | 0e05f38 | 2016-03-22 17:17:44 -0700 | [diff] [blame] | 137 | inline void Sk4x4f::transpose(float fs[16]) const { |
| 138 | Sk4f x,y,z,w; |
| 139 | this->transpose(&x,&y,&z,&w); |
| 140 | x.store(fs+ 0); |
| 141 | y.store(fs+ 4); |
| 142 | z.store(fs+ 8); |
| 143 | w.store(fs+12); |
| 144 | } |
| 145 | |
| 146 | inline void Sk4x4f::transpose(uint8_t bs[16]) const { |
| 147 | bs[ 0] = (uint8_t)r[0]; bs[ 1] = (uint8_t)g[0]; bs[ 2] = (uint8_t)b[0]; bs[ 3] = (uint8_t)a[0]; |
| 148 | bs[ 4] = (uint8_t)r[1]; bs[ 5] = (uint8_t)g[1]; bs[ 6] = (uint8_t)b[1]; bs[ 7] = (uint8_t)a[1]; |
| 149 | bs[ 8] = (uint8_t)r[2]; bs[ 9] = (uint8_t)g[2]; bs[10] = (uint8_t)b[2]; bs[11] = (uint8_t)a[2]; |
| 150 | bs[12] = (uint8_t)r[3]; bs[13] = (uint8_t)g[3]; bs[14] = (uint8_t)b[3]; bs[15] = (uint8_t)a[3]; |
| 151 | } |
| 152 | |
| 153 | #endif |
| 154 | |
Mike Klein | 1e76464 | 2016-10-14 17:09:03 -0400 | [diff] [blame^] | 155 | } // namespace |
| 156 | |
mtklein | 0e05f38 | 2016-03-22 17:17:44 -0700 | [diff] [blame] | 157 | #endif//Sk4x4f_DEFINED |