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

Side by Side Diff: src/core/Sk4pxXfermode.h

Issue 1214443002: Color dodge and burn with SkPMFloat. (Closed) Base URL: https://skia.googlesource.com/skia@master
Patch Set: reed Created 5 years, 5 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 | « no previous file | src/core/SkPMFloat.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 2015 Google Inc. 2 * Copyright 2015 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 Sk4pxXfermode_DEFINED 8 #ifndef Sk4pxXfermode_DEFINED
9 #define Sk4pxXfermode_DEFINED 9 #define Sk4pxXfermode_DEFINED
10 10
11 #include "Sk4px.h" 11 #include "Sk4px.h"
12 #include "SkPMFloat.h"
12 13
13 // This file is possibly included into multiple .cpp files. 14 // This file is possibly included into multiple .cpp files.
14 // Each gets its own independent instantiation by wrapping in an anonymous names pace. 15 // Each gets its own independent instantiation by wrapping in an anonymous names pace.
15 namespace { 16 namespace {
16 17
18 // Most xfermodes can be done most efficiently 4 pixels at a time in 8 or 16-bit fixed point.
17 #define XFERMODE(Name) \ 19 #define XFERMODE(Name) \
18 struct Name { \ 20 struct Name { \
19 static Sk4px Xfer(const Sk4px&, const Sk4px&); \ 21 static Sk4px Xfer(const Sk4px&, const Sk4px&); \
20 static const SkXfermode::Mode kMode = SkXfermode::k##Name##_Mode; \ 22 static const SkXfermode::Mode kMode = SkXfermode::k##Name##_Mode; \
21 }; \ 23 }; \
22 inline Sk4px Name::Xfer(const Sk4px& s, const Sk4px& d) 24 inline Sk4px Name::Xfer(const Sk4px& s, const Sk4px& d)
23 25
24 XFERMODE(Clear) { return Sk4px::DupPMColor(0); } 26 XFERMODE(Clear) { return Sk4px::DupPMColor(0); }
25 XFERMODE(Src) { return s; } 27 XFERMODE(Src) { return s; }
26 XFERMODE(Dst) { return d; } 28 XFERMODE(Dst) { return d; }
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 } 92 }
91 XFERMODE(Lighten) { 93 XFERMODE(Lighten) {
92 auto sda = s.approxMulDiv255(d.alphas()), 94 auto sda = s.approxMulDiv255(d.alphas()),
93 dsa = d.approxMulDiv255(s.alphas()); 95 dsa = d.approxMulDiv255(s.alphas());
94 auto srcover = s + (d - dsa), 96 auto srcover = s + (d - dsa),
95 dstover = d + (s - sda); 97 dstover = d + (s - sda);
96 auto alphas = srcover, 98 auto alphas = srcover,
97 colors = (sda < dsa).thenElse(dstover, srcover); 99 colors = (sda < dsa).thenElse(dstover, srcover);
98 return alphas.zeroColors() + colors.zeroAlphas(); 100 return alphas.zeroColors() + colors.zeroAlphas();
99 } 101 }
102 #undef XFERMODE
100 103
104 // Some xfermodes use math like divide or sqrt that's best done in floats 1 pixe l at a time.
105 #define XFERMODE(Name) \
106 struct Name { \
107 static SkPMFloat Xfer(const SkPMFloat&, const SkPMFloat&); \
108 static const SkXfermode::Mode kMode = SkXfermode::k##Name##_Mode; \
109 }; \
110 inline SkPMFloat Name::Xfer(const SkPMFloat& s, const SkPMFloat& d)
111
112 XFERMODE(ColorDodge) {
113 auto sa = s.alphas(),
114 da = d.alphas(),
115 isa = Sk4f(1)-sa,
116 ida = Sk4f(1)-da;
117
118 auto srcover = s + d*isa,
119 dstover = d + s*ida,
120 otherwise = sa * Sk4f::Min(da, (d*sa)*(sa-s).approxInvert()) + s*ida + d*isa;
121
122 // Order matters here, preferring d==0 over s==sa.
123 auto colors = (d == Sk4f(0)).thenElse(dstover,
124 (s == sa).thenElse(srcover,
125 otherwise));
126 return srcover * SkPMFloat(1,0,0,0) + colors * SkPMFloat(0,1,1,1);
127 }
128 XFERMODE(ColorBurn) {
129 auto sa = s.alphas(),
130 da = d.alphas(),
131 isa = Sk4f(1)-sa,
132 ida = Sk4f(1)-da;
133
134 auto srcover = s + d*isa,
135 dstover = d + s*ida,
136 otherwise = sa*(da-Sk4f::Min(da, (da-d)*sa*s.approxInvert())) + s*ida + d*isa;
137
138 // Order matters here, preferring d==da over s==0.
139 auto colors = (d == da).thenElse(dstover,
140 (s == Sk4f(0)).thenElse(srcover,
141 otherwise));
142 return srcover * SkPMFloat(1,0,0,0) + colors * SkPMFloat(0,1,1,1);
143 }
101 #undef XFERMODE 144 #undef XFERMODE
102 145
103 // A reasonable fallback mode for doing AA is to simply apply the transfermode f irst, 146 // A reasonable fallback mode for doing AA is to simply apply the transfermode f irst,
104 // then linearly interpolate the AA. 147 // then linearly interpolate the AA.
105 template <typename Mode> 148 template <typename Mode>
106 static Sk4px xfer_aa(const Sk4px& s, const Sk4px& d, const Sk4px& aa) { 149 static Sk4px xfer_aa(const Sk4px& s, const Sk4px& d, const Sk4px& aa) {
107 Sk4px bw = Mode::Xfer(s, d); 150 Sk4px bw = Mode::Xfer(s, d);
108 return (bw * aa + d * aa.inv()).div255(); 151 return (bw * aa + d * aa.inv()).div255();
109 } 152 }
110 153
(...skipping 22 matching lines...) Expand all
133 }); 176 });
134 } else { 177 } else {
135 Sk4px::MapDstSrcAlpha(n, dst, src, aa, 178 Sk4px::MapDstSrcAlpha(n, dst, src, aa,
136 [&](const Sk4px& dst4, const Sk4px& src4, const Sk4px& alpha ) { 179 [&](const Sk4px& dst4, const Sk4px& src4, const Sk4px& alpha ) {
137 return xfer_aa<ProcType>(src4, dst4, alpha); 180 return xfer_aa<ProcType>(src4, dst4, alpha);
138 }); 181 });
139 } 182 }
140 } 183 }
141 184
142 private: 185 private:
143 SkT4pxXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, ProcType::kM ode) {} 186 SkT4pxXfermode(const ProcCoeff& rec) : INHERITED(rec, ProcType::kMode) {}
144 187
145 typedef SkProcCoeffXfermode INHERITED; 188 typedef SkProcCoeffXfermode INHERITED;
146 }; 189 };
190
191 template <typename ProcType>
192 class SkTPMFloatXfermode : public SkProcCoeffXfermode {
193 public:
194 static SkProcCoeffXfermode* Create(const ProcCoeff& rec) {
195 return SkNEW_ARGS(SkTPMFloatXfermode, (rec));
196 }
197
198 void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[ ]) const override {
199 for (int i = 0; i < n; i++) {
200 SkPMFloat s(src[i]),
201 d(dst[i]),
202 b(ProcType::Xfer(s,d));
203 if (aa) {
204 // We do aa in full float precision before going back down to by tes, because we can!
205 SkPMFloat a = Sk4f(aa[i]) * Sk4f(1.0f/255);
206 b = b*a + d*(Sk4f(1)-a);
207 }
208 dst[i] = b.round();
209 }
210 }
211
212 private:
213 SkTPMFloatXfermode(const ProcCoeff& rec) : INHERITED(rec, ProcType::kMode) { }
214
215 typedef SkProcCoeffXfermode INHERITED;
216 };
147 217
148 static SkProcCoeffXfermode* SkCreate4pxXfermode(const ProcCoeff& rec, SkXfermode ::Mode mode) { 218 static SkProcCoeffXfermode* SkCreate4pxXfermode(const ProcCoeff& rec, SkXfermode ::Mode mode) {
149 #if !defined(SK_CPU_ARM32) || defined(SK_ARM_HAS_NEON) 219 #if !defined(SK_CPU_ARM32) || defined(SK_ARM_HAS_NEON)
150 switch (mode) { 220 switch (mode) {
151 case SkXfermode::kClear_Mode: return SkT4pxXfermode<Clear>::Create( rec); 221 case SkXfermode::kClear_Mode: return SkT4pxXfermode<Clear>::Create( rec);
152 case SkXfermode::kSrc_Mode: return SkT4pxXfermode<Src>::Create(re c); 222 case SkXfermode::kSrc_Mode: return SkT4pxXfermode<Src>::Create(re c);
153 case SkXfermode::kDst_Mode: return SkT4pxXfermode<Dst>::Create(re c); 223 case SkXfermode::kDst_Mode: return SkT4pxXfermode<Dst>::Create(re c);
154 case SkXfermode::kSrcOver_Mode: return SkT4pxXfermode<SrcOver>::Creat e(rec); 224 case SkXfermode::kSrcOver_Mode: return SkT4pxXfermode<SrcOver>::Creat e(rec);
155 case SkXfermode::kDstOver_Mode: return SkT4pxXfermode<DstOver>::Creat e(rec); 225 case SkXfermode::kDstOver_Mode: return SkT4pxXfermode<DstOver>::Creat e(rec);
156 case SkXfermode::kSrcIn_Mode: return SkT4pxXfermode<SrcIn>::Create( rec); 226 case SkXfermode::kSrcIn_Mode: return SkT4pxXfermode<SrcIn>::Create( rec);
157 case SkXfermode::kDstIn_Mode: return SkT4pxXfermode<DstIn>::Create( rec); 227 case SkXfermode::kDstIn_Mode: return SkT4pxXfermode<DstIn>::Create( rec);
158 case SkXfermode::kSrcOut_Mode: return SkT4pxXfermode<SrcOut>::Create (rec); 228 case SkXfermode::kSrcOut_Mode: return SkT4pxXfermode<SrcOut>::Create (rec);
159 case SkXfermode::kDstOut_Mode: return SkT4pxXfermode<DstOut>::Create (rec); 229 case SkXfermode::kDstOut_Mode: return SkT4pxXfermode<DstOut>::Create (rec);
160 case SkXfermode::kSrcATop_Mode: return SkT4pxXfermode<SrcATop>::Creat e(rec); 230 case SkXfermode::kSrcATop_Mode: return SkT4pxXfermode<SrcATop>::Creat e(rec);
161 case SkXfermode::kDstATop_Mode: return SkT4pxXfermode<DstATop>::Creat e(rec); 231 case SkXfermode::kDstATop_Mode: return SkT4pxXfermode<DstATop>::Creat e(rec);
162 case SkXfermode::kXor_Mode: return SkT4pxXfermode<Xor>::Create(re c); 232 case SkXfermode::kXor_Mode: return SkT4pxXfermode<Xor>::Create(re c);
163 case SkXfermode::kPlus_Mode: return SkT4pxXfermode<Plus>::Create(r ec); 233 case SkXfermode::kPlus_Mode: return SkT4pxXfermode<Plus>::Create(r ec);
164 case SkXfermode::kModulate_Mode: return SkT4pxXfermode<Modulate>::Crea te(rec); 234 case SkXfermode::kModulate_Mode: return SkT4pxXfermode<Modulate>::Crea te(rec);
165 case SkXfermode::kScreen_Mode: return SkT4pxXfermode<Screen>::Create (rec); 235 case SkXfermode::kScreen_Mode: return SkT4pxXfermode<Screen>::Create (rec);
166 case SkXfermode::kMultiply_Mode: return SkT4pxXfermode<Multiply>::Crea te(rec); 236 case SkXfermode::kMultiply_Mode: return SkT4pxXfermode<Multiply>::Crea te(rec);
167 case SkXfermode::kDifference_Mode: return SkT4pxXfermode<Difference>::Cr eate(rec); 237 case SkXfermode::kDifference_Mode: return SkT4pxXfermode<Difference>::Cr eate(rec);
168 case SkXfermode::kExclusion_Mode: return SkT4pxXfermode<Exclusion>::Cre ate(rec); 238 case SkXfermode::kExclusion_Mode: return SkT4pxXfermode<Exclusion>::Cre ate(rec);
169 #if !defined(SK_SUPPORT_LEGACY_XFERMODES) // For staging in Chrome (layout test s). 239 #if !defined(SK_SUPPORT_LEGACY_XFERMODES) // For staging in Chrome (layout test s).
170 case SkXfermode::kHardLight_Mode: return SkT4pxXfermode<HardLight>::Cre ate(rec); 240 case SkXfermode::kHardLight_Mode: return SkT4pxXfermode<HardLight>::Cre ate(rec);
171 case SkXfermode::kOverlay_Mode: return SkT4pxXfermode<Overlay>::Creat e(rec); 241 case SkXfermode::kOverlay_Mode: return SkT4pxXfermode<Overlay>::Creat e(rec);
172 case SkXfermode::kDarken_Mode: return SkT4pxXfermode<Darken>::Create (rec); 242 case SkXfermode::kDarken_Mode: return SkT4pxXfermode<Darken>::Create (rec);
173 case SkXfermode::kLighten_Mode: return SkT4pxXfermode<Lighten>::Creat e(rec); 243 case SkXfermode::kLighten_Mode: return SkT4pxXfermode<Lighten>::Creat e(rec);
244
245 case SkXfermode::kColorDodge_Mode: return SkTPMFloatXfermode<ColorDodge> ::Create(rec);
246 case SkXfermode::kColorBurn_Mode: return SkTPMFloatXfermode<ColorBurn>: :Create(rec);
174 #endif 247 #endif
175 default: break; 248 default: break;
176 } 249 }
177 #endif 250 #endif
178 return nullptr; 251 return nullptr;
179 } 252 }
180 253
181 } // namespace 254 } // namespace
182 255
183 #endif//Sk4pxXfermode_DEFINED 256 #endif//Sk4pxXfermode_DEFINED
OLDNEW
« no previous file with comments | « no previous file | src/core/SkPMFloat.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698