1b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com/*
2b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com * Copyright 2013 Google Inc.
3b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com *
4b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com * Use of this source code is governed by a BSD-style license that can be
5b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com * found in the LICENSE file.
6b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com */
7b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com
8e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org#include "SkArithmeticMode.h"
9e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org#include "SkColorPriv.h"
108b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
118b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h"
12b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com#include "SkString.h"
13e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org#include "SkUnPreMultiply.h"
149a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org#if SK_SUPPORT_GPU
159a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org#include "GrContext.h"
1677af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com#include "GrCoordTransform.h"
179a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org#include "gl/GrGLEffect.h"
189a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org#include "GrTBackendEffectFactory.h"
199a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org#endif
20e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
21b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.orgstatic const bool gUseUnpremul = false;
22b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org
23e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgclass SkArithmeticMode_scalar : public SkXfermode {
24e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgpublic:
2551a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    static SkArithmeticMode_scalar* Create(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4,
2651a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org                                           bool enforcePMColor) {
2751a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org        return SkNEW_ARGS(SkArithmeticMode_scalar, (k1, k2, k3, k4, enforcePMColor));
28e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    }
29e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
30e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
3130da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com                        const SkAlpha aa[]) const SK_OVERRIDE;
32e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
330f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org    SK_TO_STRING_OVERRIDE()
349a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkArithmeticMode_scalar)
359a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
369a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org#if SK_SUPPORT_GPU
371a6382f5e76c051ffbbb60f3a68524dfe57cf798senorblanco@chromium.org    virtual bool asNewEffect(GrEffectRef** effect, GrTexture* background) const SK_OVERRIDE;
389a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org#endif
39e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
40e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgprivate:
4151a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    SkArithmeticMode_scalar(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4, bool enforcePMColor) {
420a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org        fK[0] = k1;
430a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org        fK[1] = k2;
440a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org        fK[2] = k3;
450a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org        fK[3] = k4;
4651a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org        fEnforcePMColor = enforcePMColor;
470a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    }
480a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org
498b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    SkArithmeticMode_scalar(SkReadBuffer& buffer) : INHERITED(buffer) {
509a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org        fK[0] = buffer.readScalar();
519a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org        fK[1] = buffer.readScalar();
529a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org        fK[2] = buffer.readScalar();
539a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org        fK[3] = buffer.readScalar();
5451a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org        fEnforcePMColor = buffer.readBool();
559a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    }
569a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
578b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE {
589a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org        INHERITED::flatten(buffer);
599a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org        buffer.writeScalar(fK[0]);
609a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org        buffer.writeScalar(fK[1]);
619a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org        buffer.writeScalar(fK[2]);
629a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org        buffer.writeScalar(fK[3]);
6351a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org        buffer.writeBool(fEnforcePMColor);
649a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    }
65e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    SkScalar fK[4];
6651a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    bool fEnforcePMColor;
67b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com
6898ded84b80918ac1e40224c125922941f3b2eb03skia.committer@gmail.com    typedef SkXfermode INHERITED;
69e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org};
70e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
71e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgstatic int pinToByte(int value) {
72e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    if (value < 0) {
73e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        value = 0;
74e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    } else if (value > 255) {
75e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        value = 255;
76e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    }
77e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    return value;
78e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org}
79e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
80e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgstatic int arith(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4,
81e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org                 int src, int dst) {
82e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    SkScalar result = SkScalarMul(k1, src * dst) +
83e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org                      SkScalarMul(k2, src) +
84e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org                      SkScalarMul(k3, dst) +
85e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org                      k4;
86e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    int res = SkScalarRoundToInt(result);
87e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    return pinToByte(res);
88e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org}
89e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
90e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgstatic int blend(int src, int dst, int scale) {
91e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    return dst + ((src - dst) * scale >> 8);
92e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org}
93e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
94e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgstatic bool needsUnpremul(int alpha) {
95e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    return 0 != alpha && 0xFF != alpha;
96e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org}
97e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
98e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgvoid SkArithmeticMode_scalar::xfer32(SkPMColor dst[], const SkPMColor src[],
9930da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com                                 int count, const SkAlpha aaCoverage[]) const {
100e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    SkScalar k1 = fK[0] / 255;
101e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    SkScalar k2 = fK[1];
102e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    SkScalar k3 = fK[2];
103e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    SkScalar k4 = fK[3] * 255;
104e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
105e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    for (int i = 0; i < count; ++i) {
106e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        if ((NULL == aaCoverage) || aaCoverage[i]) {
107e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org            SkPMColor sc = src[i];
108e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org            SkPMColor dc = dst[i];
109e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
110e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org            int a, r, g, b;
111e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
112b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org            if (gUseUnpremul) {
113b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                int sa = SkGetPackedA32(sc);
114b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                int da = SkGetPackedA32(dc);
115b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org
116b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                int srcNeedsUnpremul = needsUnpremul(sa);
117b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                int dstNeedsUnpremul = needsUnpremul(da);
118b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org
119b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                if (!srcNeedsUnpremul && !dstNeedsUnpremul) {
120b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    a = arith(k1, k2, k3, k4, sa, da);
121b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    r = arith(k1, k2, k3, k4, SkGetPackedR32(sc), SkGetPackedR32(dc));
122b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    g = arith(k1, k2, k3, k4, SkGetPackedG32(sc), SkGetPackedG32(dc));
123b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    b = arith(k1, k2, k3, k4, SkGetPackedB32(sc), SkGetPackedB32(dc));
124b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                } else {
125b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    int sr = SkGetPackedR32(sc);
126b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    int sg = SkGetPackedG32(sc);
127b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    int sb = SkGetPackedB32(sc);
128b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    if (srcNeedsUnpremul) {
129b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                        SkUnPreMultiply::Scale scale = SkUnPreMultiply::GetScale(sa);
130b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                        sr = SkUnPreMultiply::ApplyScale(scale, sr);
131b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                        sg = SkUnPreMultiply::ApplyScale(scale, sg);
132b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                        sb = SkUnPreMultiply::ApplyScale(scale, sb);
133b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    }
134b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org
135b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    int dr = SkGetPackedR32(dc);
136b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    int dg = SkGetPackedG32(dc);
137b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    int db = SkGetPackedB32(dc);
138b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    if (dstNeedsUnpremul) {
139b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                        SkUnPreMultiply::Scale scale = SkUnPreMultiply::GetScale(da);
140b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                        dr = SkUnPreMultiply::ApplyScale(scale, dr);
141b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                        dg = SkUnPreMultiply::ApplyScale(scale, dg);
142b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                        db = SkUnPreMultiply::ApplyScale(scale, db);
143b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    }
144b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org
145b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    a = arith(k1, k2, k3, k4, sa, da);
146b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    r = arith(k1, k2, k3, k4, sr, dr);
147b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    g = arith(k1, k2, k3, k4, sg, dg);
148b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    b = arith(k1, k2, k3, k4, sb, db);
149b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                }
150b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org            } else {
151b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                a = arith(k1, k2, k3, k4, SkGetPackedA32(sc), SkGetPackedA32(dc));
152e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org                r = arith(k1, k2, k3, k4, SkGetPackedR32(sc), SkGetPackedR32(dc));
153e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org                g = arith(k1, k2, k3, k4, SkGetPackedG32(sc), SkGetPackedG32(dc));
154e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org                b = arith(k1, k2, k3, k4, SkGetPackedB32(sc), SkGetPackedB32(dc));
15551a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org                if (fEnforcePMColor) {
15651a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org                    r = SkMin32(r, a);
15751a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org                    g = SkMin32(g, a);
15851a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org                    b = SkMin32(b, a);
15951a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org                }
160e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org            }
161e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
162e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org            // apply antialias coverage if necessary
163e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org            if (aaCoverage && 0xFF != aaCoverage[i]) {
164e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org                int scale = aaCoverage[i] + (aaCoverage[i] >> 7);
165e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org                a = blend(a, SkGetPackedA32(sc), scale);
166e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org                r = blend(r, SkGetPackedR32(sc), scale);
167e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org                g = blend(g, SkGetPackedG32(sc), scale);
168e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org                b = blend(b, SkGetPackedB32(sc), scale);
169e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org            }
170e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
1710e330ae5f90ef8a4a864329b9a634644a05bf124mike@reedtribe.org            // turn the result back into premul
172b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org            if (gUseUnpremul && (0xFF != a)) {
1730e330ae5f90ef8a4a864329b9a634644a05bf124mike@reedtribe.org                int scale = a + (a >> 7);
1740e330ae5f90ef8a4a864329b9a634644a05bf124mike@reedtribe.org                r = SkAlphaMul(r, scale);
1750e330ae5f90ef8a4a864329b9a634644a05bf124mike@reedtribe.org                g = SkAlphaMul(g, scale);
1760e330ae5f90ef8a4a864329b9a634644a05bf124mike@reedtribe.org                b = SkAlphaMul(b, scale);
1770e330ae5f90ef8a4a864329b9a634644a05bf124mike@reedtribe.org            }
17851a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org            dst[i] = fEnforcePMColor ? SkPackARGB32(a, r, g, b) : SkPackARGB32NoCheck(a, r, g, b);
179e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        }
180e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    }
181e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org}
182e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
1830f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
184b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.comvoid SkArithmeticMode_scalar::toString(SkString* str) const {
185b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    str->append("SkArithmeticMode_scalar: ");
186b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    for (int i = 0; i < 4; ++i) {
187b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com        str->appendScalar(fK[i]);
18851a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org        str->append(" ");
189b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    }
19051a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    str->appendS32(fEnforcePMColor ? 1 : 0);
191b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com}
192b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com#endif
193e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
194e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org///////////////////////////////////////////////////////////////////////////////
195e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
196e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgstatic bool fitsInBits(SkScalar x, int bits) {
197e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    return SkScalarAbs(x) < (1 << (bits - 1));
198e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org}
199e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
200383d5d494992554cde776c8b5b359d30e431bc78caryclark@google.com#if 0 // UNUSED
201e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgstatic int32_t toDot8(SkScalar x) {
202e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    return (int32_t)(x * 256);
203e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org}
204383d5d494992554cde776c8b5b359d30e431bc78caryclark@google.com#endif
205e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
206e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgSkXfermode* SkArithmeticMode::Create(SkScalar k1, SkScalar k2,
20751a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org                                     SkScalar k3, SkScalar k4,
20851a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org                                     bool enforcePMColor) {
209e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    if (fitsInBits(k1, 8) && fitsInBits(k2, 16) &&
210e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        fitsInBits(k2, 16) && fitsInBits(k2, 24)) {
211e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
212383d5d494992554cde776c8b5b359d30e431bc78caryclark@google.com#if 0 // UNUSED
213e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        int32_t i1 = toDot8(k1);
214e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        int32_t i2 = toDot8(k2);
215e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        int32_t i3 = toDot8(k3);
216e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        int32_t i4 = toDot8(k4);
217e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        if (i1) {
218e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org            return SkNEW_ARGS(SkArithmeticMode_quad, (i1, i2, i3, i4));
219e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        }
220e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        if (0 == i2) {
221e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org            return SkNEW_ARGS(SkArithmeticMode_dst, (i3, i4));
222e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        }
223e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        if (0 == i3) {
224e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org            return SkNEW_ARGS(SkArithmeticMode_src, (i2, i4));
225e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        }
226e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        return SkNEW_ARGS(SkArithmeticMode_linear, (i2, i3, i4));
227e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org#endif
228e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    }
22951a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    return SkArithmeticMode_scalar::Create(k1, k2, k3, k4, enforcePMColor);
230e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org}
2319a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
2329a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
2339a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org//////////////////////////////////////////////////////////////////////////////
2349a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
2359a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org#if SK_SUPPORT_GPU
2369a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
2379a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgclass GrGLArithmeticEffect : public GrGLEffect {
2389a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgpublic:
2399a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    GrGLArithmeticEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
2409a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    virtual ~GrGLArithmeticEffect();
2419a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
2429a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    virtual void emitCode(GrGLShaderBuilder*,
2439a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org                          const GrDrawEffect&,
2449a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org                          EffectKey,
2459a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org                          const char* outputColor,
2469a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org                          const char* inputColor,
24777af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com                          const TransformedCoordsArray&,
2489a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org                          const TextureSamplerArray&) SK_OVERRIDE;
2499a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
2509a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
2519a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
25251a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps& caps);
25351a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org
2549a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgprivate:
2559a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    GrGLUniformManager::UniformHandle fKUni;
25651a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    bool fEnforcePMColor;
2579a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
2589a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    typedef GrGLEffect INHERITED;
2599a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org};
2609a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
2619a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
2629a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
2639a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgclass GrArithmeticEffect : public GrEffect {
2649a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgpublic:
26551a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    static GrEffectRef* Create(float k1, float k2, float k3, float k4, bool enforcePMColor,
26651a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org                               GrTexture* background) {
26751a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org        AutoEffectUnref effect(SkNEW_ARGS(GrArithmeticEffect, (k1, k2, k3, k4, enforcePMColor,
26851a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org                                                               background)));
2699a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org        return CreateEffectRef(effect);
2709a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    }
2719a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
2729a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    virtual ~GrArithmeticEffect();
2739a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
2749a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
2759a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
2769a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    typedef GrGLArithmeticEffect GLEffect;
2779a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    static const char* Name() { return "Arithmetic"; }
27886fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org    GrTexture* backgroundTexture() const { return fBackgroundAccess.getTexture(); }
2799a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
2809a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
2819a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
2829a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    float k1() const { return fK1; }
2839a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    float k2() const { return fK2; }
2849a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    float k3() const { return fK3; }
2859a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    float k4() const { return fK4; }
28651a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    bool enforcePMColor() const { return fEnforcePMColor; }
2879a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
2889a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgprivate:
2899a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
2909a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
29151a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    GrArithmeticEffect(float k1, float k2, float k3, float k4, bool enforcePMColor,
29251a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org                       GrTexture* background);
2939a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    float                       fK1, fK2, fK3, fK4;
29451a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    bool                        fEnforcePMColor;
29577af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com    GrCoordTransform            fBackgroundTransform;
29686fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org    GrTextureAccess             fBackgroundAccess;
2979a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
2989a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    GR_DECLARE_EFFECT_TEST;
2999a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    typedef GrEffect INHERITED;
3009a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
3019a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org};
3029a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
3039a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
3049a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
30586fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.orgGrArithmeticEffect::GrArithmeticEffect(float k1, float k2, float k3, float k4,
30651a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org                                       bool enforcePMColor, GrTexture* background)
30751a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org  : fK1(k1), fK2(k2), fK3(k3), fK4(k4), fEnforcePMColor(enforcePMColor) {
30886fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org    if (background) {
30977af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com        fBackgroundTransform.reset(kLocal_GrCoordSet, background);
31077af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com        this->addCoordTransform(&fBackgroundTransform);
31186fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org        fBackgroundAccess.reset(background);
31286fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org        this->addTextureAccess(&fBackgroundAccess);
31386fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org    } else {
31486fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org        this->setWillReadDstColor();
31586fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org    }
3169a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org}
3179a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
3189a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgGrArithmeticEffect::~GrArithmeticEffect() {
3199a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org}
3209a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
3219a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgbool GrArithmeticEffect::onIsEqual(const GrEffect& sBase) const {
3229a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    const GrArithmeticEffect& s = CastEffect<GrArithmeticEffect>(sBase);
3239a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    return fK1 == s.fK1 &&
3249a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org           fK2 == s.fK2 &&
3259a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org           fK3 == s.fK3 &&
32686fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org           fK4 == s.fK4 &&
32751a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org           fEnforcePMColor == s.fEnforcePMColor &&
32886fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org           backgroundTexture() == s.backgroundTexture();
3299a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org}
3309a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
3319a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgconst GrBackendEffectFactory& GrArithmeticEffect::getFactory() const {
3329a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    return GrTBackendEffectFactory<GrArithmeticEffect>::getInstance();
3339a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org}
3349a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
3359a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgvoid GrArithmeticEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
3369a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    // TODO: optimize this
3379a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    *validFlags = 0;
3389a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org}
3399a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
3409a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
3419a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
3429a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgGrGLArithmeticEffect::GrGLArithmeticEffect(const GrBackendEffectFactory& factory,
34386fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org                                           const GrDrawEffect& drawEffect)
34451a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org   : INHERITED(factory),
34551a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org     fEnforcePMColor(true) {
3469a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org}
3479a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
3489a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgGrGLArithmeticEffect::~GrGLArithmeticEffect() {
3499a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org}
3509a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
3519a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgvoid GrGLArithmeticEffect::emitCode(GrGLShaderBuilder* builder,
35286fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org                                    const GrDrawEffect& drawEffect,
3539a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org                                    EffectKey key,
3549a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org                                    const char* outputColor,
3559a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org                                    const char* inputColor,
35677af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com                                    const TransformedCoordsArray& coords,
3579a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org                                    const TextureSamplerArray& samplers) {
35886fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org
35986fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org    GrTexture* backgroundTex = drawEffect.castEffect<GrArithmeticEffect>().backgroundTexture();
36086fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org    const char* dstColor;
36186fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org    if (backgroundTex) {
36286fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org        builder->fsCodeAppend("\t\tvec4 bgColor = ");
36377af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com        builder->fsAppendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type());
36486fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org        builder->fsCodeAppendf(";\n");
36586fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org        dstColor = "bgColor";
36686fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org    } else {
36786fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org        dstColor = builder->dstColor();
36886fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org    }
36986fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org
37096ae688f03f05a53c2ae6e66a431e180b90be9cdcommit-bot@chromium.org    SkASSERT(NULL != dstColor);
37174a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org    fKUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
3729a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org                                kVec4f_GrSLType, "k");
3739a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    const char* kUni = builder->getUniformCStr(fKUni);
3749a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
3759a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    // We don't try to optimize for this case at all
3769a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    if (NULL == inputColor) {
377824c346b6e0e114063c1a8ad4ba7c3a669ee2cffcommit-bot@chromium.org        builder->fsCodeAppendf("\t\tconst vec4 src = vec4(1);\n");
3789a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    } else {
3791afa3fff2987e3f4ea4383477467a13be78bc210senorblanco@chromium.org        builder->fsCodeAppendf("\t\tvec4 src = %s;\n", inputColor);
380b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org        if (gUseUnpremul) {
381b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org            builder->fsCodeAppendf("\t\tsrc.rgb = clamp(src.rgb / src.a, 0.0, 1.0);\n");
382b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org        }
3839a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    }
3849a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
3851afa3fff2987e3f4ea4383477467a13be78bc210senorblanco@chromium.org    builder->fsCodeAppendf("\t\tvec4 dst = %s;\n", dstColor);
386b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org    if (gUseUnpremul) {
387b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org        builder->fsCodeAppendf("\t\tdst.rgb = clamp(dst.rgb / dst.a, 0.0, 1.0);\n");
388b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org    }
3899a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
3901afa3fff2987e3f4ea4383477467a13be78bc210senorblanco@chromium.org    builder->fsCodeAppendf("\t\t%s = %s.x * src * dst + %s.y * src + %s.z * dst + %s.w;\n", outputColor, kUni, kUni, kUni, kUni);
3919a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    builder->fsCodeAppendf("\t\t%s = clamp(%s, 0.0, 1.0);\n", outputColor, outputColor);
392b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org    if (gUseUnpremul) {
393b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org        builder->fsCodeAppendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor);
39451a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    } else if (fEnforcePMColor) {
395b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org        builder->fsCodeAppendf("\t\t%s.rgb = min(%s.rgb, %s.a);\n", outputColor, outputColor, outputColor);
396b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org    }
3979a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org}
3989a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
3999a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgvoid GrGLArithmeticEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) {
4009a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    const GrArithmeticEffect& arith = drawEffect.castEffect<GrArithmeticEffect>();
4019a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    uman.set4f(fKUni, arith.k1(), arith.k2(), arith.k3(), arith.k4());
40251a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    fEnforcePMColor = arith.enforcePMColor();
40351a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org}
40451a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org
40551a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.orgGrGLEffect::EffectKey GrGLArithmeticEffect::GenKey(const GrDrawEffect& drawEffect,
40651a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org                                                   const GrGLCaps&) {
40751a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    const GrArithmeticEffect& arith = drawEffect.castEffect<GrArithmeticEffect>();
40851a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    EffectKey key = arith.enforcePMColor() ? 1 : 0;
40951a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    if (arith.backgroundTexture()) {
41051a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org        key |= 2;
41151a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    }
41251a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    return key;
4139a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org}
4149a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
415e0e7cfe44bb9d66d76120a79e5275c294bacaa22commit-bot@chromium.orgGrEffectRef* GrArithmeticEffect::TestCreate(SkRandom* rand,
4169a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org                                            GrContext*,
4179a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org                                            const GrDrawTargetCaps&,
4189a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org                                            GrTexture*[]) {
4199a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    float k1 = rand->nextF();
4209a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    float k2 = rand->nextF();
4219a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    float k3 = rand->nextF();
4229a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    float k4 = rand->nextF();
42351a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    bool enforcePMColor = rand->nextBool();
4249a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
42551a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    AutoEffectUnref gEffect(SkNEW_ARGS(GrArithmeticEffect,
42651a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org                                       (k1, k2, k3, k4, enforcePMColor, NULL)));
4279a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    return CreateEffectRef(gEffect);
4289a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org}
4299a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
4309a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgGR_DEFINE_EFFECT_TEST(GrArithmeticEffect);
4319a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
4321a6382f5e76c051ffbbb60f3a68524dfe57cf798senorblanco@chromium.orgbool SkArithmeticMode_scalar::asNewEffect(GrEffectRef** effect, GrTexture* background) const {
4339a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    if (effect) {
4349a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org        *effect = GrArithmeticEffect::Create(SkScalarToFloat(fK[0]),
4359a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org                                             SkScalarToFloat(fK[1]),
4369a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org                                             SkScalarToFloat(fK[2]),
43786fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org                                             SkScalarToFloat(fK[3]),
43851a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org                                             fEnforcePMColor,
43986fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org                                             background);
4409a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    }
4419a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    return true;
4429a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org}
4439a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
4449a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org#endif
4459a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
4469a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkArithmeticMode)
4479a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkArithmeticMode_scalar)
4489a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
449