Line data Source code
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 0 : 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 0 : inline Sk4x4f Sk4x4f::Transpose(const Sk4f& x, const Sk4f& y, const Sk4f& z, const Sk4f& w) {
36 0 : auto r = x.fVec,
37 0 : g = y.fVec,
38 0 : b = z.fVec,
39 0 : a = w.fVec;
40 0 : _MM_TRANSPOSE4_PS(r,g,b,a);
41 0 : return { r,g,b,a };
42 : }
43 :
44 0 : inline Sk4x4f Sk4x4f::Transpose(const float fs[16]) {
45 0 : 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
|