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