| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  * Copyright 2016 Google Inc. | 2  * Copyright 2016 Google Inc. | 
| 3  * | 3  * | 
| 4  * Use of this source code is governed by a BSD-style license that can be | 4  * Use of this source code is governed by a BSD-style license that can be | 
| 5  * found in the LICENSE file. | 5  * found in the LICENSE file. | 
| 6  */ | 6  */ | 
| 7 | 7 | 
| 8 #ifndef Sk4fGradientPriv_DEFINED | 8 #ifndef Sk4fGradientPriv_DEFINED | 
| 9 #define Sk4fGradientPriv_DEFINED | 9 #define Sk4fGradientPriv_DEFINED | 
| 10 | 10 | 
| 11 #include "SkColor.h" | 11 #include "SkColor.h" | 
| 12 #include "SkHalf.h" | 12 #include "SkHalf.h" | 
| 13 #include "SkImageInfo.h" | 13 #include "SkImageInfo.h" | 
| 14 #include "SkNx.h" | 14 #include "SkNx.h" | 
| 15 #include "SkPM4f.h" | 15 #include "SkPM4f.h" | 
| 16 #include "SkPM4fPriv.h" | 16 #include "SkPM4fPriv.h" | 
|  | 17 #include "SkUtils.h" | 
| 17 | 18 | 
| 18 // Templates shared by various 4f gradient flavors. | 19 // Templates shared by various 4f gradient flavors. | 
| 19 | 20 | 
| 20 namespace { | 21 namespace { | 
| 21 | 22 | 
| 22 enum class ApplyPremul { True, False }; | 23 enum class ApplyPremul { True, False }; | 
| 23 | 24 | 
| 24 inline Sk4f premul_4f(const Sk4f& c) { | 25 enum class DstType { | 
| 25     const float alpha = c[SkPM4f::A]; | 26     L32,  // Linear 32bit.  Used for both shader/blitter paths. | 
| 26     // FIXME: portable swizzle? | 27     S32,  // SRGB 32bit.  Used for the blitter path only. | 
| 27     return c * Sk4f(alpha, alpha, alpha, 1); | 28     F16,  // Linear half-float.  Used for blitters only. | 
| 28 } | 29     F32,  // Linear float.  Used for shaders only. | 
|  | 30 }; | 
| 29 | 31 | 
| 30 template <ApplyPremul premul> | 32 template <ApplyPremul premul> | 
| 31 inline SkPMColor trunc_from_4f_255(const Sk4f& c) { | 33 inline SkPMColor trunc_from_4f_255(const Sk4f& c) { | 
| 32     SkPMColor pmc; | 34     SkPMColor pmc; | 
| 33     SkNx_cast<uint8_t>(c).store(&pmc); | 35     SkNx_cast<uint8_t>(c).store(&pmc); | 
| 34     if (premul == ApplyPremul::True) { | 36     if (premul == ApplyPremul::True) { | 
| 35         pmc = SkPreMultiplyARGB(SkGetPackedA32(pmc), SkGetPackedR32(pmc), | 37         pmc = SkPreMultiplyARGB(SkGetPackedA32(pmc), SkGetPackedR32(pmc), | 
| 36                                 SkGetPackedG32(pmc), SkGetPackedB32(pmc)); | 38                                 SkGetPackedG32(pmc), SkGetPackedB32(pmc)); | 
| 37     } | 39     } | 
| 38     return pmc; | 40     return pmc; | 
| 39 } | 41 } | 
| 40 | 42 | 
| 41 template<typename DstType, SkColorProfileType, ApplyPremul premul> | 43 template <ApplyPremul> | 
| 42 void store(const Sk4f& color, DstType* dst); | 44 struct PremulTraits; | 
| 43 | 45 | 
| 44 template<> | 46 template <> | 
| 45 inline void store<SkPM4f, kLinear_SkColorProfileType, ApplyPremul::False> | 47 struct PremulTraits<ApplyPremul::False> { | 
| 46                  (const Sk4f& c, SkPM4f* dst) { | 48     static Sk4f apply(const Sk4f& c) { return c; } | 
| 47     c.store(dst); | 49 }; | 
| 48 } |  | 
| 49 | 50 | 
| 50 template<> | 51 template <> | 
| 51 inline void store<SkPM4f, kLinear_SkColorProfileType, ApplyPremul::True> | 52 struct PremulTraits<ApplyPremul::True> { | 
| 52                  (const Sk4f& c, SkPM4f* dst) { | 53     static Sk4f apply(const Sk4f& c) { | 
| 53     premul_4f(c).store(dst); | 54         const float alpha = c[SkPM4f::A]; | 
| 54 } | 55         // FIXME: portable swizzle? | 
|  | 56         return c * Sk4f(alpha, alpha, alpha, 1); | 
|  | 57     } | 
|  | 58 }; | 
| 55 | 59 | 
| 56 template<> | 60 // Struct encapsulating various dest-dependent ops: | 
| 57 inline void store<SkPMColor, kLinear_SkColorProfileType, ApplyPremul::False> | 61 // | 
| 58                  (const Sk4f& c, SkPMColor* dst) { | 62 //   - load()       Load a SkPM4f value into Sk4f.  Normally called once per int
     erval | 
| 59     *dst = trunc_from_4f_255<ApplyPremul::False>(c); | 63 //                  advance.  Also applies a scale and swizzle suitable for DstT
     ype. | 
| 60 } | 64 // | 
|  | 65 //   - store()      Store one Sk4f to dest.  Optionally handles premul, color sp
     ace | 
|  | 66 //                  conversion, etc. | 
|  | 67 // | 
|  | 68 //   - store(count) Store the Sk4f value repeatedly to dest, count times. | 
|  | 69 // | 
|  | 70 //   - store4x()    Store 4 Sk4f values to dest (opportunistic optimization). | 
|  | 71 // | 
|  | 72 template <DstType, ApplyPremul premul = ApplyPremul::False> | 
|  | 73 struct DstTraits; | 
| 61 | 74 | 
| 62 template<> | 75 template <ApplyPremul premul> | 
| 63 inline void store<SkPMColor, kLinear_SkColorProfileType, ApplyPremul::True> | 76 struct DstTraits<DstType::L32, premul> { | 
| 64                  (const Sk4f& c, SkPMColor* dst) { | 77     using Type = SkPMColor; | 
| 65     *dst = trunc_from_4f_255<ApplyPremul::True>(c); |  | 
| 66 } |  | 
| 67 | 78 | 
| 68 template<> | 79     // For L32, we prescale the values by 255 to save a per-pixel multiplication
     . | 
| 69 inline void store<SkPMColor, kSRGB_SkColorProfileType, ApplyPremul::False> | 80     static Sk4f load(const SkPM4f& c) { | 
| 70                  (const Sk4f& c, SkPMColor* dst) { | 81         return c.to4f_pmorder() * Sk4f(255); | 
| 71     // FIXME: this assumes opaque colors.  Handle unpremultiplication. | 82     } | 
| 72     *dst = Sk4f_toS32(c); |  | 
| 73 } |  | 
| 74 | 83 | 
| 75 template<> | 84     static void store(const Sk4f& c, Type* dst) { | 
| 76 inline void store<SkPMColor, kSRGB_SkColorProfileType, ApplyPremul::True> | 85         *dst = trunc_from_4f_255<premul>(c); | 
| 77                  (const Sk4f& c, SkPMColor* dst) { | 86     } | 
| 78     *dst = Sk4f_toS32(premul_4f(c)); |  | 
| 79 } |  | 
| 80 | 87 | 
| 81 template<> | 88     static void store(const Sk4f& c, Type* dst, int n) { | 
| 82 inline void store<uint64_t, kLinear_SkColorProfileType, ApplyPremul::False> | 89         sk_memset32(dst, trunc_from_4f_255<premul>(c), n); | 
| 83                  (const Sk4f& c, uint64_t* dst) { | 90     } | 
| 84     *dst = SkFloatToHalf_01(c); |  | 
| 85 } |  | 
| 86 | 91 | 
| 87 template<> | 92     static void store4x(const Sk4f& c0, const Sk4f& c1, | 
| 88 inline void store<uint64_t, kLinear_SkColorProfileType, ApplyPremul::True> | 93                         const Sk4f& c2, const Sk4f& c3, | 
| 89                  (const Sk4f& c, uint64_t* dst) { | 94                         Type* dst) { | 
| 90     *dst = SkFloatToHalf_01(premul_4f(c)); | 95         if (premul == ApplyPremul::False) { | 
| 91 } | 96             Sk4f_ToBytes((uint8_t*)dst, c0, c1, c2, c3); | 
|  | 97         } else { | 
|  | 98             store(c0, dst + 0); | 
|  | 99             store(c1, dst + 1); | 
|  | 100             store(c2, dst + 2); | 
|  | 101             store(c3, dst + 3); | 
|  | 102         } | 
|  | 103     } | 
|  | 104 }; | 
| 92 | 105 | 
| 93 template<typename DstType, SkColorProfileType profile, ApplyPremul premul> | 106 template <ApplyPremul premul> | 
| 94 inline void store4x(const Sk4f& c0, | 107 struct DstTraits<DstType::S32, premul> { | 
| 95                     const Sk4f& c1, | 108     using PM   = PremulTraits<premul>; | 
| 96                     const Sk4f& c2, | 109     using Type = SkPMColor; | 
| 97                     const Sk4f& c3, |  | 
| 98                     DstType* dst) { |  | 
| 99     store<DstType, profile, premul>(c0, dst++); |  | 
| 100     store<DstType, profile, premul>(c1, dst++); |  | 
| 101     store<DstType, profile, premul>(c2, dst++); |  | 
| 102     store<DstType, profile, premul>(c3, dst++); |  | 
| 103 } |  | 
| 104 | 110 | 
| 105 template<> | 111     // TODO: prescale by something like (255^2, 255^2, 255^2, 255) and use | 
| 106 inline void store4x<SkPMColor, kLinear_SkColorProfileType, ApplyPremul::False> | 112     //       linear_to_srgb to save a mult in store? | 
| 107                    (const Sk4f& c0, const Sk4f& c1, | 113     static Sk4f load(const SkPM4f& c) { | 
| 108                     const Sk4f& c2, const Sk4f& c3, | 114         return c.to4f_pmorder(); | 
| 109                     SkPMColor* dst) { | 115     } | 
| 110     Sk4f_ToBytes((uint8_t*)dst, c0, c1, c2, c3); |  | 
| 111 } |  | 
| 112 | 116 | 
| 113 template<typename DstType, SkColorProfileType> | 117     static void store(const Sk4f& c, Type* dst) { | 
| 114 Sk4f scale_for_dest(const Sk4f& c)  { | 118         // FIXME: this assumes opaque colors.  Handle unpremultiplication. | 
| 115     return c; | 119         *dst = Sk4f_toS32(PM::apply(c)); | 
| 116 } | 120     } | 
| 117 | 121 | 
| 118 template<> | 122     static void store(const Sk4f& c, Type* dst, int n) { | 
| 119 inline Sk4f scale_for_dest<SkPMColor, kLinear_SkColorProfileType>(const Sk4f& c)
       { | 123         sk_memset32(dst, Sk4f_toS32(PM::apply(c)), n); | 
| 120     return c * 255; | 124     } | 
| 121 } |  | 
| 122 | 125 | 
| 123 template<typename DstType> | 126     static void store4x(const Sk4f& c0, const Sk4f& c1, | 
| 124 Sk4f dst_swizzle(const SkPM4f&); | 127                         const Sk4f& c2, const Sk4f& c3, | 
|  | 128                         Type* dst) { | 
|  | 129         store(c0, dst + 0); | 
|  | 130         store(c1, dst + 1); | 
|  | 131         store(c2, dst + 2); | 
|  | 132         store(c3, dst + 3); | 
|  | 133     } | 
|  | 134 }; | 
| 125 | 135 | 
| 126 template<> | 136 template <ApplyPremul premul> | 
| 127 inline Sk4f dst_swizzle<SkPM4f>(const SkPM4f& c) { | 137 struct DstTraits<DstType::F16, premul> { | 
| 128     return c.to4f(); | 138     using PM   = PremulTraits<premul>; | 
| 129 } | 139     using Type = uint64_t; | 
| 130 | 140 | 
| 131 template<> | 141     static Sk4f load(const SkPM4f& c) { | 
| 132 inline Sk4f dst_swizzle<SkPMColor>(const SkPM4f& c) { | 142         return c.to4f(); | 
| 133     return c.to4f_pmorder(); | 143     } | 
| 134 } |  | 
| 135 | 144 | 
| 136 template<> | 145     static void store(const Sk4f& c, Type* dst) { | 
| 137 inline Sk4f dst_swizzle<uint64_t>(const SkPM4f& c) { | 146         *dst = SkFloatToHalf_01(PM::apply(c)); | 
| 138     return c.to4f(); | 147     } | 
| 139 } |  | 
| 140 | 148 | 
| 141 } | 149     static void store(const Sk4f& c, Type* dst, int n) { | 
|  | 150         sk_memset64(dst, SkFloatToHalf_01(PM::apply(c)), n); | 
|  | 151     } | 
|  | 152 | 
|  | 153     static void store4x(const Sk4f& c0, const Sk4f& c1, | 
|  | 154                         const Sk4f& c2, const Sk4f& c3, | 
|  | 155                         Type* dst) { | 
|  | 156         store(c0, dst + 0); | 
|  | 157         store(c1, dst + 1); | 
|  | 158         store(c2, dst + 2); | 
|  | 159         store(c3, dst + 3); | 
|  | 160     } | 
|  | 161 }; | 
|  | 162 | 
|  | 163 template <ApplyPremul premul> | 
|  | 164 struct DstTraits<DstType::F32, premul> { | 
|  | 165     using PM   = PremulTraits<premul>; | 
|  | 166     using Type = SkPM4f; | 
|  | 167 | 
|  | 168     static Sk4f load(const SkPM4f& c) { | 
|  | 169         return c.to4f(); | 
|  | 170     } | 
|  | 171 | 
|  | 172     static void store(const Sk4f& c, Type* dst) { | 
|  | 173         PM::apply(c).store(dst->fVec); | 
|  | 174     } | 
|  | 175 | 
|  | 176     static void store(const Sk4f& c, Type* dst, int n) { | 
|  | 177         const Sk4f pmc = PM::apply(c); | 
|  | 178         for (int i = 0; i < n; ++i) { | 
|  | 179             pmc.store(dst[i].fVec); | 
|  | 180         } | 
|  | 181     } | 
|  | 182 | 
|  | 183     static void store4x(const Sk4f& c0, const Sk4f& c1, | 
|  | 184                         const Sk4f& c2, const Sk4f& c3, | 
|  | 185                         Type* dst) { | 
|  | 186         store(c0, dst + 0); | 
|  | 187         store(c1, dst + 1); | 
|  | 188         store(c2, dst + 2); | 
|  | 189         store(c3, dst + 3); | 
|  | 190     } | 
|  | 191 }; | 
|  | 192 | 
|  | 193 } // anonymous namespace | 
| 142 | 194 | 
| 143 #endif // Sk4fGradientPriv_DEFINED | 195 #endif // Sk4fGradientPriv_DEFINED | 
| OLD | NEW | 
|---|