Home | History | Annotate | Download | only in core
      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