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

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

Issue 1150313003: Move Sk4px Xfermode code to a header so we can use it twice. (Closed) Base URL: https://skia.googlesource.com/skia@master
Patch Set: wrong date Created 5 years, 7 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/SkXfermode.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2015 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 Sk4pxXfermode_DEFINED
9 #define Sk4pxXfermode_DEFINED
10
11 #include "Sk4px.h"
12
13 // This file is possibly included into multiple .cpp files.
14 // Each gets its own independent instantiation by wrapping in an anonymous names pace.
15 namespace {
16
17 #define XFERMODE(Name) \
18 struct Name { \
19 static Sk4px Xfer(const Sk4px&, const Sk4px&); \
20 static const SkXfermode::Mode kMode = SkXfermode::k##Name##_Mode; \
21 }; \
22 inline Sk4px Name::Xfer(const Sk4px& s, const Sk4px& d)
23
24 XFERMODE(Clear) { return Sk4px((SkPMColor)0); }
25 XFERMODE(Src) { return s; }
26 XFERMODE(Dst) { return d; }
27 XFERMODE(SrcIn) { return s.fastMulDiv255Round(d.alphas() ); }
28 XFERMODE(SrcOut) { return s.fastMulDiv255Round(d.alphas().inv()); }
29 XFERMODE(SrcOver) { return s + d.fastMulDiv255Round(s.alphas().inv()); }
30 XFERMODE(DstIn) { return SrcIn ::Xfer(d,s); }
31 XFERMODE(DstOut) { return SrcOut ::Xfer(d,s); }
32 XFERMODE(DstOver) { return SrcOver::Xfer(d,s); }
33
34 // [ S * Da + (1 - Sa) * D]
35 XFERMODE(SrcATop) {
36 return Sk4px::Wide(s.mulWiden(d.alphas()) + d.mulWiden(s.alphas().inv()))
37 .div255RoundNarrow();
38 }
39 XFERMODE(DstATop) { return SrcATop::Xfer(d,s); }
40 //[ S * (1 - Da) + (1 - Sa) * D ]
41 XFERMODE(Xor) {
42 return Sk4px::Wide(s.mulWiden(d.alphas().inv()) + d.mulWiden(s.alphas().inv( )))
43 .div255RoundNarrow();
44 }
45 // [S + D ]
46 XFERMODE(Plus) { return s.saturatedAdd(d); }
47 // [S * D ]
48 XFERMODE(Modulate) { return s.fastMulDiv255Round(d); }
49 // [S + D - S * D]
50 XFERMODE(Screen) {
51 // Doing the math as S + (1-S)*D or S + (D - S*D) means the add and subtract can be done
52 // in 8-bit space without overflow. S + (1-S)*D is a touch faster because i nv() is cheap.
53 return s + d.fastMulDiv255Round(s.inv());
54 }
55 XFERMODE(Multiply) {
56 return Sk4px::Wide(s.mulWiden(d.alphas().inv()) +
57 d.mulWiden(s.alphas().inv()) +
58 s.mulWiden(d))
59 .div255RoundNarrow();
60 }
61 // [ Sa + Da - Sa*Da, Sc + Dc - 2*min(Sc*Da, Dc*Sa) ] (And notice Sa*Da == min( Sa*Da, Da*Sa).)
62 XFERMODE(Difference) {
63 auto m = Sk4px::Wide(Sk16h::Min(s.mulWiden(d.alphas()), d.mulWiden(s.alphas( ))))
64 .div255RoundNarrow();
65 // There's no chance of underflow, and if we subtract m before adding s+d, n o overflow.
66 return (s - m) + (d - m.zeroAlphas());
67 }
68 // [ Sa + Da - Sa*Da, Sc + Dc - 2*Sc*Dc ]
69 XFERMODE(Exclusion) {
70 auto p = s.fastMulDiv255Round(d);
71 // There's no chance of underflow, and if we subtract p before adding src+ds t, no overflow.
72 return (s - p) + (d - p.zeroAlphas());
73 }
74
75 #undef XFERMODE
76
77 // A reasonable fallback mode for doing AA is to simply apply the transfermode f irst,
78 // then linearly interpolate the AA.
79 template <typename Mode>
80 static Sk4px xfer_aa(const Sk4px& s, const Sk4px& d, const Sk16b& aa) {
81 Sk4px noAA = Mode::Xfer(s, d);
82 return Sk4px::Wide(noAA.mulWiden(aa) + d.mulWiden(Sk4px(aa).inv()))
83 .div255RoundNarrow();
84 }
85
86 // For some transfermodes we specialize AA, either for correctness or performanc e.
87 #ifndef SK_NO_SPECIALIZED_AA_XFERMODES
88 #define XFERMODE_AA(Name) \
89 template <> Sk4px xfer_aa<Name>(const Sk4px& s, const Sk4px& d, const Sk 16b& aa)
90
91 // Plus' clamp needs to happen after AA. skia:3852
92 XFERMODE_AA(Plus) { // [ clamp(D + AA*S) ]
93 // We implement this as D + Min(S*AA, (1-D)) to fit the arguments to Min in 16 bits.
94 return d +
95 Sk4px::Wide(Sk16h::Min(s.mulWiden(aa), d.inv().mul255Widen())).div25 5RoundNarrow();
96 }
97
98 #undef XFERMODE_AA
99 #endif
100
101 template <typename ProcType>
102 class SkT4pxXfermode : public SkProcCoeffXfermode {
103 public:
104 static SkProcCoeffXfermode* Create(const ProcCoeff& rec) {
105 return SkNEW_ARGS(SkT4pxXfermode, (rec));
106 }
107
108 void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[ ]) const override {
109 if (NULL == aa) {
110 Sk4px::MapDstSrc(n, dst, src, [&](const Sk4px& dst4, const Sk4px& sr c4) {
111 return ProcType::Xfer(src4, dst4);
112 });
113 } else {
114 Sk4px::MapDstSrcAlpha(n, dst, src, aa,
115 [&](const Sk4px& dst4, const Sk4px& src4, const Sk16b& alpha ) {
116 return xfer_aa<ProcType>(src4, dst4, alpha);
117 });
118 }
119 }
120
121 private:
122 SkT4pxXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, ProcType::kM ode) {}
123
124 typedef SkProcCoeffXfermode INHERITED;
125 };
126
127 static SkProcCoeffXfermode* SkCreate4pxXfermode(const ProcCoeff& rec, SkXfermode ::Mode mode) {
128 #if !defined(SK_CPU_ARM32) || defined(SK_ARM_HAS_NEON)
129 switch (mode) {
130 case SkXfermode::kClear_Mode: return SkT4pxXfermode<Clear>::Create( rec);
131 case SkXfermode::kSrc_Mode: return SkT4pxXfermode<Src>::Create(re c);
132 case SkXfermode::kDst_Mode: return SkT4pxXfermode<Dst>::Create(re c);
133 case SkXfermode::kSrcOver_Mode: return SkT4pxXfermode<SrcOver>::Creat e(rec);
134 case SkXfermode::kDstOver_Mode: return SkT4pxXfermode<DstOver>::Creat e(rec);
135 case SkXfermode::kSrcIn_Mode: return SkT4pxXfermode<SrcIn>::Create( rec);
136 case SkXfermode::kDstIn_Mode: return SkT4pxXfermode<DstIn>::Create( rec);
137 case SkXfermode::kSrcOut_Mode: return SkT4pxXfermode<SrcOut>::Create (rec);
138 case SkXfermode::kDstOut_Mode: return SkT4pxXfermode<DstOut>::Create (rec);
139 case SkXfermode::kSrcATop_Mode: return SkT4pxXfermode<SrcATop>::Creat e(rec);
140 case SkXfermode::kDstATop_Mode: return SkT4pxXfermode<DstATop>::Creat e(rec);
141 case SkXfermode::kXor_Mode: return SkT4pxXfermode<Xor>::Create(re c);
142 case SkXfermode::kPlus_Mode: return SkT4pxXfermode<Plus>::Create(r ec);
143 case SkXfermode::kModulate_Mode: return SkT4pxXfermode<Modulate>::Crea te(rec);
144 case SkXfermode::kScreen_Mode: return SkT4pxXfermode<Screen>::Create (rec);
145 case SkXfermode::kMultiply_Mode: return SkT4pxXfermode<Multiply>::Crea te(rec);
146 case SkXfermode::kDifference_Mode: return SkT4pxXfermode<Difference>::Cr eate(rec);
147 case SkXfermode::kExclusion_Mode: return SkT4pxXfermode<Exclusion>::Cre ate(rec);
148 default: break;
149 }
150 #endif
151 return nullptr;
152 }
153
154 } // namespace
155
156 #endif//Sk4pxXfermode_DEFINED
OLDNEW
« no previous file with comments | « no previous file | src/core/SkXfermode.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698