Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(243)

Side by Side Diff: src/effects/gradients/Sk4fGradientPriv.h

Issue 1816883002: Refactor 4f gradients using trait templates (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/effects/gradients/Sk4fGradientBase.cpp ('k') | src/effects/gradients/Sk4fLinearGradient.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
OLDNEW
« no previous file with comments | « src/effects/gradients/Sk4fGradientBase.cpp ('k') | src/effects/gradients/Sk4fLinearGradient.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698