116a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel/*
216a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel * Copyright 2015 Google Inc.
316a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel *
416a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel * Use of this source code is governed by a BSD-style license that can be
516a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel * found in the LICENSE file.
616a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel */
716a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
816a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel#include "SkArithmeticMode_gpu.h"
916a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
1016a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel#if SK_SUPPORT_GPU
1116a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel#include "GrContext.h"
1216a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel#include "GrFragmentProcessor.h"
1316a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel#include "GrInvariantOutput.h"
1416a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel#include "GrProcessor.h"
1516a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel#include "GrTexture.h"
1616a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel#include "gl/GrGLCaps.h"
1716a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel#include "gl/GrGLProcessor.h"
1816a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel#include "gl/GrGLProgramDataManager.h"
1916a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel#include "gl/builders/GrGLProgramBuilder.h"
2016a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
2116a04b84147867b62f92969ac8f4f4a9ab009aeaegdanielstatic const bool gUseUnpremul = false;
2216a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
2329bee0fe657fabf7c396502b69c9167fba13eaaaegdanielstatic void add_arithmetic_code(GrGLFragmentBuilder* fsBuilder,
24f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                                const char* inputColor,
25f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                                const char* dstColor,
26f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                                const char* outputColor,
27f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                                const char* kUni,
28f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                                bool enforcePMColor) {
29f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    // We don't try to optimize for this case at all
30f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    if (NULL == inputColor) {
31f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        fsBuilder->codeAppend("const vec4 src = vec4(1);");
32f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    } else {
33f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        fsBuilder->codeAppendf("vec4 src = %s;", inputColor);
34f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        if (gUseUnpremul) {
35f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel            fsBuilder->codeAppend("src.rgb = clamp(src.rgb / src.a, 0.0, 1.0);");
36f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        }
37f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    }
38f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel
39f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    fsBuilder->codeAppendf("vec4 dst = %s;", dstColor);
40f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    if (gUseUnpremul) {
41f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        fsBuilder->codeAppend("dst.rgb = clamp(dst.rgb / dst.a, 0.0, 1.0);");
42f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    }
43f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel
44f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    fsBuilder->codeAppendf("%s = %s.x * src * dst + %s.y * src + %s.z * dst + %s.w;",
45f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                           outputColor, kUni, kUni, kUni, kUni);
46f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    fsBuilder->codeAppendf("%s = clamp(%s, 0.0, 1.0);\n", outputColor, outputColor);
47f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    if (gUseUnpremul) {
48f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        fsBuilder->codeAppendf("%s.rgb *= %s.a;", outputColor, outputColor);
49f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    } else if (enforcePMColor) {
50f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        fsBuilder->codeAppendf("%s.rgb = min(%s.rgb, %s.a);",
51f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                               outputColor, outputColor, outputColor);
52f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    }
53f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel}
54f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel
5516a04b84147867b62f92969ac8f4f4a9ab009aeaegdanielclass GLArithmeticFP : public GrGLFragmentProcessor {
5616a04b84147867b62f92969ac8f4f4a9ab009aeaegdanielpublic:
57f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    GLArithmeticFP(const GrProcessor&)
58f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        : fEnforcePMColor(true) {
59f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    }
6016a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
6136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    ~GLArithmeticFP() override {}
62f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel
63f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    void emitCode(GrGLFPBuilder* builder,
64f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                  const GrFragmentProcessor& fp,
65f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                  const char* outputColor,
66f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                  const char* inputColor,
67f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                  const TransformedCoordsArray& coords,
6836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                  const TextureSamplerArray& samplers) override {
6929bee0fe657fabf7c396502b69c9167fba13eaaaegdaniel        GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
70f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        fsBuilder->codeAppend("vec4 bgColor = ");
71f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType());
72f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        fsBuilder->codeAppendf(";");
73f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        const char* dstColor = "bgColor";
74f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel
75f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        fKUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
76f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                                    kVec4f_GrSLType, kDefault_GrSLPrecision,
77f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                                    "k");
78f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        const char* kUni = builder->getUniformCStr(fKUni);
79f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel
80f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        add_arithmetic_code(fsBuilder, inputColor, dstColor, outputColor, kUni, fEnforcePMColor);
81f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    }
8216a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
8336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void setData(const GrGLProgramDataManager& pdman, const GrProcessor& proc) override {
84f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        const GrArithmeticFP& arith = proc.cast<GrArithmeticFP>();
85f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        pdman.set4f(fKUni, arith.k1(), arith.k2(), arith.k3(), arith.k4());
86f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        fEnforcePMColor = arith.enforcePMColor();
87f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    }
8816a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
89cfc18867d982119d9dc2888bf09f1093012daaddjvanverth    static void GenKey(const GrProcessor& proc, const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) {
90f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        const GrArithmeticFP& arith = proc.cast<GrArithmeticFP>();
91f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        uint32_t key = arith.enforcePMColor() ? 1 : 0;
92f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        b->add32(key);
93f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    }
9416a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
9516a04b84147867b62f92969ac8f4f4a9ab009aeaegdanielprivate:
9616a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel    GrGLProgramDataManager::UniformHandle fKUni;
9716a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel    bool fEnforcePMColor;
9816a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
9916a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel    typedef GrGLFragmentProcessor INHERITED;
10016a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel};
10116a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
10216a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel///////////////////////////////////////////////////////////////////////////////
10316a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
10416a04b84147867b62f92969ac8f4f4a9ab009aeaegdanielGrArithmeticFP::GrArithmeticFP(float k1, float k2, float k3, float k4,
10516a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel                               bool enforcePMColor, GrTexture* background)
10616a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel  : fK1(k1), fK2(k2), fK3(k3), fK4(k4), fEnforcePMColor(enforcePMColor) {
10716a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel    this->initClassID<GrArithmeticFP>();
108f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel
109f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    SkASSERT(background);
110f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel
111f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    fBackgroundTransform.reset(kLocal_GrCoordSet, background,
112f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                               GrTextureParams::kNone_FilterMode);
113f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    this->addCoordTransform(&fBackgroundTransform);
114f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    fBackgroundAccess.reset(background);
115f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    this->addTextureAccess(&fBackgroundAccess);
11616a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel}
11716a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
118cfc18867d982119d9dc2888bf09f1093012daaddjvanverthvoid GrArithmeticFP::getGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const {
11916a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel    GLArithmeticFP::GenKey(*this, caps, b);
12016a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel}
12116a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
12216a04b84147867b62f92969ac8f4f4a9ab009aeaegdanielGrGLFragmentProcessor* GrArithmeticFP::createGLInstance() const {
12316a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel    return SkNEW_ARGS(GLArithmeticFP, (*this));
12416a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel}
12516a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
12616a04b84147867b62f92969ac8f4f4a9ab009aeaegdanielbool GrArithmeticFP::onIsEqual(const GrFragmentProcessor& fpBase) const {
12716a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel    const GrArithmeticFP& fp = fpBase.cast<GrArithmeticFP>();
12816a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel    return fK1 == fp.fK1 &&
12916a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel           fK2 == fp.fK2 &&
13016a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel           fK3 == fp.fK3 &&
13116a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel           fK4 == fp.fK4 &&
13216a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel           fEnforcePMColor == fp.fEnforcePMColor;
13316a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel}
13416a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
13516a04b84147867b62f92969ac8f4f4a9ab009aeaegdanielvoid GrArithmeticFP::onComputeInvariantOutput(GrInvariantOutput* inout) const {
13616a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel    // TODO: optimize this
13716a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel    inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
13816a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel}
13916a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
14016a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel///////////////////////////////////////////////////////////////////////////////
14116a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
142f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdanielGrFragmentProcessor* GrArithmeticFP::TestCreate(SkRandom* rand,
143f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                                                GrContext*,
144f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                                                const GrDrawTargetCaps&,
145f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                                                GrTexture* textures[]) {
146f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    float k1 = rand->nextF();
147f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    float k2 = rand->nextF();
148f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    float k3 = rand->nextF();
149f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    float k4 = rand->nextF();
150f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    bool enforcePMColor = rand->nextBool();
15116a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
152f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    return SkNEW_ARGS(GrArithmeticFP, (k1, k2, k3, k4, enforcePMColor, textures[0]));
15316a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel}
15416a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
155f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdanielGR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrArithmeticFP);
15616a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
157f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel///////////////////////////////////////////////////////////////////////////////
158f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel// Xfer Processor
159f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel///////////////////////////////////////////////////////////////////////////////
16016a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
16141d4f09356567ead0216e1a7e4110bd58822b81fegdanielclass ArithmeticXP : public GrXferProcessor {
16241d4f09356567ead0216e1a7e4110bd58822b81fegdanielpublic:
16341d4f09356567ead0216e1a7e4110bd58822b81fegdaniel    static GrXferProcessor* Create(float k1, float k2, float k3, float k4, bool enforcePMColor,
16441d4f09356567ead0216e1a7e4110bd58822b81fegdaniel                                   const GrDeviceCoordTexture* dstCopy,
16541d4f09356567ead0216e1a7e4110bd58822b81fegdaniel                                   bool willReadDstColor) {
16641d4f09356567ead0216e1a7e4110bd58822b81fegdaniel        return SkNEW_ARGS(ArithmeticXP, (k1, k2, k3, k4, enforcePMColor, dstCopy,
16741d4f09356567ead0216e1a7e4110bd58822b81fegdaniel                                         willReadDstColor));
16841d4f09356567ead0216e1a7e4110bd58822b81fegdaniel    }
16941d4f09356567ead0216e1a7e4110bd58822b81fegdaniel
17036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    ~ArithmeticXP() override {};
17141d4f09356567ead0216e1a7e4110bd58822b81fegdaniel
17236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    const char* name() const override { return "Arithmetic"; }
17341d4f09356567ead0216e1a7e4110bd58822b81fegdaniel
17436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    GrGLXferProcessor* createGLInstance() const override;
17541d4f09356567ead0216e1a7e4110bd58822b81fegdaniel
17636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    bool hasSecondaryOutput() const override { return false; }
17741d4f09356567ead0216e1a7e4110bd58822b81fegdaniel
17841d4f09356567ead0216e1a7e4110bd58822b81fegdaniel    float k1() const { return fK1; }
17941d4f09356567ead0216e1a7e4110bd58822b81fegdaniel    float k2() const { return fK2; }
18041d4f09356567ead0216e1a7e4110bd58822b81fegdaniel    float k3() const { return fK3; }
18141d4f09356567ead0216e1a7e4110bd58822b81fegdaniel    float k4() const { return fK4; }
18241d4f09356567ead0216e1a7e4110bd58822b81fegdaniel    bool enforcePMColor() const { return fEnforcePMColor; }
18341d4f09356567ead0216e1a7e4110bd58822b81fegdaniel
18441d4f09356567ead0216e1a7e4110bd58822b81fegdanielprivate:
18541d4f09356567ead0216e1a7e4110bd58822b81fegdaniel    ArithmeticXP(float k1, float k2, float k3, float k4, bool enforcePMColor,
18641d4f09356567ead0216e1a7e4110bd58822b81fegdaniel                   const GrDeviceCoordTexture* dstCopy, bool willReadDstColor);
18741d4f09356567ead0216e1a7e4110bd58822b81fegdaniel
188c19cdc254cc08f334b00c3b9fdb703818c8ca681egdaniel    GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI,
189c19cdc254cc08f334b00c3b9fdb703818c8ca681egdaniel                                                 const GrProcOptInfo& coveragePOI,
190c19cdc254cc08f334b00c3b9fdb703818c8ca681egdaniel                                                 bool doesStencilWrite,
191c19cdc254cc08f334b00c3b9fdb703818c8ca681egdaniel                                                 GrColor* overrideColor,
192c19cdc254cc08f334b00c3b9fdb703818c8ca681egdaniel                                                 const GrDrawTargetCaps& caps) override;
193c19cdc254cc08f334b00c3b9fdb703818c8ca681egdaniel
194cfc18867d982119d9dc2888bf09f1093012daaddjvanverth    void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
19541d4f09356567ead0216e1a7e4110bd58822b81fegdaniel
19636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    bool onIsEqual(const GrXferProcessor& xpBase) const override {
19741d4f09356567ead0216e1a7e4110bd58822b81fegdaniel        const ArithmeticXP& xp = xpBase.cast<ArithmeticXP>();
19841d4f09356567ead0216e1a7e4110bd58822b81fegdaniel        if (fK1 != xp.fK1 ||
19941d4f09356567ead0216e1a7e4110bd58822b81fegdaniel            fK2 != xp.fK2 ||
20041d4f09356567ead0216e1a7e4110bd58822b81fegdaniel            fK3 != xp.fK3 ||
20141d4f09356567ead0216e1a7e4110bd58822b81fegdaniel            fK4 != xp.fK4 ||
20241d4f09356567ead0216e1a7e4110bd58822b81fegdaniel            fEnforcePMColor != xp.fEnforcePMColor) {
20341d4f09356567ead0216e1a7e4110bd58822b81fegdaniel            return false;
20441d4f09356567ead0216e1a7e4110bd58822b81fegdaniel        }
20541d4f09356567ead0216e1a7e4110bd58822b81fegdaniel        return true;
20641d4f09356567ead0216e1a7e4110bd58822b81fegdaniel    }
20741d4f09356567ead0216e1a7e4110bd58822b81fegdaniel
20841d4f09356567ead0216e1a7e4110bd58822b81fegdaniel    float                       fK1, fK2, fK3, fK4;
20941d4f09356567ead0216e1a7e4110bd58822b81fegdaniel    bool                        fEnforcePMColor;
21041d4f09356567ead0216e1a7e4110bd58822b81fegdaniel
21141d4f09356567ead0216e1a7e4110bd58822b81fegdaniel    typedef GrXferProcessor INHERITED;
21241d4f09356567ead0216e1a7e4110bd58822b81fegdaniel};
21341d4f09356567ead0216e1a7e4110bd58822b81fegdaniel
21441d4f09356567ead0216e1a7e4110bd58822b81fegdaniel///////////////////////////////////////////////////////////////////////////////
21541d4f09356567ead0216e1a7e4110bd58822b81fegdaniel
216f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdanielclass GLArithmeticXP : public GrGLXferProcessor {
217f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdanielpublic:
218f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    GLArithmeticXP(const GrProcessor&)
219f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        : fEnforcePMColor(true) {
22016a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel    }
22116a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
22236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    ~GLArithmeticXP() override {}
223f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel
224cfc18867d982119d9dc2888bf09f1093012daaddjvanverth    static void GenKey(const GrProcessor& processor, const GrGLSLCaps& caps,
22550785a3d10b53bea5beb6e18431a2449860be237bsalomon                       GrProcessorKeyBuilder* b) {
22641d4f09356567ead0216e1a7e4110bd58822b81fegdaniel        const ArithmeticXP& arith = processor.cast<ArithmeticXP>();
22750785a3d10b53bea5beb6e18431a2449860be237bsalomon        uint32_t key = arith.enforcePMColor() ? 1 : 0;
22850785a3d10b53bea5beb6e18431a2449860be237bsalomon        b->add32(key);
22950785a3d10b53bea5beb6e18431a2449860be237bsalomon    }
23050785a3d10b53bea5beb6e18431a2449860be237bsalomon
23150785a3d10b53bea5beb6e18431a2449860be237bsalomonprivate:
23236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onEmitCode(const EmitArgs& args) override {
23329bee0fe657fabf7c396502b69c9167fba13eaaaegdaniel        GrGLXPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
234f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel
235f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        const char* dstColor = fsBuilder->dstColor();
236f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel
237f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        fKUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
238f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                                     kVec4f_GrSLType, kDefault_GrSLPrecision,
239f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                                     "k");
240f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        const char* kUni = args.fPB->getUniformCStr(fKUni);
241f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel
242f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        add_arithmetic_code(fsBuilder, args.fInputColor, dstColor, args.fOutputPrimary, kUni,
243f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                            fEnforcePMColor);
244f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel
245f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        fsBuilder->codeAppendf("%s = %s * %s + (vec4(1.0) - %s) * %s;",
246f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                               args.fOutputPrimary, args.fOutputPrimary, args.fInputCoverage,
247f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                               args.fInputCoverage, dstColor);
24816a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel    }
24916a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
25050785a3d10b53bea5beb6e18431a2449860be237bsalomon    void onSetData(const GrGLProgramDataManager& pdman,
25136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                   const GrXferProcessor& processor) override {
25241d4f09356567ead0216e1a7e4110bd58822b81fegdaniel        const ArithmeticXP& arith = processor.cast<ArithmeticXP>();
253f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        pdman.set4f(fKUni, arith.k1(), arith.k2(), arith.k3(), arith.k4());
254f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel        fEnforcePMColor = arith.enforcePMColor();
255f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    };
256f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel
257f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    GrGLProgramDataManager::UniformHandle fKUni;
258f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    bool fEnforcePMColor;
259f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel
260f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    typedef GrGLXferProcessor INHERITED;
261f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel};
262f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel
263f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel///////////////////////////////////////////////////////////////////////////////
264f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel
26541d4f09356567ead0216e1a7e4110bd58822b81fegdanielArithmeticXP::ArithmeticXP(float k1, float k2, float k3, float k4, bool enforcePMColor,
26641d4f09356567ead0216e1a7e4110bd58822b81fegdaniel                           const GrDeviceCoordTexture* dstCopy, bool willReadDstColor)
26750785a3d10b53bea5beb6e18431a2449860be237bsalomon    : INHERITED(dstCopy, willReadDstColor)
26850785a3d10b53bea5beb6e18431a2449860be237bsalomon    , fK1(k1)
269f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    , fK2(k2)
270f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    , fK3(k3)
271f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    , fK4(k4)
272f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    , fEnforcePMColor(enforcePMColor) {
27341d4f09356567ead0216e1a7e4110bd58822b81fegdaniel    this->initClassID<ArithmeticXP>();
27416a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel}
27516a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
276cfc18867d982119d9dc2888bf09f1093012daaddjvanverthvoid ArithmeticXP::onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const {
277f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    GLArithmeticXP::GenKey(*this, caps, b);
27816a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel}
27916a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
28041d4f09356567ead0216e1a7e4110bd58822b81fegdanielGrGLXferProcessor* ArithmeticXP::createGLInstance() const {
281f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    return SkNEW_ARGS(GLArithmeticXP, (*this));
28216a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel}
28316a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
284c19cdc254cc08f334b00c3b9fdb703818c8ca681egdanielGrXferProcessor::OptFlags ArithmeticXP::onGetOptimizations(const GrProcOptInfo& colorPOI,
285c19cdc254cc08f334b00c3b9fdb703818c8ca681egdaniel                                                           const GrProcOptInfo& coveragePOI,
286c19cdc254cc08f334b00c3b9fdb703818c8ca681egdaniel                                                           bool doesStencilWrite,
287c19cdc254cc08f334b00c3b9fdb703818c8ca681egdaniel                                                           GrColor* overrideColor,
288c19cdc254cc08f334b00c3b9fdb703818c8ca681egdaniel                                                           const GrDrawTargetCaps& caps) {
289f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel   return GrXferProcessor::kNone_Opt;
290f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel}
29116a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
292f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel///////////////////////////////////////////////////////////////////////////////
293f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel
294f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdanielGrArithmeticXPFactory::GrArithmeticXPFactory(float k1, float k2, float k3, float k4,
295f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                                             bool enforcePMColor)
296f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    : fK1(k1), fK2(k2), fK3(k3), fK4(k4), fEnforcePMColor(enforcePMColor) {
29754f0e9d784122cfd3f5968e0fea971d5b5a4805aegdaniel    this->initClassID<GrArithmeticXPFactory>();
29816a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel}
29916a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
30041d4f09356567ead0216e1a7e4110bd58822b81fegdanielGrXferProcessor*
3013ad6570e94965d54871eaea8b314f560b82ca792egdanielGrArithmeticXPFactory::onCreateXferProcessor(const GrDrawTargetCaps& caps,
3023ad6570e94965d54871eaea8b314f560b82ca792egdaniel                                             const GrProcOptInfo& colorPOI,
30341d4f09356567ead0216e1a7e4110bd58822b81fegdaniel                                             const GrProcOptInfo& coveragePOI,
30441d4f09356567ead0216e1a7e4110bd58822b81fegdaniel                                             const GrDeviceCoordTexture* dstCopy) const {
30541d4f09356567ead0216e1a7e4110bd58822b81fegdaniel    return ArithmeticXP::Create(fK1, fK2, fK3, fK4, fEnforcePMColor, dstCopy,
3063ad6570e94965d54871eaea8b314f560b82ca792egdaniel                                this->willReadDstColor(caps, colorPOI, coveragePOI));
30741d4f09356567ead0216e1a7e4110bd58822b81fegdaniel}
30841d4f09356567ead0216e1a7e4110bd58822b81fegdaniel
30941d4f09356567ead0216e1a7e4110bd58822b81fegdaniel
310f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdanielvoid GrArithmeticXPFactory::getInvariantOutput(const GrProcOptInfo& colorPOI,
311f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                                               const GrProcOptInfo& coveragePOI,
312f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                                               GrXPFactory::InvariantOutput* output) const {
313f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    output->fWillBlendWithDst = true;
314f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel
315f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    // TODO: We could try to optimize this more. For example if we have solid coverage and fK1 and
316f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    // fK3 are zero, then we won't be blending the color with dst at all so we can know what the
317f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    // output color is (up to the valid color components passed in).
318f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    output->fBlendedColorFlags = 0;
319f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel}
320f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel
321f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdanielGR_DEFINE_XP_FACTORY_TEST(GrArithmeticXPFactory);
322f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel
323f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdanielGrXPFactory* GrArithmeticXPFactory::TestCreate(SkRandom* random,
324f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                                               GrContext*,
325f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                                               const GrDrawTargetCaps&,
326f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel                                               GrTexture*[]) {
327f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    float k1 = random->nextF();
328f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    float k2 = random->nextF();
329f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    float k3 = random->nextF();
330f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    float k4 = random->nextF();
331f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    bool enforcePMColor = random->nextBool();
332f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel
333f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel    return GrArithmeticXPFactory::Create(k1, k2, k3, k4, enforcePMColor);
334f351aa3bf1b1d7639be8e1e6a35137b89a8dd93degdaniel}
33516a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel
33616a04b84147867b62f92969ac8f4f4a9ab009aeaegdaniel#endif
337