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 namespace { 14 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 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 } 29 void transpose( float[16]) const; 30 void transpose(uint8_t[16]) const; 31 }; 32 33 #if 1 && !defined(SKNX_NO_SIMD) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 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); 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)); 56 return { r,g,b,a }; 57 } 58 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 { 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)))); 74 } 75 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 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 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 155 } // namespace 156 157 #endif//Sk4x4f_DEFINED 158