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

Side by Side Diff: src/core/SkXfermode4f.cpp

Issue 1634273002: float components in xfermodes (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: disable blitter for official checkin Created 4 years, 10 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
OLDNEW
(Empty)
1 /*
2 * Copyright 2016 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 #include "SkPM4fPriv.h"
9 #include "SkUtils.h"
10 #include "SkXfermode.h"
11
12 struct XferProcPair {
13 SkXfermode::PM4fProc1 fP1;
14 SkXfermode::PM4fProcN fPN;
15 };
16
17 enum DstType {
18 kLinear_Dst,
19 kSRGB_Dst,
20 };
21
22 static Sk4f scale_by_coverage(const Sk4f& x4, uint8_t coverage) {
23 return x4 * Sk4f(coverage * (1/255.0f));
24 }
25
26 static Sk4f lerp(const Sk4f& src, const Sk4f& dst, uint8_t srcCoverage) {
27 return dst + (src - dst) * Sk4f(srcCoverage * (1/255.0f));
28 }
29
30 template <DstType D> Sk4f load_dst(SkPMColor dstC) {
31 return (D == kSRGB_Dst) ? Sk4f_fromS32(dstC) : Sk4f_fromL32(dstC);
32 }
33
34 template <DstType D> uint32_t store_dst(const Sk4f& x4) {
35 return (D == kSRGB_Dst) ? Sk4f_toS32(x4) : Sk4f_toL32(x4);
36 }
37
38 //////////////////////////////////////////////////////////////////////////////// ///////////////////
39
40 static Sk4f scale_255_round(const SkPM4f& pm4) {
mtklein 2016/02/01 22:53:52 Generally I like to scope one-shot helpers like th
reed1 2016/02/02 14:20:54 We can change. I find some value in naming these a
mtklein 2016/02/02 14:24:10 Lambdas can have names too... auto scale_255_roun
41 return Sk4f::Load(pm4.fVec) * Sk4f(255) + Sk4f(0.5f);
42 }
43
44 static void pm4f_to_linear_32(SkPMColor dst[], const SkPM4f src[], int count) {
45 while (count >= 4) {
46 src[0].assertIsUnit();
47 src[1].assertIsUnit();
48 src[2].assertIsUnit();
49 src[3].assertIsUnit();
50 Sk4f_ToBytes((uint8_t*)dst,
51 scale_255_round(src[0]), scale_255_round(src[1]),
52 scale_255_round(src[2]), scale_255_round(src[3]));
53 src += 4;
54 dst += 4;
55 count -= 4;
56 }
57 for (int i = 0; i < count; ++i) {
58 src[i].assertIsUnit();
59 SkNx_cast<uint8_t>(scale_255_round(src[i])).store((uint8_t*)&dst[i]);
60 }
61 }
62
63 //////////////////////////////////////////////////////////////////////////////// ///////////////////
64 // These are our fallback impl for the SkPM4f procs...
65 //
66 // They just convert the src color(s) into a linear SkPMColor value(s), and then
67 // call the existing virtual xfer32. This clear throws away data (converting flo ats to bytes)
68 // in the src, and ignores the sRGB flag, but should draw about the same as if t he caller
69 // had passed in SkPMColor values directly.
70 //
71
72 void xfer_pm4_proc_1(const SkXfermode::PM4fState& state, uint32_t dst[], const S kPM4f& src,
73 int count, const SkAlpha aa[]) {
74 uint32_t pm;
75 pm4f_to_linear_32(&pm, &src, 1);
76
77 const int N = 128;
78 SkPMColor tmp[N];
mtklein 2016/02/01 22:53:52 yeesh. _1 variants are a really good idea. We mi
79 sk_memset32(tmp, pm, SkMin32(count, N));
80 while (count > 0) {
81 const int n = SkMin32(count, N);
82 state.fXfer->xfer32(dst, tmp, n, aa);
83
84 dst += n;
85 if (aa) {
86 aa += n;
87 }
88 count -= n;
89 }
90 }
91
92 void xfer_pm4_proc_n(const SkXfermode::PM4fState& state, uint32_t dst[], const S kPM4f src[],
93 int count, const SkAlpha aa[]) {
94 const int N = 128;
95 SkPMColor tmp[N];
96 while (count > 0) {
97 const int n = SkMin32(count, N);
98 pm4f_to_linear_32(tmp, src, n);
99 state.fXfer->xfer32(dst, tmp, n, aa);
100
101 src += n;
102 dst += n;
103 if (aa) {
104 aa += n;
105 }
106 count -= n;
107 }
108 }
109
110 //////////////////////////////////////////////////////////////////////////////// ///////////////////
111
112 static void clear_linear_n(const SkXfermode::PM4fState& state, uint32_t dst[], c onst SkPM4f[],
113 int count, const SkAlpha aa[]) {
114 if (aa) {
115 for (int i = 0; i < count; ++i) {
116 unsigned a = aa[i];
117 if (a) {
118 SkPMColor dstC = dst[i];
119 SkPMColor C = 0;
120 if (0xFF != a) {
121 C = SkFourByteInterp(C, dstC, a);
122 }
123 dst[i] = C;
124 }
125 }
126 } else {
127 sk_bzero(dst, count * sizeof(SkPMColor));
128 }
129 }
130
131 static void clear_linear_1(const SkXfermode::PM4fState& state, uint32_t dst[], c onst SkPM4f&,
132 int count, const SkAlpha coverage[]) {
133 clear_linear_n(state, dst, nullptr, count, coverage);
mtklein 2016/02/01 22:53:52 We might want to make the _1 and _n variants take
reed1 2016/02/02 14:20:54 I certainly pondered this. Can't tell if that help
134 }
135
136 static void clear_srgb_n(const SkXfermode::PM4fState& state, uint32_t dst[], con st SkPM4f[],
137 int count, const SkAlpha aa[]) {
138 if (aa) {
139 for (int i = 0; i < count; ++i) {
140 unsigned a = aa[i];
141 if (a) {
142 Sk4f d = Sk4f_fromS32(dst[i]) * Sk4f((255 - a) * (1/255.0f));
143 dst[i] = Sk4f_toS32(d);
144 }
145 }
146 } else {
147 sk_bzero(dst, count * sizeof(SkPMColor));
148 }
149 }
150
151 static void clear_srgb_1(const SkXfermode::PM4fState& state, uint32_t dst[], con st SkPM4f&,
152 int count, const SkAlpha coverage[]) {
153 clear_srgb_n(state, dst, nullptr, count, coverage);
154 }
155
156 const XferProcPair gProcs_Clear[] = {
157 { clear_linear_1, clear_linear_n }, // linear [alpha]
158 { clear_linear_1, clear_linear_n }, // linear [opaque]
159 { clear_srgb_1, clear_srgb_n }, // srgb [alpha]
160 { clear_srgb_1, clear_srgb_n }, // srgb [opaque]
161 };
162
163 //////////////////////////////////////////////////////////////////////////////// ///////////////////
164
165 template <DstType D> void src_n(const SkXfermode::PM4fState& state, uint32_t dst [],
166 const SkPM4f src[], int count, const SkAlpha aa[ ]) {
167 for (int i = 0; i < count; ++i) {
168 unsigned a = 0xFF;
169 if (aa) {
170 a = aa[i];
171 if (0 == a) {
172 continue;
173 }
174 }
175 Sk4f r4 = Sk4f::Load(src[i].fVec); // src always overrides dst
176 if (a != 0xFF) {
177 Sk4f d4 = load_dst<D>(dst[i]);
178 r4 = lerp(r4, d4, a);
179 }
180 dst[i] = store_dst<D>(r4);
181 }
182 }
183
184 template <DstType D> void src_1(const SkXfermode::PM4fState& state, uint32_t dst [],
185 const SkPM4f& src, int count, const SkAlpha aa[] ) {
186 const Sk4f r4 = Sk4f::Load(src.fVec); // src always overrides dst
187 const uint32_t r32 = store_dst<D>(r4);
188
189 if (aa) {
190 for (int i = 0; i < count; ++i) {
191 unsigned a = aa[i];
192 if (0 == a) {
193 continue;
194 }
195 if (a != 0xFF) {
196 Sk4f d4 = load_dst<D>(dst[i]);
197 dst[i] = store_dst<D>(lerp(r4, d4, a));
198 } else {
199 dst[i] = r32;
200 }
201 }
202 } else {
203 sk_memset32(dst, r32, count);
204 }
205 }
206
207 const XferProcPair gProcs_Src[] = {
208 { src_1<kLinear_Dst>, src_n<kLinear_Dst> }, // linear [alpha]
209 { src_1<kLinear_Dst>, src_n<kLinear_Dst> }, // linear [opaque]
210 { src_1<kSRGB_Dst>, src_n<kSRGB_Dst> }, // srgb [alpha]
211 { src_1<kSRGB_Dst>, src_n<kSRGB_Dst> }, // srgb [opaque]
212 };
213
214 //////////////////////////////////////////////////////////////////////////////// ///////////////////
215
216 static void dst_n(const SkXfermode::PM4fState& state, uint32_t dst[], const SkPM 4f[],
217 int count, const SkAlpha aa[]) {}
218
219 static void dst_1(const SkXfermode::PM4fState& state, uint32_t dst[], const SkPM 4f&,
220 int count, const SkAlpha coverage[]) {}
221
222 const XferProcPair gProcs_Dst[] = {
223 { dst_1, dst_n },
224 { dst_1, dst_n },
225 { dst_1, dst_n },
226 { dst_1, dst_n },
227 };
228
229 //////////////////////////////////////////////////////////////////////////////// ///////////////////
230
231 template <DstType D> void srcover_n(const SkXfermode::PM4fState& state, uint32_t dst[],
232 const SkPM4f src[], int count, const SkAlpha aa[]) {
233 if (aa) {
234 for (int i = 0; i < count; ++i) {
235 unsigned a = aa[i];
236 if (0 == a) {
237 continue;
238 }
239 Sk4f s4 = Sk4f::Load(src[i].fVec);
240 Sk4f d4 = load_dst<D>(dst[i]);
241 if (a != 0xFF) {
242 s4 = scale_by_coverage(s4, a);
243 }
244 Sk4f r4 = s4 + d4 * Sk4f(1 - get_alpha(s4));
245 dst[i] = store_dst<D>(r4);
246 }
247 } else {
248 for (int i = 0; i < count; ++i) {
249 Sk4f s4 = Sk4f::Load(src[i].fVec);
250 Sk4f d4 = load_dst<D>(dst[i]);
251 Sk4f r4 = s4 + d4 * Sk4f(1 - get_alpha(s4));
252 dst[i] = store_dst<D>(r4);
253 }
254 }
255 }
256
257 template <DstType D> void srcover_1(const SkXfermode::PM4fState& state, uint32_t dst[],
258 const SkPM4f& src, int count, const SkAlpha aa[]) {
259 Sk4f s4 = Sk4f::Load(src.fVec);
260 Sk4f scale = Sk4f(1 - get_alpha(s4));
261
262 if (aa) {
263 for (int i = 0; i < count; ++i) {
264 unsigned a = aa[i];
265 if (0 == a) {
266 continue;
267 }
268 Sk4f d4 = load_dst<D>(dst[i]);
269 Sk4f r4;
270 if (a != 0xFF) {
271 s4 = scale_by_coverage(s4, a);
272 r4 = s4 + d4 * Sk4f(1 - get_alpha(s4));
273 } else {
274 r4 = s4 + d4 * scale;
275 }
276 dst[i] = store_dst<D>(r4);
277 }
278 } else {
279 for (int i = 0; i < count; ++i) {
280 Sk4f d4 = load_dst<D>(dst[i]);
281 Sk4f r4 = s4 + d4 * scale;
282 dst[i] = store_dst<D>(r4);
283 }
284 }
285 }
286
287 const XferProcPair gProcs_SrcOver[] = {
288 { srcover_1<kLinear_Dst>, srcover_n<kLinear_Dst> }, // linear alpha
289 { src_1<kLinear_Dst>, src_n<kLinear_Dst> }, // linear opaque [ we are src-mode ]
290 { srcover_1<kSRGB_Dst>, srcover_n<kSRGB_Dst> }, // srgb alpha
291 { src_1<kSRGB_Dst>, src_n<kSRGB_Dst> }, // srgb opaque [ we are src-mode ]
292 };
293
294 //////////////////////////////////////////////////////////////////////////////// ///////////////////
295
296 static XferProcPair find_procs(SkXfermode::Mode mode, uint32_t flags) {
297 SkASSERT(0 == (flags & ~3));
298 flags &= 3;
299
300 switch (mode) {
301 case SkXfermode::kClear_Mode: return gProcs_Clear[flags];
302 case SkXfermode::kSrc_Mode: return gProcs_Src[flags];
303 case SkXfermode::kDst_Mode: return gProcs_Dst[flags];
304 case SkXfermode::kSrcOver_Mode: return gProcs_SrcOver[flags];
305 default:
306 break;
307 }
308 return { xfer_pm4_proc_1, xfer_pm4_proc_n };
309 }
310
311 SkXfermode::PM4fProc1 SkXfermode::GetPM4fProc1(Mode mode, uint32_t flags) {
312 return find_procs(mode, flags).fP1;
313 }
314
315 SkXfermode::PM4fProcN SkXfermode::GetPM4fProcN(Mode mode, uint32_t flags) {
316 return find_procs(mode, flags).fPN;
317 }
318
319 SkXfermode::PM4fProc1 SkXfermode::getPM4fProc1(uint32_t flags) const {
320 Mode mode;
321 return this->asMode(&mode) ? GetPM4fProc1(mode, flags) : xfer_pm4_proc_1;
322 }
323
324 SkXfermode::PM4fProcN SkXfermode::getPM4fProcN(uint32_t flags) const {
325 Mode mode;
326 return this->asMode(&mode) ? GetPM4fProcN(mode, flags) : xfer_pm4_proc_n;
327 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698