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

Side by Side Diff: src/opts/SkXfermode_opts.h

Issue 1465483002: Revert float xfermodes back to Sk4f (from Sk8f). (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 1 month 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 | no next file » | 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
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 dsa = (d*sa).div255(); 102 dsa = (d*sa).div255();
103 103
104 auto srcover = s + (d * sa.inv()).div255(), 104 auto srcover = s + (d * sa.inv()).div255(),
105 dstover = d + (s * da.inv()).div255(); 105 dstover = d + (s * da.inv()).div255();
106 auto alphas = srcover, 106 auto alphas = srcover,
107 colors = (dsa < sda).thenElse(srcover, dstover); 107 colors = (dsa < sda).thenElse(srcover, dstover);
108 return alphas.zeroColors() + colors.zeroAlphas(); 108 return alphas.zeroColors() + colors.zeroAlphas();
109 } 109 }
110 #undef XFERMODE 110 #undef XFERMODE
111 111
112 // Some xfermodes use math like divide or sqrt that's best done in floats. 112 // Some xfermodes use math like divide or sqrt that's best done in floats 1 pixe l at a time.
113 // We write it generically, then call it 1 or 2 pixels at a time (T == Sk4f or S k8f). 113 #define XFERMODE(Name) static Sk4f SK_VECTORCALL Name(Sk4f d, Sk4f s)
114 #define XFERMODE(Name) struct Name { template <typename T> T operator()(const T& , const T&); }; \
115 template <typename T> T Name::operator()(const T& d, const T& s)
116 114
117 static_assert(SK_A32_SHIFT == 24, "");
118 static inline Sk4f a_rgb(const Sk4f& a, const Sk4f& rgb) { 115 static inline Sk4f a_rgb(const Sk4f& a, const Sk4f& rgb) {
116 static_assert(SK_A32_SHIFT == 24, "");
119 return a * Sk4f(0,0,0,1) + rgb * Sk4f(1,1,1,0); 117 return a * Sk4f(0,0,0,1) + rgb * Sk4f(1,1,1,0);
120 } 118 }
121 static inline Sk8f a_rgb(const Sk8f& a, const Sk8f& rgb) { 119 static inline Sk4f alphas(const Sk4f& f) {
122 // TODO: SkNx_blend<0,0,0,1,0,0,0,1>(a, rgb) to let us use _mm256_blend_ps? 120 return SkNx_dup<SK_A32_SHIFT/8>(f);
123 return a * Sk8f(0,0,0,1,0,0,0,1) + rgb * Sk8f(1,1,1,0,1,1,1,0);
124 } 121 }
125 static inline Sk4f alphas(const Sk4f& f) { return SkNx_shuffle<3,3,3,3> ( f); }
126 static inline Sk8f alphas(const Sk8f& f) { return SkNx_shuffle<3,3,3,3,7,7,7,7>( f); }
127 122
128 XFERMODE(ColorDodge) { 123 XFERMODE(ColorDodge) {
129 auto sa = alphas(s), 124 auto sa = alphas(s),
130 da = alphas(d), 125 da = alphas(d),
131 isa = T(1)-sa, 126 isa = Sk4f(1)-sa,
132 ida = T(1)-da; 127 ida = Sk4f(1)-da;
133 128
134 auto srcover = s + d*isa, 129 auto srcover = s + d*isa,
135 dstover = d + s*ida, 130 dstover = d + s*ida,
136 otherwise = sa * T::Min(da, (d*sa)*(sa-s).approxInvert()) + s*ida + d*i sa; 131 otherwise = sa * Sk4f::Min(da, (d*sa)*(sa-s).approxInvert()) + s*ida + d*isa;
137 132
138 // Order matters here, preferring d==0 over s==sa. 133 // Order matters here, preferring d==0 over s==sa.
139 auto colors = (d == 0).thenElse(dstover, 134 auto colors = (d == Sk4f(0)).thenElse(dstover,
140 (s == sa).thenElse(srcover, 135 (s == sa).thenElse(srcover,
141 otherwise)); 136 otherwise));
142 return a_rgb(srcover, colors); 137 return a_rgb(srcover, colors);
143 } 138 }
144 XFERMODE(ColorBurn) { 139 XFERMODE(ColorBurn) {
145 auto sa = alphas(s), 140 auto sa = alphas(s),
146 da = alphas(d), 141 da = alphas(d),
147 isa = T(1)-sa, 142 isa = Sk4f(1)-sa,
148 ida = T(1)-da; 143 ida = Sk4f(1)-da;
149 144
150 auto srcover = s + d*isa, 145 auto srcover = s + d*isa,
151 dstover = d + s*ida, 146 dstover = d + s*ida,
152 otherwise = sa*(da-T::Min(da, (da-d)*sa*s.approxInvert())) + s*ida + d* isa; 147 otherwise = sa*(da-Sk4f::Min(da, (da-d)*sa*s.approxInvert())) + s*ida + d*isa;
153 148
154 // Order matters here, preferring d==da over s==0. 149 // Order matters here, preferring d==da over s==0.
155 auto colors = (d == da).thenElse(dstover, 150 auto colors = (d == da).thenElse(dstover,
156 (s == 0).thenElse(srcover, 151 (s == Sk4f(0)).thenElse(srcover,
157 otherwise)); 152 otherwise));
158 return a_rgb(srcover, colors); 153 return a_rgb(srcover, colors);
159 } 154 }
160 XFERMODE(SoftLight) { 155 XFERMODE(SoftLight) {
161 auto sa = alphas(s), 156 auto sa = alphas(s),
162 da = alphas(d), 157 da = alphas(d),
163 isa = T(1)-sa, 158 isa = Sk4f(1)-sa,
164 ida = T(1)-da; 159 ida = Sk4f(1)-da;
165 160
166 // Some common terms. 161 // Some common terms.
167 auto m = (da > 0).thenElse(d / da, 0), 162 auto m = (da > Sk4f(0)).thenElse(d / da, Sk4f(0)),
168 s2 = s*2, 163 s2 = Sk4f(2)*s,
169 m4 = m*4; 164 m4 = Sk4f(4)*m;
170 165
171 // The logic forks three ways: 166 // The logic forks three ways:
172 // 1. dark src? 167 // 1. dark src?
173 // 2. light src, dark dst? 168 // 2. light src, dark dst?
174 // 3. light src, light dst? 169 // 3. light src, light dst?
175 auto darkSrc = d*(sa + (s2 - sa)*(T(1) - m)), // Used in case 1. 170 auto darkSrc = d*(sa + (s2 - sa)*(Sk4f(1) - m)), // Used in case 1.
176 darkDst = (m4*m4 + m4)*(m - 1) + m*7, // Used in case 2. 171 darkDst = (m4*m4 + m4)*(m - Sk4f(1)) + Sk4f(7)*m, // Used in case 2.
177 liteDst = m.sqrt() - m, // Used in case 3. 172 liteDst = m.sqrt() - m, // Used in case 3.
178 liteSrc = d*sa + da*(s2-sa)*(d*4 <= da).thenElse(darkDst, liteDst); // Case 2 or 3? 173 liteSrc = d*sa + da*(s2-sa)*(Sk4f(4)*d <= da).thenElse(darkDst, liteDst ); // Case 2 or 3?
179 174
180 auto alpha = s + d*isa; 175 auto alpha = s + d*isa;
181 auto colors = s*ida + d*isa + (s2 <= sa).thenElse(darkSrc, liteSrc); // Case 1 or 2/3? 176 auto colors = s*ida + d*isa + (s2 <= sa).thenElse(darkSrc, liteSrc); // Case 1 or 2/3?
182 177
183 return a_rgb(alpha, colors); 178 return a_rgb(alpha, colors);
184 } 179 }
185 #undef XFERMODE 180 #undef XFERMODE
186 181
187 // A reasonable fallback mode for doing AA is to simply apply the transfermode f irst, 182 // A reasonable fallback mode for doing AA is to simply apply the transfermode f irst,
188 // then linearly interpolate the AA. 183 // then linearly interpolate the AA.
189 template <Sk4px (SK_VECTORCALL *Mode)(Sk4px, Sk4px)> 184 template <Sk4px (SK_VECTORCALL *Mode)(Sk4px, Sk4px)>
190 static Sk4px SK_VECTORCALL xfer_aa(Sk4px s, Sk4px d, Sk4px aa) { 185 static Sk4px SK_VECTORCALL xfer_aa(Sk4px s, Sk4px d, Sk4px aa) {
191 Sk4px bw = Mode(s, d); 186 Sk4px bw = Mode(s, d);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 }); 233 });
239 } 234 }
240 } 235 }
241 236
242 private: 237 private:
243 Proc4 fProc4; 238 Proc4 fProc4;
244 AAProc4 fAAProc4; 239 AAProc4 fAAProc4;
245 typedef SkProcCoeffXfermode INHERITED; 240 typedef SkProcCoeffXfermode INHERITED;
246 }; 241 };
247 242
248 template <typename BlendFn> 243 class Sk4fXfermode : public SkProcCoeffXfermode {
249 class FloatXfermode : public SkProcCoeffXfermode {
250 public: 244 public:
251 FloatXfermode(const ProcCoeff& rec, SkXfermode::Mode mode) 245 typedef Sk4f (SK_VECTORCALL *ProcF)(Sk4f, Sk4f);
252 : INHERITED(rec, mode) {} 246 Sk4fXfermode(const ProcCoeff& rec, SkXfermode::Mode mode, ProcF procf)
247 : INHERITED(rec, mode)
248 , fProcF(procf) {}
253 249
254 void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[ ]) const override { 250 void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[ ]) const override {
255 BlendFn blend; 251 for (int i = 0; i < n; i++) {
256 while (n >= 2) { 252 dst[i] = aa ? this->xfer32(dst[i], src[i], aa[i])
257 auto d = Sk8f::FromBytes((const uint8_t*)dst) * (1.0f/255), 253 : this->xfer32(dst[i], src[i]);
258 s = Sk8f::FromBytes((const uint8_t*)src) * (1.0f/255),
259 b = blend(d, s);
260 if (aa) {
261 auto a255 = Sk8f(aa[0],aa[0],aa[0],aa[0], aa[1],aa[1],aa[1],aa[1 ]);
262 (b*a255 + d*(Sk8f(255)-a255) + 0.5).toBytes((uint8_t*)dst);
263 aa += 2;
264 } else {
265 (b * 255 + 0.5).toBytes((uint8_t*)dst);
266 }
267 dst += 2;
268 src += 2;
269 n -= 2;
270 }
271 if (n) {
272 auto d = Sk4f::FromBytes((const uint8_t*)dst) * (1.0f/255),
273 s = Sk4f::FromBytes((const uint8_t*)src) * (1.0f/255),
274 b = blend(d, s);
275 if (aa) {
276 auto a255 = Sk4f(aa[0],aa[0],aa[0],aa[0]);
277 (b*a255 + d*(Sk4f(255)-a255) + 0.5).toBytes((uint8_t*)dst);
278 aa++;
279 } else {
280 (b * 255 + 0.5).toBytes((uint8_t*)dst);
281 }
282 } 254 }
283 } 255 }
284 256
285 void xfer16(uint16_t dst[], const SkPMColor src[], int n, const SkAlpha aa[] ) const override { 257 void xfer16(uint16_t dst[], const SkPMColor src[], int n, const SkAlpha aa[] ) const override {
286 for (int i = 0; i < n; i++) { 258 for (int i = 0; i < n; i++) {
287 SkPMColor dst32 = SkPixel16ToPixel32(dst[i]); // Convert d st up to 8888. 259 SkPMColor dst32 = SkPixel16ToPixel32(dst[i]);
288 this->xfer32(&dst32, src+i, 1, aa ? aa+i : nullptr); // Blend 1 p ixel. 260 dst32 = aa ? this->xfer32(dst32, src[i], aa[i])
289 dst[i] = SkPixel32ToPixel16(dst32); // Repack ds t to 565 and store. 261 : this->xfer32(dst32, src[i]);
262 dst[i] = SkPixel32ToPixel16(dst32);
290 } 263 }
291 } 264 }
292 265
293 private: 266 private:
267 static Sk4f Load(SkPMColor c) {
268 return Sk4f::FromBytes((uint8_t*)&c) * Sk4f(1.0f/255);
269 }
270 static SkPMColor Round(const Sk4f& f) {
271 SkPMColor c;
272 (f * Sk4f(255) + Sk4f(0.5f)).toBytes((uint8_t*)&c);
273 return c;
274 }
275 inline SkPMColor xfer32(SkPMColor dst, SkPMColor src) const {
276 return Round(fProcF(Load(dst), Load(src)));
277 }
278
279 inline SkPMColor xfer32(SkPMColor dst, SkPMColor src, SkAlpha aa) const {
280 Sk4f s(Load(src)),
281 d(Load(dst)),
282 b(fProcF(d,s));
283 // We do aa in full float precision before going back down to bytes, bec ause we can!
284 Sk4f a = Sk4f(aa) * Sk4f(1.0f/255);
285 b = b*a + d*(Sk4f(1)-a);
286 return Round(b);
287 }
288
289 ProcF fProcF;
294 typedef SkProcCoeffXfermode INHERITED; 290 typedef SkProcCoeffXfermode INHERITED;
295 }; 291 };
296 292
297 } // namespace 293 } // namespace
298 294
299 namespace SK_OPTS_NS { 295 namespace SK_OPTS_NS {
300 296
301 static SkXfermode* create_xfermode(const ProcCoeff& rec, SkXfermode::Mode mode) { 297 static SkXfermode* create_xfermode(const ProcCoeff& rec, SkXfermode::Mode mode) {
302 switch (mode) { 298 switch (mode) {
303 #define CASE(Mode) \ 299 #define CASE(Mode) \
(...skipping 16 matching lines...) Expand all
320 CASE(Multiply); 316 CASE(Multiply);
321 CASE(Difference); 317 CASE(Difference);
322 CASE(Exclusion); 318 CASE(Exclusion);
323 CASE(HardLight); 319 CASE(HardLight);
324 CASE(Overlay); 320 CASE(Overlay);
325 CASE(Darken); 321 CASE(Darken);
326 CASE(Lighten); 322 CASE(Lighten);
327 #undef CASE 323 #undef CASE
328 324
329 #define CASE(Mode) \ 325 #define CASE(Mode) \
330 case SkXfermode::k##Mode##_Mode: return new FloatXfermode<Mode>(rec, mode) 326 case SkXfermode::k##Mode##_Mode: return new Sk4fXfermode(rec, mode, &Mode)
331 CASE(ColorDodge); 327 CASE(ColorDodge);
332 CASE(ColorBurn); 328 CASE(ColorBurn);
333 CASE(SoftLight); 329 CASE(SoftLight);
334 #undef CASE 330 #undef CASE
335 331
336 default: break; 332 default: break;
337 } 333 }
338 return nullptr; 334 return nullptr;
339 } 335 }
340 336
341 } // namespace SK_OPTS_NS 337 } // namespace SK_OPTS_NS
342 338
343 #endif//Sk4pxXfermode_DEFINED 339 #endif//Sk4pxXfermode_DEFINED
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698