1378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel/*
2378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel * Copyright 2014 Google Inc.
3378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel *
4378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel * Use of this source code is governed by a BSD-style license that can be
5378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel * found in the LICENSE file.
6378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel */
7378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel
8ced90108b763b1eb3bd7f78b5614d4643b577a24egdaniel#include "effects/GrPorterDuffXferProcessor.h"
9378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel
109513143efa734bef0c1a0c7f945022572dbc8518egdaniel#include "GrBlend.h"
11eb1cb5c5b50febad115d859faca91d2d6af3fff2bsalomon#include "GrCaps.h"
12de4166a3b45d859512e27e3257841f064d67549cethannicholas#include "GrPipeline.h"
13378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel#include "GrProcessor.h"
14a811b1200cc0b5e3819c89f62def23ec203d4b5aBrian Salomon#include "GrProcessorAnalysis.h"
15378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel#include "GrTypes.h"
16378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel#include "GrXferProcessor.h"
1764c4728c70001ed074fecf5c4e083781987b12e9egdaniel#include "glsl/GrGLSLBlend.h"
182d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel#include "glsl/GrGLSLFragmentShaderBuilder.h"
19018fb62d12d1febf121fe265da5b6117b86a6541egdaniel#include "glsl/GrGLSLProgramDataManager.h"
207ea439b2203855db97330b25945b87dd4b170b8begdaniel#include "glsl/GrGLSLUniformHandler.h"
21fa4cc8bf2aa782431609dd2ac16b1fc36de72e44egdaniel#include "glsl/GrGLSLXferProcessor.h"
22378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel
236fd158ea47472c4d038e48980a95e36623f840c9cdalton/**
246fd158ea47472c4d038e48980a95e36623f840c9cdalton * Wraps the shader outputs and HW blend state that comprise a Porter Duff blend mode with coverage.
256fd158ea47472c4d038e48980a95e36623f840c9cdalton */
267b29749c13deab4588cbe0414a93191326800712Brian Salomonclass BlendFormula {
276fd158ea47472c4d038e48980a95e36623f840c9cdaltonpublic:
286fd158ea47472c4d038e48980a95e36623f840c9cdalton    /**
296fd158ea47472c4d038e48980a95e36623f840c9cdalton     * Values the shader can write to primary and secondary outputs. These must all be modulated by
306fd158ea47472c4d038e48980a95e36623f840c9cdalton     * coverage to support mixed samples. The XP will ignore the multiplies when not using coverage.
319513143efa734bef0c1a0c7f945022572dbc8518egdaniel     */
326fd158ea47472c4d038e48980a95e36623f840c9cdalton    enum OutputType {
336fd158ea47472c4d038e48980a95e36623f840c9cdalton        kNone_OutputType,        //<! 0
346fd158ea47472c4d038e48980a95e36623f840c9cdalton        kCoverage_OutputType,    //<! inputCoverage
356fd158ea47472c4d038e48980a95e36623f840c9cdalton        kModulate_OutputType,    //<! inputColor * inputCoverage
36723b0501e22373bb3e6c306daaceae02cda8a124egdaniel        kSAModulate_OutputType,  //<! inputColor.a * inputCoverage
376fd158ea47472c4d038e48980a95e36623f840c9cdalton        kISAModulate_OutputType, //<! (1 - inputColor.a) * inputCoverage
386fd158ea47472c4d038e48980a95e36623f840c9cdalton        kISCModulate_OutputType, //<! (1 - inputColor) * inputCoverage
396fd158ea47472c4d038e48980a95e36623f840c9cdalton
406fd158ea47472c4d038e48980a95e36623f840c9cdalton        kLast_OutputType = kISCModulate_OutputType
416fd158ea47472c4d038e48980a95e36623f840c9cdalton    };
429513143efa734bef0c1a0c7f945022572dbc8518egdaniel
437b29749c13deab4588cbe0414a93191326800712Brian Salomon    BlendFormula() = default;
446fd158ea47472c4d038e48980a95e36623f840c9cdalton
457b29749c13deab4588cbe0414a93191326800712Brian Salomon    constexpr BlendFormula(OutputType primaryOut, OutputType secondaryOut, GrBlendEquation equation,
467b29749c13deab4588cbe0414a93191326800712Brian Salomon                           GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff)
477b29749c13deab4588cbe0414a93191326800712Brian Salomon            : fPrimaryOutputType(primaryOut)
487b29749c13deab4588cbe0414a93191326800712Brian Salomon            , fSecondaryOutputType(secondaryOut)
497b29749c13deab4588cbe0414a93191326800712Brian Salomon            , fBlendEquation(equation)
507b29749c13deab4588cbe0414a93191326800712Brian Salomon            , fSrcCoeff(srcCoeff)
517b29749c13deab4588cbe0414a93191326800712Brian Salomon            , fDstCoeff(dstCoeff)
527b29749c13deab4588cbe0414a93191326800712Brian Salomon            , fProps(GetProperties(primaryOut, secondaryOut, equation, srcCoeff, dstCoeff)) {}
5341d4f09356567ead0216e1a7e4110bd58822b81fegdaniel
547b29749c13deab4588cbe0414a93191326800712Brian Salomon    BlendFormula& operator=(const BlendFormula& other) {
557b29749c13deab4588cbe0414a93191326800712Brian Salomon        SkDEBUGCODE(other.validatePreoptimized());
566fd158ea47472c4d038e48980a95e36623f840c9cdalton        fData = other.fData;
576fd158ea47472c4d038e48980a95e36623f840c9cdalton        return *this;
586fd158ea47472c4d038e48980a95e36623f840c9cdalton    }
5941d4f09356567ead0216e1a7e4110bd58822b81fegdaniel
607b29749c13deab4588cbe0414a93191326800712Brian Salomon    bool operator==(const BlendFormula& other) const {
617b29749c13deab4588cbe0414a93191326800712Brian Salomon        SkDEBUGCODE(this->validatePreoptimized());
627b29749c13deab4588cbe0414a93191326800712Brian Salomon        SkDEBUGCODE(other.validatePreoptimized());
636fd158ea47472c4d038e48980a95e36623f840c9cdalton        return fData == other.fData;
646fd158ea47472c4d038e48980a95e36623f840c9cdalton    }
6541d4f09356567ead0216e1a7e4110bd58822b81fegdaniel
667b29749c13deab4588cbe0414a93191326800712Brian Salomon    bool hasSecondaryOutput() const {
677b29749c13deab4588cbe0414a93191326800712Brian Salomon        SkDEBUGCODE(this->validatePreoptimized());
687b29749c13deab4588cbe0414a93191326800712Brian Salomon        return kNone_OutputType != fSecondaryOutputType;
697b29749c13deab4588cbe0414a93191326800712Brian Salomon    }
707b29749c13deab4588cbe0414a93191326800712Brian Salomon    bool modifiesDst() const {
717b29749c13deab4588cbe0414a93191326800712Brian Salomon        SkDEBUGCODE(this->validatePreoptimized());
727b29749c13deab4588cbe0414a93191326800712Brian Salomon        return SkToBool(fProps & kModifiesDst_Property);
737b29749c13deab4588cbe0414a93191326800712Brian Salomon    }
747b29749c13deab4588cbe0414a93191326800712Brian Salomon    bool usesDstColor() const {
757b29749c13deab4588cbe0414a93191326800712Brian Salomon        SkDEBUGCODE(this->validatePreoptimized());
767b29749c13deab4588cbe0414a93191326800712Brian Salomon        return SkToBool(fProps & kUsesDstColor_Property);
777b29749c13deab4588cbe0414a93191326800712Brian Salomon    }
787b29749c13deab4588cbe0414a93191326800712Brian Salomon    bool usesInputColor() const {
797b29749c13deab4588cbe0414a93191326800712Brian Salomon        SkDEBUGCODE(this->validatePreoptimized());
807b29749c13deab4588cbe0414a93191326800712Brian Salomon        return SkToBool(fProps & kUsesInputColor_Property);
817b29749c13deab4588cbe0414a93191326800712Brian Salomon    }
826fd158ea47472c4d038e48980a95e36623f840c9cdalton    bool canTweakAlphaForCoverage() const {
837b29749c13deab4588cbe0414a93191326800712Brian Salomon        SkDEBUGCODE(this->validatePreoptimized());
846fd158ea47472c4d038e48980a95e36623f840c9cdalton        return SkToBool(fProps & kCanTweakAlphaForCoverage_Property);
856fd158ea47472c4d038e48980a95e36623f840c9cdalton    }
8641d4f09356567ead0216e1a7e4110bd58822b81fegdaniel
877b29749c13deab4588cbe0414a93191326800712Brian Salomon    GrBlendEquation equation() const {
887b29749c13deab4588cbe0414a93191326800712Brian Salomon        SkDEBUGCODE(this->validatePreoptimized());
897b29749c13deab4588cbe0414a93191326800712Brian Salomon        return fBlendEquation;
907b29749c13deab4588cbe0414a93191326800712Brian Salomon    }
917b29749c13deab4588cbe0414a93191326800712Brian Salomon
927b29749c13deab4588cbe0414a93191326800712Brian Salomon    GrBlendCoeff srcCoeff() const {
937b29749c13deab4588cbe0414a93191326800712Brian Salomon        SkDEBUGCODE(this->validatePreoptimized());
947b29749c13deab4588cbe0414a93191326800712Brian Salomon        return fSrcCoeff;
957b29749c13deab4588cbe0414a93191326800712Brian Salomon    }
967b29749c13deab4588cbe0414a93191326800712Brian Salomon
977b29749c13deab4588cbe0414a93191326800712Brian Salomon    GrBlendCoeff dstCoeff() const {
987b29749c13deab4588cbe0414a93191326800712Brian Salomon        SkDEBUGCODE(this->validatePreoptimized());
997b29749c13deab4588cbe0414a93191326800712Brian Salomon        return fDstCoeff;
1007b29749c13deab4588cbe0414a93191326800712Brian Salomon    }
1017b29749c13deab4588cbe0414a93191326800712Brian Salomon
1027b29749c13deab4588cbe0414a93191326800712Brian Salomon    OutputType primaryOutput() const {
1037b29749c13deab4588cbe0414a93191326800712Brian Salomon        SkDEBUGCODE(this->validatePreoptimized());
1047b29749c13deab4588cbe0414a93191326800712Brian Salomon        return fPrimaryOutputType;
1057b29749c13deab4588cbe0414a93191326800712Brian Salomon    }
1067b29749c13deab4588cbe0414a93191326800712Brian Salomon
1077b29749c13deab4588cbe0414a93191326800712Brian Salomon    OutputType secondaryOutput() const {
1087b29749c13deab4588cbe0414a93191326800712Brian Salomon        SkDEBUGCODE(this->validatePreoptimized());
1097b29749c13deab4588cbe0414a93191326800712Brian Salomon        return fSecondaryOutputType;
1107b29749c13deab4588cbe0414a93191326800712Brian Salomon    }
1117b29749c13deab4588cbe0414a93191326800712Brian Salomon
1127b29749c13deab4588cbe0414a93191326800712Brian Salomonprivate:
1137b29749c13deab4588cbe0414a93191326800712Brian Salomon    enum Properties {
1147b29749c13deab4588cbe0414a93191326800712Brian Salomon        kModifiesDst_Property              = 1,
1157b29749c13deab4588cbe0414a93191326800712Brian Salomon        kUsesDstColor_Property             = 1 << 1,
1167b29749c13deab4588cbe0414a93191326800712Brian Salomon        kUsesInputColor_Property           = 1 << 2,
1177b29749c13deab4588cbe0414a93191326800712Brian Salomon        kCanTweakAlphaForCoverage_Property = 1 << 3,
1187b29749c13deab4588cbe0414a93191326800712Brian Salomon
1197b29749c13deab4588cbe0414a93191326800712Brian Salomon        kLast_Property = kCanTweakAlphaForCoverage_Property
1207b29749c13deab4588cbe0414a93191326800712Brian Salomon    };
1217b29749c13deab4588cbe0414a93191326800712Brian Salomon    GR_DECL_BITFIELD_OPS_FRIENDS(Properties)
1227b29749c13deab4588cbe0414a93191326800712Brian Salomon
1237b29749c13deab4588cbe0414a93191326800712Brian Salomon#ifdef SK_DEBUG
1247b29749c13deab4588cbe0414a93191326800712Brian Salomon    void validatePreoptimized() const {
1257b29749c13deab4588cbe0414a93191326800712Brian Salomon        // The provided formula should already be optimized before a BlendFormula is constructed.
1267b29749c13deab4588cbe0414a93191326800712Brian Salomon        // Preferably these asserts would be done statically in the constexpr constructor, but this
1277b29749c13deab4588cbe0414a93191326800712Brian Salomon        // is not allowed in C++11.
1287b29749c13deab4588cbe0414a93191326800712Brian Salomon        SkASSERT((kNone_OutputType == fPrimaryOutputType) ==
1297b29749c13deab4588cbe0414a93191326800712Brian Salomon                 !GrBlendCoeffsUseSrcColor(fSrcCoeff, fDstCoeff));
1307b29749c13deab4588cbe0414a93191326800712Brian Salomon        SkASSERT(!GrBlendCoeffRefsSrc2(fSrcCoeff));
1317b29749c13deab4588cbe0414a93191326800712Brian Salomon        SkASSERT((kNone_OutputType == fSecondaryOutputType) == !GrBlendCoeffRefsSrc2(fDstCoeff));
1327b29749c13deab4588cbe0414a93191326800712Brian Salomon        SkASSERT(fPrimaryOutputType != fSecondaryOutputType ||
1337b29749c13deab4588cbe0414a93191326800712Brian Salomon                 kNone_OutputType == fPrimaryOutputType);
1347b29749c13deab4588cbe0414a93191326800712Brian Salomon        SkASSERT(kNone_OutputType != fPrimaryOutputType ||
1357b29749c13deab4588cbe0414a93191326800712Brian Salomon                 kNone_OutputType == fSecondaryOutputType);
1367b29749c13deab4588cbe0414a93191326800712Brian Salomon    }
1377b29749c13deab4588cbe0414a93191326800712Brian Salomon#endif
1387b29749c13deab4588cbe0414a93191326800712Brian Salomon
1396fd158ea47472c4d038e48980a95e36623f840c9cdalton    /**
1407b29749c13deab4588cbe0414a93191326800712Brian Salomon     * Deduce the properties of a BlendFormula.
1416fd158ea47472c4d038e48980a95e36623f840c9cdalton     */
1427b29749c13deab4588cbe0414a93191326800712Brian Salomon    static constexpr Properties GetProperties(OutputType PrimaryOut, OutputType SecondaryOut,
1437b29749c13deab4588cbe0414a93191326800712Brian Salomon                                              GrBlendEquation BlendEquation, GrBlendCoeff SrcCoeff,
1447b29749c13deab4588cbe0414a93191326800712Brian Salomon                                              GrBlendCoeff DstCoeff);
145c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman
1466fd158ea47472c4d038e48980a95e36623f840c9cdalton    union {
1476fd158ea47472c4d038e48980a95e36623f840c9cdalton        struct {
1486fd158ea47472c4d038e48980a95e36623f840c9cdalton            // We allot the enums one more bit than they require because MSVC seems to sign-extend
1496fd158ea47472c4d038e48980a95e36623f840c9cdalton            // them when the top bit is set. (This is in violation of the C++03 standard 9.6/4)
1506fd158ea47472c4d038e48980a95e36623f840c9cdalton            OutputType        fPrimaryOutputType    : 4;
1516fd158ea47472c4d038e48980a95e36623f840c9cdalton            OutputType        fSecondaryOutputType  : 4;
1526fd158ea47472c4d038e48980a95e36623f840c9cdalton            GrBlendEquation   fBlendEquation        : 6;
1536fd158ea47472c4d038e48980a95e36623f840c9cdalton            GrBlendCoeff      fSrcCoeff             : 6;
1546fd158ea47472c4d038e48980a95e36623f840c9cdalton            GrBlendCoeff      fDstCoeff             : 6;
1556fd158ea47472c4d038e48980a95e36623f840c9cdalton            Properties        fProps                : 32 - (4 + 4 + 6 + 6 + 6);
1566fd158ea47472c4d038e48980a95e36623f840c9cdalton        };
1576fd158ea47472c4d038e48980a95e36623f840c9cdalton        uint32_t fData;
158c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman    };
15941d4f09356567ead0216e1a7e4110bd58822b81fegdaniel
1606fd158ea47472c4d038e48980a95e36623f840c9cdalton    GR_STATIC_ASSERT(kLast_OutputType      < (1 << 3));
1616fd158ea47472c4d038e48980a95e36623f840c9cdalton    GR_STATIC_ASSERT(kLast_GrBlendEquation < (1 << 5));
1626fd158ea47472c4d038e48980a95e36623f840c9cdalton    GR_STATIC_ASSERT(kLast_GrBlendCoeff    < (1 << 5));
1636fd158ea47472c4d038e48980a95e36623f840c9cdalton    GR_STATIC_ASSERT(kLast_Property        < (1 << 6));
1646fd158ea47472c4d038e48980a95e36623f840c9cdalton};
1656fd158ea47472c4d038e48980a95e36623f840c9cdalton
1666fd158ea47472c4d038e48980a95e36623f840c9cdaltonGR_STATIC_ASSERT(4 == sizeof(BlendFormula));
1676fd158ea47472c4d038e48980a95e36623f840c9cdalton
1686fd158ea47472c4d038e48980a95e36623f840c9cdaltonGR_MAKE_BITFIELD_OPS(BlendFormula::Properties);
1696fd158ea47472c4d038e48980a95e36623f840c9cdalton
1707b29749c13deab4588cbe0414a93191326800712Brian Salomonconstexpr BlendFormula::Properties BlendFormula::GetProperties(OutputType PrimaryOut,
1717b29749c13deab4588cbe0414a93191326800712Brian Salomon                                                               OutputType SecondaryOut,
1727b29749c13deab4588cbe0414a93191326800712Brian Salomon                                                               GrBlendEquation BlendEquation,
1737b29749c13deab4588cbe0414a93191326800712Brian Salomon                                                               GrBlendCoeff SrcCoeff,
1747b29749c13deab4588cbe0414a93191326800712Brian Salomon                                                               GrBlendCoeff DstCoeff) {
1757b29749c13deab4588cbe0414a93191326800712Brian Salomon    return static_cast<Properties>(
1767b29749c13deab4588cbe0414a93191326800712Brian Salomon            (GrBlendModifiesDst(BlendEquation, SrcCoeff, DstCoeff) ? kModifiesDst_Property : 0) |
1777b29749c13deab4588cbe0414a93191326800712Brian Salomon            (GrBlendCoeffsUseDstColor(SrcCoeff, DstCoeff) ? kUsesDstColor_Property : 0) |
1787b29749c13deab4588cbe0414a93191326800712Brian Salomon            ((PrimaryOut >= kModulate_OutputType && GrBlendCoeffsUseSrcColor(SrcCoeff, DstCoeff)) ||
1797b29749c13deab4588cbe0414a93191326800712Brian Salomon                             (SecondaryOut >= kModulate_OutputType &&
1807b29749c13deab4588cbe0414a93191326800712Brian Salomon                              GrBlendCoeffRefsSrc2(DstCoeff))
1817b29749c13deab4588cbe0414a93191326800712Brian Salomon                     ? kUsesInputColor_Property
1827b29749c13deab4588cbe0414a93191326800712Brian Salomon                     : 0) |  // We assert later that SrcCoeff doesn't ref src2.
1837b29749c13deab4588cbe0414a93191326800712Brian Salomon            ((kModulate_OutputType == PrimaryOut || kNone_OutputType == PrimaryOut) &&
1847b29749c13deab4588cbe0414a93191326800712Brian Salomon                             kNone_OutputType == SecondaryOut &&
1857b29749c13deab4588cbe0414a93191326800712Brian Salomon                             GrBlendAllowsCoverageAsAlpha(BlendEquation, SrcCoeff, DstCoeff)
1867b29749c13deab4588cbe0414a93191326800712Brian Salomon                     ? kCanTweakAlphaForCoverage_Property
1877b29749c13deab4588cbe0414a93191326800712Brian Salomon                     : 0));
1887b29749c13deab4588cbe0414a93191326800712Brian Salomon}
1896fd158ea47472c4d038e48980a95e36623f840c9cdalton
1906fd158ea47472c4d038e48980a95e36623f840c9cdalton/**
1916fd158ea47472c4d038e48980a95e36623f840c9cdalton * When there is no coverage, or the blend mode can tweak alpha for coverage, we use the standard
1926fd158ea47472c4d038e48980a95e36623f840c9cdalton * Porter Duff formula.
1936fd158ea47472c4d038e48980a95e36623f840c9cdalton */
1947b29749c13deab4588cbe0414a93191326800712Brian Salomonstatic constexpr BlendFormula MakeCoeffFormula(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
1957b29749c13deab4588cbe0414a93191326800712Brian Salomon    // When the coeffs are (Zero, Zero) or (Zero, One) we set the primary output to none.
1967b29749c13deab4588cbe0414a93191326800712Brian Salomon    return (kZero_GrBlendCoeff == srcCoeff &&
1977b29749c13deab4588cbe0414a93191326800712Brian Salomon            (kZero_GrBlendCoeff == dstCoeff || kOne_GrBlendCoeff == dstCoeff))
1987b29749c13deab4588cbe0414a93191326800712Brian Salomon           ? BlendFormula(BlendFormula::kNone_OutputType, BlendFormula::kNone_OutputType,
1997b29749c13deab4588cbe0414a93191326800712Brian Salomon                          kAdd_GrBlendEquation, kZero_GrBlendCoeff, dstCoeff)
2007b29749c13deab4588cbe0414a93191326800712Brian Salomon           : BlendFormula(BlendFormula::kModulate_OutputType, BlendFormula::kNone_OutputType,
2017b29749c13deab4588cbe0414a93191326800712Brian Salomon                        kAdd_GrBlendEquation, srcCoeff, dstCoeff);
2027b29749c13deab4588cbe0414a93191326800712Brian Salomon}
2036fd158ea47472c4d038e48980a95e36623f840c9cdalton
2046fd158ea47472c4d038e48980a95e36623f840c9cdalton/**
2057b29749c13deab4588cbe0414a93191326800712Brian Salomon * Basic coeff formula similar to MakeCoeffFormula but we will make the src f*Sa. This is used in
206723b0501e22373bb3e6c306daaceae02cda8a124egdaniel * LCD dst-out.
207723b0501e22373bb3e6c306daaceae02cda8a124egdaniel */
2087b29749c13deab4588cbe0414a93191326800712Brian Salomonstatic constexpr BlendFormula MakeSAModulateFormula(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
2097b29749c13deab4588cbe0414a93191326800712Brian Salomon    return BlendFormula(BlendFormula::kSAModulate_OutputType, BlendFormula::kNone_OutputType,
2107b29749c13deab4588cbe0414a93191326800712Brian Salomon                        kAdd_GrBlendEquation, srcCoeff, dstCoeff);
2117b29749c13deab4588cbe0414a93191326800712Brian Salomon}
212c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman
2136fd158ea47472c4d038e48980a95e36623f840c9cdalton/**
2146fd158ea47472c4d038e48980a95e36623f840c9cdalton * When there is coverage, the equation with f=coverage is:
2156fd158ea47472c4d038e48980a95e36623f840c9cdalton *
2166fd158ea47472c4d038e48980a95e36623f840c9cdalton *   D' = f * (S * srcCoeff + D * dstCoeff) + (1-f) * D
2176fd158ea47472c4d038e48980a95e36623f840c9cdalton *
2186fd158ea47472c4d038e48980a95e36623f840c9cdalton * This can be rewritten as:
2196fd158ea47472c4d038e48980a95e36623f840c9cdalton *
2206fd158ea47472c4d038e48980a95e36623f840c9cdalton *   D' = f * S * srcCoeff + D * (1 - [f * (1 - dstCoeff)])
2216fd158ea47472c4d038e48980a95e36623f840c9cdalton *
2226fd158ea47472c4d038e48980a95e36623f840c9cdalton * To implement this formula, we output [f * (1 - dstCoeff)] for the secondary color and replace the
2236fd158ea47472c4d038e48980a95e36623f840c9cdalton * HW dst coeff with IS2C.
2246fd158ea47472c4d038e48980a95e36623f840c9cdalton *
2256fd158ea47472c4d038e48980a95e36623f840c9cdalton * Xfer modes: dst-atop (Sa!=1)
2266fd158ea47472c4d038e48980a95e36623f840c9cdalton */
2277b29749c13deab4588cbe0414a93191326800712Brian Salomonstatic constexpr BlendFormula MakeCoverageFormula(
2287b29749c13deab4588cbe0414a93191326800712Brian Salomon        BlendFormula::OutputType oneMinusDstCoeffModulateOutput, GrBlendCoeff srcCoeff) {
2297b29749c13deab4588cbe0414a93191326800712Brian Salomon    return BlendFormula(BlendFormula::kModulate_OutputType, oneMinusDstCoeffModulateOutput,
2307b29749c13deab4588cbe0414a93191326800712Brian Salomon                        kAdd_GrBlendEquation, srcCoeff, kIS2C_GrBlendCoeff);
2317b29749c13deab4588cbe0414a93191326800712Brian Salomon}
2326fd158ea47472c4d038e48980a95e36623f840c9cdalton
2336fd158ea47472c4d038e48980a95e36623f840c9cdalton/**
2346fd158ea47472c4d038e48980a95e36623f840c9cdalton * When there is coverage and the src coeff is Zero, the equation with f=coverage becomes:
2356fd158ea47472c4d038e48980a95e36623f840c9cdalton *
2366fd158ea47472c4d038e48980a95e36623f840c9cdalton *   D' = f * D * dstCoeff + (1-f) * D
2376fd158ea47472c4d038e48980a95e36623f840c9cdalton *
2386fd158ea47472c4d038e48980a95e36623f840c9cdalton * This can be rewritten as:
2396fd158ea47472c4d038e48980a95e36623f840c9cdalton *
2406fd158ea47472c4d038e48980a95e36623f840c9cdalton *   D' = D - D * [f * (1 - dstCoeff)]
2416fd158ea47472c4d038e48980a95e36623f840c9cdalton *
2426fd158ea47472c4d038e48980a95e36623f840c9cdalton * To implement this formula, we output [f * (1 - dstCoeff)] for the primary color and use a reverse
2436fd158ea47472c4d038e48980a95e36623f840c9cdalton * subtract HW blend equation with coeffs of (DC, One).
2446fd158ea47472c4d038e48980a95e36623f840c9cdalton *
2456fd158ea47472c4d038e48980a95e36623f840c9cdalton * Xfer modes: clear, dst-out (Sa=1), dst-in (Sa!=1), modulate (Sc!=1)
2466fd158ea47472c4d038e48980a95e36623f840c9cdalton */
2477b29749c13deab4588cbe0414a93191326800712Brian Salomonstatic constexpr BlendFormula MakeCoverageSrcCoeffZeroFormula(
2487b29749c13deab4588cbe0414a93191326800712Brian Salomon        BlendFormula::OutputType oneMinusDstCoeffModulateOutput) {
2497b29749c13deab4588cbe0414a93191326800712Brian Salomon    return BlendFormula(oneMinusDstCoeffModulateOutput, BlendFormula::kNone_OutputType,
2507b29749c13deab4588cbe0414a93191326800712Brian Salomon                        kReverseSubtract_GrBlendEquation, kDC_GrBlendCoeff, kOne_GrBlendCoeff);
2517b29749c13deab4588cbe0414a93191326800712Brian Salomon}
2526fd158ea47472c4d038e48980a95e36623f840c9cdalton
2536fd158ea47472c4d038e48980a95e36623f840c9cdalton/**
2546fd158ea47472c4d038e48980a95e36623f840c9cdalton * When there is coverage and the dst coeff is Zero, the equation with f=coverage becomes:
2556fd158ea47472c4d038e48980a95e36623f840c9cdalton *
2566fd158ea47472c4d038e48980a95e36623f840c9cdalton *   D' = f * S * srcCoeff + (1-f) * D
2576fd158ea47472c4d038e48980a95e36623f840c9cdalton *
2586fd158ea47472c4d038e48980a95e36623f840c9cdalton * To implement this formula, we output [f] for the secondary color and replace the HW dst coeff
2596fd158ea47472c4d038e48980a95e36623f840c9cdalton * with IS2A. (Note that we can avoid dual source blending when Sa=1 by using ISA.)
2606fd158ea47472c4d038e48980a95e36623f840c9cdalton *
2616fd158ea47472c4d038e48980a95e36623f840c9cdalton * Xfer modes (Sa!=1): src, src-in, src-out
2626fd158ea47472c4d038e48980a95e36623f840c9cdalton */
2637b29749c13deab4588cbe0414a93191326800712Brian Salomonstatic constexpr BlendFormula MakeCoverageDstCoeffZeroFormula(GrBlendCoeff srcCoeff) {
2647b29749c13deab4588cbe0414a93191326800712Brian Salomon    return BlendFormula(BlendFormula::kModulate_OutputType, BlendFormula::kCoverage_OutputType,
2657b29749c13deab4588cbe0414a93191326800712Brian Salomon                        kAdd_GrBlendEquation, srcCoeff, kIS2A_GrBlendCoeff);
2667b29749c13deab4588cbe0414a93191326800712Brian Salomon}
2677b29749c13deab4588cbe0414a93191326800712Brian Salomon
2687b29749c13deab4588cbe0414a93191326800712Brian Salomon// Older GCC won't like the constexpr arrays because of
2697b29749c13deab4588cbe0414a93191326800712Brian Salomon// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61484.
270f86d3680b19f05b43a2404bbc87db14133047829Bruce Dawson// MSVC 2015 crashes with an internal compiler error.
271f86d3680b19f05b43a2404bbc87db14133047829Bruce Dawson#if !defined(__clang__) && ((defined(__GNUC__) && __GNUC__ < 5) || (defined(_MSC_VER) && _MSC_VER <= 1910))
2727b29749c13deab4588cbe0414a93191326800712Brian Salomon#   define MAYBE_CONSTEXPR const
2737b29749c13deab4588cbe0414a93191326800712Brian Salomon#else
2747b29749c13deab4588cbe0414a93191326800712Brian Salomon#   define MAYBE_CONSTEXPR constexpr
2757b29749c13deab4588cbe0414a93191326800712Brian Salomon#endif
2766fd158ea47472c4d038e48980a95e36623f840c9cdalton
2776fd158ea47472c4d038e48980a95e36623f840c9cdalton/**
2786fd158ea47472c4d038e48980a95e36623f840c9cdalton * This table outlines the blend formulas we will use with each xfermode, with and without coverage,
2796fd158ea47472c4d038e48980a95e36623f840c9cdalton * with and without an opaque input color. Optimization properties are deduced at compile time so we
2806fd158ea47472c4d038e48980a95e36623f840c9cdalton * can make runtime decisions quickly. RGB coverage is not supported.
2816fd158ea47472c4d038e48980a95e36623f840c9cdalton */
2827b29749c13deab4588cbe0414a93191326800712Brian Salomonstatic MAYBE_CONSTEXPR BlendFormula gBlendTable[2][2][(int)SkBlendMode::kLastCoeffMode + 1] = {
2836fd158ea47472c4d038e48980a95e36623f840c9cdalton                     /*>> No coverage, input color unknown <<*/ {{
2846fd158ea47472c4d038e48980a95e36623f840c9cdalton
2857b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* clear */      MakeCoeffFormula(kZero_GrBlendCoeff, kZero_GrBlendCoeff),
2867b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* src */        MakeCoeffFormula(kOne_GrBlendCoeff,  kZero_GrBlendCoeff),
2877b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* dst */        MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
2887b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* src-over */   MakeCoeffFormula(kOne_GrBlendCoeff,  kISA_GrBlendCoeff),
2897b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* dst-over */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kOne_GrBlendCoeff),
2907b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* src-in */     MakeCoeffFormula(kDA_GrBlendCoeff,   kZero_GrBlendCoeff),
2917b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* dst-in */     MakeCoeffFormula(kZero_GrBlendCoeff, kSA_GrBlendCoeff),
2927b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* src-out */    MakeCoeffFormula(kIDA_GrBlendCoeff,  kZero_GrBlendCoeff),
2937b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* dst-out */    MakeCoeffFormula(kZero_GrBlendCoeff, kISA_GrBlendCoeff),
2947b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* src-atop */   MakeCoeffFormula(kDA_GrBlendCoeff,   kISA_GrBlendCoeff),
2957b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* dst-atop */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kSA_GrBlendCoeff),
2967b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* xor */        MakeCoeffFormula(kIDA_GrBlendCoeff,  kISA_GrBlendCoeff),
2977b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* plus */       MakeCoeffFormula(kOne_GrBlendCoeff,  kOne_GrBlendCoeff),
2987b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* modulate */   MakeCoeffFormula(kZero_GrBlendCoeff, kSC_GrBlendCoeff),
2997b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* screen */     MakeCoeffFormula(kOne_GrBlendCoeff,  kISC_GrBlendCoeff),
3006fd158ea47472c4d038e48980a95e36623f840c9cdalton
3016fd158ea47472c4d038e48980a95e36623f840c9cdalton                     }, /*>> Has coverage, input color unknown <<*/ {
3026fd158ea47472c4d038e48980a95e36623f840c9cdalton
3037b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* clear */      MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType),
3047b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* src */        MakeCoverageDstCoeffZeroFormula(kOne_GrBlendCoeff),
3057b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* dst */        MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
3067b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* src-over */   MakeCoeffFormula(kOne_GrBlendCoeff,  kISA_GrBlendCoeff),
3077b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* dst-over */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kOne_GrBlendCoeff),
3087b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* src-in */     MakeCoverageDstCoeffZeroFormula(kDA_GrBlendCoeff),
3097b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* dst-in */     MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISAModulate_OutputType),
3107b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* src-out */    MakeCoverageDstCoeffZeroFormula(kIDA_GrBlendCoeff),
3117b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* dst-out */    MakeCoeffFormula(kZero_GrBlendCoeff, kISA_GrBlendCoeff),
3127b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* src-atop */   MakeCoeffFormula(kDA_GrBlendCoeff,   kISA_GrBlendCoeff),
3137b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* dst-atop */   MakeCoverageFormula(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff),
3147b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* xor */        MakeCoeffFormula(kIDA_GrBlendCoeff,  kISA_GrBlendCoeff),
3157b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* plus */       MakeCoeffFormula(kOne_GrBlendCoeff,  kOne_GrBlendCoeff),
3167b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* modulate */   MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISCModulate_OutputType),
3177b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* screen */     MakeCoeffFormula(kOne_GrBlendCoeff,  kISC_GrBlendCoeff),
3186fd158ea47472c4d038e48980a95e36623f840c9cdalton
3196fd158ea47472c4d038e48980a95e36623f840c9cdalton                     }}, /*>> No coverage, input color opaque <<*/ {{
3206fd158ea47472c4d038e48980a95e36623f840c9cdalton
3217b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* clear */      MakeCoeffFormula(kZero_GrBlendCoeff, kZero_GrBlendCoeff),
3227b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* src */        MakeCoeffFormula(kOne_GrBlendCoeff,  kZero_GrBlendCoeff),
3237b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* dst */        MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
32428207df02b3dee83141520adf23df2c6aa087860Brian Salomon    /* src-over */   MakeCoeffFormula(kOne_GrBlendCoeff,  kISA_GrBlendCoeff), // see comment below
3257b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* dst-over */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kOne_GrBlendCoeff),
3267b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* src-in */     MakeCoeffFormula(kDA_GrBlendCoeff,   kZero_GrBlendCoeff),
3277b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* dst-in */     MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
3287b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* src-out */    MakeCoeffFormula(kIDA_GrBlendCoeff,  kZero_GrBlendCoeff),
3297b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* dst-out */    MakeCoeffFormula(kZero_GrBlendCoeff, kZero_GrBlendCoeff),
3307b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* src-atop */   MakeCoeffFormula(kDA_GrBlendCoeff,   kZero_GrBlendCoeff),
3317b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* dst-atop */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kOne_GrBlendCoeff),
3327b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* xor */        MakeCoeffFormula(kIDA_GrBlendCoeff,  kZero_GrBlendCoeff),
3337b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* plus */       MakeCoeffFormula(kOne_GrBlendCoeff,  kOne_GrBlendCoeff),
3347b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* modulate */   MakeCoeffFormula(kZero_GrBlendCoeff, kSC_GrBlendCoeff),
3357b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* screen */     MakeCoeffFormula(kOne_GrBlendCoeff,  kISC_GrBlendCoeff),
3366fd158ea47472c4d038e48980a95e36623f840c9cdalton
3376fd158ea47472c4d038e48980a95e36623f840c9cdalton                     }, /*>> Has coverage, input color opaque <<*/ {
3386fd158ea47472c4d038e48980a95e36623f840c9cdalton
3397b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* clear */      MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType),
3407b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* src */        MakeCoeffFormula(kOne_GrBlendCoeff,  kISA_GrBlendCoeff),
3417b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* dst */        MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
3427b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* src-over */   MakeCoeffFormula(kOne_GrBlendCoeff,  kISA_GrBlendCoeff),
3437b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* dst-over */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kOne_GrBlendCoeff),
3447b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* src-in */     MakeCoeffFormula(kDA_GrBlendCoeff,   kISA_GrBlendCoeff),
3457b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* dst-in */     MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
3467b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* src-out */    MakeCoeffFormula(kIDA_GrBlendCoeff,  kISA_GrBlendCoeff),
3477b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* dst-out */    MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType),
3487b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* src-atop */   MakeCoeffFormula(kDA_GrBlendCoeff,   kISA_GrBlendCoeff),
3497b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* dst-atop */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kOne_GrBlendCoeff),
3507b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* xor */        MakeCoeffFormula(kIDA_GrBlendCoeff,  kISA_GrBlendCoeff),
3517b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* plus */       MakeCoeffFormula(kOne_GrBlendCoeff,  kOne_GrBlendCoeff),
3527b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* modulate */   MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISCModulate_OutputType),
3537b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* screen */     MakeCoeffFormula(kOne_GrBlendCoeff,  kISC_GrBlendCoeff),
3546fd158ea47472c4d038e48980a95e36623f840c9cdalton}}};
35528207df02b3dee83141520adf23df2c6aa087860Brian Salomon// In the above table src-over is not optimized to src mode when the color is opaque because we
35628207df02b3dee83141520adf23df2c6aa087860Brian Salomon// found no advantage to doing so. Also, we are using a global src-over XP in most cases which is
35728207df02b3dee83141520adf23df2c6aa087860Brian Salomon// not specialized for opaque input. If the table were set to use the src formula then we'd have to
35828207df02b3dee83141520adf23df2c6aa087860Brian Salomon// change when we use this global XP to keep analysis and practice in sync.
3596fd158ea47472c4d038e48980a95e36623f840c9cdalton
3607b29749c13deab4588cbe0414a93191326800712Brian Salomonstatic MAYBE_CONSTEXPR BlendFormula gLCDBlendTable[(int)SkBlendMode::kLastCoeffMode + 1] = {
3617b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* clear */      MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType),
3627b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* src */        MakeCoverageFormula(BlendFormula::kCoverage_OutputType, kOne_GrBlendCoeff),
3637b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* dst */        MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
3647b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* src-over */   MakeCoverageFormula(BlendFormula::kSAModulate_OutputType, kOne_GrBlendCoeff),
3657b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* dst-over */   MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
3667b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* src-in */     MakeCoverageFormula(BlendFormula::kCoverage_OutputType, kDA_GrBlendCoeff),
3677b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* dst-in */     MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISAModulate_OutputType),
3687b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* src-out */    MakeCoverageFormula(BlendFormula::kCoverage_OutputType, kIDA_GrBlendCoeff),
3697b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* dst-out */    MakeSAModulateFormula(kZero_GrBlendCoeff, kISC_GrBlendCoeff),
3707b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* src-atop */   MakeCoverageFormula(BlendFormula::kSAModulate_OutputType, kDA_GrBlendCoeff),
3717b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* dst-atop */   MakeCoverageFormula(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff),
3727b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* xor */        MakeCoverageFormula(BlendFormula::kSAModulate_OutputType, kIDA_GrBlendCoeff),
3737b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* plus */       MakeCoeffFormula(kOne_GrBlendCoeff, kOne_GrBlendCoeff),
3747b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* modulate */   MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISCModulate_OutputType),
3757b29749c13deab4588cbe0414a93191326800712Brian Salomon    /* screen */     MakeCoeffFormula(kOne_GrBlendCoeff, kISC_GrBlendCoeff),
376723b0501e22373bb3e6c306daaceae02cda8a124egdaniel};
377723b0501e22373bb3e6c306daaceae02cda8a124egdaniel
3787b29749c13deab4588cbe0414a93191326800712Brian Salomon#undef MAYBE_CONSTEXPR
3797b29749c13deab4588cbe0414a93191326800712Brian Salomon
3805be6c95fa95a518ab109339df4695d6dda6e2419Brian Salomonstatic BlendFormula get_blend_formula(bool isOpaque,
3815be6c95fa95a518ab109339df4695d6dda6e2419Brian Salomon                                      bool hasCoverage,
38286ae0a9e465f157eaa263ef7515e10619946ff83cdalton                                      bool hasMixedSamples,
3837d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed                                      SkBlendMode xfermode) {
3847d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed    SkASSERT((unsigned)xfermode <= (unsigned)SkBlendMode::kLastCoeffMode);
3855be6c95fa95a518ab109339df4695d6dda6e2419Brian Salomon    bool conflatesCoverage = hasCoverage || hasMixedSamples;
3865be6c95fa95a518ab109339df4695d6dda6e2419Brian Salomon    return gBlendTable[isOpaque][conflatesCoverage][(int)xfermode];
3876fd158ea47472c4d038e48980a95e36623f840c9cdalton}
3886fd158ea47472c4d038e48980a95e36623f840c9cdalton
3895be6c95fa95a518ab109339df4695d6dda6e2419Brian Salomonstatic BlendFormula get_lcd_blend_formula(SkBlendMode xfermode) {
3907d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed    SkASSERT((unsigned)xfermode <= (unsigned)SkBlendMode::kLastCoeffMode);
391723b0501e22373bb3e6c306daaceae02cda8a124egdaniel
3927d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed    return gLCDBlendTable[(int)xfermode];
393723b0501e22373bb3e6c306daaceae02cda8a124egdaniel}
394723b0501e22373bb3e6c306daaceae02cda8a124egdaniel
3956fd158ea47472c4d038e48980a95e36623f840c9cdalton///////////////////////////////////////////////////////////////////////////////
3966fd158ea47472c4d038e48980a95e36623f840c9cdalton
3976fd158ea47472c4d038e48980a95e36623f840c9cdaltonclass PorterDuffXferProcessor : public GrXferProcessor {
3986fd158ea47472c4d038e48980a95e36623f840c9cdaltonpublic:
3996ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel    PorterDuffXferProcessor(BlendFormula blendFormula, GrProcessorAnalysisCoverage coverage)
400abff956455637b12eab374fd44b99e1338799113Ethan Nicholas            : INHERITED(kPorterDuffXferProcessor_ClassID, false, false, coverage)
4016ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel            , fBlendFormula(blendFormula) {
4026fd158ea47472c4d038e48980a95e36623f840c9cdalton    }
4036fd158ea47472c4d038e48980a95e36623f840c9cdalton
4046fd158ea47472c4d038e48980a95e36623f840c9cdalton    const char* name() const override { return "Porter Duff"; }
4056fd158ea47472c4d038e48980a95e36623f840c9cdalton
40657d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel    GrGLSLXferProcessor* createGLSLInstance() const override;
4076fd158ea47472c4d038e48980a95e36623f840c9cdalton
4086fd158ea47472c4d038e48980a95e36623f840c9cdalton    BlendFormula getBlendFormula() const { return fBlendFormula; }
409f4f2b442228ca188cfb6b44ee3faa86773bb9db3cdalton
410f4f2b442228ca188cfb6b44ee3faa86773bb9db3cdaltonprivate:
41194efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon    void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
412f4f2b442228ca188cfb6b44ee3faa86773bb9db3cdalton
413edbb31f7ddea834b8e55ea66587ea8d33adc53facdalton    bool onHasSecondaryOutput() const override { return fBlendFormula.hasSecondaryOutput(); }
414edbb31f7ddea834b8e55ea66587ea8d33adc53facdalton
415f4f2b442228ca188cfb6b44ee3faa86773bb9db3cdalton    void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override {
4167b29749c13deab4588cbe0414a93191326800712Brian Salomon        blendInfo->fEquation = fBlendFormula.equation();
4177b29749c13deab4588cbe0414a93191326800712Brian Salomon        blendInfo->fSrcBlend = fBlendFormula.srcCoeff();
4187b29749c13deab4588cbe0414a93191326800712Brian Salomon        blendInfo->fDstBlend = fBlendFormula.dstCoeff();
4196fd158ea47472c4d038e48980a95e36623f840c9cdalton        blendInfo->fWriteColor = fBlendFormula.modifiesDst();
42041d4f09356567ead0216e1a7e4110bd58822b81fegdaniel    }
42141d4f09356567ead0216e1a7e4110bd58822b81fegdaniel
42236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    bool onIsEqual(const GrXferProcessor& xpBase) const override {
42341d4f09356567ead0216e1a7e4110bd58822b81fegdaniel        const PorterDuffXferProcessor& xp = xpBase.cast<PorterDuffXferProcessor>();
4246fd158ea47472c4d038e48980a95e36623f840c9cdalton        return fBlendFormula == xp.fBlendFormula;
42541d4f09356567ead0216e1a7e4110bd58822b81fegdaniel    }
42641d4f09356567ead0216e1a7e4110bd58822b81fegdaniel
4276fd158ea47472c4d038e48980a95e36623f840c9cdalton    const BlendFormula fBlendFormula;
42841d4f09356567ead0216e1a7e4110bd58822b81fegdaniel
42941d4f09356567ead0216e1a7e4110bd58822b81fegdaniel    typedef GrXferProcessor INHERITED;
43041d4f09356567ead0216e1a7e4110bd58822b81fegdaniel};
43141d4f09356567ead0216e1a7e4110bd58822b81fegdaniel
43241d4f09356567ead0216e1a7e4110bd58822b81fegdaniel///////////////////////////////////////////////////////////////////////////////
43341d4f09356567ead0216e1a7e4110bd58822b81fegdaniel
4342d721d33aad192cc8a7a1321504b39bdca2a57ceegdanielstatic void append_color_output(const PorterDuffXferProcessor& xp,
4354ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                                GrGLSLXPFragmentBuilder* fragBuilder,
4366fd158ea47472c4d038e48980a95e36623f840c9cdalton                                BlendFormula::OutputType outputType, const char* output,
4376fd158ea47472c4d038e48980a95e36623f840c9cdalton                                const char* inColor, const char* inCoverage) {
4388c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon    SkASSERT(inCoverage);
4398c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon    SkASSERT(inColor);
4406fd158ea47472c4d038e48980a95e36623f840c9cdalton    switch (outputType) {
4416fd158ea47472c4d038e48980a95e36623f840c9cdalton        case BlendFormula::kNone_OutputType:
442f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas            fragBuilder->codeAppendf("%s = half4(0.0);", output);
4436fd158ea47472c4d038e48980a95e36623f840c9cdalton            break;
4446fd158ea47472c4d038e48980a95e36623f840c9cdalton        case BlendFormula::kCoverage_OutputType:
44586ae0a9e465f157eaa263ef7515e10619946ff83cdalton            // We can have a coverage formula while not reading coverage if there are mixed samples.
4468c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon            fragBuilder->codeAppendf("%s = %s;", output, inCoverage);
4476fd158ea47472c4d038e48980a95e36623f840c9cdalton            break;
4486fd158ea47472c4d038e48980a95e36623f840c9cdalton        case BlendFormula::kModulate_OutputType:
4498c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon            fragBuilder->codeAppendf("%s = %s * %s;", output, inColor, inCoverage);
4506fd158ea47472c4d038e48980a95e36623f840c9cdalton            break;
451723b0501e22373bb3e6c306daaceae02cda8a124egdaniel        case BlendFormula::kSAModulate_OutputType:
4528c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon            fragBuilder->codeAppendf("%s = %s.a * %s;", output, inColor, inCoverage);
453723b0501e22373bb3e6c306daaceae02cda8a124egdaniel            break;
4546fd158ea47472c4d038e48980a95e36623f840c9cdalton        case BlendFormula::kISAModulate_OutputType:
4558c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon            fragBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", output, inColor, inCoverage);
4566fd158ea47472c4d038e48980a95e36623f840c9cdalton            break;
4576fd158ea47472c4d038e48980a95e36623f840c9cdalton        case BlendFormula::kISCModulate_OutputType:
458f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas            fragBuilder->codeAppendf("%s = (half4(1.0) - %s) * %s;", output, inColor, inCoverage);
4596fd158ea47472c4d038e48980a95e36623f840c9cdalton            break;
4606fd158ea47472c4d038e48980a95e36623f840c9cdalton        default:
461b4aab9ae6d27c446af8302b79d15b832c816c633Ben Wagner            SK_ABORT("Unsupported output type.");
4626fd158ea47472c4d038e48980a95e36623f840c9cdalton            break;
4633ad6570e94965d54871eaea8b314f560b82ca792egdaniel    }
4643ad6570e94965d54871eaea8b314f560b82ca792egdaniel}
4653ad6570e94965d54871eaea8b314f560b82ca792egdaniel
466fa4cc8bf2aa782431609dd2ac16b1fc36de72e44egdanielclass GLPorterDuffXferProcessor : public GrGLSLXferProcessor {
46741d4f09356567ead0216e1a7e4110bd58822b81fegdanielpublic:
4686fd158ea47472c4d038e48980a95e36623f840c9cdalton    static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) {
46941d4f09356567ead0216e1a7e4110bd58822b81fegdaniel        const PorterDuffXferProcessor& xp = processor.cast<PorterDuffXferProcessor>();
4707b29749c13deab4588cbe0414a93191326800712Brian Salomon        b->add32(xp.getBlendFormula().primaryOutput() |
4717b29749c13deab4588cbe0414a93191326800712Brian Salomon                 (xp.getBlendFormula().secondaryOutput() << 3));
4726fd158ea47472c4d038e48980a95e36623f840c9cdalton        GR_STATIC_ASSERT(BlendFormula::kLast_OutputType < 8);
473fc6c37b981daeece7474ce61070c707c37eefa62Mike Klein    }
47450785a3d10b53bea5beb6e18431a2449860be237bsalomon
47550785a3d10b53bea5beb6e18431a2449860be237bsalomonprivate:
476edbb31f7ddea834b8e55ea66587ea8d33adc53facdalton    void emitOutputsForBlendState(const EmitArgs& args) override {
47741d4f09356567ead0216e1a7e4110bd58822b81fegdaniel        const PorterDuffXferProcessor& xp = args.fXP.cast<PorterDuffXferProcessor>();
4784ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel        GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
479c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman
4806fd158ea47472c4d038e48980a95e36623f840c9cdalton        BlendFormula blendFormula = xp.getBlendFormula();
4816fd158ea47472c4d038e48980a95e36623f840c9cdalton        if (blendFormula.hasSecondaryOutput()) {
4827b29749c13deab4588cbe0414a93191326800712Brian Salomon            append_color_output(xp, fragBuilder, blendFormula.secondaryOutput(),
4836fd158ea47472c4d038e48980a95e36623f840c9cdalton                                args.fOutputSecondary, args.fInputColor, args.fInputCoverage);
484c230414861558ce20b74281b1ca363e56c441832egdaniel        }
4857b29749c13deab4588cbe0414a93191326800712Brian Salomon        append_color_output(xp, fragBuilder, blendFormula.primaryOutput(), args.fOutputPrimary,
4867b29749c13deab4588cbe0414a93191326800712Brian Salomon                            args.fInputColor, args.fInputCoverage);
487378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel    }
488378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel
489018fb62d12d1febf121fe265da5b6117b86a6541egdaniel    void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
490378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel
491fa4cc8bf2aa782431609dd2ac16b1fc36de72e44egdaniel    typedef GrGLSLXferProcessor INHERITED;
492378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel};
493378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel
494378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel///////////////////////////////////////////////////////////////////////////////
495378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel
49694efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomonvoid PorterDuffXferProcessor::onGetGLSLProcessorKey(const GrShaderCaps&,
49757d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel                                                    GrProcessorKeyBuilder* b) const {
4986fd158ea47472c4d038e48980a95e36623f840c9cdalton    GLPorterDuffXferProcessor::GenKey(*this, b);
499eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt}
500eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
50157d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielGrGLSLXferProcessor* PorterDuffXferProcessor::createGLSLInstance() const {
502385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    return new GLPorterDuffXferProcessor;
503378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel}
504378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel
5056fd158ea47472c4d038e48980a95e36623f840c9cdalton///////////////////////////////////////////////////////////////////////////////
5066fd158ea47472c4d038e48980a95e36623f840c9cdalton
5076fd158ea47472c4d038e48980a95e36623f840c9cdaltonclass ShaderPDXferProcessor : public GrXferProcessor {
5086fd158ea47472c4d038e48980a95e36623f840c9cdaltonpublic:
5096ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel    ShaderPDXferProcessor(bool hasMixedSamples, SkBlendMode xfermode,
5106ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel                          GrProcessorAnalysisCoverage coverage)
511abff956455637b12eab374fd44b99e1338799113Ethan Nicholas            : INHERITED(kShaderPDXferProcessor_ClassID, true, hasMixedSamples, coverage)
512abff956455637b12eab374fd44b99e1338799113Ethan Nicholas            , fXfermode(xfermode) {
513c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman    }
514c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman
5156fd158ea47472c4d038e48980a95e36623f840c9cdalton    const char* name() const override { return "Porter Duff Shader"; }
5166fd158ea47472c4d038e48980a95e36623f840c9cdalton
51757d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel    GrGLSLXferProcessor* createGLSLInstance() const override;
5186fd158ea47472c4d038e48980a95e36623f840c9cdalton
5197d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed    SkBlendMode getXfermode() const { return fXfermode; }
5206fd158ea47472c4d038e48980a95e36623f840c9cdalton
5216fd158ea47472c4d038e48980a95e36623f840c9cdaltonprivate:
52294efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon    void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
5236fd158ea47472c4d038e48980a95e36623f840c9cdalton
5246fd158ea47472c4d038e48980a95e36623f840c9cdalton    bool onIsEqual(const GrXferProcessor& xpBase) const override {
5256fd158ea47472c4d038e48980a95e36623f840c9cdalton        const ShaderPDXferProcessor& xp = xpBase.cast<ShaderPDXferProcessor>();
5266fd158ea47472c4d038e48980a95e36623f840c9cdalton        return fXfermode == xp.fXfermode;
5273ad6570e94965d54871eaea8b314f560b82ca792egdaniel    }
5288750924a1470e8215b2a344155259b93062d3fa2egdaniel
5297d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed    const SkBlendMode fXfermode;
5306fd158ea47472c4d038e48980a95e36623f840c9cdalton
5316fd158ea47472c4d038e48980a95e36623f840c9cdalton    typedef GrXferProcessor INHERITED;
5326fd158ea47472c4d038e48980a95e36623f840c9cdalton};
5336fd158ea47472c4d038e48980a95e36623f840c9cdalton
5346fd158ea47472c4d038e48980a95e36623f840c9cdalton///////////////////////////////////////////////////////////////////////////////
5356fd158ea47472c4d038e48980a95e36623f840c9cdalton
536fa4cc8bf2aa782431609dd2ac16b1fc36de72e44egdanielclass GLShaderPDXferProcessor : public GrGLSLXferProcessor {
5376fd158ea47472c4d038e48980a95e36623f840c9cdaltonpublic:
5386fd158ea47472c4d038e48980a95e36623f840c9cdalton    static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) {
5396fd158ea47472c4d038e48980a95e36623f840c9cdalton        const ShaderPDXferProcessor& xp = processor.cast<ShaderPDXferProcessor>();
5407d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed        b->add32((int)xp.getXfermode());
541c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman    }
542c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman
5436fd158ea47472c4d038e48980a95e36623f840c9cdaltonprivate:
5447ea439b2203855db97330b25945b87dd4b170b8begdaniel    void emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder* fragBuilder,
5457ea439b2203855db97330b25945b87dd4b170b8begdaniel                                 GrGLSLUniformHandler* uniformHandler,
5464ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                                 const char* srcColor,
547f34b293681ea49aaa4aaa70d84515e4a58a112e7egdaniel                                 const char* srcCoverage,
5484ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                                 const char* dstColor,
5494ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                                 const char* outColor,
550f34b293681ea49aaa4aaa70d84515e4a58a112e7egdaniel                                 const char* outColorSecondary,
5514ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                                 const GrXferProcessor& proc) override {
552edbb31f7ddea834b8e55ea66587ea8d33adc53facdalton        const ShaderPDXferProcessor& xp = proc.cast<ShaderPDXferProcessor>();
553c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman
5544ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel        GrGLSLBlend::AppendMode(fragBuilder, srcColor, dstColor, outColor, xp.getXfermode());
555f34b293681ea49aaa4aaa70d84515e4a58a112e7egdaniel
556f34b293681ea49aaa4aaa70d84515e4a58a112e7egdaniel        // Apply coverage.
557f42fca4027ed4f235ef927786813a5ed0e6652b9robertphillips        INHERITED::DefaultCoverageModulation(fragBuilder, srcCoverage, dstColor, outColor,
558f42fca4027ed4f235ef927786813a5ed0e6652b9robertphillips                                             outColorSecondary, xp);
559c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman    }
560c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman
561018fb62d12d1febf121fe265da5b6117b86a6541egdaniel    void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
562c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman
563fa4cc8bf2aa782431609dd2ac16b1fc36de72e44egdaniel    typedef GrGLSLXferProcessor INHERITED;
5646fd158ea47472c4d038e48980a95e36623f840c9cdalton};
5656fd158ea47472c4d038e48980a95e36623f840c9cdalton
5666fd158ea47472c4d038e48980a95e36623f840c9cdalton///////////////////////////////////////////////////////////////////////////////
5679513143efa734bef0c1a0c7f945022572dbc8518egdaniel
56894efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomonvoid ShaderPDXferProcessor::onGetGLSLProcessorKey(const GrShaderCaps&,
56957d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel                                                  GrProcessorKeyBuilder* b) const {
5706fd158ea47472c4d038e48980a95e36623f840c9cdalton    GLShaderPDXferProcessor::GenKey(*this, b);
571c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman}
572c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman
57357d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielGrGLSLXferProcessor* ShaderPDXferProcessor::createGLSLInstance() const {
574385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    return new GLShaderPDXferProcessor;
575c230414861558ce20b74281b1ca363e56c441832egdaniel}
576c230414861558ce20b74281b1ca363e56c441832egdaniel
577378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel///////////////////////////////////////////////////////////////////////////////
578378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel
5790d5fd110e0b7ce9b892833d874145a79ca67da8degdanielclass PDLCDXferProcessor : public GrXferProcessor {
5800d5fd110e0b7ce9b892833d874145a79ca67da8degdanielpublic:
581d61c9d93b126dca0af17eff89be8536944dadf81Brian Salomon    static sk_sp<const GrXferProcessor> Make(SkBlendMode mode,
582d61c9d93b126dca0af17eff89be8536944dadf81Brian Salomon                                             const GrProcessorAnalysisColor& inputColor);
5830d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel
5840d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel    ~PDLCDXferProcessor() override;
5850d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel
5860d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel    const char* name() const override { return "Porter Duff LCD"; }
5870d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel
58857d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel    GrGLSLXferProcessor* createGLSLInstance() const override;
5890d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel
5901c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon    uint8_t alpha() const { return fAlpha; }
5911c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon
5920d5fd110e0b7ce9b892833d874145a79ca67da8degdanielprivate:
5930d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel    PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha);
5940d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel
59594efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon    void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
5960d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel
5970d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel    void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override {
5980d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel        blendInfo->fSrcBlend = kConstC_GrBlendCoeff;
5990d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel        blendInfo->fDstBlend = kISC_GrBlendCoeff;
6000d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel        blendInfo->fBlendConstant = fBlendConstant;
6010d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel    }
6020d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel
6030d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel    bool onIsEqual(const GrXferProcessor& xpBase) const override {
6040d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel        const PDLCDXferProcessor& xp = xpBase.cast<PDLCDXferProcessor>();
6051c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon        if (fBlendConstant != xp.fBlendConstant || fAlpha != xp.fAlpha) {
6060d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel            return false;
6070d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel        }
6080d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel        return true;
6090d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel    }
6100d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel
6111c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon    GrColor fBlendConstant;
6121c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon    uint8_t fAlpha;
6130d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel
6140d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel    typedef GrXferProcessor INHERITED;
6150d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel};
6160d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel
6170d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel///////////////////////////////////////////////////////////////////////////////
6180d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel
619fa4cc8bf2aa782431609dd2ac16b1fc36de72e44egdanielclass GLPDLCDXferProcessor : public GrGLSLXferProcessor {
6200d5fd110e0b7ce9b892833d874145a79ca67da8degdanielpublic:
6211c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon    GLPDLCDXferProcessor(const GrProcessor&) : fLastAlpha(SK_MaxU32) {}
6220d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel
623d3b65972aad96453ff4510caa3e25a2b847c6d1eBrian Salomon    ~GLPDLCDXferProcessor() override {}
6240d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel
62594efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon    static void GenKey(const GrProcessor& processor, const GrShaderCaps& caps,
6260d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel                       GrProcessorKeyBuilder* b) {}
6270d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel
6280d5fd110e0b7ce9b892833d874145a79ca67da8degdanielprivate:
629edbb31f7ddea834b8e55ea66587ea8d33adc53facdalton    void emitOutputsForBlendState(const EmitArgs& args) override {
6301c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon        const char* alpha;
631f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        fAlphaUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
632f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas                                                         "alpha", &alpha);
6334ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel        GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
6341c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon        // We want to force our primary output to be alpha * Coverage, where alpha is the alpha
6351c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon        // value of the src color. We know that there are no color stages (or we wouldn't have
6361c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon        // created this xp) and the r,g, and b channels of the op's input color are baked into the
6371c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon        // blend constant.
63856cf6dcb6572f1d355af041c1ebf157b2b3d0165egdaniel        SkASSERT(args.fInputCoverage);
6391c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon        fragBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, alpha, args.fInputCoverage);
6400d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel    }
6410d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel
6421c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon    void onSetData(const GrGLSLProgramDataManager& pdm, const GrXferProcessor& xp) override {
6431c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon        uint32_t alpha = SkToU32(xp.cast<PDLCDXferProcessor>().alpha());
6441c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon        if (fLastAlpha != alpha) {
6451c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon            pdm.set1f(fAlphaUniform, alpha / 255.f);
6461c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon            fLastAlpha = alpha;
6471c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon        }
6481c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon    }
6490d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel
6501c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon    GrGLSLUniformHandler::UniformHandle fAlphaUniform;
6511c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon    uint32_t fLastAlpha;
652fa4cc8bf2aa782431609dd2ac16b1fc36de72e44egdaniel    typedef GrGLSLXferProcessor INHERITED;
6530d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel};
6540d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel
6550d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel///////////////////////////////////////////////////////////////////////////////
6560d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel
6570d5fd110e0b7ce9b892833d874145a79ca67da8degdanielPDLCDXferProcessor::PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha)
658abff956455637b12eab374fd44b99e1338799113Ethan Nicholas    : INHERITED(kPDLCDXferProcessor_ClassID, false, false, GrProcessorAnalysisCoverage::kLCD)
6596ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel    , fBlendConstant(blendConstant)
6600d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel    , fAlpha(alpha) {
6610d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel}
6620d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel
663d61c9d93b126dca0af17eff89be8536944dadf81Brian Salomonsk_sp<const GrXferProcessor> PDLCDXferProcessor::Make(SkBlendMode mode,
664d61c9d93b126dca0af17eff89be8536944dadf81Brian Salomon                                                      const GrProcessorAnalysisColor& color) {
665d61c9d93b126dca0af17eff89be8536944dadf81Brian Salomon    if (SkBlendMode::kSrcOver != mode) {
66696fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
6670d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel    }
668eec6f7be5461e588210f383b8af18f324a2bdb46Brian Salomon    GrColor blendConstant;
6691c6025cc9da4a4f3a8ad16dde2ae8dcf120ed270Brian Salomon    if (!color.isConstant(&blendConstant)) {
67096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
6710d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel    }
672afb41033efae3f5c71cac8c6127236efab613125Brian Salomon    blendConstant = GrUnpremulColor(blendConstant);
6730d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel    uint8_t alpha = GrColorUnpackA(blendConstant);
6740d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel    blendConstant |= (0xff << GrColor_SHIFT_A);
675a076d8711d24b8181f894038a4fd34d5327f1717Brian Salomon    return sk_sp<GrXferProcessor>(new PDLCDXferProcessor(blendConstant, alpha));
6760d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel}
6770d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel
6780d5fd110e0b7ce9b892833d874145a79ca67da8degdanielPDLCDXferProcessor::~PDLCDXferProcessor() {
6790d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel}
6800d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel
68194efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomonvoid PDLCDXferProcessor::onGetGLSLProcessorKey(const GrShaderCaps& caps,
68257d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel                                               GrProcessorKeyBuilder* b) const {
683cc25297364433ad66450faf391e599274ed4bc7degdaniel    GLPDLCDXferProcessor::GenKey(*this, caps, b);
6840d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel}
6850d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel
68657d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielGrGLSLXferProcessor* PDLCDXferProcessor::createGLSLInstance() const {
687385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    return new GLPDLCDXferProcessor(*this);
6880d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel}
6890d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel
6900d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel///////////////////////////////////////////////////////////////////////////////
6916fd158ea47472c4d038e48980a95e36623f840c9cdalton
692a16339297859f37df69230e64f05624cef511ad3Brian Salomonconstexpr GrPorterDuffXPFactory::GrPorterDuffXPFactory(SkBlendMode xfermode)
693a16339297859f37df69230e64f05624cef511ad3Brian Salomon        : fBlendMode(xfermode) {}
694a16339297859f37df69230e64f05624cef511ad3Brian Salomon
695a16339297859f37df69230e64f05624cef511ad3Brian Salomonconst GrXPFactory* GrPorterDuffXPFactory::Get(SkBlendMode blendMode) {
696a16339297859f37df69230e64f05624cef511ad3Brian Salomon    SkASSERT((unsigned)blendMode <= (unsigned)SkBlendMode::kLastCoeffMode);
697a16339297859f37df69230e64f05624cef511ad3Brian Salomon
698a16339297859f37df69230e64f05624cef511ad3Brian Salomon    // If these objects are constructed as static constexpr by cl.exe (2015 SP2) the vtables are
699a16339297859f37df69230e64f05624cef511ad3Brian Salomon    // null.
700a16339297859f37df69230e64f05624cef511ad3Brian Salomon#ifdef SK_BUILD_FOR_WIN
701a16339297859f37df69230e64f05624cef511ad3Brian Salomon#define _CONSTEXPR_
702a16339297859f37df69230e64f05624cef511ad3Brian Salomon#else
703a16339297859f37df69230e64f05624cef511ad3Brian Salomon#define _CONSTEXPR_ constexpr
704a16339297859f37df69230e64f05624cef511ad3Brian Salomon#endif
705a16339297859f37df69230e64f05624cef511ad3Brian Salomon    static _CONSTEXPR_ const GrPorterDuffXPFactory gClearPDXPF(SkBlendMode::kClear);
706a16339297859f37df69230e64f05624cef511ad3Brian Salomon    static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcPDXPF(SkBlendMode::kSrc);
707a16339297859f37df69230e64f05624cef511ad3Brian Salomon    static _CONSTEXPR_ const GrPorterDuffXPFactory gDstPDXPF(SkBlendMode::kDst);
708a16339297859f37df69230e64f05624cef511ad3Brian Salomon    static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcOverPDXPF(SkBlendMode::kSrcOver);
709a16339297859f37df69230e64f05624cef511ad3Brian Salomon    static _CONSTEXPR_ const GrPorterDuffXPFactory gDstOverPDXPF(SkBlendMode::kDstOver);
710a16339297859f37df69230e64f05624cef511ad3Brian Salomon    static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcInPDXPF(SkBlendMode::kSrcIn);
711a16339297859f37df69230e64f05624cef511ad3Brian Salomon    static _CONSTEXPR_ const GrPorterDuffXPFactory gDstInPDXPF(SkBlendMode::kDstIn);
712a16339297859f37df69230e64f05624cef511ad3Brian Salomon    static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcOutPDXPF(SkBlendMode::kSrcOut);
713a16339297859f37df69230e64f05624cef511ad3Brian Salomon    static _CONSTEXPR_ const GrPorterDuffXPFactory gDstOutPDXPF(SkBlendMode::kDstOut);
714a16339297859f37df69230e64f05624cef511ad3Brian Salomon    static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcATopPDXPF(SkBlendMode::kSrcATop);
715a16339297859f37df69230e64f05624cef511ad3Brian Salomon    static _CONSTEXPR_ const GrPorterDuffXPFactory gDstATopPDXPF(SkBlendMode::kDstATop);
716a16339297859f37df69230e64f05624cef511ad3Brian Salomon    static _CONSTEXPR_ const GrPorterDuffXPFactory gXorPDXPF(SkBlendMode::kXor);
717a16339297859f37df69230e64f05624cef511ad3Brian Salomon    static _CONSTEXPR_ const GrPorterDuffXPFactory gPlusPDXPF(SkBlendMode::kPlus);
718a16339297859f37df69230e64f05624cef511ad3Brian Salomon    static _CONSTEXPR_ const GrPorterDuffXPFactory gModulatePDXPF(SkBlendMode::kModulate);
719a16339297859f37df69230e64f05624cef511ad3Brian Salomon    static _CONSTEXPR_ const GrPorterDuffXPFactory gScreenPDXPF(SkBlendMode::kScreen);
720a16339297859f37df69230e64f05624cef511ad3Brian Salomon#undef _CONSTEXPR_
721a16339297859f37df69230e64f05624cef511ad3Brian Salomon
722a16339297859f37df69230e64f05624cef511ad3Brian Salomon    switch (blendMode) {
723a16339297859f37df69230e64f05624cef511ad3Brian Salomon        case SkBlendMode::kClear:
724a16339297859f37df69230e64f05624cef511ad3Brian Salomon            return &gClearPDXPF;
725a16339297859f37df69230e64f05624cef511ad3Brian Salomon        case SkBlendMode::kSrc:
726a16339297859f37df69230e64f05624cef511ad3Brian Salomon            return &gSrcPDXPF;
727a16339297859f37df69230e64f05624cef511ad3Brian Salomon        case SkBlendMode::kDst:
728a16339297859f37df69230e64f05624cef511ad3Brian Salomon            return &gDstPDXPF;
729a16339297859f37df69230e64f05624cef511ad3Brian Salomon        case SkBlendMode::kSrcOver:
730a16339297859f37df69230e64f05624cef511ad3Brian Salomon            return &gSrcOverPDXPF;
731a16339297859f37df69230e64f05624cef511ad3Brian Salomon        case SkBlendMode::kDstOver:
732a16339297859f37df69230e64f05624cef511ad3Brian Salomon            return &gDstOverPDXPF;
733a16339297859f37df69230e64f05624cef511ad3Brian Salomon        case SkBlendMode::kSrcIn:
734a16339297859f37df69230e64f05624cef511ad3Brian Salomon            return &gSrcInPDXPF;
735a16339297859f37df69230e64f05624cef511ad3Brian Salomon        case SkBlendMode::kDstIn:
736a16339297859f37df69230e64f05624cef511ad3Brian Salomon            return &gDstInPDXPF;
737a16339297859f37df69230e64f05624cef511ad3Brian Salomon        case SkBlendMode::kSrcOut:
738a16339297859f37df69230e64f05624cef511ad3Brian Salomon            return &gSrcOutPDXPF;
739a16339297859f37df69230e64f05624cef511ad3Brian Salomon        case SkBlendMode::kDstOut:
740a16339297859f37df69230e64f05624cef511ad3Brian Salomon            return &gDstOutPDXPF;
741a16339297859f37df69230e64f05624cef511ad3Brian Salomon        case SkBlendMode::kSrcATop:
742a16339297859f37df69230e64f05624cef511ad3Brian Salomon            return &gSrcATopPDXPF;
743a16339297859f37df69230e64f05624cef511ad3Brian Salomon        case SkBlendMode::kDstATop:
744a16339297859f37df69230e64f05624cef511ad3Brian Salomon            return &gDstATopPDXPF;
745a16339297859f37df69230e64f05624cef511ad3Brian Salomon        case SkBlendMode::kXor:
746a16339297859f37df69230e64f05624cef511ad3Brian Salomon            return &gXorPDXPF;
747a16339297859f37df69230e64f05624cef511ad3Brian Salomon        case SkBlendMode::kPlus:
748a16339297859f37df69230e64f05624cef511ad3Brian Salomon            return &gPlusPDXPF;
749a16339297859f37df69230e64f05624cef511ad3Brian Salomon        case SkBlendMode::kModulate:
750a16339297859f37df69230e64f05624cef511ad3Brian Salomon            return &gModulatePDXPF;
751a16339297859f37df69230e64f05624cef511ad3Brian Salomon        case SkBlendMode::kScreen:
752a16339297859f37df69230e64f05624cef511ad3Brian Salomon            return &gScreenPDXPF;
753a16339297859f37df69230e64f05624cef511ad3Brian Salomon        default:
754b4aab9ae6d27c446af8302b79d15b832c816c633Ben Wagner            SK_ABORT("Unexpected blend mode.");
755a16339297859f37df69230e64f05624cef511ad3Brian Salomon            return nullptr;
756c016fb8f9fb53dd8d4936c5e9e16a9dc99ab392eegdaniel    }
757c016fb8f9fb53dd8d4936c5e9e16a9dc99ab392eegdaniel}
758c016fb8f9fb53dd8d4936c5e9e16a9dc99ab392eegdaniel
759d61c9d93b126dca0af17eff89be8536944dadf81Brian Salomonsk_sp<const GrXferProcessor> GrPorterDuffXPFactory::makeXferProcessor(
760a076d8711d24b8181f894038a4fd34d5327f1717Brian Salomon        const GrProcessorAnalysisColor& color, GrProcessorAnalysisCoverage coverage,
7619a725dd9485654155e2e4196c32d372360bcdb61Brian Osman        bool hasMixedSamples, const GrCaps& caps, GrPixelConfigIsClamped dstIsClamped) const {
762723b0501e22373bb3e6c306daaceae02cda8a124egdaniel    BlendFormula blendFormula;
7636ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel    bool isLCD = coverage == GrProcessorAnalysisCoverage::kLCD;
7646ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel    if (isLCD) {
765d7b1159d787de27d75032ec213903a03962ec839Greg Daniel        // See comment in MakeSrcOverXferProcessor about color.isOpaque here
766d7b1159d787de27d75032ec213903a03962ec839Greg Daniel        if (SkBlendMode::kSrcOver == fBlendMode && color.isConstant() && /*color.isOpaque() &&*/
767e73f1f6dfa665802a942e743a227b5c98bc958dbegdaniel            !caps.shaderCaps()->dualSourceBlendingSupport() &&
768e73f1f6dfa665802a942e743a227b5c98bc958dbegdaniel            !caps.shaderCaps()->dstReadInShaderSupport()) {
769e73f1f6dfa665802a942e743a227b5c98bc958dbegdaniel            // If we don't have dual source blending or in shader dst reads, we fall back to this
770e73f1f6dfa665802a942e743a227b5c98bc958dbegdaniel            // trick for rendering SrcOver LCD text instead of doing a dst copy.
771a076d8711d24b8181f894038a4fd34d5327f1717Brian Salomon            return PDLCDXferProcessor::Make(fBlendMode, color);
772723b0501e22373bb3e6c306daaceae02cda8a124egdaniel        }
7735be6c95fa95a518ab109339df4695d6dda6e2419Brian Salomon        blendFormula = get_lcd_blend_formula(fBlendMode);
774723b0501e22373bb3e6c306daaceae02cda8a124egdaniel    } else {
7751c6025cc9da4a4f3a8ad16dde2ae8dcf120ed270Brian Salomon        blendFormula =
776a811b1200cc0b5e3819c89f62def23ec203d4b5aBrian Salomon                get_blend_formula(color.isOpaque(), GrProcessorAnalysisCoverage::kNone != coverage,
7771c6025cc9da4a4f3a8ad16dde2ae8dcf120ed270Brian Salomon                                  hasMixedSamples, fBlendMode);
7786fd158ea47472c4d038e48980a95e36623f840c9cdalton    }
7796fd158ea47472c4d038e48980a95e36623f840c9cdalton
7809a725dd9485654155e2e4196c32d372360bcdb61Brian Osman    bool needsClamp = SkBlendMode::kPlus == fBlendMode;
7816ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel    if ((blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) ||
7829a725dd9485654155e2e4196c32d372360bcdb61Brian Osman        (isLCD && (SkBlendMode::kSrcOver != fBlendMode /*|| !color.isOpaque()*/)) ||
7839a725dd9485654155e2e4196c32d372360bcdb61Brian Osman        (needsClamp && (GrPixelConfigIsClamped::kNo == dstIsClamped))) {
7846ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel        return sk_sp<const GrXferProcessor>(new ShaderPDXferProcessor(hasMixedSamples, fBlendMode,
7856ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel                                                                      coverage));
7869513143efa734bef0c1a0c7f945022572dbc8518egdaniel    }
7876ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel    return sk_sp<const GrXferProcessor>(new PorterDuffXferProcessor(blendFormula, coverage));
788378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel}
7899513143efa734bef0c1a0c7f945022572dbc8518egdaniel
790318538484f99253b6a2acf97d4d1b420e628b289Brian Salomonstatic inline GrXPFactory::AnalysisProperties analysis_properties(
791a811b1200cc0b5e3819c89f62def23ec203d4b5aBrian Salomon        const GrProcessorAnalysisColor& color, const GrProcessorAnalysisCoverage& coverage,
7929a725dd9485654155e2e4196c32d372360bcdb61Brian Osman        const GrCaps& caps, GrPixelConfigIsClamped dstIsClamped, SkBlendMode mode) {
793318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon    using AnalysisProperties = GrXPFactory::AnalysisProperties;
794318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon    AnalysisProperties props = AnalysisProperties::kNone;
795a811b1200cc0b5e3819c89f62def23ec203d4b5aBrian Salomon    bool hasCoverage = GrProcessorAnalysisCoverage::kNone != coverage;
7966ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel    bool isLCD = GrProcessorAnalysisCoverage::kLCD == coverage;
7976ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel    BlendFormula formula;
7986ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel    if (isLCD) {
7996ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel        formula = gLCDBlendTable[(int)mode];
8006ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel    } else {
8016ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel        formula = gBlendTable[color.isOpaque()][hasCoverage][(int)mode];
8026ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel    }
80379cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel
80479cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel    if (formula.canTweakAlphaForCoverage() && !isLCD) {
805318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon        props |= AnalysisProperties::kCompatibleWithAlphaAsCoverage;
806318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon    }
80779cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel
80879cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel    if (isLCD) {
809aa13223f54d1f55ba702582f61359f8b43782730Greg Daniel        // See comment in MakeSrcOverXferProcessor about color.isOpaque here
810aa13223f54d1f55ba702582f61359f8b43782730Greg Daniel        if (SkBlendMode::kSrcOver == mode && color.isConstant() && /*color.isOpaque() &&*/
81179cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel            !caps.shaderCaps()->dualSourceBlendingSupport() &&
81279cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel            !caps.shaderCaps()->dstReadInShaderSupport()) {
81379cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel            props |= AnalysisProperties::kIgnoresInputColor;
81479cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel        } else {
81579cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel            // For LCD blending, if the color is not opaque we must read the dst in shader even if
81679cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel            // we have dual source blending. The opaqueness check must be done after blending so for
81779cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel            // simplicity we only allow src-over to not take the dst read path (though src, src-in,
81879cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel            // and DstATop would also work). We also fall into the dst read case for src-over if we
81979cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel            // do not have dual source blending.
82079cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel            if (SkBlendMode::kSrcOver != mode ||
821d7b1159d787de27d75032ec213903a03962ec839Greg Daniel                /*!color.isOpaque() ||*/ // See comment in MakeSrcOverXferProcessor about isOpaque.
822d7b1159d787de27d75032ec213903a03962ec839Greg Daniel                (formula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport())) {
82379cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel                props |= AnalysisProperties::kReadsDstInShader;
824318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon            }
825723b0501e22373bb3e6c306daaceae02cda8a124egdaniel        }
8266ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel    } else {
82779cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel        // With dual-source blending we never need the destination color in the shader.
82879cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel        if (!caps.shaderCaps()->dualSourceBlendingSupport()) {
82979cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel            // Mixed samples implicity computes a fractional coverage from sample coverage. This
83079cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel            // could affect the formula used. However, we don't expect to have mixed samples without
83179cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel            // dual source blending.
83279cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel            SkASSERT(!caps.usesMixedSamples());
83379cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel            if (formula.hasSecondaryOutput()) {
83479cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel                props |= AnalysisProperties::kReadsDstInShader;
83579cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel            }
8366ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel        }
837c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman    }
83879cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel
8399a725dd9485654155e2e4196c32d372360bcdb61Brian Osman    bool needsClamp = SkBlendMode::kPlus == mode;
8409a725dd9485654155e2e4196c32d372360bcdb61Brian Osman    if (needsClamp && (GrPixelConfigIsClamped::kNo == dstIsClamped)) {
8419a725dd9485654155e2e4196c32d372360bcdb61Brian Osman        props |= AnalysisProperties::kReadsDstInShader;
8429a725dd9485654155e2e4196c32d372360bcdb61Brian Osman    }
8439a725dd9485654155e2e4196c32d372360bcdb61Brian Osman
844318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon    if (!formula.modifiesDst() || !formula.usesInputColor()) {
845318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon        props |= AnalysisProperties::kIgnoresInputColor;
846318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon    }
847318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon    // Ignore the effect of coverage here for overlap stencil and cover property
848318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon    auto colorFormula = gBlendTable[color.isOpaque()][0][(int)mode];
8497b29749c13deab4588cbe0414a93191326800712Brian Salomon    SkASSERT(kAdd_GrBlendEquation == colorFormula.equation());
850318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon    if (!colorFormula.usesDstColor()) {
851318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon        props |= AnalysisProperties::kCanCombineOverlappedStencilAndCover;
852318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon    }
853318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon    return props;
85450785a3d10b53bea5beb6e18431a2449860be237bsalomon}
85550785a3d10b53bea5beb6e18431a2449860be237bsalomon
856318538484f99253b6a2acf97d4d1b420e628b289Brian SalomonGrXPFactory::AnalysisProperties GrPorterDuffXPFactory::analysisProperties(
857a811b1200cc0b5e3819c89f62def23ec203d4b5aBrian Salomon        const GrProcessorAnalysisColor& color,
858a811b1200cc0b5e3819c89f62def23ec203d4b5aBrian Salomon        const GrProcessorAnalysisCoverage& coverage,
8599a725dd9485654155e2e4196c32d372360bcdb61Brian Osman        const GrCaps& caps,
8609a725dd9485654155e2e4196c32d372360bcdb61Brian Osman        GrPixelConfigIsClamped dstIsClamped) const {
8619a725dd9485654155e2e4196c32d372360bcdb61Brian Osman    return analysis_properties(color, coverage, caps, dstIsClamped, fBlendMode);
862780b41fc10fb212ec6d9a9aeb7ca4cc0292fb85eBrian Salomon}
863780b41fc10fb212ec6d9a9aeb7ca4cc0292fb85eBrian Salomon
864f234272cbdcbcd46be462317e75cd138999c9fe9egdanielGR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory);
865c230414861558ce20b74281b1ca363e56c441832egdaniel
8666f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#if GR_TEST_UTILS
867a16339297859f37df69230e64f05624cef511ad3Brian Salomonconst GrXPFactory* GrPorterDuffXPFactory::TestGet(GrProcessorTestData* d) {
8687d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed    SkBlendMode mode = SkBlendMode(d->fRandom->nextULessThan((int)SkBlendMode::kLastCoeffMode));
869a16339297859f37df69230e64f05624cef511ad3Brian Salomon    return GrPorterDuffXPFactory::Get(mode);
870c230414861558ce20b74281b1ca363e56c441832egdaniel}
8716f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#endif
8729513143efa734bef0c1a0c7f945022572dbc8518egdaniel
873f234272cbdcbcd46be462317e75cd138999c9fe9egdanielvoid GrPorterDuffXPFactory::TestGetXPOutputTypes(const GrXferProcessor* xp,
874f234272cbdcbcd46be462317e75cd138999c9fe9egdaniel                                                 int* outPrimary,
875f234272cbdcbcd46be462317e75cd138999c9fe9egdaniel                                                 int* outSecondary) {
8766fd158ea47472c4d038e48980a95e36623f840c9cdalton    if (!!strcmp(xp->name(), "Porter Duff")) {
8776fd158ea47472c4d038e48980a95e36623f840c9cdalton        *outPrimary = *outSecondary = -1;
8786fd158ea47472c4d038e48980a95e36623f840c9cdalton        return;
8796fd158ea47472c4d038e48980a95e36623f840c9cdalton    }
8806fd158ea47472c4d038e48980a95e36623f840c9cdalton    BlendFormula blendFormula = static_cast<const PorterDuffXferProcessor*>(xp)->getBlendFormula();
8817b29749c13deab4588cbe0414a93191326800712Brian Salomon    *outPrimary = blendFormula.primaryOutput();
8827b29749c13deab4588cbe0414a93191326800712Brian Salomon    *outSecondary = blendFormula.secondaryOutput();
8836fd158ea47472c4d038e48980a95e36623f840c9cdalton}
884c4b72720e75313079212e69e46a5ef7c474b2305egdaniel
885c4b72720e75313079212e69e46a5ef7c474b2305egdaniel////////////////////////////////////////////////////////////////////////////////////////////////
886c4b72720e75313079212e69e46a5ef7c474b2305egdaniel// SrcOver Global functions
887c4b72720e75313079212e69e46a5ef7c474b2305egdaniel////////////////////////////////////////////////////////////////////////////////////////////////
8882047b7855546b21f7956c398592c070b3f91a9dbbsalomonconst GrXferProcessor& GrPorterDuffXPFactory::SimpleSrcOverXP() {
8897b29749c13deab4588cbe0414a93191326800712Brian Salomon    static BlendFormula gSrcOverBlendFormula =
8907b29749c13deab4588cbe0414a93191326800712Brian Salomon            MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff);
8916ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel    static PorterDuffXferProcessor gSrcOverXP(gSrcOverBlendFormula,
8926ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel                                              GrProcessorAnalysisCoverage::kSingleChannel);
8932047b7855546b21f7956c398592c070b3f91a9dbbsalomon    return gSrcOverXP;
8942047b7855546b21f7956c398592c070b3f91a9dbbsalomon}
895c4b72720e75313079212e69e46a5ef7c474b2305egdaniel
896d61c9d93b126dca0af17eff89be8536944dadf81Brian Salomonsk_sp<const GrXferProcessor> GrPorterDuffXPFactory::MakeSrcOverXferProcessor(
897a076d8711d24b8181f894038a4fd34d5327f1717Brian Salomon        const GrProcessorAnalysisColor& color, GrProcessorAnalysisCoverage coverage,
898a076d8711d24b8181f894038a4fd34d5327f1717Brian Salomon        bool hasMixedSamples, const GrCaps& caps) {
899abe795e4db533c2e230be0c2be868754e5a02a7eegdaniel    // We want to not make an xfer processor if possible. Thus for the simple case where we are not
900abe795e4db533c2e230be0c2be868754e5a02a7eegdaniel    // doing lcd blending we will just use our global SimpleSrcOverXP. This slightly differs from
901abe795e4db533c2e230be0c2be868754e5a02a7eegdaniel    // the general case where we convert a src-over blend that has solid coverage and an opaque
902abe795e4db533c2e230be0c2be868754e5a02a7eegdaniel    // color to src-mode, which allows disabling of blending.
903a811b1200cc0b5e3819c89f62def23ec203d4b5aBrian Salomon    if (coverage != GrProcessorAnalysisCoverage::kLCD) {
9042047b7855546b21f7956c398592c070b3f91a9dbbsalomon        // We return nullptr here, which our caller interprets as meaning "use SimpleSrcOverXP".
9052047b7855546b21f7956c398592c070b3f91a9dbbsalomon        // We don't simply return the address of that XP here because our caller would have to unref
9062047b7855546b21f7956c398592c070b3f91a9dbbsalomon        // it and since it is a global object and GrProgramElement's ref-cnting system is not thread
9072047b7855546b21f7956c398592c070b3f91a9dbbsalomon        // safe.
9082047b7855546b21f7956c398592c070b3f91a9dbbsalomon        return nullptr;
90956cf6dcb6572f1d355af041c1ebf157b2b3d0165egdaniel    }
91056cf6dcb6572f1d355af041c1ebf157b2b3d0165egdaniel
911aa13223f54d1f55ba702582f61359f8b43782730Greg Daniel    // Currently up the stack Skia is requiring that the dst is opaque or that the client has said
912aa13223f54d1f55ba702582f61359f8b43782730Greg Daniel    // the opaqueness doesn't matter. Thus for src-over we don't need to worry about the src color
913d7b1159d787de27d75032ec213903a03962ec839Greg Daniel    // being opaque or not. This allows us to use faster code paths as well as avoid various bugs
914d7b1159d787de27d75032ec213903a03962ec839Greg Daniel    // that occur with dst reads in the shader blending. For now we disable the check for
915d7b1159d787de27d75032ec213903a03962ec839Greg Daniel    // opaqueness, but in the future we should pass down the knowledge about dst opaqueness and make
916d7b1159d787de27d75032ec213903a03962ec839Greg Daniel    // the correct decision here.
917aa13223f54d1f55ba702582f61359f8b43782730Greg Daniel    //
918aa13223f54d1f55ba702582f61359f8b43782730Greg Daniel    // This also fixes a chrome bug on macs where we are getting random fuzziness when doing
919aa13223f54d1f55ba702582f61359f8b43782730Greg Daniel    // blending in the shader for non opaque sources.
920aa13223f54d1f55ba702582f61359f8b43782730Greg Daniel    if (color.isConstant() && /*color.isOpaque() &&*/
921aa13223f54d1f55ba702582f61359f8b43782730Greg Daniel        !caps.shaderCaps()->dualSourceBlendingSupport() &&
922abe795e4db533c2e230be0c2be868754e5a02a7eegdaniel        !caps.shaderCaps()->dstReadInShaderSupport()) {
923abe795e4db533c2e230be0c2be868754e5a02a7eegdaniel        // If we don't have dual source blending or in shader dst reads, we fall
924abe795e4db533c2e230be0c2be868754e5a02a7eegdaniel        // back to this trick for rendering SrcOver LCD text instead of doing a
925abe795e4db533c2e230be0c2be868754e5a02a7eegdaniel        // dst copy.
926a076d8711d24b8181f894038a4fd34d5327f1717Brian Salomon        return PDLCDXferProcessor::Make(SkBlendMode::kSrcOver, color);
927c4b72720e75313079212e69e46a5ef7c474b2305egdaniel    }
928c4b72720e75313079212e69e46a5ef7c474b2305egdaniel
929abe795e4db533c2e230be0c2be868754e5a02a7eegdaniel    BlendFormula blendFormula;
9305be6c95fa95a518ab109339df4695d6dda6e2419Brian Salomon    blendFormula = get_lcd_blend_formula(SkBlendMode::kSrcOver);
931d7b1159d787de27d75032ec213903a03962ec839Greg Daniel    // See comment above regarding why the opaque check is commented out here.
932d7b1159d787de27d75032ec213903a03962ec839Greg Daniel    if (/*!color.isOpaque() ||*/
9336ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel        (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport())) {
934a076d8711d24b8181f894038a4fd34d5327f1717Brian Salomon        return sk_sp<GrXferProcessor>(
9356ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel                new ShaderPDXferProcessor(hasMixedSamples, SkBlendMode::kSrcOver, coverage));
936c4b72720e75313079212e69e46a5ef7c474b2305egdaniel    }
9376ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel    return sk_sp<GrXferProcessor>(new PorterDuffXferProcessor(blendFormula, coverage));
938c4b72720e75313079212e69e46a5ef7c474b2305egdaniel}
939c4b72720e75313079212e69e46a5ef7c474b2305egdaniel
940d61c9d93b126dca0af17eff89be8536944dadf81Brian Salomonsk_sp<const GrXferProcessor> GrPorterDuffXPFactory::MakeNoCoverageXP(SkBlendMode blendmode) {
941119fb2b9505aea87900d2cf5cf3573814bcae08ccsmartdalton    BlendFormula formula = get_blend_formula(false, false, false, blendmode);
9426ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel    return sk_make_sp<PorterDuffXferProcessor>(formula, GrProcessorAnalysisCoverage::kNone);
943119fb2b9505aea87900d2cf5cf3573814bcae08ccsmartdalton}
944119fb2b9505aea87900d2cf5cf3573814bcae08ccsmartdalton
945318538484f99253b6a2acf97d4d1b420e628b289Brian SalomonGrXPFactory::AnalysisProperties GrPorterDuffXPFactory::SrcOverAnalysisProperties(
946a811b1200cc0b5e3819c89f62def23ec203d4b5aBrian Salomon        const GrProcessorAnalysisColor& color,
947a811b1200cc0b5e3819c89f62def23ec203d4b5aBrian Salomon        const GrProcessorAnalysisCoverage& coverage,
9489a725dd9485654155e2e4196c32d372360bcdb61Brian Osman        const GrCaps& caps,
9499a725dd9485654155e2e4196c32d372360bcdb61Brian Osman        GrPixelConfigIsClamped dstIsClamped) {
9509a725dd9485654155e2e4196c32d372360bcdb61Brian Osman    return analysis_properties(color, coverage, caps, dstIsClamped, SkBlendMode::kSrcOver);
951c4b72720e75313079212e69e46a5ef7c474b2305egdaniel}
952