|
1 |
|
2 /* |
|
3 * Copyright 2006 The Android Open Source Project |
|
4 * |
|
5 * Use of this source code is governed by a BSD-style license that can be |
|
6 * found in the LICENSE file. |
|
7 */ |
|
8 |
|
9 |
|
10 #include "SkXfermode.h" |
|
11 #include "SkXfermode_proccoeff.h" |
|
12 #include "SkColorPriv.h" |
|
13 #include "SkReadBuffer.h" |
|
14 #include "SkWriteBuffer.h" |
|
15 #include "SkMathPriv.h" |
|
16 #include "SkString.h" |
|
17 #include "SkUtilsArm.h" |
|
18 |
|
19 #if !SK_ARM_NEON_IS_NONE |
|
20 #include "SkXfermode_opts_arm_neon.h" |
|
21 #endif |
|
22 |
|
23 #define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b) |
|
24 |
|
25 #if 0 |
|
26 // idea for higher precision blends in xfer procs (and slightly faster) |
|
27 // see DstATop as a probable caller |
|
28 static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) { |
|
29 SkASSERT(a <= 255); |
|
30 SkASSERT(b <= 255); |
|
31 SkASSERT(c <= 255); |
|
32 SkASSERT(d <= 255); |
|
33 unsigned prod = SkMulS16(a, b) + SkMulS16(c, d) + 128; |
|
34 unsigned result = (prod + (prod >> 8)) >> 8; |
|
35 SkASSERT(result <= 255); |
|
36 return result; |
|
37 } |
|
38 #endif |
|
39 |
|
40 static inline unsigned saturated_add(unsigned a, unsigned b) { |
|
41 SkASSERT(a <= 255); |
|
42 SkASSERT(b <= 255); |
|
43 unsigned sum = a + b; |
|
44 if (sum > 255) { |
|
45 sum = 255; |
|
46 } |
|
47 return sum; |
|
48 } |
|
49 |
|
50 static inline int clamp_signed_byte(int n) { |
|
51 if (n < 0) { |
|
52 n = 0; |
|
53 } else if (n > 255) { |
|
54 n = 255; |
|
55 } |
|
56 return n; |
|
57 } |
|
58 |
|
59 static inline int clamp_div255round(int prod) { |
|
60 if (prod <= 0) { |
|
61 return 0; |
|
62 } else if (prod >= 255*255) { |
|
63 return 255; |
|
64 } else { |
|
65 return SkDiv255Round(prod); |
|
66 } |
|
67 } |
|
68 |
|
69 /////////////////////////////////////////////////////////////////////////////// |
|
70 |
|
71 // kClear_Mode, //!< [0, 0] |
|
72 static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) { |
|
73 return 0; |
|
74 } |
|
75 |
|
76 // kSrc_Mode, //!< [Sa, Sc] |
|
77 static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) { |
|
78 return src; |
|
79 } |
|
80 |
|
81 // kDst_Mode, //!< [Da, Dc] |
|
82 static SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) { |
|
83 return dst; |
|
84 } |
|
85 |
|
86 // kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc] |
|
87 static SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) { |
|
88 #if 0 |
|
89 // this is the old, more-correct way, but it doesn't guarantee that dst==255 |
|
90 // will always stay opaque |
|
91 return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src))); |
|
92 #else |
|
93 // this is slightly faster, but more importantly guarantees that dst==255 |
|
94 // will always stay opaque |
|
95 return src + SkAlphaMulQ(dst, 256 - SkGetPackedA32(src)); |
|
96 #endif |
|
97 } |
|
98 |
|
99 // kDstOver_Mode, //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc] |
|
100 static SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) { |
|
101 // this is the reverse of srcover, just flipping src and dst |
|
102 // see srcover's comment about the 256 for opaqueness guarantees |
|
103 return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst)); |
|
104 } |
|
105 |
|
106 // kSrcIn_Mode, //!< [Sa * Da, Sc * Da] |
|
107 static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) { |
|
108 return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst))); |
|
109 } |
|
110 |
|
111 // kDstIn_Mode, //!< [Sa * Da, Sa * Dc] |
|
112 static SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) { |
|
113 return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src))); |
|
114 } |
|
115 |
|
116 // kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)] |
|
117 static SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) { |
|
118 return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst))); |
|
119 } |
|
120 |
|
121 // kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)] |
|
122 static SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) { |
|
123 return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src))); |
|
124 } |
|
125 |
|
126 // kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc] |
|
127 static SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) { |
|
128 unsigned sa = SkGetPackedA32(src); |
|
129 unsigned da = SkGetPackedA32(dst); |
|
130 unsigned isa = 255 - sa; |
|
131 |
|
132 return SkPackARGB32(da, |
|
133 SkAlphaMulAlpha(da, SkGetPackedR32(src)) + |
|
134 SkAlphaMulAlpha(isa, SkGetPackedR32(dst)), |
|
135 SkAlphaMulAlpha(da, SkGetPackedG32(src)) + |
|
136 SkAlphaMulAlpha(isa, SkGetPackedG32(dst)), |
|
137 SkAlphaMulAlpha(da, SkGetPackedB32(src)) + |
|
138 SkAlphaMulAlpha(isa, SkGetPackedB32(dst))); |
|
139 } |
|
140 |
|
141 // kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)] |
|
142 static SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) { |
|
143 unsigned sa = SkGetPackedA32(src); |
|
144 unsigned da = SkGetPackedA32(dst); |
|
145 unsigned ida = 255 - da; |
|
146 |
|
147 return SkPackARGB32(sa, |
|
148 SkAlphaMulAlpha(ida, SkGetPackedR32(src)) + |
|
149 SkAlphaMulAlpha(sa, SkGetPackedR32(dst)), |
|
150 SkAlphaMulAlpha(ida, SkGetPackedG32(src)) + |
|
151 SkAlphaMulAlpha(sa, SkGetPackedG32(dst)), |
|
152 SkAlphaMulAlpha(ida, SkGetPackedB32(src)) + |
|
153 SkAlphaMulAlpha(sa, SkGetPackedB32(dst))); |
|
154 } |
|
155 |
|
156 // kXor_Mode [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] |
|
157 static SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) { |
|
158 unsigned sa = SkGetPackedA32(src); |
|
159 unsigned da = SkGetPackedA32(dst); |
|
160 unsigned isa = 255 - sa; |
|
161 unsigned ida = 255 - da; |
|
162 |
|
163 return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1), |
|
164 SkAlphaMulAlpha(ida, SkGetPackedR32(src)) + |
|
165 SkAlphaMulAlpha(isa, SkGetPackedR32(dst)), |
|
166 SkAlphaMulAlpha(ida, SkGetPackedG32(src)) + |
|
167 SkAlphaMulAlpha(isa, SkGetPackedG32(dst)), |
|
168 SkAlphaMulAlpha(ida, SkGetPackedB32(src)) + |
|
169 SkAlphaMulAlpha(isa, SkGetPackedB32(dst))); |
|
170 } |
|
171 |
|
172 /////////////////////////////////////////////////////////////////////////////// |
|
173 |
|
174 // kPlus_Mode |
|
175 static SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) { |
|
176 unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst)); |
|
177 unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst)); |
|
178 unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst)); |
|
179 unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst)); |
|
180 return SkPackARGB32(a, r, g, b); |
|
181 } |
|
182 |
|
183 // kModulate_Mode |
|
184 static SkPMColor modulate_modeproc(SkPMColor src, SkPMColor dst) { |
|
185 int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst)); |
|
186 int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst)); |
|
187 int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst)); |
|
188 int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst)); |
|
189 return SkPackARGB32(a, r, g, b); |
|
190 } |
|
191 |
|
192 static inline int srcover_byte(int a, int b) { |
|
193 return a + b - SkAlphaMulAlpha(a, b); |
|
194 } |
|
195 |
|
196 // kMultiply_Mode |
|
197 // B(Cb, Cs) = Cb x Cs |
|
198 // multiply uses its own version of blendfunc_byte because sa and da are not needed |
|
199 static int blendfunc_multiply_byte(int sc, int dc, int sa, int da) { |
|
200 return clamp_div255round(sc * (255 - da) + dc * (255 - sa) + sc * dc); |
|
201 } |
|
202 |
|
203 static SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) { |
|
204 int sa = SkGetPackedA32(src); |
|
205 int da = SkGetPackedA32(dst); |
|
206 int a = srcover_byte(sa, da); |
|
207 int r = blendfunc_multiply_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); |
|
208 int g = blendfunc_multiply_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); |
|
209 int b = blendfunc_multiply_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); |
|
210 return SkPackARGB32(a, r, g, b); |
|
211 } |
|
212 |
|
213 // kScreen_Mode |
|
214 static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) { |
|
215 int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst)); |
|
216 int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst)); |
|
217 int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst)); |
|
218 int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst)); |
|
219 return SkPackARGB32(a, r, g, b); |
|
220 } |
|
221 |
|
222 // kOverlay_Mode |
|
223 static inline int overlay_byte(int sc, int dc, int sa, int da) { |
|
224 int tmp = sc * (255 - da) + dc * (255 - sa); |
|
225 int rc; |
|
226 if (2 * dc <= da) { |
|
227 rc = 2 * sc * dc; |
|
228 } else { |
|
229 rc = sa * da - 2 * (da - dc) * (sa - sc); |
|
230 } |
|
231 return clamp_div255round(rc + tmp); |
|
232 } |
|
233 static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) { |
|
234 int sa = SkGetPackedA32(src); |
|
235 int da = SkGetPackedA32(dst); |
|
236 int a = srcover_byte(sa, da); |
|
237 int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); |
|
238 int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); |
|
239 int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); |
|
240 return SkPackARGB32(a, r, g, b); |
|
241 } |
|
242 |
|
243 // kDarken_Mode |
|
244 static inline int darken_byte(int sc, int dc, int sa, int da) { |
|
245 int sd = sc * da; |
|
246 int ds = dc * sa; |
|
247 if (sd < ds) { |
|
248 // srcover |
|
249 return sc + dc - SkDiv255Round(ds); |
|
250 } else { |
|
251 // dstover |
|
252 return dc + sc - SkDiv255Round(sd); |
|
253 } |
|
254 } |
|
255 static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) { |
|
256 int sa = SkGetPackedA32(src); |
|
257 int da = SkGetPackedA32(dst); |
|
258 int a = srcover_byte(sa, da); |
|
259 int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); |
|
260 int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); |
|
261 int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); |
|
262 return SkPackARGB32(a, r, g, b); |
|
263 } |
|
264 |
|
265 // kLighten_Mode |
|
266 static inline int lighten_byte(int sc, int dc, int sa, int da) { |
|
267 int sd = sc * da; |
|
268 int ds = dc * sa; |
|
269 if (sd > ds) { |
|
270 // srcover |
|
271 return sc + dc - SkDiv255Round(ds); |
|
272 } else { |
|
273 // dstover |
|
274 return dc + sc - SkDiv255Round(sd); |
|
275 } |
|
276 } |
|
277 static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) { |
|
278 int sa = SkGetPackedA32(src); |
|
279 int da = SkGetPackedA32(dst); |
|
280 int a = srcover_byte(sa, da); |
|
281 int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); |
|
282 int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); |
|
283 int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); |
|
284 return SkPackARGB32(a, r, g, b); |
|
285 } |
|
286 |
|
287 // kColorDodge_Mode |
|
288 static inline int colordodge_byte(int sc, int dc, int sa, int da) { |
|
289 int diff = sa - sc; |
|
290 int rc; |
|
291 if (0 == dc) { |
|
292 return SkAlphaMulAlpha(sc, 255 - da); |
|
293 } else if (0 == diff) { |
|
294 rc = sa * da + sc * (255 - da) + dc * (255 - sa); |
|
295 } else { |
|
296 diff = dc * sa / diff; |
|
297 rc = sa * ((da < diff) ? da : diff) + sc * (255 - da) + dc * (255 - sa); |
|
298 } |
|
299 return clamp_div255round(rc); |
|
300 } |
|
301 static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) { |
|
302 int sa = SkGetPackedA32(src); |
|
303 int da = SkGetPackedA32(dst); |
|
304 int a = srcover_byte(sa, da); |
|
305 int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); |
|
306 int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); |
|
307 int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); |
|
308 return SkPackARGB32(a, r, g, b); |
|
309 } |
|
310 |
|
311 // kColorBurn_Mode |
|
312 static inline int colorburn_byte(int sc, int dc, int sa, int da) { |
|
313 int rc; |
|
314 if (dc == da) { |
|
315 rc = sa * da + sc * (255 - da) + dc * (255 - sa); |
|
316 } else if (0 == sc) { |
|
317 return SkAlphaMulAlpha(dc, 255 - sa); |
|
318 } else { |
|
319 int tmp = (da - dc) * sa / sc; |
|
320 rc = sa * (da - ((da < tmp) ? da : tmp)) |
|
321 + sc * (255 - da) + dc * (255 - sa); |
|
322 } |
|
323 return clamp_div255round(rc); |
|
324 } |
|
325 static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) { |
|
326 int sa = SkGetPackedA32(src); |
|
327 int da = SkGetPackedA32(dst); |
|
328 int a = srcover_byte(sa, da); |
|
329 int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); |
|
330 int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); |
|
331 int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); |
|
332 return SkPackARGB32(a, r, g, b); |
|
333 } |
|
334 |
|
335 // kHardLight_Mode |
|
336 static inline int hardlight_byte(int sc, int dc, int sa, int da) { |
|
337 int rc; |
|
338 if (2 * sc <= sa) { |
|
339 rc = 2 * sc * dc; |
|
340 } else { |
|
341 rc = sa * da - 2 * (da - dc) * (sa - sc); |
|
342 } |
|
343 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa)); |
|
344 } |
|
345 static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) { |
|
346 int sa = SkGetPackedA32(src); |
|
347 int da = SkGetPackedA32(dst); |
|
348 int a = srcover_byte(sa, da); |
|
349 int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); |
|
350 int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); |
|
351 int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); |
|
352 return SkPackARGB32(a, r, g, b); |
|
353 } |
|
354 |
|
355 // returns 255 * sqrt(n/255) |
|
356 static U8CPU sqrt_unit_byte(U8CPU n) { |
|
357 return SkSqrtBits(n, 15+4); |
|
358 } |
|
359 |
|
360 // kSoftLight_Mode |
|
361 static inline int softlight_byte(int sc, int dc, int sa, int da) { |
|
362 int m = da ? dc * 256 / da : 0; |
|
363 int rc; |
|
364 if (2 * sc <= sa) { |
|
365 rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8)); |
|
366 } else if (4 * dc <= da) { |
|
367 int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m; |
|
368 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8); |
|
369 } else { |
|
370 int tmp = sqrt_unit_byte(m) - m; |
|
371 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8); |
|
372 } |
|
373 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa)); |
|
374 } |
|
375 static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) { |
|
376 int sa = SkGetPackedA32(src); |
|
377 int da = SkGetPackedA32(dst); |
|
378 int a = srcover_byte(sa, da); |
|
379 int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); |
|
380 int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); |
|
381 int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); |
|
382 return SkPackARGB32(a, r, g, b); |
|
383 } |
|
384 |
|
385 // kDifference_Mode |
|
386 static inline int difference_byte(int sc, int dc, int sa, int da) { |
|
387 int tmp = SkMin32(sc * da, dc * sa); |
|
388 return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp)); |
|
389 } |
|
390 static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) { |
|
391 int sa = SkGetPackedA32(src); |
|
392 int da = SkGetPackedA32(dst); |
|
393 int a = srcover_byte(sa, da); |
|
394 int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); |
|
395 int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); |
|
396 int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); |
|
397 return SkPackARGB32(a, r, g, b); |
|
398 } |
|
399 |
|
400 // kExclusion_Mode |
|
401 static inline int exclusion_byte(int sc, int dc, int, int) { |
|
402 // this equations is wacky, wait for SVG to confirm it |
|
403 //int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa); |
|
404 |
|
405 // The above equation can be simplified as follows |
|
406 int r = 255*(sc + dc) - 2 * sc * dc; |
|
407 return clamp_div255round(r); |
|
408 } |
|
409 static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) { |
|
410 int sa = SkGetPackedA32(src); |
|
411 int da = SkGetPackedA32(dst); |
|
412 int a = srcover_byte(sa, da); |
|
413 int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); |
|
414 int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); |
|
415 int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); |
|
416 return SkPackARGB32(a, r, g, b); |
|
417 } |
|
418 |
|
419 // The CSS compositing spec introduces the following formulas: |
|
420 // (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable) |
|
421 // SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709 |
|
422 // while PDF and CG uses the one from Rec. Rec. 601 |
|
423 // See http://www.glennchan.info/articles/technical/hd-versus-sd-color-space/hd-versus-sd-color-space.htm |
|
424 static inline int Lum(int r, int g, int b) |
|
425 { |
|
426 return SkDiv255Round(r * 77 + g * 150 + b * 28); |
|
427 } |
|
428 |
|
429 static inline int min2(int a, int b) { return a < b ? a : b; } |
|
430 static inline int max2(int a, int b) { return a > b ? a : b; } |
|
431 #define minimum(a, b, c) min2(min2(a, b), c) |
|
432 #define maximum(a, b, c) max2(max2(a, b), c) |
|
433 |
|
434 static inline int Sat(int r, int g, int b) { |
|
435 return maximum(r, g, b) - minimum(r, g, b); |
|
436 } |
|
437 |
|
438 static inline void setSaturationComponents(int* Cmin, int* Cmid, int* Cmax, int s) { |
|
439 if(*Cmax > *Cmin) { |
|
440 *Cmid = SkMulDiv(*Cmid - *Cmin, s, *Cmax - *Cmin); |
|
441 *Cmax = s; |
|
442 } else { |
|
443 *Cmax = 0; |
|
444 *Cmid = 0; |
|
445 } |
|
446 |
|
447 *Cmin = 0; |
|
448 } |
|
449 |
|
450 static inline void SetSat(int* r, int* g, int* b, int s) { |
|
451 if(*r <= *g) { |
|
452 if(*g <= *b) { |
|
453 setSaturationComponents(r, g, b, s); |
|
454 } else if(*r <= *b) { |
|
455 setSaturationComponents(r, b, g, s); |
|
456 } else { |
|
457 setSaturationComponents(b, r, g, s); |
|
458 } |
|
459 } else if(*r <= *b) { |
|
460 setSaturationComponents(g, r, b, s); |
|
461 } else if(*g <= *b) { |
|
462 setSaturationComponents(g, b, r, s); |
|
463 } else { |
|
464 setSaturationComponents(b, g, r, s); |
|
465 } |
|
466 } |
|
467 |
|
468 static inline void clipColor(int* r, int* g, int* b, int a) { |
|
469 int L = Lum(*r, *g, *b); |
|
470 int n = minimum(*r, *g, *b); |
|
471 int x = maximum(*r, *g, *b); |
|
472 int denom; |
|
473 if ((n < 0) && (denom = L - n)) { // Compute denom and make sure it's non zero |
|
474 *r = L + SkMulDiv(*r - L, L, denom); |
|
475 *g = L + SkMulDiv(*g - L, L, denom); |
|
476 *b = L + SkMulDiv(*b - L, L, denom); |
|
477 } |
|
478 |
|
479 if ((x > a) && (denom = x - L)) { // Compute denom and make sure it's non zero |
|
480 int numer = a - L; |
|
481 *r = L + SkMulDiv(*r - L, numer, denom); |
|
482 *g = L + SkMulDiv(*g - L, numer, denom); |
|
483 *b = L + SkMulDiv(*b - L, numer, denom); |
|
484 } |
|
485 } |
|
486 |
|
487 static inline void SetLum(int* r, int* g, int* b, int a, int l) { |
|
488 int d = l - Lum(*r, *g, *b); |
|
489 *r += d; |
|
490 *g += d; |
|
491 *b += d; |
|
492 |
|
493 clipColor(r, g, b, a); |
|
494 } |
|
495 |
|
496 // non-separable blend modes are done in non-premultiplied alpha |
|
497 #define blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \ |
|
498 clamp_div255round(sc * (255 - da) + dc * (255 - sa) + blendval) |
|
499 |
|
500 // kHue_Mode |
|
501 // B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb)) |
|
502 // Create a color with the hue of the source color and the saturation and luminosity of the backdrop color. |
|
503 static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) { |
|
504 int sr = SkGetPackedR32(src); |
|
505 int sg = SkGetPackedG32(src); |
|
506 int sb = SkGetPackedB32(src); |
|
507 int sa = SkGetPackedA32(src); |
|
508 |
|
509 int dr = SkGetPackedR32(dst); |
|
510 int dg = SkGetPackedG32(dst); |
|
511 int db = SkGetPackedB32(dst); |
|
512 int da = SkGetPackedA32(dst); |
|
513 int Sr, Sg, Sb; |
|
514 |
|
515 if(sa && da) { |
|
516 Sr = sr * sa; |
|
517 Sg = sg * sa; |
|
518 Sb = sb * sa; |
|
519 SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa); |
|
520 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa); |
|
521 } else { |
|
522 Sr = 0; |
|
523 Sg = 0; |
|
524 Sb = 0; |
|
525 } |
|
526 |
|
527 int a = srcover_byte(sa, da); |
|
528 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr); |
|
529 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg); |
|
530 int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb); |
|
531 return SkPackARGB32(a, r, g, b); |
|
532 } |
|
533 |
|
534 // kSaturation_Mode |
|
535 // B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb)) |
|
536 // Create a color with the saturation of the source color and the hue and luminosity of the backdrop color. |
|
537 static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) { |
|
538 int sr = SkGetPackedR32(src); |
|
539 int sg = SkGetPackedG32(src); |
|
540 int sb = SkGetPackedB32(src); |
|
541 int sa = SkGetPackedA32(src); |
|
542 |
|
543 int dr = SkGetPackedR32(dst); |
|
544 int dg = SkGetPackedG32(dst); |
|
545 int db = SkGetPackedB32(dst); |
|
546 int da = SkGetPackedA32(dst); |
|
547 int Dr, Dg, Db; |
|
548 |
|
549 if(sa && da) { |
|
550 Dr = dr * sa; |
|
551 Dg = dg * sa; |
|
552 Db = db * sa; |
|
553 SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da); |
|
554 SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa); |
|
555 } else { |
|
556 Dr = 0; |
|
557 Dg = 0; |
|
558 Db = 0; |
|
559 } |
|
560 |
|
561 int a = srcover_byte(sa, da); |
|
562 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr); |
|
563 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg); |
|
564 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db); |
|
565 return SkPackARGB32(a, r, g, b); |
|
566 } |
|
567 |
|
568 // kColor_Mode |
|
569 // B(Cb, Cs) = SetLum(Cs, Lum(Cb)) |
|
570 // Create a color with the hue and saturation of the source color and the luminosity of the backdrop color. |
|
571 static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) { |
|
572 int sr = SkGetPackedR32(src); |
|
573 int sg = SkGetPackedG32(src); |
|
574 int sb = SkGetPackedB32(src); |
|
575 int sa = SkGetPackedA32(src); |
|
576 |
|
577 int dr = SkGetPackedR32(dst); |
|
578 int dg = SkGetPackedG32(dst); |
|
579 int db = SkGetPackedB32(dst); |
|
580 int da = SkGetPackedA32(dst); |
|
581 int Sr, Sg, Sb; |
|
582 |
|
583 if(sa && da) { |
|
584 Sr = sr * da; |
|
585 Sg = sg * da; |
|
586 Sb = sb * da; |
|
587 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa); |
|
588 } else { |
|
589 Sr = 0; |
|
590 Sg = 0; |
|
591 Sb = 0; |
|
592 } |
|
593 |
|
594 int a = srcover_byte(sa, da); |
|
595 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr); |
|
596 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg); |
|
597 int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb); |
|
598 return SkPackARGB32(a, r, g, b); |
|
599 } |
|
600 |
|
601 // kLuminosity_Mode |
|
602 // B(Cb, Cs) = SetLum(Cb, Lum(Cs)) |
|
603 // Create a color with the luminosity of the source color and the hue and saturation of the backdrop color. |
|
604 static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) { |
|
605 int sr = SkGetPackedR32(src); |
|
606 int sg = SkGetPackedG32(src); |
|
607 int sb = SkGetPackedB32(src); |
|
608 int sa = SkGetPackedA32(src); |
|
609 |
|
610 int dr = SkGetPackedR32(dst); |
|
611 int dg = SkGetPackedG32(dst); |
|
612 int db = SkGetPackedB32(dst); |
|
613 int da = SkGetPackedA32(dst); |
|
614 int Dr, Dg, Db; |
|
615 |
|
616 if(sa && da) { |
|
617 Dr = dr * sa; |
|
618 Dg = dg * sa; |
|
619 Db = db * sa; |
|
620 SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da); |
|
621 } else { |
|
622 Dr = 0; |
|
623 Dg = 0; |
|
624 Db = 0; |
|
625 } |
|
626 |
|
627 int a = srcover_byte(sa, da); |
|
628 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr); |
|
629 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg); |
|
630 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db); |
|
631 return SkPackARGB32(a, r, g, b); |
|
632 } |
|
633 |
|
634 const ProcCoeff gProcCoeffs[] = { |
|
635 { clear_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kZero_Coeff }, |
|
636 { src_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kZero_Coeff }, |
|
637 { dst_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kOne_Coeff }, |
|
638 { srcover_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISA_Coeff }, |
|
639 { dstover_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kOne_Coeff }, |
|
640 { srcin_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kZero_Coeff }, |
|
641 { dstin_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kSA_Coeff }, |
|
642 { srcout_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kZero_Coeff }, |
|
643 { dstout_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kISA_Coeff }, |
|
644 { srcatop_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kISA_Coeff }, |
|
645 { dstatop_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kSA_Coeff }, |
|
646 { xor_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kISA_Coeff }, |
|
647 |
|
648 { plus_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kOne_Coeff }, |
|
649 { modulate_modeproc,SkXfermode::kZero_Coeff, SkXfermode::kSC_Coeff }, |
|
650 { screen_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISC_Coeff }, |
|
651 { overlay_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
652 { darken_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
653 { lighten_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
654 { colordodge_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
655 { colorburn_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
656 { hardlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
657 { softlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
658 { difference_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
659 { exclusion_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
660 { multiply_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
661 { hue_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
662 { saturation_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
663 { color_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
664 { luminosity_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
|
665 }; |
|
666 |
|
667 /////////////////////////////////////////////////////////////////////////////// |
|
668 |
|
669 bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) const { |
|
670 return false; |
|
671 } |
|
672 |
|
673 bool SkXfermode::asMode(Mode* mode) const { |
|
674 return false; |
|
675 } |
|
676 |
|
677 bool SkXfermode::asNewEffect(GrEffectRef** effect, GrTexture* background) const { |
|
678 return false; |
|
679 } |
|
680 |
|
681 bool SkXfermode::AsNewEffectOrCoeff(SkXfermode* xfermode, |
|
682 GrEffectRef** effect, |
|
683 Coeff* src, |
|
684 Coeff* dst, |
|
685 GrTexture* background) { |
|
686 if (NULL == xfermode) { |
|
687 return ModeAsCoeff(kSrcOver_Mode, src, dst); |
|
688 } else if (xfermode->asCoeff(src, dst)) { |
|
689 return true; |
|
690 } else { |
|
691 return xfermode->asNewEffect(effect, background); |
|
692 } |
|
693 } |
|
694 |
|
695 SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{ |
|
696 // no-op. subclasses should override this |
|
697 return dst; |
|
698 } |
|
699 |
|
700 void SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst, |
|
701 const SkPMColor* SK_RESTRICT src, int count, |
|
702 const SkAlpha* SK_RESTRICT aa) const { |
|
703 SkASSERT(dst && src && count >= 0); |
|
704 |
|
705 if (NULL == aa) { |
|
706 for (int i = count - 1; i >= 0; --i) { |
|
707 dst[i] = this->xferColor(src[i], dst[i]); |
|
708 } |
|
709 } else { |
|
710 for (int i = count - 1; i >= 0; --i) { |
|
711 unsigned a = aa[i]; |
|
712 if (0 != a) { |
|
713 SkPMColor dstC = dst[i]; |
|
714 SkPMColor C = this->xferColor(src[i], dstC); |
|
715 if (0xFF != a) { |
|
716 C = SkFourByteInterp(C, dstC, a); |
|
717 } |
|
718 dst[i] = C; |
|
719 } |
|
720 } |
|
721 } |
|
722 } |
|
723 |
|
724 void SkXfermode::xfer16(uint16_t* dst, |
|
725 const SkPMColor* SK_RESTRICT src, int count, |
|
726 const SkAlpha* SK_RESTRICT aa) const { |
|
727 SkASSERT(dst && src && count >= 0); |
|
728 |
|
729 if (NULL == aa) { |
|
730 for (int i = count - 1; i >= 0; --i) { |
|
731 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); |
|
732 dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC)); |
|
733 } |
|
734 } else { |
|
735 for (int i = count - 1; i >= 0; --i) { |
|
736 unsigned a = aa[i]; |
|
737 if (0 != a) { |
|
738 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); |
|
739 SkPMColor C = this->xferColor(src[i], dstC); |
|
740 if (0xFF != a) { |
|
741 C = SkFourByteInterp(C, dstC, a); |
|
742 } |
|
743 dst[i] = SkPixel32ToPixel16_ToU16(C); |
|
744 } |
|
745 } |
|
746 } |
|
747 } |
|
748 |
|
749 void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst, |
|
750 const SkPMColor src[], int count, |
|
751 const SkAlpha* SK_RESTRICT aa) const { |
|
752 SkASSERT(dst && src && count >= 0); |
|
753 |
|
754 if (NULL == aa) { |
|
755 for (int i = count - 1; i >= 0; --i) { |
|
756 SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT)); |
|
757 dst[i] = SkToU8(SkGetPackedA32(res)); |
|
758 } |
|
759 } else { |
|
760 for (int i = count - 1; i >= 0; --i) { |
|
761 unsigned a = aa[i]; |
|
762 if (0 != a) { |
|
763 SkAlpha dstA = dst[i]; |
|
764 unsigned A = SkGetPackedA32(this->xferColor(src[i], |
|
765 (SkPMColor)(dstA << SK_A32_SHIFT))); |
|
766 if (0xFF != a) { |
|
767 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a)); |
|
768 } |
|
769 dst[i] = SkToU8(A); |
|
770 } |
|
771 } |
|
772 } |
|
773 } |
|
774 |
|
775 /////////////////////////////////////////////////////////////////////////////// |
|
776 |
|
777 void SkProcXfermode::xfer32(SkPMColor* SK_RESTRICT dst, |
|
778 const SkPMColor* SK_RESTRICT src, int count, |
|
779 const SkAlpha* SK_RESTRICT aa) const { |
|
780 SkASSERT(dst && src && count >= 0); |
|
781 |
|
782 SkXfermodeProc proc = fProc; |
|
783 |
|
784 if (NULL != proc) { |
|
785 if (NULL == aa) { |
|
786 for (int i = count - 1; i >= 0; --i) { |
|
787 dst[i] = proc(src[i], dst[i]); |
|
788 } |
|
789 } else { |
|
790 for (int i = count - 1; i >= 0; --i) { |
|
791 unsigned a = aa[i]; |
|
792 if (0 != a) { |
|
793 SkPMColor dstC = dst[i]; |
|
794 SkPMColor C = proc(src[i], dstC); |
|
795 if (a != 0xFF) { |
|
796 C = SkFourByteInterp(C, dstC, a); |
|
797 } |
|
798 dst[i] = C; |
|
799 } |
|
800 } |
|
801 } |
|
802 } |
|
803 } |
|
804 |
|
805 void SkProcXfermode::xfer16(uint16_t* SK_RESTRICT dst, |
|
806 const SkPMColor* SK_RESTRICT src, int count, |
|
807 const SkAlpha* SK_RESTRICT aa) const { |
|
808 SkASSERT(dst && src && count >= 0); |
|
809 |
|
810 SkXfermodeProc proc = fProc; |
|
811 |
|
812 if (NULL != proc) { |
|
813 if (NULL == aa) { |
|
814 for (int i = count - 1; i >= 0; --i) { |
|
815 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); |
|
816 dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC)); |
|
817 } |
|
818 } else { |
|
819 for (int i = count - 1; i >= 0; --i) { |
|
820 unsigned a = aa[i]; |
|
821 if (0 != a) { |
|
822 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); |
|
823 SkPMColor C = proc(src[i], dstC); |
|
824 if (0xFF != a) { |
|
825 C = SkFourByteInterp(C, dstC, a); |
|
826 } |
|
827 dst[i] = SkPixel32ToPixel16_ToU16(C); |
|
828 } |
|
829 } |
|
830 } |
|
831 } |
|
832 } |
|
833 |
|
834 void SkProcXfermode::xferA8(SkAlpha* SK_RESTRICT dst, |
|
835 const SkPMColor* SK_RESTRICT src, int count, |
|
836 const SkAlpha* SK_RESTRICT aa) const { |
|
837 SkASSERT(dst && src && count >= 0); |
|
838 |
|
839 SkXfermodeProc proc = fProc; |
|
840 |
|
841 if (NULL != proc) { |
|
842 if (NULL == aa) { |
|
843 for (int i = count - 1; i >= 0; --i) { |
|
844 SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT); |
|
845 dst[i] = SkToU8(SkGetPackedA32(res)); |
|
846 } |
|
847 } else { |
|
848 for (int i = count - 1; i >= 0; --i) { |
|
849 unsigned a = aa[i]; |
|
850 if (0 != a) { |
|
851 SkAlpha dstA = dst[i]; |
|
852 SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT); |
|
853 unsigned A = SkGetPackedA32(res); |
|
854 if (0xFF != a) { |
|
855 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a)); |
|
856 } |
|
857 dst[i] = SkToU8(A); |
|
858 } |
|
859 } |
|
860 } |
|
861 } |
|
862 } |
|
863 |
|
864 SkProcXfermode::SkProcXfermode(SkReadBuffer& buffer) |
|
865 : SkXfermode(buffer) { |
|
866 fProc = NULL; |
|
867 if (!buffer.isCrossProcess()) { |
|
868 fProc = (SkXfermodeProc)buffer.readFunctionPtr(); |
|
869 } |
|
870 } |
|
871 |
|
872 void SkProcXfermode::flatten(SkWriteBuffer& buffer) const { |
|
873 this->INHERITED::flatten(buffer); |
|
874 if (!buffer.isCrossProcess()) { |
|
875 buffer.writeFunctionPtr((void*)fProc); |
|
876 } |
|
877 } |
|
878 |
|
879 #ifndef SK_IGNORE_TO_STRING |
|
880 void SkProcXfermode::toString(SkString* str) const { |
|
881 str->appendf("SkProcXfermode: %p", fProc); |
|
882 } |
|
883 #endif |
|
884 |
|
885 ////////////////////////////////////////////////////////////////////////////// |
|
886 |
|
887 #if SK_SUPPORT_GPU |
|
888 |
|
889 #include "GrEffect.h" |
|
890 #include "GrCoordTransform.h" |
|
891 #include "GrEffectUnitTest.h" |
|
892 #include "GrTBackendEffectFactory.h" |
|
893 #include "gl/GrGLEffect.h" |
|
894 |
|
895 /** |
|
896 * GrEffect that implements the all the separable xfer modes that cannot be expressed as Coeffs. |
|
897 */ |
|
898 class XferEffect : public GrEffect { |
|
899 public: |
|
900 static bool IsSupportedMode(SkXfermode::Mode mode) { |
|
901 return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode; |
|
902 } |
|
903 |
|
904 static GrEffectRef* Create(SkXfermode::Mode mode, GrTexture* background) { |
|
905 if (!IsSupportedMode(mode)) { |
|
906 return NULL; |
|
907 } else { |
|
908 AutoEffectUnref effect(SkNEW_ARGS(XferEffect, (mode, background))); |
|
909 return CreateEffectRef(effect); |
|
910 } |
|
911 } |
|
912 |
|
913 virtual void getConstantColorComponents(GrColor* color, |
|
914 uint32_t* validFlags) const SK_OVERRIDE { |
|
915 *validFlags = 0; |
|
916 } |
|
917 |
|
918 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { |
|
919 return GrTBackendEffectFactory<XferEffect>::getInstance(); |
|
920 } |
|
921 |
|
922 static const char* Name() { return "XferEffect"; } |
|
923 |
|
924 SkXfermode::Mode mode() const { return fMode; } |
|
925 const GrTextureAccess& backgroundAccess() const { return fBackgroundAccess; } |
|
926 |
|
927 class GLEffect : public GrGLEffect { |
|
928 public: |
|
929 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) |
|
930 : GrGLEffect(factory) { |
|
931 } |
|
932 virtual void emitCode(GrGLShaderBuilder* builder, |
|
933 const GrDrawEffect& drawEffect, |
|
934 EffectKey key, |
|
935 const char* outputColor, |
|
936 const char* inputColor, |
|
937 const TransformedCoordsArray& coords, |
|
938 const TextureSamplerArray& samplers) SK_OVERRIDE { |
|
939 SkXfermode::Mode mode = drawEffect.castEffect<XferEffect>().mode(); |
|
940 const GrTexture* backgroundTex = drawEffect.castEffect<XferEffect>().backgroundAccess().getTexture(); |
|
941 const char* dstColor; |
|
942 if (backgroundTex) { |
|
943 dstColor = "bgColor"; |
|
944 builder->fsCodeAppendf("\t\tvec4 %s = ", dstColor); |
|
945 builder->fsAppendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type()); |
|
946 builder->fsCodeAppendf(";\n"); |
|
947 } else { |
|
948 dstColor = builder->dstColor(); |
|
949 } |
|
950 SkASSERT(NULL != dstColor); |
|
951 |
|
952 // We don't try to optimize for this case at all |
|
953 if (NULL == inputColor) { |
|
954 builder->fsCodeAppendf("\t\tconst vec4 ones = vec4(1);\n"); |
|
955 inputColor = "ones"; |
|
956 } |
|
957 builder->fsCodeAppendf("\t\t// SkXfermode::Mode: %s\n", SkXfermode::ModeName(mode)); |
|
958 |
|
959 // These all perform src-over on the alpha channel. |
|
960 builder->fsCodeAppendf("\t\t%s.a = %s.a + (1.0 - %s.a) * %s.a;\n", |
|
961 outputColor, inputColor, inputColor, dstColor); |
|
962 |
|
963 switch (mode) { |
|
964 case SkXfermode::kOverlay_Mode: |
|
965 // Overlay is Hard-Light with the src and dst reversed |
|
966 HardLight(builder, outputColor, dstColor, inputColor); |
|
967 break; |
|
968 case SkXfermode::kDarken_Mode: |
|
969 builder->fsCodeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb, " |
|
970 "(1.0 - %s.a) * %s.rgb + %s.rgb);\n", |
|
971 outputColor, |
|
972 inputColor, dstColor, inputColor, |
|
973 dstColor, inputColor, dstColor); |
|
974 break; |
|
975 case SkXfermode::kLighten_Mode: |
|
976 builder->fsCodeAppendf("\t\t%s.rgb = max((1.0 - %s.a) * %s.rgb + %s.rgb, " |
|
977 "(1.0 - %s.a) * %s.rgb + %s.rgb);\n", |
|
978 outputColor, |
|
979 inputColor, dstColor, inputColor, |
|
980 dstColor, inputColor, dstColor); |
|
981 break; |
|
982 case SkXfermode::kColorDodge_Mode: |
|
983 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'r'); |
|
984 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'g'); |
|
985 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'b'); |
|
986 break; |
|
987 case SkXfermode::kColorBurn_Mode: |
|
988 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'r'); |
|
989 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'g'); |
|
990 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'b'); |
|
991 break; |
|
992 case SkXfermode::kHardLight_Mode: |
|
993 HardLight(builder, outputColor, inputColor, dstColor); |
|
994 break; |
|
995 case SkXfermode::kSoftLight_Mode: |
|
996 builder->fsCodeAppendf("\t\tif (0.0 == %s.a) {\n", dstColor); |
|
997 builder->fsCodeAppendf("\t\t\t%s.rgba = %s;\n", outputColor, inputColor); |
|
998 builder->fsCodeAppendf("\t\t} else {\n"); |
|
999 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'r'); |
|
1000 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'g'); |
|
1001 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'b'); |
|
1002 builder->fsCodeAppendf("\t\t}\n"); |
|
1003 break; |
|
1004 case SkXfermode::kDifference_Mode: |
|
1005 builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb -" |
|
1006 "2.0 * min(%s.rgb * %s.a, %s.rgb * %s.a);\n", |
|
1007 outputColor, inputColor, dstColor, inputColor, dstColor, |
|
1008 dstColor, inputColor); |
|
1009 break; |
|
1010 case SkXfermode::kExclusion_Mode: |
|
1011 builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb - " |
|
1012 "2.0 * %s.rgb * %s.rgb;\n", |
|
1013 outputColor, dstColor, inputColor, dstColor, inputColor); |
|
1014 break; |
|
1015 case SkXfermode::kMultiply_Mode: |
|
1016 builder->fsCodeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + " |
|
1017 "(1.0 - %s.a) * %s.rgb + " |
|
1018 "%s.rgb * %s.rgb;\n", |
|
1019 outputColor, inputColor, dstColor, dstColor, inputColor, |
|
1020 inputColor, dstColor); |
|
1021 break; |
|
1022 case SkXfermode::kHue_Mode: { |
|
1023 // SetLum(SetSat(S * Da, Sat(D * Sa)), Sa*Da, D*Sa) + (1 - Sa) * D + (1 - Da) * S |
|
1024 SkString setSat, setLum; |
|
1025 AddSatFunction(builder, &setSat); |
|
1026 AddLumFunction(builder, &setLum); |
|
1027 builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n", |
|
1028 dstColor, inputColor); |
|
1029 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(%s.rgb * %s.a, dstSrcAlpha.rgb), dstSrcAlpha.a, dstSrcAlpha.rgb);\n", |
|
1030 outputColor, setLum.c_str(), setSat.c_str(), inputColor, |
|
1031 dstColor); |
|
1032 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", |
|
1033 outputColor, inputColor, dstColor, dstColor, inputColor); |
|
1034 break; |
|
1035 } |
|
1036 case SkXfermode::kSaturation_Mode: { |
|
1037 // SetLum(SetSat(D * Sa, Sat(S * Da)), Sa*Da, D*Sa)) + (1 - Sa) * D + (1 - Da) * S |
|
1038 SkString setSat, setLum; |
|
1039 AddSatFunction(builder, &setSat); |
|
1040 AddLumFunction(builder, &setLum); |
|
1041 builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n", |
|
1042 dstColor, inputColor); |
|
1043 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.a), dstSrcAlpha.a, dstSrcAlpha.rgb);\n", |
|
1044 outputColor, setLum.c_str(), setSat.c_str(), inputColor, |
|
1045 dstColor); |
|
1046 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", |
|
1047 outputColor, inputColor, dstColor, dstColor, inputColor); |
|
1048 break; |
|
1049 } |
|
1050 case SkXfermode::kColor_Mode: { |
|
1051 // SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S |
|
1052 SkString setLum; |
|
1053 AddLumFunction(builder, &setLum); |
|
1054 builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n", |
|
1055 inputColor, dstColor); |
|
1056 builder->fsCodeAppendf("\t\t%s.rgb = %s(srcDstAlpha.rgb, srcDstAlpha.a, %s.rgb * %s.a);\n", |
|
1057 outputColor, setLum.c_str(), dstColor, inputColor); |
|
1058 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", |
|
1059 outputColor, inputColor, dstColor, dstColor, inputColor); |
|
1060 break; |
|
1061 } |
|
1062 case SkXfermode::kLuminosity_Mode: { |
|
1063 // SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S |
|
1064 SkString setLum; |
|
1065 AddLumFunction(builder, &setLum); |
|
1066 builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n", |
|
1067 inputColor, dstColor); |
|
1068 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s.rgb * %s.a, srcDstAlpha.a, srcDstAlpha.rgb);\n", |
|
1069 outputColor, setLum.c_str(), dstColor, inputColor); |
|
1070 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", |
|
1071 outputColor, inputColor, dstColor, dstColor, inputColor); |
|
1072 break; |
|
1073 } |
|
1074 default: |
|
1075 GrCrash("Unknown XferEffect mode."); |
|
1076 break; |
|
1077 } |
|
1078 } |
|
1079 |
|
1080 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { |
|
1081 return drawEffect.castEffect<XferEffect>().mode(); |
|
1082 } |
|
1083 |
|
1084 private: |
|
1085 static void HardLight(GrGLShaderBuilder* builder, |
|
1086 const char* final, |
|
1087 const char* src, |
|
1088 const char* dst) { |
|
1089 static const char kComponents[] = {'r', 'g', 'b'}; |
|
1090 for (size_t i = 0; i < SK_ARRAY_COUNT(kComponents); ++i) { |
|
1091 char component = kComponents[i]; |
|
1092 builder->fsCodeAppendf("\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src); |
|
1093 builder->fsCodeAppendf("\t\t\t%s.%c = 2.0 * %s.%c * %s.%c;\n", final, component, src, component, dst, component); |
|
1094 builder->fsCodeAppend("\t\t} else {\n"); |
|
1095 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a - 2.0 * (%s.a - %s.%c) * (%s.a - %s.%c);\n", |
|
1096 final, component, src, dst, dst, dst, component, src, src, component); |
|
1097 builder->fsCodeAppend("\t\t}\n"); |
|
1098 } |
|
1099 builder->fsCodeAppendf("\t\t%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s.a);\n", |
|
1100 final, src, dst, dst, src); |
|
1101 } |
|
1102 |
|
1103 // Does one component of color-dodge |
|
1104 static void ColorDodgeComponent(GrGLShaderBuilder* builder, |
|
1105 const char* final, |
|
1106 const char* src, |
|
1107 const char* dst, |
|
1108 const char component) { |
|
1109 builder->fsCodeAppendf("\t\tif (0.0 == %s.%c) {\n", dst, component); |
|
1110 builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n", |
|
1111 final, component, src, component, dst); |
|
1112 builder->fsCodeAppend("\t\t} else {\n"); |
|
1113 builder->fsCodeAppendf("\t\t\tfloat d = %s.a - %s.%c;\n", src, src, component); |
|
1114 builder->fsCodeAppend("\t\t\tif (0.0 == d) {\n"); |
|
1115 builder->fsCodeAppendf("\t\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", |
|
1116 final, component, src, dst, src, component, dst, dst, component, |
|
1117 src); |
|
1118 builder->fsCodeAppend("\t\t\t} else {\n"); |
|
1119 builder->fsCodeAppendf("\t\t\t\td = min(%s.a, %s.%c * %s.a / d);\n", |
|
1120 dst, dst, component, src); |
|
1121 builder->fsCodeAppendf("\t\t\t\t%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", |
|
1122 final, component, src, src, component, dst, dst, component, src); |
|
1123 builder->fsCodeAppend("\t\t\t}\n"); |
|
1124 builder->fsCodeAppend("\t\t}\n"); |
|
1125 } |
|
1126 |
|
1127 // Does one component of color-burn |
|
1128 static void ColorBurnComponent(GrGLShaderBuilder* builder, |
|
1129 const char* final, |
|
1130 const char* src, |
|
1131 const char* dst, |
|
1132 const char component) { |
|
1133 builder->fsCodeAppendf("\t\tif (%s.a == %s.%c) {\n", dst, dst, component); |
|
1134 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", |
|
1135 final, component, src, dst, src, component, dst, dst, component, |
|
1136 src); |
|
1137 builder->fsCodeAppendf("\t\t} else if (0.0 == %s.%c) {\n", src, component); |
|
1138 builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n", |
|
1139 final, component, dst, component, src); |
|
1140 builder->fsCodeAppend("\t\t} else {\n"); |
|
1141 builder->fsCodeAppendf("\t\t\tfloat d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / %s.%c);\n", |
|
1142 dst, dst, dst, component, src, src, component); |
|
1143 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", |
|
1144 final, component, src, src, component, dst, dst, component, src); |
|
1145 builder->fsCodeAppend("\t\t}\n"); |
|
1146 } |
|
1147 |
|
1148 // Does one component of soft-light. Caller should have already checked that dst alpha > 0. |
|
1149 static void SoftLightComponentPosDstAlpha(GrGLShaderBuilder* builder, |
|
1150 const char* final, |
|
1151 const char* src, |
|
1152 const char* dst, |
|
1153 const char component) { |
|
1154 // if (2S < Sa) |
|
1155 builder->fsCodeAppendf("\t\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src); |
|
1156 // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1) |
|
1157 builder->fsCodeAppendf("\t\t\t\t%s.%c = (%s.%c*%s.%c*(%s.a - 2.0*%s.%c)) / %s.a + (1.0 - %s.a) * %s.%c + %s.%c*(-%s.a + 2.0*%s.%c + 1.0);\n", |
|
1158 final, component, dst, component, dst, component, src, src, |
|
1159 component, dst, dst, src, component, dst, component, src, src, |
|
1160 component); |
|
1161 // else if (4D < Da) |
|
1162 builder->fsCodeAppendf("\t\t\t} else if (4.0 * %s.%c <= %s.a) {\n", |
|
1163 dst, component, dst); |
|
1164 builder->fsCodeAppendf("\t\t\t\tfloat DSqd = %s.%c * %s.%c;\n", |
|
1165 dst, component, dst, component); |
|
1166 builder->fsCodeAppendf("\t\t\t\tfloat DCub = DSqd * %s.%c;\n", dst, component); |
|
1167 builder->fsCodeAppendf("\t\t\t\tfloat DaSqd = %s.a * %s.a;\n", dst, dst); |
|
1168 builder->fsCodeAppendf("\t\t\t\tfloat DaCub = DaSqd * %s.a;\n", dst); |
|
1169 // (Da^3 (-S)+Da^2 (S-D (3 Sa-6 S-1))+12 Da D^2 (Sa-2 S)-16 D^3 (Sa-2 S))/Da^2 |
|
1170 builder->fsCodeAppendf("\t\t\t\t%s.%c = (-DaCub*%s.%c + DaSqd*(%s.%c - %s.%c * (3.0*%s.a - 6.0*%s.%c - 1.0)) + 12.0*%s.a*DSqd*(%s.a - 2.0*%s.%c) - 16.0*DCub * (%s.a - 2.0*%s.%c)) / DaSqd;\n", |
|
1171 final, component, src, component, src, component, dst, component, |
|
1172 src, src, component, dst, src, src, component, src, src, |
|
1173 component); |
|
1174 builder->fsCodeAppendf("\t\t\t} else {\n"); |
|
1175 // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S |
|
1176 builder->fsCodeAppendf("\t\t\t\t%s.%c = -sqrt(%s.a*%s.%c)*(%s.a - 2.0*%s.%c) - %s.a*%s.%c + %s.%c*(%s.a - 2.0*%s.%c + 1.0) + %s.%c;\n", |
|
1177 final, component, dst, dst, component, src, src, component, dst, |
|
1178 src, component, dst, component, src, src, component, src, |
|
1179 component); |
|
1180 builder->fsCodeAppendf("\t\t\t}\n"); |
|
1181 } |
|
1182 |
|
1183 // Adds a function that takes two colors and an alpha as input. It produces a color with the |
|
1184 // hue and saturation of the first color, the luminosity of the second color, and the input |
|
1185 // alpha. It has this signature: |
|
1186 // vec3 set_luminance(vec3 hueSatColor, float alpha, vec3 lumColor). |
|
1187 static void AddLumFunction(GrGLShaderBuilder* builder, SkString* setLumFunction) { |
|
1188 // Emit a helper that gets the luminance of a color. |
|
1189 SkString getFunction; |
|
1190 GrGLShaderVar getLumArgs[] = { |
|
1191 GrGLShaderVar("color", kVec3f_GrSLType), |
|
1192 }; |
|
1193 SkString getLumBody("\treturn dot(vec3(0.3, 0.59, 0.11), color);\n"); |
|
1194 builder->fsEmitFunction(kFloat_GrSLType, |
|
1195 "luminance", |
|
1196 SK_ARRAY_COUNT(getLumArgs), getLumArgs, |
|
1197 getLumBody.c_str(), |
|
1198 &getFunction); |
|
1199 |
|
1200 // Emit the set luminance function. |
|
1201 GrGLShaderVar setLumArgs[] = { |
|
1202 GrGLShaderVar("hueSat", kVec3f_GrSLType), |
|
1203 GrGLShaderVar("alpha", kFloat_GrSLType), |
|
1204 GrGLShaderVar("lumColor", kVec3f_GrSLType), |
|
1205 }; |
|
1206 SkString setLumBody; |
|
1207 setLumBody.printf("\tfloat diff = %s(lumColor - hueSat);\n", getFunction.c_str()); |
|
1208 setLumBody.append("\tvec3 outColor = hueSat + diff;\n"); |
|
1209 setLumBody.appendf("\tfloat outLum = %s(outColor);\n", getFunction.c_str()); |
|
1210 setLumBody.append("\tfloat minComp = min(min(outColor.r, outColor.g), outColor.b);\n" |
|
1211 "\tfloat maxComp = max(max(outColor.r, outColor.g), outColor.b);\n" |
|
1212 "\tif (minComp < 0.0) {\n" |
|
1213 "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * outLum) / (outLum - minComp);\n" |
|
1214 "\t}\n" |
|
1215 "\tif (maxComp > alpha) {\n" |
|
1216 "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * (alpha - outLum)) / (maxComp - outLum);\n" |
|
1217 "\t}\n" |
|
1218 "\treturn outColor;\n"); |
|
1219 builder->fsEmitFunction(kVec3f_GrSLType, |
|
1220 "set_luminance", |
|
1221 SK_ARRAY_COUNT(setLumArgs), setLumArgs, |
|
1222 setLumBody.c_str(), |
|
1223 setLumFunction); |
|
1224 } |
|
1225 |
|
1226 // Adds a function that creates a color with the hue and luminosity of one input color and |
|
1227 // the saturation of another color. It will have this signature: |
|
1228 // float set_saturation(vec3 hueLumColor, vec3 satColor) |
|
1229 static void AddSatFunction(GrGLShaderBuilder* builder, SkString* setSatFunction) { |
|
1230 // Emit a helper that gets the saturation of a color |
|
1231 SkString getFunction; |
|
1232 GrGLShaderVar getSatArgs[] = { GrGLShaderVar("color", kVec3f_GrSLType) }; |
|
1233 SkString getSatBody; |
|
1234 getSatBody.printf("\treturn max(max(color.r, color.g), color.b) - " |
|
1235 "min(min(color.r, color.g), color.b);\n"); |
|
1236 builder->fsEmitFunction(kFloat_GrSLType, |
|
1237 "saturation", |
|
1238 SK_ARRAY_COUNT(getSatArgs), getSatArgs, |
|
1239 getSatBody.c_str(), |
|
1240 &getFunction); |
|
1241 |
|
1242 // Emit a helper that sets the saturation given sorted input channels. This used |
|
1243 // to use inout params for min, mid, and max components but that seems to cause |
|
1244 // problems on PowerVR drivers. So instead it returns a vec3 where r, g ,b are the |
|
1245 // adjusted min, mid, and max inputs, respectively. |
|
1246 SkString helperFunction; |
|
1247 GrGLShaderVar helperArgs[] = { |
|
1248 GrGLShaderVar("minComp", kFloat_GrSLType), |
|
1249 GrGLShaderVar("midComp", kFloat_GrSLType), |
|
1250 GrGLShaderVar("maxComp", kFloat_GrSLType), |
|
1251 GrGLShaderVar("sat", kFloat_GrSLType), |
|
1252 }; |
|
1253 static const char kHelperBody[] = "\tif (minComp < maxComp) {\n" |
|
1254 "\t\tvec3 result;\n" |
|
1255 "\t\tresult.r = 0.0;\n" |
|
1256 "\t\tresult.g = sat * (midComp - minComp) / (maxComp - minComp);\n" |
|
1257 "\t\tresult.b = sat;\n" |
|
1258 "\t\treturn result;\n" |
|
1259 "\t} else {\n" |
|
1260 "\t\treturn vec3(0, 0, 0);\n" |
|
1261 "\t}\n"; |
|
1262 builder->fsEmitFunction(kVec3f_GrSLType, |
|
1263 "set_saturation_helper", |
|
1264 SK_ARRAY_COUNT(helperArgs), helperArgs, |
|
1265 kHelperBody, |
|
1266 &helperFunction); |
|
1267 |
|
1268 GrGLShaderVar setSatArgs[] = { |
|
1269 GrGLShaderVar("hueLumColor", kVec3f_GrSLType), |
|
1270 GrGLShaderVar("satColor", kVec3f_GrSLType), |
|
1271 }; |
|
1272 const char* helpFunc = helperFunction.c_str(); |
|
1273 SkString setSatBody; |
|
1274 setSatBody.appendf("\tfloat sat = %s(satColor);\n" |
|
1275 "\tif (hueLumColor.r <= hueLumColor.g) {\n" |
|
1276 "\t\tif (hueLumColor.g <= hueLumColor.b) {\n" |
|
1277 "\t\t\thueLumColor.rgb = %s(hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);\n" |
|
1278 "\t\t} else if (hueLumColor.r <= hueLumColor.b) {\n" |
|
1279 "\t\t\thueLumColor.rbg = %s(hueLumColor.r, hueLumColor.b, hueLumColor.g, sat);\n" |
|
1280 "\t\t} else {\n" |
|
1281 "\t\t\thueLumColor.brg = %s(hueLumColor.b, hueLumColor.r, hueLumColor.g, sat);\n" |
|
1282 "\t\t}\n" |
|
1283 "\t} else if (hueLumColor.r <= hueLumColor.b) {\n" |
|
1284 "\t\thueLumColor.grb = %s(hueLumColor.g, hueLumColor.r, hueLumColor.b, sat);\n" |
|
1285 "\t} else if (hueLumColor.g <= hueLumColor.b) {\n" |
|
1286 "\t\thueLumColor.gbr = %s(hueLumColor.g, hueLumColor.b, hueLumColor.r, sat);\n" |
|
1287 "\t} else {\n" |
|
1288 "\t\thueLumColor.bgr = %s(hueLumColor.b, hueLumColor.g, hueLumColor.r, sat);\n" |
|
1289 "\t}\n" |
|
1290 "\treturn hueLumColor;\n", |
|
1291 getFunction.c_str(), helpFunc, helpFunc, helpFunc, helpFunc, |
|
1292 helpFunc, helpFunc); |
|
1293 builder->fsEmitFunction(kVec3f_GrSLType, |
|
1294 "set_saturation", |
|
1295 SK_ARRAY_COUNT(setSatArgs), setSatArgs, |
|
1296 setSatBody.c_str(), |
|
1297 setSatFunction); |
|
1298 |
|
1299 } |
|
1300 |
|
1301 typedef GrGLEffect INHERITED; |
|
1302 }; |
|
1303 |
|
1304 GR_DECLARE_EFFECT_TEST; |
|
1305 |
|
1306 private: |
|
1307 XferEffect(SkXfermode::Mode mode, GrTexture* background) |
|
1308 : fMode(mode) { |
|
1309 if (background) { |
|
1310 fBackgroundTransform.reset(kLocal_GrCoordSet, background); |
|
1311 this->addCoordTransform(&fBackgroundTransform); |
|
1312 fBackgroundAccess.reset(background); |
|
1313 this->addTextureAccess(&fBackgroundAccess); |
|
1314 } else { |
|
1315 this->setWillReadDstColor(); |
|
1316 } |
|
1317 } |
|
1318 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { |
|
1319 const XferEffect& s = CastEffect<XferEffect>(other); |
|
1320 return fMode == s.fMode && |
|
1321 fBackgroundAccess.getTexture() == s.fBackgroundAccess.getTexture(); |
|
1322 } |
|
1323 |
|
1324 SkXfermode::Mode fMode; |
|
1325 GrCoordTransform fBackgroundTransform; |
|
1326 GrTextureAccess fBackgroundAccess; |
|
1327 |
|
1328 typedef GrEffect INHERITED; |
|
1329 }; |
|
1330 |
|
1331 GR_DEFINE_EFFECT_TEST(XferEffect); |
|
1332 GrEffectRef* XferEffect::TestCreate(SkRandom* rand, |
|
1333 GrContext*, |
|
1334 const GrDrawTargetCaps&, |
|
1335 GrTexture*[]) { |
|
1336 int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLastSeparableMode); |
|
1337 |
|
1338 AutoEffectUnref gEffect(SkNEW_ARGS(XferEffect, (static_cast<SkXfermode::Mode>(mode), NULL))); |
|
1339 return CreateEffectRef(gEffect); |
|
1340 } |
|
1341 |
|
1342 #endif |
|
1343 |
|
1344 /////////////////////////////////////////////////////////////////////////////// |
|
1345 /////////////////////////////////////////////////////////////////////////////// |
|
1346 |
|
1347 SkProcCoeffXfermode::SkProcCoeffXfermode(SkReadBuffer& buffer) : INHERITED(buffer) { |
|
1348 uint32_t mode32 = buffer.read32() % SK_ARRAY_COUNT(gProcCoeffs); |
|
1349 if (mode32 >= SK_ARRAY_COUNT(gProcCoeffs)) { |
|
1350 // out of range, just set to something harmless |
|
1351 mode32 = SkXfermode::kSrcOut_Mode; |
|
1352 } |
|
1353 fMode = (SkXfermode::Mode)mode32; |
|
1354 |
|
1355 const ProcCoeff& rec = gProcCoeffs[fMode]; |
|
1356 // these may be valid, or may be CANNOT_USE_COEFF |
|
1357 fSrcCoeff = rec.fSC; |
|
1358 fDstCoeff = rec.fDC; |
|
1359 // now update our function-ptr in the super class |
|
1360 this->INHERITED::setProc(rec.fProc); |
|
1361 } |
|
1362 |
|
1363 bool SkProcCoeffXfermode::asMode(Mode* mode) const { |
|
1364 if (mode) { |
|
1365 *mode = fMode; |
|
1366 } |
|
1367 return true; |
|
1368 } |
|
1369 |
|
1370 bool SkProcCoeffXfermode::asCoeff(Coeff* sc, Coeff* dc) const { |
|
1371 if (CANNOT_USE_COEFF == fSrcCoeff) { |
|
1372 return false; |
|
1373 } |
|
1374 |
|
1375 if (sc) { |
|
1376 *sc = fSrcCoeff; |
|
1377 } |
|
1378 if (dc) { |
|
1379 *dc = fDstCoeff; |
|
1380 } |
|
1381 return true; |
|
1382 } |
|
1383 |
|
1384 #if SK_SUPPORT_GPU |
|
1385 bool SkProcCoeffXfermode::asNewEffect(GrEffectRef** effect, |
|
1386 GrTexture* background) const { |
|
1387 if (XferEffect::IsSupportedMode(fMode)) { |
|
1388 if (NULL != effect) { |
|
1389 *effect = XferEffect::Create(fMode, background); |
|
1390 SkASSERT(NULL != *effect); |
|
1391 } |
|
1392 return true; |
|
1393 } |
|
1394 return false; |
|
1395 } |
|
1396 #endif |
|
1397 |
|
1398 void SkProcCoeffXfermode::flatten(SkWriteBuffer& buffer) const { |
|
1399 this->INHERITED::flatten(buffer); |
|
1400 buffer.write32(fMode); |
|
1401 } |
|
1402 |
|
1403 const char* SkXfermode::ModeName(Mode mode) { |
|
1404 SkASSERT((unsigned) mode <= (unsigned)kLastMode); |
|
1405 const char* gModeStrings[] = { |
|
1406 "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn", |
|
1407 "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus", |
|
1408 "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge", |
|
1409 "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion", |
|
1410 "Multiply", "Hue", "Saturation", "Color", "Luminosity" |
|
1411 }; |
|
1412 return gModeStrings[mode]; |
|
1413 SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count); |
|
1414 } |
|
1415 |
|
1416 #ifndef SK_IGNORE_TO_STRING |
|
1417 void SkProcCoeffXfermode::toString(SkString* str) const { |
|
1418 str->append("SkProcCoeffXfermode: "); |
|
1419 |
|
1420 str->append("mode: "); |
|
1421 str->append(ModeName(fMode)); |
|
1422 |
|
1423 static const char* gCoeffStrings[kCoeffCount] = { |
|
1424 "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA" |
|
1425 }; |
|
1426 |
|
1427 str->append(" src: "); |
|
1428 if (CANNOT_USE_COEFF == fSrcCoeff) { |
|
1429 str->append("can't use"); |
|
1430 } else { |
|
1431 str->append(gCoeffStrings[fSrcCoeff]); |
|
1432 } |
|
1433 |
|
1434 str->append(" dst: "); |
|
1435 if (CANNOT_USE_COEFF == fDstCoeff) { |
|
1436 str->append("can't use"); |
|
1437 } else { |
|
1438 str->append(gCoeffStrings[fDstCoeff]); |
|
1439 } |
|
1440 } |
|
1441 #endif |
|
1442 |
|
1443 /////////////////////////////////////////////////////////////////////////////// |
|
1444 |
|
1445 class SkClearXfermode : public SkProcCoeffXfermode { |
|
1446 public: |
|
1447 static SkClearXfermode* Create(const ProcCoeff& rec) { |
|
1448 return SkNEW_ARGS(SkClearXfermode, (rec)); |
|
1449 } |
|
1450 |
|
1451 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; |
|
1452 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; |
|
1453 |
|
1454 SK_TO_STRING_OVERRIDE() |
|
1455 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkClearXfermode) |
|
1456 |
|
1457 private: |
|
1458 SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {} |
|
1459 SkClearXfermode(SkReadBuffer& buffer) |
|
1460 : SkProcCoeffXfermode(buffer) {} |
|
1461 |
|
1462 typedef SkProcCoeffXfermode INHERITED; |
|
1463 }; |
|
1464 |
|
1465 void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst, |
|
1466 const SkPMColor* SK_RESTRICT, int count, |
|
1467 const SkAlpha* SK_RESTRICT aa) const { |
|
1468 SkASSERT(dst && count >= 0); |
|
1469 |
|
1470 if (NULL == aa) { |
|
1471 memset(dst, 0, count << 2); |
|
1472 } else { |
|
1473 for (int i = count - 1; i >= 0; --i) { |
|
1474 unsigned a = aa[i]; |
|
1475 if (0xFF == a) { |
|
1476 dst[i] = 0; |
|
1477 } else if (a != 0) { |
|
1478 dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a)); |
|
1479 } |
|
1480 } |
|
1481 } |
|
1482 } |
|
1483 void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst, |
|
1484 const SkPMColor* SK_RESTRICT, int count, |
|
1485 const SkAlpha* SK_RESTRICT aa) const { |
|
1486 SkASSERT(dst && count >= 0); |
|
1487 |
|
1488 if (NULL == aa) { |
|
1489 memset(dst, 0, count); |
|
1490 } else { |
|
1491 for (int i = count - 1; i >= 0; --i) { |
|
1492 unsigned a = aa[i]; |
|
1493 if (0xFF == a) { |
|
1494 dst[i] = 0; |
|
1495 } else if (0 != a) { |
|
1496 dst[i] = SkAlphaMulAlpha(dst[i], 255 - a); |
|
1497 } |
|
1498 } |
|
1499 } |
|
1500 } |
|
1501 |
|
1502 #ifndef SK_IGNORE_TO_STRING |
|
1503 void SkClearXfermode::toString(SkString* str) const { |
|
1504 this->INHERITED::toString(str); |
|
1505 } |
|
1506 #endif |
|
1507 |
|
1508 /////////////////////////////////////////////////////////////////////////////// |
|
1509 |
|
1510 class SkSrcXfermode : public SkProcCoeffXfermode { |
|
1511 public: |
|
1512 static SkSrcXfermode* Create(const ProcCoeff& rec) { |
|
1513 return SkNEW_ARGS(SkSrcXfermode, (rec)); |
|
1514 } |
|
1515 |
|
1516 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; |
|
1517 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; |
|
1518 |
|
1519 SK_TO_STRING_OVERRIDE() |
|
1520 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSrcXfermode) |
|
1521 |
|
1522 private: |
|
1523 SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {} |
|
1524 SkSrcXfermode(SkReadBuffer& buffer) |
|
1525 : SkProcCoeffXfermode(buffer) {} |
|
1526 |
|
1527 typedef SkProcCoeffXfermode INHERITED; |
|
1528 }; |
|
1529 |
|
1530 void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst, |
|
1531 const SkPMColor* SK_RESTRICT src, int count, |
|
1532 const SkAlpha* SK_RESTRICT aa) const { |
|
1533 SkASSERT(dst && src && count >= 0); |
|
1534 |
|
1535 if (NULL == aa) { |
|
1536 memcpy(dst, src, count << 2); |
|
1537 } else { |
|
1538 for (int i = count - 1; i >= 0; --i) { |
|
1539 unsigned a = aa[i]; |
|
1540 if (a == 0xFF) { |
|
1541 dst[i] = src[i]; |
|
1542 } else if (a != 0) { |
|
1543 dst[i] = SkFourByteInterp(src[i], dst[i], a); |
|
1544 } |
|
1545 } |
|
1546 } |
|
1547 } |
|
1548 |
|
1549 void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst, |
|
1550 const SkPMColor* SK_RESTRICT src, int count, |
|
1551 const SkAlpha* SK_RESTRICT aa) const { |
|
1552 SkASSERT(dst && src && count >= 0); |
|
1553 |
|
1554 if (NULL == aa) { |
|
1555 for (int i = count - 1; i >= 0; --i) { |
|
1556 dst[i] = SkToU8(SkGetPackedA32(src[i])); |
|
1557 } |
|
1558 } else { |
|
1559 for (int i = count - 1; i >= 0; --i) { |
|
1560 unsigned a = aa[i]; |
|
1561 if (0 != a) { |
|
1562 unsigned srcA = SkGetPackedA32(src[i]); |
|
1563 if (a == 0xFF) { |
|
1564 dst[i] = SkToU8(srcA); |
|
1565 } else { |
|
1566 dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a)); |
|
1567 } |
|
1568 } |
|
1569 } |
|
1570 } |
|
1571 } |
|
1572 #ifndef SK_IGNORE_TO_STRING |
|
1573 void SkSrcXfermode::toString(SkString* str) const { |
|
1574 this->INHERITED::toString(str); |
|
1575 } |
|
1576 #endif |
|
1577 |
|
1578 /////////////////////////////////////////////////////////////////////////////// |
|
1579 |
|
1580 class SkDstInXfermode : public SkProcCoeffXfermode { |
|
1581 public: |
|
1582 static SkDstInXfermode* Create(const ProcCoeff& rec) { |
|
1583 return SkNEW_ARGS(SkDstInXfermode, (rec)); |
|
1584 } |
|
1585 |
|
1586 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; |
|
1587 |
|
1588 SK_TO_STRING_OVERRIDE() |
|
1589 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstInXfermode) |
|
1590 |
|
1591 private: |
|
1592 SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {} |
|
1593 SkDstInXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {} |
|
1594 |
|
1595 typedef SkProcCoeffXfermode INHERITED; |
|
1596 }; |
|
1597 |
|
1598 void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst, |
|
1599 const SkPMColor* SK_RESTRICT src, int count, |
|
1600 const SkAlpha* SK_RESTRICT aa) const { |
|
1601 SkASSERT(dst && src); |
|
1602 |
|
1603 if (count <= 0) { |
|
1604 return; |
|
1605 } |
|
1606 if (NULL != aa) { |
|
1607 return this->INHERITED::xfer32(dst, src, count, aa); |
|
1608 } |
|
1609 |
|
1610 do { |
|
1611 unsigned a = SkGetPackedA32(*src); |
|
1612 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a)); |
|
1613 dst++; |
|
1614 src++; |
|
1615 } while (--count != 0); |
|
1616 } |
|
1617 |
|
1618 #ifndef SK_IGNORE_TO_STRING |
|
1619 void SkDstInXfermode::toString(SkString* str) const { |
|
1620 this->INHERITED::toString(str); |
|
1621 } |
|
1622 #endif |
|
1623 |
|
1624 /////////////////////////////////////////////////////////////////////////////// |
|
1625 |
|
1626 class SkDstOutXfermode : public SkProcCoeffXfermode { |
|
1627 public: |
|
1628 static SkDstOutXfermode* Create(const ProcCoeff& rec) { |
|
1629 return SkNEW_ARGS(SkDstOutXfermode, (rec)); |
|
1630 } |
|
1631 |
|
1632 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; |
|
1633 |
|
1634 SK_TO_STRING_OVERRIDE() |
|
1635 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstOutXfermode) |
|
1636 |
|
1637 private: |
|
1638 SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {} |
|
1639 SkDstOutXfermode(SkReadBuffer& buffer) |
|
1640 : INHERITED(buffer) {} |
|
1641 |
|
1642 typedef SkProcCoeffXfermode INHERITED; |
|
1643 }; |
|
1644 |
|
1645 void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst, |
|
1646 const SkPMColor* SK_RESTRICT src, int count, |
|
1647 const SkAlpha* SK_RESTRICT aa) const { |
|
1648 SkASSERT(dst && src); |
|
1649 |
|
1650 if (count <= 0) { |
|
1651 return; |
|
1652 } |
|
1653 if (NULL != aa) { |
|
1654 return this->INHERITED::xfer32(dst, src, count, aa); |
|
1655 } |
|
1656 |
|
1657 do { |
|
1658 unsigned a = SkGetPackedA32(*src); |
|
1659 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a)); |
|
1660 dst++; |
|
1661 src++; |
|
1662 } while (--count != 0); |
|
1663 } |
|
1664 |
|
1665 #ifndef SK_IGNORE_TO_STRING |
|
1666 void SkDstOutXfermode::toString(SkString* str) const { |
|
1667 this->INHERITED::toString(str); |
|
1668 } |
|
1669 #endif |
|
1670 |
|
1671 /////////////////////////////////////////////////////////////////////////////// |
|
1672 |
|
1673 SK_DECLARE_STATIC_MUTEX(gCachedXfermodesMutex); |
|
1674 static SkXfermode* gCachedXfermodes[SkXfermode::kLastMode + 1]; |
|
1675 |
|
1676 void SkXfermode::Term() { |
|
1677 SkAutoMutexAcquire ac(gCachedXfermodesMutex); |
|
1678 |
|
1679 for (size_t i = 0; i < SK_ARRAY_COUNT(gCachedXfermodes); ++i) { |
|
1680 SkSafeUnref(gCachedXfermodes[i]); |
|
1681 gCachedXfermodes[i] = NULL; |
|
1682 } |
|
1683 } |
|
1684 |
|
1685 extern SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec, |
|
1686 SkXfermode::Mode mode); |
|
1687 extern SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode); |
|
1688 |
|
1689 SkXfermode* SkXfermode::Create(Mode mode) { |
|
1690 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount); |
|
1691 SkASSERT(SK_ARRAY_COUNT(gCachedXfermodes) == kModeCount); |
|
1692 |
|
1693 if ((unsigned)mode >= kModeCount) { |
|
1694 // report error |
|
1695 return NULL; |
|
1696 } |
|
1697 |
|
1698 // Skia's "defaut" mode is srcover. NULL in SkPaint is interpreted as srcover |
|
1699 // so we can just return NULL from the factory. |
|
1700 if (kSrcOver_Mode == mode) { |
|
1701 return NULL; |
|
1702 } |
|
1703 |
|
1704 // guard our access to gCachedXfermodes, since we may write into it |
|
1705 SkAutoMutexAcquire ac(gCachedXfermodesMutex); |
|
1706 |
|
1707 SkXfermode* xfer = gCachedXfermodes[mode]; |
|
1708 if (NULL == xfer) { |
|
1709 ProcCoeff rec = gProcCoeffs[mode]; |
|
1710 |
|
1711 SkXfermodeProc pp = SkPlatformXfermodeProcFactory(mode); |
|
1712 |
|
1713 if (pp != NULL) { |
|
1714 rec.fProc = pp; |
|
1715 } |
|
1716 |
|
1717 // check if we have a platform optim for that |
|
1718 SkProcCoeffXfermode* xfm = SkPlatformXfermodeFactory(rec, mode); |
|
1719 if (xfm != NULL) { |
|
1720 xfer = xfm; |
|
1721 } else { |
|
1722 // All modes can in theory be represented by the ProcCoeff rec, since |
|
1723 // it contains function ptrs. However, a few modes are both simple and |
|
1724 // commonly used, so we call those out for their own subclasses here. |
|
1725 switch (mode) { |
|
1726 case kClear_Mode: |
|
1727 xfer = SkClearXfermode::Create(rec); |
|
1728 break; |
|
1729 case kSrc_Mode: |
|
1730 xfer = SkSrcXfermode::Create(rec); |
|
1731 break; |
|
1732 case kSrcOver_Mode: |
|
1733 SkASSERT(false); // should not land here |
|
1734 break; |
|
1735 case kDstIn_Mode: |
|
1736 xfer = SkDstInXfermode::Create(rec); |
|
1737 break; |
|
1738 case kDstOut_Mode: |
|
1739 xfer = SkDstOutXfermode::Create(rec); |
|
1740 break; |
|
1741 default: |
|
1742 // no special-case, just rely in the rec and its function-ptrs |
|
1743 xfer = SkProcCoeffXfermode::Create(rec, mode); |
|
1744 break; |
|
1745 } |
|
1746 } |
|
1747 gCachedXfermodes[mode] = xfer; |
|
1748 } |
|
1749 return SkSafeRef(xfer); |
|
1750 } |
|
1751 |
|
1752 SkXfermodeProc SkXfermode::GetProc(Mode mode) { |
|
1753 SkXfermodeProc proc = NULL; |
|
1754 if ((unsigned)mode < kModeCount) { |
|
1755 proc = gProcCoeffs[mode].fProc; |
|
1756 } |
|
1757 return proc; |
|
1758 } |
|
1759 |
|
1760 bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) { |
|
1761 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount); |
|
1762 |
|
1763 if ((unsigned)mode >= (unsigned)kModeCount) { |
|
1764 // illegal mode parameter |
|
1765 return false; |
|
1766 } |
|
1767 |
|
1768 const ProcCoeff& rec = gProcCoeffs[mode]; |
|
1769 |
|
1770 if (CANNOT_USE_COEFF == rec.fSC) { |
|
1771 return false; |
|
1772 } |
|
1773 |
|
1774 SkASSERT(CANNOT_USE_COEFF != rec.fDC); |
|
1775 if (src) { |
|
1776 *src = rec.fSC; |
|
1777 } |
|
1778 if (dst) { |
|
1779 *dst = rec.fDC; |
|
1780 } |
|
1781 return true; |
|
1782 } |
|
1783 |
|
1784 bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) { |
|
1785 if (NULL == xfer) { |
|
1786 if (mode) { |
|
1787 *mode = kSrcOver_Mode; |
|
1788 } |
|
1789 return true; |
|
1790 } |
|
1791 return xfer->asMode(mode); |
|
1792 } |
|
1793 |
|
1794 bool SkXfermode::AsCoeff(const SkXfermode* xfer, Coeff* src, Coeff* dst) { |
|
1795 if (NULL == xfer) { |
|
1796 return ModeAsCoeff(kSrcOver_Mode, src, dst); |
|
1797 } |
|
1798 return xfer->asCoeff(src, dst); |
|
1799 } |
|
1800 |
|
1801 bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) { |
|
1802 // if xfer==null then the mode is srcover |
|
1803 Mode m = kSrcOver_Mode; |
|
1804 if (xfer && !xfer->asMode(&m)) { |
|
1805 return false; |
|
1806 } |
|
1807 return mode == m; |
|
1808 } |
|
1809 |
|
1810 /////////////////////////////////////////////////////////////////////////////// |
|
1811 //////////// 16bit xfermode procs |
|
1812 |
|
1813 #ifdef SK_DEBUG |
|
1814 static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; } |
|
1815 static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; } |
|
1816 #endif |
|
1817 |
|
1818 static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) { |
|
1819 SkASSERT(require_255(src)); |
|
1820 return SkPixel32ToPixel16(src); |
|
1821 } |
|
1822 |
|
1823 static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) { |
|
1824 return dst; |
|
1825 } |
|
1826 |
|
1827 static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) { |
|
1828 SkASSERT(require_0(src)); |
|
1829 return dst; |
|
1830 } |
|
1831 |
|
1832 static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) { |
|
1833 SkASSERT(require_255(src)); |
|
1834 return SkPixel32ToPixel16(src); |
|
1835 } |
|
1836 |
|
1837 static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) { |
|
1838 SkASSERT(require_0(src)); |
|
1839 return dst; |
|
1840 } |
|
1841 |
|
1842 static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) { |
|
1843 SkASSERT(require_255(src)); |
|
1844 return dst; |
|
1845 } |
|
1846 |
|
1847 static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) { |
|
1848 SkASSERT(require_255(src)); |
|
1849 return SkPixel32ToPixel16(src); |
|
1850 } |
|
1851 |
|
1852 static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) { |
|
1853 SkASSERT(require_255(src)); |
|
1854 return dst; |
|
1855 } |
|
1856 |
|
1857 static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) { |
|
1858 SkASSERT(require_0(src)); |
|
1859 return dst; |
|
1860 } |
|
1861 |
|
1862 static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) { |
|
1863 unsigned isa = 255 - SkGetPackedA32(src); |
|
1864 |
|
1865 return SkPackRGB16( |
|
1866 SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa), |
|
1867 SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa), |
|
1868 SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa)); |
|
1869 } |
|
1870 |
|
1871 static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) { |
|
1872 SkASSERT(require_0(src)); |
|
1873 return dst; |
|
1874 } |
|
1875 |
|
1876 static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) { |
|
1877 SkASSERT(require_255(src)); |
|
1878 return SkPixel32ToPixel16(src); |
|
1879 } |
|
1880 |
|
1881 static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) { |
|
1882 SkASSERT(require_255(src)); |
|
1883 return dst; |
|
1884 } |
|
1885 |
|
1886 /********* |
|
1887 darken and lighten boil down to this. |
|
1888 |
|
1889 darken = (1 - Sa) * Dc + min(Sc, Dc) |
|
1890 lighten = (1 - Sa) * Dc + max(Sc, Dc) |
|
1891 |
|
1892 if (Sa == 0) these become |
|
1893 darken = Dc + min(0, Dc) = 0 |
|
1894 lighten = Dc + max(0, Dc) = Dc |
|
1895 |
|
1896 if (Sa == 1) these become |
|
1897 darken = min(Sc, Dc) |
|
1898 lighten = max(Sc, Dc) |
|
1899 */ |
|
1900 |
|
1901 static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) { |
|
1902 SkASSERT(require_0(src)); |
|
1903 return 0; |
|
1904 } |
|
1905 |
|
1906 static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) { |
|
1907 SkASSERT(require_255(src)); |
|
1908 unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst)); |
|
1909 unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst)); |
|
1910 unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst)); |
|
1911 return SkPackRGB16(r, g, b); |
|
1912 } |
|
1913 |
|
1914 static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) { |
|
1915 SkASSERT(require_0(src)); |
|
1916 return dst; |
|
1917 } |
|
1918 |
|
1919 static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) { |
|
1920 SkASSERT(require_255(src)); |
|
1921 unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst)); |
|
1922 unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst)); |
|
1923 unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst)); |
|
1924 return SkPackRGB16(r, g, b); |
|
1925 } |
|
1926 |
|
1927 struct Proc16Rec { |
|
1928 SkXfermodeProc16 fProc16_0; |
|
1929 SkXfermodeProc16 fProc16_255; |
|
1930 SkXfermodeProc16 fProc16_General; |
|
1931 }; |
|
1932 |
|
1933 static const Proc16Rec gModeProcs16[] = { |
|
1934 { NULL, NULL, NULL }, // CLEAR |
|
1935 { NULL, src_modeproc16_255, NULL }, |
|
1936 { dst_modeproc16, dst_modeproc16, dst_modeproc16 }, |
|
1937 { srcover_modeproc16_0, srcover_modeproc16_255, NULL }, |
|
1938 { dstover_modeproc16_0, dstover_modeproc16_255, NULL }, |
|
1939 { NULL, srcin_modeproc16_255, NULL }, |
|
1940 { NULL, dstin_modeproc16_255, NULL }, |
|
1941 { NULL, NULL, NULL },// SRC_OUT |
|
1942 { dstout_modeproc16_0, NULL, NULL }, |
|
1943 { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16 }, |
|
1944 { NULL, dstatop_modeproc16_255, NULL }, |
|
1945 { NULL, NULL, NULL }, // XOR |
|
1946 |
|
1947 { NULL, NULL, NULL }, // plus |
|
1948 { NULL, NULL, NULL }, // modulate |
|
1949 { NULL, NULL, NULL }, // screen |
|
1950 { NULL, NULL, NULL }, // overlay |
|
1951 { darken_modeproc16_0, darken_modeproc16_255, NULL }, // darken |
|
1952 { lighten_modeproc16_0, lighten_modeproc16_255, NULL }, // lighten |
|
1953 { NULL, NULL, NULL }, // colordodge |
|
1954 { NULL, NULL, NULL }, // colorburn |
|
1955 { NULL, NULL, NULL }, // hardlight |
|
1956 { NULL, NULL, NULL }, // softlight |
|
1957 { NULL, NULL, NULL }, // difference |
|
1958 { NULL, NULL, NULL }, // exclusion |
|
1959 { NULL, NULL, NULL }, // multiply |
|
1960 { NULL, NULL, NULL }, // hue |
|
1961 { NULL, NULL, NULL }, // saturation |
|
1962 { NULL, NULL, NULL }, // color |
|
1963 { NULL, NULL, NULL }, // luminosity |
|
1964 }; |
|
1965 |
|
1966 SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) { |
|
1967 SkXfermodeProc16 proc16 = NULL; |
|
1968 if ((unsigned)mode < kModeCount) { |
|
1969 const Proc16Rec& rec = gModeProcs16[mode]; |
|
1970 unsigned a = SkColorGetA(srcColor); |
|
1971 |
|
1972 if (0 == a) { |
|
1973 proc16 = rec.fProc16_0; |
|
1974 } else if (255 == a) { |
|
1975 proc16 = rec.fProc16_255; |
|
1976 } else { |
|
1977 proc16 = rec.fProc16_General; |
|
1978 } |
|
1979 } |
|
1980 return proc16; |
|
1981 } |
|
1982 |
|
1983 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode) |
|
1984 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode) |
|
1985 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode) |
|
1986 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode) |
|
1987 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode) |
|
1988 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode) |
|
1989 #if !SK_ARM_NEON_IS_NONE |
|
1990 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkNEONProcCoeffXfermode) |
|
1991 #endif |
|
1992 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |