Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / effects / SkArithmeticMode.cpp
1 /*
2  * Copyright 2013 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 "SkArithmeticMode.h"
9 #include "SkColorPriv.h"
10 #include "SkReadBuffer.h"
11 #include "SkWriteBuffer.h"
12 #include "SkString.h"
13 #include "SkUnPreMultiply.h"
14 #if SK_SUPPORT_GPU
15 #include "GrContext.h"
16 #include "GrCoordTransform.h"
17 #include "gl/GrGLProcessor.h"
18 #include "gl/builders/GrGLProgramBuilder.h"
19 #include "GrTBackendProcessorFactory.h"
20 #endif
21
22 static const bool gUseUnpremul = false;
23
24 class SkArithmeticMode_scalar : public SkXfermode {
25 public:
26     static SkArithmeticMode_scalar* Create(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4,
27                                            bool enforcePMColor) {
28         return SkNEW_ARGS(SkArithmeticMode_scalar, (k1, k2, k3, k4, enforcePMColor));
29     }
30
31     virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
32                         const SkAlpha aa[]) const SK_OVERRIDE;
33
34     SK_TO_STRING_OVERRIDE()
35     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkArithmeticMode_scalar)
36
37 #if SK_SUPPORT_GPU
38     virtual bool asFragmentProcessor(GrFragmentProcessor**,
39                                      GrTexture* background) const SK_OVERRIDE;
40 #endif
41
42 private:
43     SkArithmeticMode_scalar(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4, bool enforcePMColor) {
44         fK[0] = k1;
45         fK[1] = k2;
46         fK[2] = k3;
47         fK[3] = k4;
48         fEnforcePMColor = enforcePMColor;
49     }
50
51 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
52     SkArithmeticMode_scalar(SkReadBuffer& buffer) : INHERITED(buffer) {
53         fK[0] = buffer.readScalar();
54         fK[1] = buffer.readScalar();
55         fK[2] = buffer.readScalar();
56         fK[3] = buffer.readScalar();
57         fEnforcePMColor = buffer.readBool();
58     }
59 #endif
60
61     virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE {
62         buffer.writeScalar(fK[0]);
63         buffer.writeScalar(fK[1]);
64         buffer.writeScalar(fK[2]);
65         buffer.writeScalar(fK[3]);
66         buffer.writeBool(fEnforcePMColor);
67     }
68     SkScalar fK[4];
69     bool fEnforcePMColor;
70
71     friend class SkArithmeticMode;
72
73     typedef SkXfermode INHERITED;
74 };
75
76 SkFlattenable* SkArithmeticMode_scalar::CreateProc(SkReadBuffer& buffer) {
77     const SkScalar k1 = buffer.readScalar();
78     const SkScalar k2 = buffer.readScalar();
79     const SkScalar k3 = buffer.readScalar();
80     const SkScalar k4 = buffer.readScalar();
81     const bool enforcePMColor = buffer.readBool();
82     return Create(k1, k2, k3, k4, enforcePMColor);
83 }
84
85 static int pinToByte(int value) {
86     if (value < 0) {
87         value = 0;
88     } else if (value > 255) {
89         value = 255;
90     }
91     return value;
92 }
93
94 static int arith(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4,
95                  int src, int dst) {
96     SkScalar result = SkScalarMul(k1, src * dst) +
97                       SkScalarMul(k2, src) +
98                       SkScalarMul(k3, dst) +
99                       k4;
100     int res = SkScalarRoundToInt(result);
101     return pinToByte(res);
102 }
103
104 static int blend(int src, int dst, int scale) {
105     return dst + ((src - dst) * scale >> 8);
106 }
107
108 static bool needsUnpremul(int alpha) {
109     return 0 != alpha && 0xFF != alpha;
110 }
111
112 void SkArithmeticMode_scalar::xfer32(SkPMColor dst[], const SkPMColor src[],
113                                  int count, const SkAlpha aaCoverage[]) const {
114     SkScalar k1 = fK[0] / 255;
115     SkScalar k2 = fK[1];
116     SkScalar k3 = fK[2];
117     SkScalar k4 = fK[3] * 255;
118
119     for (int i = 0; i < count; ++i) {
120         if ((NULL == aaCoverage) || aaCoverage[i]) {
121             SkPMColor sc = src[i];
122             SkPMColor dc = dst[i];
123
124             int a, r, g, b;
125
126             if (gUseUnpremul) {
127                 int sa = SkGetPackedA32(sc);
128                 int da = SkGetPackedA32(dc);
129
130                 int srcNeedsUnpremul = needsUnpremul(sa);
131                 int dstNeedsUnpremul = needsUnpremul(da);
132
133                 if (!srcNeedsUnpremul && !dstNeedsUnpremul) {
134                     a = arith(k1, k2, k3, k4, sa, da);
135                     r = arith(k1, k2, k3, k4, SkGetPackedR32(sc), SkGetPackedR32(dc));
136                     g = arith(k1, k2, k3, k4, SkGetPackedG32(sc), SkGetPackedG32(dc));
137                     b = arith(k1, k2, k3, k4, SkGetPackedB32(sc), SkGetPackedB32(dc));
138                 } else {
139                     int sr = SkGetPackedR32(sc);
140                     int sg = SkGetPackedG32(sc);
141                     int sb = SkGetPackedB32(sc);
142                     if (srcNeedsUnpremul) {
143                         SkUnPreMultiply::Scale scale = SkUnPreMultiply::GetScale(sa);
144                         sr = SkUnPreMultiply::ApplyScale(scale, sr);
145                         sg = SkUnPreMultiply::ApplyScale(scale, sg);
146                         sb = SkUnPreMultiply::ApplyScale(scale, sb);
147                     }
148
149                     int dr = SkGetPackedR32(dc);
150                     int dg = SkGetPackedG32(dc);
151                     int db = SkGetPackedB32(dc);
152                     if (dstNeedsUnpremul) {
153                         SkUnPreMultiply::Scale scale = SkUnPreMultiply::GetScale(da);
154                         dr = SkUnPreMultiply::ApplyScale(scale, dr);
155                         dg = SkUnPreMultiply::ApplyScale(scale, dg);
156                         db = SkUnPreMultiply::ApplyScale(scale, db);
157                     }
158
159                     a = arith(k1, k2, k3, k4, sa, da);
160                     r = arith(k1, k2, k3, k4, sr, dr);
161                     g = arith(k1, k2, k3, k4, sg, dg);
162                     b = arith(k1, k2, k3, k4, sb, db);
163                 }
164             } else {
165                 a = arith(k1, k2, k3, k4, SkGetPackedA32(sc), SkGetPackedA32(dc));
166                 r = arith(k1, k2, k3, k4, SkGetPackedR32(sc), SkGetPackedR32(dc));
167                 g = arith(k1, k2, k3, k4, SkGetPackedG32(sc), SkGetPackedG32(dc));
168                 b = arith(k1, k2, k3, k4, SkGetPackedB32(sc), SkGetPackedB32(dc));
169                 if (fEnforcePMColor) {
170                     r = SkMin32(r, a);
171                     g = SkMin32(g, a);
172                     b = SkMin32(b, a);
173                 }
174             }
175
176             // apply antialias coverage if necessary
177             if (aaCoverage && 0xFF != aaCoverage[i]) {
178                 int scale = aaCoverage[i] + (aaCoverage[i] >> 7);
179                 a = blend(a, SkGetPackedA32(sc), scale);
180                 r = blend(r, SkGetPackedR32(sc), scale);
181                 g = blend(g, SkGetPackedG32(sc), scale);
182                 b = blend(b, SkGetPackedB32(sc), scale);
183             }
184
185             // turn the result back into premul
186             if (gUseUnpremul && (0xFF != a)) {
187                 int scale = a + (a >> 7);
188                 r = SkAlphaMul(r, scale);
189                 g = SkAlphaMul(g, scale);
190                 b = SkAlphaMul(b, scale);
191             }
192             dst[i] = fEnforcePMColor ? SkPackARGB32(a, r, g, b) : SkPackARGB32NoCheck(a, r, g, b);
193         }
194     }
195 }
196
197 #ifndef SK_IGNORE_TO_STRING
198 void SkArithmeticMode_scalar::toString(SkString* str) const {
199     str->append("SkArithmeticMode_scalar: ");
200     for (int i = 0; i < 4; ++i) {
201         str->appendScalar(fK[i]);
202         str->append(" ");
203     }
204     str->appendS32(fEnforcePMColor ? 1 : 0);
205 }
206 #endif
207
208 ///////////////////////////////////////////////////////////////////////////////
209
210 static bool fitsInBits(SkScalar x, int bits) {
211     return SkScalarAbs(x) < (1 << (bits - 1));
212 }
213
214 #if 0 // UNUSED
215 static int32_t toDot8(SkScalar x) {
216     return (int32_t)(x * 256);
217 }
218 #endif
219
220 SkXfermode* SkArithmeticMode::Create(SkScalar k1, SkScalar k2,
221                                      SkScalar k3, SkScalar k4,
222                                      bool enforcePMColor) {
223     if (fitsInBits(k1, 8) && fitsInBits(k2, 16) &&
224         fitsInBits(k2, 16) && fitsInBits(k2, 24)) {
225
226 #if 0 // UNUSED
227         int32_t i1 = toDot8(k1);
228         int32_t i2 = toDot8(k2);
229         int32_t i3 = toDot8(k3);
230         int32_t i4 = toDot8(k4);
231         if (i1) {
232             return SkNEW_ARGS(SkArithmeticMode_quad, (i1, i2, i3, i4));
233         }
234         if (0 == i2) {
235             return SkNEW_ARGS(SkArithmeticMode_dst, (i3, i4));
236         }
237         if (0 == i3) {
238             return SkNEW_ARGS(SkArithmeticMode_src, (i2, i4));
239         }
240         return SkNEW_ARGS(SkArithmeticMode_linear, (i2, i3, i4));
241 #endif
242     }
243     return SkArithmeticMode_scalar::Create(k1, k2, k3, k4, enforcePMColor);
244 }
245
246
247 //////////////////////////////////////////////////////////////////////////////
248
249 #if SK_SUPPORT_GPU
250
251 class GrGLArithmeticEffect : public GrGLFragmentProcessor {
252 public:
253     GrGLArithmeticEffect(const GrBackendProcessorFactory&, const GrProcessor&);
254     virtual ~GrGLArithmeticEffect();
255
256     virtual void emitCode(GrGLFPBuilder*,
257                           const GrFragmentProcessor&,
258                           const GrProcessorKey&,
259                           const char* outputColor,
260                           const char* inputColor,
261                           const TransformedCoordsArray&,
262                           const TextureSamplerArray&) SK_OVERRIDE;
263
264     virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;
265
266     static void GenKey(const GrProcessor&, const GrGLCaps& caps, GrProcessorKeyBuilder* b);
267
268 private:
269     GrGLProgramDataManager::UniformHandle fKUni;
270     bool fEnforcePMColor;
271
272     typedef GrGLFragmentProcessor INHERITED;
273 };
274
275 ///////////////////////////////////////////////////////////////////////////////
276
277 class GrArithmeticEffect : public GrFragmentProcessor {
278 public:
279     static GrFragmentProcessor* Create(float k1, float k2, float k3, float k4, bool enforcePMColor,
280                                GrTexture* background) {
281         return SkNEW_ARGS(GrArithmeticEffect, (k1, k2, k3, k4, enforcePMColor, background));
282     }
283
284     virtual ~GrArithmeticEffect();
285
286     virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE;
287
288     typedef GrGLArithmeticEffect GLProcessor;
289     static const char* Name() { return "Arithmetic"; }
290     GrTexture* backgroundTexture() const { return fBackgroundAccess.getTexture(); }
291
292     float k1() const { return fK1; }
293     float k2() const { return fK2; }
294     float k3() const { return fK3; }
295     float k4() const { return fK4; }
296     bool enforcePMColor() const { return fEnforcePMColor; }
297
298 private:
299     virtual bool onIsEqual(const GrFragmentProcessor&) const SK_OVERRIDE;
300
301     virtual void onComputeInvariantOutput(InvariantOutput* inout) const SK_OVERRIDE;
302
303     GrArithmeticEffect(float k1, float k2, float k3, float k4, bool enforcePMColor,
304                        GrTexture* background);
305     float                       fK1, fK2, fK3, fK4;
306     bool                        fEnforcePMColor;
307     GrCoordTransform            fBackgroundTransform;
308     GrTextureAccess             fBackgroundAccess;
309
310     GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
311     typedef GrFragmentProcessor INHERITED;
312
313 };
314
315 ///////////////////////////////////////////////////////////////////////////////
316
317 GrArithmeticEffect::GrArithmeticEffect(float k1, float k2, float k3, float k4,
318                                        bool enforcePMColor, GrTexture* background)
319   : fK1(k1), fK2(k2), fK3(k3), fK4(k4), fEnforcePMColor(enforcePMColor) {
320     if (background) {
321         fBackgroundTransform.reset(kLocal_GrCoordSet, background);
322         this->addCoordTransform(&fBackgroundTransform);
323         fBackgroundAccess.reset(background);
324         this->addTextureAccess(&fBackgroundAccess);
325     } else {
326         this->setWillReadDstColor();
327     }
328 }
329
330 GrArithmeticEffect::~GrArithmeticEffect() {
331 }
332
333 bool GrArithmeticEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
334     const GrArithmeticEffect& s = sBase.cast<GrArithmeticEffect>();
335     return fK1 == s.fK1 &&
336            fK2 == s.fK2 &&
337            fK3 == s.fK3 &&
338            fK4 == s.fK4 &&
339            fEnforcePMColor == s.fEnforcePMColor;
340 }
341
342 const GrBackendFragmentProcessorFactory& GrArithmeticEffect::getFactory() const {
343     return GrTBackendFragmentProcessorFactory<GrArithmeticEffect>::getInstance();
344 }
345
346 void GrArithmeticEffect::onComputeInvariantOutput(InvariantOutput* inout) const {
347     // TODO: optimize this
348     inout->setToUnknown(InvariantOutput::kWill_ReadInput);
349 }
350
351 ///////////////////////////////////////////////////////////////////////////////
352
353 GrGLArithmeticEffect::GrGLArithmeticEffect(const GrBackendProcessorFactory& factory,
354                                            const GrProcessor&)
355    : INHERITED(factory),
356      fEnforcePMColor(true) {
357 }
358
359 GrGLArithmeticEffect::~GrGLArithmeticEffect() {
360 }
361
362 void GrGLArithmeticEffect::emitCode(GrGLFPBuilder* builder,
363                                     const GrFragmentProcessor& fp,
364                                     const GrProcessorKey& key,
365                                     const char* outputColor,
366                                     const char* inputColor,
367                                     const TransformedCoordsArray& coords,
368                                     const TextureSamplerArray& samplers) {
369
370     GrTexture* backgroundTex = fp.cast<GrArithmeticEffect>().backgroundTexture();
371     GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
372     const char* dstColor;
373     if (backgroundTex) {
374         fsBuilder->codeAppend("\t\tvec4 bgColor = ");
375         fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType());
376         fsBuilder->codeAppendf(";\n");
377         dstColor = "bgColor";
378     } else {
379         dstColor = fsBuilder->dstColor();
380     }
381
382     SkASSERT(dstColor);
383     fKUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
384                                 kVec4f_GrSLType, "k");
385     const char* kUni = builder->getUniformCStr(fKUni);
386
387     // We don't try to optimize for this case at all
388     if (NULL == inputColor) {
389         fsBuilder->codeAppendf("\t\tconst vec4 src = vec4(1);\n");
390     } else {
391         fsBuilder->codeAppendf("\t\tvec4 src = %s;\n", inputColor);
392         if (gUseUnpremul) {
393             fsBuilder->codeAppendf("\t\tsrc.rgb = clamp(src.rgb / src.a, 0.0, 1.0);\n");
394         }
395     }
396
397     fsBuilder->codeAppendf("\t\tvec4 dst = %s;\n", dstColor);
398     if (gUseUnpremul) {
399         fsBuilder->codeAppendf("\t\tdst.rgb = clamp(dst.rgb / dst.a, 0.0, 1.0);\n");
400     }
401
402     fsBuilder->codeAppendf("\t\t%s = %s.x * src * dst + %s.y * src + %s.z * dst + %s.w;\n", outputColor, kUni, kUni, kUni, kUni);
403     fsBuilder->codeAppendf("\t\t%s = clamp(%s, 0.0, 1.0);\n", outputColor, outputColor);
404     if (gUseUnpremul) {
405         fsBuilder->codeAppendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor);
406     } else if (fEnforcePMColor) {
407         fsBuilder->codeAppendf("\t\t%s.rgb = min(%s.rgb, %s.a);\n", outputColor, outputColor, outputColor);
408     }
409 }
410
411 void GrGLArithmeticEffect::setData(const GrGLProgramDataManager& pdman,
412                                    const GrProcessor& processor) {
413     const GrArithmeticEffect& arith = processor.cast<GrArithmeticEffect>();
414     pdman.set4f(fKUni, arith.k1(), arith.k2(), arith.k3(), arith.k4());
415     fEnforcePMColor = arith.enforcePMColor();
416 }
417
418 void GrGLArithmeticEffect::GenKey(const GrProcessor& processor,
419                                   const GrGLCaps&, GrProcessorKeyBuilder* b) {
420     const GrArithmeticEffect& arith = processor.cast<GrArithmeticEffect>();
421     uint32_t key = arith.enforcePMColor() ? 1 : 0;
422     if (arith.backgroundTexture()) {
423         key |= 2;
424     }
425     b->add32(key);
426 }
427
428 GrFragmentProcessor* GrArithmeticEffect::TestCreate(SkRandom* rand,
429                                                     GrContext*,
430                                                     const GrDrawTargetCaps&,
431                                                     GrTexture*[]) {
432     float k1 = rand->nextF();
433     float k2 = rand->nextF();
434     float k3 = rand->nextF();
435     float k4 = rand->nextF();
436     bool enforcePMColor = rand->nextBool();
437
438     return SkNEW_ARGS(GrArithmeticEffect, (k1, k2, k3, k4, enforcePMColor, NULL));
439 }
440
441 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrArithmeticEffect);
442
443 bool SkArithmeticMode_scalar::asFragmentProcessor(GrFragmentProcessor** fp,
444                                                   GrTexture* background) const {
445     if (fp) {
446         *fp = GrArithmeticEffect::Create(SkScalarToFloat(fK[0]),
447                                          SkScalarToFloat(fK[1]),
448                                          SkScalarToFloat(fK[2]),
449                                          SkScalarToFloat(fK[3]),
450                                          fEnforcePMColor,
451                                          background);
452     }
453     return true;
454 }
455
456 #endif
457
458 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkArithmeticMode)
459     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkArithmeticMode_scalar)
460 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END