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"
17b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "gl/GrGLProcessor.h"
1830ba436f04e61d4505fb854d5fc56079636e0788joshualitt#include "gl/builders/GrGLProgramBuilder.h"
19b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrTBackendProcessorFactory.h"
209a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org#endif
21e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
22b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.orgstatic const bool gUseUnpremul = false;
23b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org
24e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgclass SkArithmeticMode_scalar : public SkXfermode {
25e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgpublic:
2651a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    static SkArithmeticMode_scalar* Create(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4,
2751a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org                                           bool enforcePMColor) {
2851a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org        return SkNEW_ARGS(SkArithmeticMode_scalar, (k1, k2, k3, k4, enforcePMColor));
29e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    }
30e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
31e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
3230da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com                        const SkAlpha aa[]) const SK_OVERRIDE;
33e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
340f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org    SK_TO_STRING_OVERRIDE()
359a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkArithmeticMode_scalar)
369a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
379a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org#if SK_SUPPORT_GPU
38b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual bool asFragmentProcessor(GrFragmentProcessor**,
39b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                     GrTexture* background) const SK_OVERRIDE;
409a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org#endif
41e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
42e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgprivate:
4351a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    SkArithmeticMode_scalar(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4, bool enforcePMColor) {
440a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org        fK[0] = k1;
450a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org        fK[1] = k2;
460a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org        fK[2] = k3;
470a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org        fK[3] = k4;
4851a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org        fEnforcePMColor = enforcePMColor;
490a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    }
500a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org
519fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
528b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    SkArithmeticMode_scalar(SkReadBuffer& buffer) : INHERITED(buffer) {
539a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org        fK[0] = buffer.readScalar();
549a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org        fK[1] = buffer.readScalar();
559a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org        fK[2] = buffer.readScalar();
569a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org        fK[3] = buffer.readScalar();
5751a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org        fEnforcePMColor = buffer.readBool();
589a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    }
599fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif
609a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
618b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE {
629a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org        buffer.writeScalar(fK[0]);
639a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org        buffer.writeScalar(fK[1]);
649a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org        buffer.writeScalar(fK[2]);
659a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org        buffer.writeScalar(fK[3]);
6651a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org        buffer.writeBool(fEnforcePMColor);
679a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    }
68e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    SkScalar fK[4];
6951a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    bool fEnforcePMColor;
70b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com
719fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    friend class SkArithmeticMode;
729fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
7398ded84b80918ac1e40224c125922941f3b2eb03skia.committer@gmail.com    typedef SkXfermode INHERITED;
74e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org};
75e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
769fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkArithmeticMode_scalar::CreateProc(SkReadBuffer& buffer) {
779fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    const SkScalar k1 = buffer.readScalar();
789fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    const SkScalar k2 = buffer.readScalar();
799fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    const SkScalar k3 = buffer.readScalar();
809fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    const SkScalar k4 = buffer.readScalar();
819fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    const bool enforcePMColor = buffer.readBool();
829fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    return Create(k1, k2, k3, k4, enforcePMColor);
839fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
849fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
85e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgstatic int pinToByte(int value) {
86e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    if (value < 0) {
87e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        value = 0;
88e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    } else if (value > 255) {
89e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        value = 255;
90e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    }
91e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    return value;
92e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org}
93e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
94e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgstatic int arith(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4,
95e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org                 int src, int dst) {
96e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    SkScalar result = SkScalarMul(k1, src * dst) +
97e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org                      SkScalarMul(k2, src) +
98e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org                      SkScalarMul(k3, dst) +
99e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org                      k4;
100e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    int res = SkScalarRoundToInt(result);
101e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    return pinToByte(res);
102e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org}
103e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
104e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgstatic int blend(int src, int dst, int scale) {
105e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    return dst + ((src - dst) * scale >> 8);
106e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org}
107e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
108e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgstatic bool needsUnpremul(int alpha) {
109e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    return 0 != alpha && 0xFF != alpha;
110e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org}
111e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
112e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgvoid SkArithmeticMode_scalar::xfer32(SkPMColor dst[], const SkPMColor src[],
11330da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com                                 int count, const SkAlpha aaCoverage[]) const {
114e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    SkScalar k1 = fK[0] / 255;
115e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    SkScalar k2 = fK[1];
116e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    SkScalar k3 = fK[2];
117e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    SkScalar k4 = fK[3] * 255;
118e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
119e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    for (int i = 0; i < count; ++i) {
120e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        if ((NULL == aaCoverage) || aaCoverage[i]) {
121e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org            SkPMColor sc = src[i];
122e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org            SkPMColor dc = dst[i];
123e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
124e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org            int a, r, g, b;
125e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
126b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org            if (gUseUnpremul) {
127b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                int sa = SkGetPackedA32(sc);
128b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                int da = SkGetPackedA32(dc);
129b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org
130b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                int srcNeedsUnpremul = needsUnpremul(sa);
131b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                int dstNeedsUnpremul = needsUnpremul(da);
132b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org
133b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                if (!srcNeedsUnpremul && !dstNeedsUnpremul) {
134b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    a = arith(k1, k2, k3, k4, sa, da);
135b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    r = arith(k1, k2, k3, k4, SkGetPackedR32(sc), SkGetPackedR32(dc));
136b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    g = arith(k1, k2, k3, k4, SkGetPackedG32(sc), SkGetPackedG32(dc));
137b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    b = arith(k1, k2, k3, k4, SkGetPackedB32(sc), SkGetPackedB32(dc));
138b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                } else {
139b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    int sr = SkGetPackedR32(sc);
140b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    int sg = SkGetPackedG32(sc);
141b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    int sb = SkGetPackedB32(sc);
142b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    if (srcNeedsUnpremul) {
143b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                        SkUnPreMultiply::Scale scale = SkUnPreMultiply::GetScale(sa);
144b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                        sr = SkUnPreMultiply::ApplyScale(scale, sr);
145b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                        sg = SkUnPreMultiply::ApplyScale(scale, sg);
146b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                        sb = SkUnPreMultiply::ApplyScale(scale, sb);
147b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    }
148b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org
149b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    int dr = SkGetPackedR32(dc);
150b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    int dg = SkGetPackedG32(dc);
151b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    int db = SkGetPackedB32(dc);
152b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    if (dstNeedsUnpremul) {
153b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                        SkUnPreMultiply::Scale scale = SkUnPreMultiply::GetScale(da);
154b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                        dr = SkUnPreMultiply::ApplyScale(scale, dr);
155b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                        dg = SkUnPreMultiply::ApplyScale(scale, dg);
156b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                        db = SkUnPreMultiply::ApplyScale(scale, db);
157b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    }
158b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org
159b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    a = arith(k1, k2, k3, k4, sa, da);
160b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    r = arith(k1, k2, k3, k4, sr, dr);
161b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    g = arith(k1, k2, k3, k4, sg, dg);
162b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                    b = arith(k1, k2, k3, k4, sb, db);
163b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                }
164b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org            } else {
165b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org                a = arith(k1, k2, k3, k4, SkGetPackedA32(sc), SkGetPackedA32(dc));
166e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org                r = arith(k1, k2, k3, k4, SkGetPackedR32(sc), SkGetPackedR32(dc));
167e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org                g = arith(k1, k2, k3, k4, SkGetPackedG32(sc), SkGetPackedG32(dc));
168e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org                b = arith(k1, k2, k3, k4, SkGetPackedB32(sc), SkGetPackedB32(dc));
16951a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org                if (fEnforcePMColor) {
17051a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org                    r = SkMin32(r, a);
17151a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org                    g = SkMin32(g, a);
17251a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org                    b = SkMin32(b, a);
17351a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org                }
174e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org            }
175e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
176e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org            // apply antialias coverage if necessary
177e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org            if (aaCoverage && 0xFF != aaCoverage[i]) {
178e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org                int scale = aaCoverage[i] + (aaCoverage[i] >> 7);
179e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org                a = blend(a, SkGetPackedA32(sc), scale);
180e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org                r = blend(r, SkGetPackedR32(sc), scale);
181e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org                g = blend(g, SkGetPackedG32(sc), scale);
182e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org                b = blend(b, SkGetPackedB32(sc), scale);
183e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org            }
184e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
1850e330ae5f90ef8a4a864329b9a634644a05bf124mike@reedtribe.org            // turn the result back into premul
186b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org            if (gUseUnpremul && (0xFF != a)) {
1870e330ae5f90ef8a4a864329b9a634644a05bf124mike@reedtribe.org                int scale = a + (a >> 7);
1880e330ae5f90ef8a4a864329b9a634644a05bf124mike@reedtribe.org                r = SkAlphaMul(r, scale);
1890e330ae5f90ef8a4a864329b9a634644a05bf124mike@reedtribe.org                g = SkAlphaMul(g, scale);
1900e330ae5f90ef8a4a864329b9a634644a05bf124mike@reedtribe.org                b = SkAlphaMul(b, scale);
1910e330ae5f90ef8a4a864329b9a634644a05bf124mike@reedtribe.org            }
19251a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org            dst[i] = fEnforcePMColor ? SkPackARGB32(a, r, g, b) : SkPackARGB32NoCheck(a, r, g, b);
193e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        }
194e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    }
195e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org}
196e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
1970f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
198b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.comvoid SkArithmeticMode_scalar::toString(SkString* str) const {
199b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    str->append("SkArithmeticMode_scalar: ");
200b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    for (int i = 0; i < 4; ++i) {
201b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com        str->appendScalar(fK[i]);
20251a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org        str->append(" ");
203b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    }
20451a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    str->appendS32(fEnforcePMColor ? 1 : 0);
205b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com}
206b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com#endif
207e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
208e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org///////////////////////////////////////////////////////////////////////////////
209e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
210e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgstatic bool fitsInBits(SkScalar x, int bits) {
211e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    return SkScalarAbs(x) < (1 << (bits - 1));
212e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org}
213e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
214383d5d494992554cde776c8b5b359d30e431bc78caryclark@google.com#if 0 // UNUSED
215e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgstatic int32_t toDot8(SkScalar x) {
216e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    return (int32_t)(x * 256);
217e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org}
218383d5d494992554cde776c8b5b359d30e431bc78caryclark@google.com#endif
219e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
220e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.orgSkXfermode* SkArithmeticMode::Create(SkScalar k1, SkScalar k2,
22151a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org                                     SkScalar k3, SkScalar k4,
22251a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org                                     bool enforcePMColor) {
223e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    if (fitsInBits(k1, 8) && fitsInBits(k2, 16) &&
224e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        fitsInBits(k2, 16) && fitsInBits(k2, 24)) {
225e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org
226383d5d494992554cde776c8b5b359d30e431bc78caryclark@google.com#if 0 // UNUSED
227e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        int32_t i1 = toDot8(k1);
228e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        int32_t i2 = toDot8(k2);
229e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        int32_t i3 = toDot8(k3);
230e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        int32_t i4 = toDot8(k4);
231e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        if (i1) {
232e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org            return SkNEW_ARGS(SkArithmeticMode_quad, (i1, i2, i3, i4));
233e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        }
234e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        if (0 == i2) {
235e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org            return SkNEW_ARGS(SkArithmeticMode_dst, (i3, i4));
236e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        }
237e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        if (0 == i3) {
238e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org            return SkNEW_ARGS(SkArithmeticMode_src, (i2, i4));
239e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        }
240e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org        return SkNEW_ARGS(SkArithmeticMode_linear, (i2, i3, i4));
241e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org#endif
242e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org    }
24351a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    return SkArithmeticMode_scalar::Create(k1, k2, k3, k4, enforcePMColor);
244e51755fc64bf5df4bed9d74f4bca4f70897d59a9mike@reedtribe.org}
2459a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
2469a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
2479a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org//////////////////////////////////////////////////////////////////////////////
2489a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
2499a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org#if SK_SUPPORT_GPU
2509a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
251b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass GrGLArithmeticEffect : public GrGLFragmentProcessor {
2529a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgpublic:
253b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GrGLArithmeticEffect(const GrBackendProcessorFactory&, const GrProcessor&);
2549a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    virtual ~GrGLArithmeticEffect();
2559a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
25630ba436f04e61d4505fb854d5fc56079636e0788joshualitt    virtual void emitCode(GrGLProgramBuilder*,
257b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                          const GrFragmentProcessor&,
258b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                          const GrProcessorKey&,
2599a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org                          const char* outputColor,
2609a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org                          const char* inputColor,
26177af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com                          const TransformedCoordsArray&,
2629a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org                          const TextureSamplerArray&) SK_OVERRIDE;
2639a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
264b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;
2659a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
266b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    static void GenKey(const GrProcessor&, const GrGLCaps& caps, GrProcessorKeyBuilder* b);
26751a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org
2689a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgprivate:
2697510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    GrGLProgramDataManager::UniformHandle fKUni;
27051a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    bool fEnforcePMColor;
2719a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
272b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    typedef GrGLFragmentProcessor INHERITED;
2739a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org};
2749a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
2759a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
2769a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
277b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass GrArithmeticEffect : public GrFragmentProcessor {
2789a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgpublic:
279b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    static GrFragmentProcessor* Create(float k1, float k2, float k3, float k4, bool enforcePMColor,
28051a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org                               GrTexture* background) {
28155fad7af61c21d502acb9891d631e8aa29e3628cbsalomon        return SkNEW_ARGS(GrArithmeticEffect, (k1, k2, k3, k4, enforcePMColor, background));
2829a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    }
2839a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
2849a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    virtual ~GrArithmeticEffect();
2859a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
286b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE;
2879a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
288b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    typedef GrGLArithmeticEffect GLProcessor;
2899a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    static const char* Name() { return "Arithmetic"; }
29086fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org    GrTexture* backgroundTexture() const { return fBackgroundAccess.getTexture(); }
2919a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
2929a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
2939a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
2949a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    float k1() const { return fK1; }
2959a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    float k2() const { return fK2; }
2969a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    float k3() const { return fK3; }
2979a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    float k4() const { return fK4; }
29851a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    bool enforcePMColor() const { return fEnforcePMColor; }
2999a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
3009a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgprivate:
301b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE;
3029a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
30351a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    GrArithmeticEffect(float k1, float k2, float k3, float k4, bool enforcePMColor,
30451a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org                       GrTexture* background);
3059a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    float                       fK1, fK2, fK3, fK4;
30651a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    bool                        fEnforcePMColor;
30777af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com    GrCoordTransform            fBackgroundTransform;
30886fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org    GrTextureAccess             fBackgroundAccess;
3099a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
310b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
311b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    typedef GrFragmentProcessor INHERITED;
3129a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
3139a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org};
3149a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
3159a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
3169a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
31786fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.orgGrArithmeticEffect::GrArithmeticEffect(float k1, float k2, float k3, float k4,
31851a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org                                       bool enforcePMColor, GrTexture* background)
31951a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org  : fK1(k1), fK2(k2), fK3(k3), fK4(k4), fEnforcePMColor(enforcePMColor) {
32086fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org    if (background) {
32177af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com        fBackgroundTransform.reset(kLocal_GrCoordSet, background);
32277af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com        this->addCoordTransform(&fBackgroundTransform);
32386fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org        fBackgroundAccess.reset(background);
32486fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org        this->addTextureAccess(&fBackgroundAccess);
32586fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org    } else {
32686fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org        this->setWillReadDstColor();
32786fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org    }
3289a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org}
3299a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
3309a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgGrArithmeticEffect::~GrArithmeticEffect() {
3319a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org}
3329a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
333b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool GrArithmeticEffect::onIsEqual(const GrProcessor& sBase) const {
33449586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt    const GrArithmeticEffect& s = sBase.cast<GrArithmeticEffect>();
3359a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    return fK1 == s.fK1 &&
3369a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org           fK2 == s.fK2 &&
3379a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org           fK3 == s.fK3 &&
33886fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org           fK4 == s.fK4 &&
33951a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org           fEnforcePMColor == s.fEnforcePMColor &&
34086fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org           backgroundTexture() == s.backgroundTexture();
3419a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org}
3429a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
343b0a8a377f832c59cee939ad721e1f87d378b7142joshualittconst GrBackendFragmentProcessorFactory& GrArithmeticEffect::getFactory() const {
344b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    return GrTBackendFragmentProcessorFactory<GrArithmeticEffect>::getInstance();
3459a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org}
3469a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
3479a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgvoid GrArithmeticEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
3489a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    // TODO: optimize this
3499a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    *validFlags = 0;
3509a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org}
3519a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
3529a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
3539a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
354b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrGLArithmeticEffect::GrGLArithmeticEffect(const GrBackendProcessorFactory& factory,
355b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                           const GrProcessor&)
35651a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org   : INHERITED(factory),
35751a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org     fEnforcePMColor(true) {
3589a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org}
3599a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
3609a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgGrGLArithmeticEffect::~GrGLArithmeticEffect() {
3619a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org}
3629a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
36330ba436f04e61d4505fb854d5fc56079636e0788joshualittvoid GrGLArithmeticEffect::emitCode(GrGLProgramBuilder* builder,
364b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                    const GrFragmentProcessor& fp,
365b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                    const GrProcessorKey& key,
3669a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org                                    const char* outputColor,
3679a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org                                    const char* inputColor,
36877af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com                                    const TransformedCoordsArray& coords,
3699a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org                                    const TextureSamplerArray& samplers) {
37086fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org
371b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GrTexture* backgroundTex = fp.cast<GrArithmeticEffect>().backgroundTexture();
37230ba436f04e61d4505fb854d5fc56079636e0788joshualitt    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
37386fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org    const char* dstColor;
37486fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org    if (backgroundTex) {
37530ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppend("\t\tvec4 bgColor = ");
37623e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt        fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType());
37730ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppendf(";\n");
37886fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org        dstColor = "bgColor";
37986fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org    } else {
38030ba436f04e61d4505fb854d5fc56079636e0788joshualitt        dstColor = fsBuilder->dstColor();
38186fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org    }
38286fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org
38349f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(dstColor);
38430ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fKUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
3859a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org                                kVec4f_GrSLType, "k");
3869a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    const char* kUni = builder->getUniformCStr(fKUni);
3879a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
3889a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    // We don't try to optimize for this case at all
3899a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    if (NULL == inputColor) {
39030ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppendf("\t\tconst vec4 src = vec4(1);\n");
3919a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    } else {
39230ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppendf("\t\tvec4 src = %s;\n", inputColor);
393b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org        if (gUseUnpremul) {
39430ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\tsrc.rgb = clamp(src.rgb / src.a, 0.0, 1.0);\n");
395b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org        }
3969a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    }
3979a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
39830ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\tvec4 dst = %s;\n", dstColor);
399b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org    if (gUseUnpremul) {
40030ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppendf("\t\tdst.rgb = clamp(dst.rgb / dst.a, 0.0, 1.0);\n");
401b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org    }
4029a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
40330ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\t%s = %s.x * src * dst + %s.y * src + %s.z * dst + %s.w;\n", outputColor, kUni, kUni, kUni, kUni);
40430ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\t%s = clamp(%s, 0.0, 1.0);\n", outputColor, outputColor);
405b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org    if (gUseUnpremul) {
40630ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor);
40751a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    } else if (fEnforcePMColor) {
40830ba436f04e61d4505fb854d5fc56079636e0788joshualitt        fsBuilder->codeAppendf("\t\t%s.rgb = min(%s.rgb, %s.a);\n", outputColor, outputColor, outputColor);
409b1b3d5122eab334f567d699d2afea641204f2acfsenorblanco@chromium.org    }
4109a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org}
4119a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
412b0a8a377f832c59cee939ad721e1f87d378b7142joshualittvoid GrGLArithmeticEffect::setData(const GrGLProgramDataManager& pdman,
413b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                   const GrProcessor& processor) {
414b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    const GrArithmeticEffect& arith = processor.cast<GrArithmeticEffect>();
4157510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set4f(fKUni, arith.k1(), arith.k2(), arith.k3(), arith.k4());
41651a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    fEnforcePMColor = arith.enforcePMColor();
41751a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org}
41851a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org
419b0a8a377f832c59cee939ad721e1f87d378b7142joshualittvoid GrGLArithmeticEffect::GenKey(const GrProcessor& processor,
420b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                  const GrGLCaps&, GrProcessorKeyBuilder* b) {
421b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    const GrArithmeticEffect& arith = processor.cast<GrArithmeticEffect>();
42263e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon    uint32_t key = arith.enforcePMColor() ? 1 : 0;
42351a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    if (arith.backgroundTexture()) {
42451a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org        key |= 2;
42551a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    }
42663e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon    b->add32(key);
4279a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org}
4289a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
429b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrFragmentProcessor* GrArithmeticEffect::TestCreate(SkRandom* rand,
430b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                    GrContext*,
431b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                    const GrDrawTargetCaps&,
432b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                    GrTexture*[]) {
4339a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    float k1 = rand->nextF();
4349a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    float k2 = rand->nextF();
4359a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    float k3 = rand->nextF();
4369a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    float k4 = rand->nextF();
43751a11b7f2f7c0021022004d0d4b0924a590990f9commit-bot@chromium.org    bool enforcePMColor = rand->nextBool();
4389a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
43955fad7af61c21d502acb9891d631e8aa29e3628cbsalomon    return SkNEW_ARGS(GrArithmeticEffect, (k1, k2, k3, k4, enforcePMColor, NULL));
4409a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org}
4419a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
442b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrArithmeticEffect);
443b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt
444b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool SkArithmeticMode_scalar::asFragmentProcessor(GrFragmentProcessor** fp,
445b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                  GrTexture* background) const {
446b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    if (fp) {
447b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        *fp = GrArithmeticEffect::Create(SkScalarToFloat(fK[0]),
448b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                         SkScalarToFloat(fK[1]),
449b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                         SkScalarToFloat(fK[2]),
450b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                         SkScalarToFloat(fK[3]),
451b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                         fEnforcePMColor,
452b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                         background);
4539a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    }
4549a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    return true;
4559a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org}
4569a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
4579a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org#endif
4589a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org
4599a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkArithmeticMode)
4609a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.org    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkArithmeticMode_scalar)
4619a6eb0e1e8a8de7371cd9604f34619b8f87de66fsenorblanco@chromium.orgSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
462