Home | History | Annotate | Download | only in effects
      1 /*
      2  * Copyright 2014 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "effects/GrPorterDuffXferProcessor.h"
      9 
     10 #include "GrBlend.h"
     11 #include "GrCaps.h"
     12 #include "GrPipeline.h"
     13 #include "GrProcessor.h"
     14 #include "GrProcessorAnalysis.h"
     15 #include "GrTypes.h"
     16 #include "GrXferProcessor.h"
     17 #include "glsl/GrGLSLBlend.h"
     18 #include "glsl/GrGLSLFragmentShaderBuilder.h"
     19 #include "glsl/GrGLSLProgramDataManager.h"
     20 #include "glsl/GrGLSLUniformHandler.h"
     21 #include "glsl/GrGLSLXferProcessor.h"
     22 
     23 /**
     24  * Wraps the shader outputs and HW blend state that comprise a Porter Duff blend mode with coverage.
     25  */
     26 class BlendFormula {
     27 public:
     28     /**
     29      * Values the shader can write to primary and secondary outputs. These must all be modulated by
     30      * coverage to support mixed samples. The XP will ignore the multiplies when not using coverage.
     31      */
     32     enum OutputType {
     33         kNone_OutputType,        //<! 0
     34         kCoverage_OutputType,    //<! inputCoverage
     35         kModulate_OutputType,    //<! inputColor * inputCoverage
     36         kSAModulate_OutputType,  //<! inputColor.a * inputCoverage
     37         kISAModulate_OutputType, //<! (1 - inputColor.a) * inputCoverage
     38         kISCModulate_OutputType, //<! (1 - inputColor) * inputCoverage
     39 
     40         kLast_OutputType = kISCModulate_OutputType
     41     };
     42 
     43     BlendFormula() = default;
     44 
     45     constexpr BlendFormula(OutputType primaryOut, OutputType secondaryOut, GrBlendEquation equation,
     46                            GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff)
     47             : fPrimaryOutputType(primaryOut)
     48             , fSecondaryOutputType(secondaryOut)
     49             , fBlendEquation(equation)
     50             , fSrcCoeff(srcCoeff)
     51             , fDstCoeff(dstCoeff)
     52             , fProps(GetProperties(primaryOut, secondaryOut, equation, srcCoeff, dstCoeff)) {}
     53 
     54     BlendFormula& operator=(const BlendFormula& other) {
     55         SkDEBUGCODE(other.validatePreoptimized());
     56         fData = other.fData;
     57         return *this;
     58     }
     59 
     60     bool operator==(const BlendFormula& other) const {
     61         SkDEBUGCODE(this->validatePreoptimized());
     62         SkDEBUGCODE(other.validatePreoptimized());
     63         return fData == other.fData;
     64     }
     65 
     66     bool hasSecondaryOutput() const {
     67         SkDEBUGCODE(this->validatePreoptimized());
     68         return kNone_OutputType != fSecondaryOutputType;
     69     }
     70     bool modifiesDst() const {
     71         SkDEBUGCODE(this->validatePreoptimized());
     72         return SkToBool(fProps & kModifiesDst_Property);
     73     }
     74     bool usesDstColor() const {
     75         SkDEBUGCODE(this->validatePreoptimized());
     76         return SkToBool(fProps & kUsesDstColor_Property);
     77     }
     78     bool usesInputColor() const {
     79         SkDEBUGCODE(this->validatePreoptimized());
     80         return SkToBool(fProps & kUsesInputColor_Property);
     81     }
     82     bool canTweakAlphaForCoverage() const {
     83         SkDEBUGCODE(this->validatePreoptimized());
     84         return SkToBool(fProps & kCanTweakAlphaForCoverage_Property);
     85     }
     86 
     87     GrBlendEquation equation() const {
     88         SkDEBUGCODE(this->validatePreoptimized());
     89         return fBlendEquation;
     90     }
     91 
     92     GrBlendCoeff srcCoeff() const {
     93         SkDEBUGCODE(this->validatePreoptimized());
     94         return fSrcCoeff;
     95     }
     96 
     97     GrBlendCoeff dstCoeff() const {
     98         SkDEBUGCODE(this->validatePreoptimized());
     99         return fDstCoeff;
    100     }
    101 
    102     OutputType primaryOutput() const {
    103         SkDEBUGCODE(this->validatePreoptimized());
    104         return fPrimaryOutputType;
    105     }
    106 
    107     OutputType secondaryOutput() const {
    108         SkDEBUGCODE(this->validatePreoptimized());
    109         return fSecondaryOutputType;
    110     }
    111 
    112 private:
    113     enum Properties {
    114         kModifiesDst_Property              = 1,
    115         kUsesDstColor_Property             = 1 << 1,
    116         kUsesInputColor_Property           = 1 << 2,
    117         kCanTweakAlphaForCoverage_Property = 1 << 3,
    118 
    119         kLast_Property = kCanTweakAlphaForCoverage_Property
    120     };
    121     GR_DECL_BITFIELD_OPS_FRIENDS(Properties)
    122 
    123 #ifdef SK_DEBUG
    124     void validatePreoptimized() const {
    125         // The provided formula should already be optimized before a BlendFormula is constructed.
    126         // Preferably these asserts would be done statically in the constexpr constructor, but this
    127         // is not allowed in C++11.
    128         SkASSERT((kNone_OutputType == fPrimaryOutputType) ==
    129                  !GrBlendCoeffsUseSrcColor(fSrcCoeff, fDstCoeff));
    130         SkASSERT(!GrBlendCoeffRefsSrc2(fSrcCoeff));
    131         SkASSERT((kNone_OutputType == fSecondaryOutputType) == !GrBlendCoeffRefsSrc2(fDstCoeff));
    132         SkASSERT(fPrimaryOutputType != fSecondaryOutputType ||
    133                  kNone_OutputType == fPrimaryOutputType);
    134         SkASSERT(kNone_OutputType != fPrimaryOutputType ||
    135                  kNone_OutputType == fSecondaryOutputType);
    136     }
    137 #endif
    138 
    139     /**
    140      * Deduce the properties of a BlendFormula.
    141      */
    142     static constexpr Properties GetProperties(OutputType PrimaryOut, OutputType SecondaryOut,
    143                                               GrBlendEquation BlendEquation, GrBlendCoeff SrcCoeff,
    144                                               GrBlendCoeff DstCoeff);
    145 
    146     union {
    147         struct {
    148             // We allot the enums one more bit than they require because MSVC seems to sign-extend
    149             // them when the top bit is set. (This is in violation of the C++03 standard 9.6/4)
    150             OutputType        fPrimaryOutputType    : 4;
    151             OutputType        fSecondaryOutputType  : 4;
    152             GrBlendEquation   fBlendEquation        : 6;
    153             GrBlendCoeff      fSrcCoeff             : 6;
    154             GrBlendCoeff      fDstCoeff             : 6;
    155             Properties        fProps                : 32 - (4 + 4 + 6 + 6 + 6);
    156         };
    157         uint32_t fData;
    158     };
    159 
    160     GR_STATIC_ASSERT(kLast_OutputType      < (1 << 3));
    161     GR_STATIC_ASSERT(kLast_GrBlendEquation < (1 << 5));
    162     GR_STATIC_ASSERT(kLast_GrBlendCoeff    < (1 << 5));
    163     GR_STATIC_ASSERT(kLast_Property        < (1 << 6));
    164 };
    165 
    166 GR_STATIC_ASSERT(4 == sizeof(BlendFormula));
    167 
    168 GR_MAKE_BITFIELD_OPS(BlendFormula::Properties);
    169 
    170 constexpr BlendFormula::Properties BlendFormula::GetProperties(OutputType PrimaryOut,
    171                                                                OutputType SecondaryOut,
    172                                                                GrBlendEquation BlendEquation,
    173                                                                GrBlendCoeff SrcCoeff,
    174                                                                GrBlendCoeff DstCoeff) {
    175     return static_cast<Properties>(
    176             (GrBlendModifiesDst(BlendEquation, SrcCoeff, DstCoeff) ? kModifiesDst_Property : 0) |
    177             (GrBlendCoeffsUseDstColor(SrcCoeff, DstCoeff) ? kUsesDstColor_Property : 0) |
    178             ((PrimaryOut >= kModulate_OutputType && GrBlendCoeffsUseSrcColor(SrcCoeff, DstCoeff)) ||
    179                              (SecondaryOut >= kModulate_OutputType &&
    180                               GrBlendCoeffRefsSrc2(DstCoeff))
    181                      ? kUsesInputColor_Property
    182                      : 0) |  // We assert later that SrcCoeff doesn't ref src2.
    183             ((kModulate_OutputType == PrimaryOut || kNone_OutputType == PrimaryOut) &&
    184                              kNone_OutputType == SecondaryOut &&
    185                              GrBlendAllowsCoverageAsAlpha(BlendEquation, SrcCoeff, DstCoeff)
    186                      ? kCanTweakAlphaForCoverage_Property
    187                      : 0));
    188 }
    189 
    190 /**
    191  * When there is no coverage, or the blend mode can tweak alpha for coverage, we use the standard
    192  * Porter Duff formula.
    193  */
    194 static constexpr BlendFormula MakeCoeffFormula(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
    195     // When the coeffs are (Zero, Zero) or (Zero, One) we set the primary output to none.
    196     return (kZero_GrBlendCoeff == srcCoeff &&
    197             (kZero_GrBlendCoeff == dstCoeff || kOne_GrBlendCoeff == dstCoeff))
    198            ? BlendFormula(BlendFormula::kNone_OutputType, BlendFormula::kNone_OutputType,
    199                           kAdd_GrBlendEquation, kZero_GrBlendCoeff, dstCoeff)
    200            : BlendFormula(BlendFormula::kModulate_OutputType, BlendFormula::kNone_OutputType,
    201                         kAdd_GrBlendEquation, srcCoeff, dstCoeff);
    202 }
    203 
    204 /**
    205  * Basic coeff formula similar to MakeCoeffFormula but we will make the src f*Sa. This is used in
    206  * LCD dst-out.
    207  */
    208 static constexpr BlendFormula MakeSAModulateFormula(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
    209     return BlendFormula(BlendFormula::kSAModulate_OutputType, BlendFormula::kNone_OutputType,
    210                         kAdd_GrBlendEquation, srcCoeff, dstCoeff);
    211 }
    212 
    213 /**
    214  * When there is coverage, the equation with f=coverage is:
    215  *
    216  *   D' = f * (S * srcCoeff + D * dstCoeff) + (1-f) * D
    217  *
    218  * This can be rewritten as:
    219  *
    220  *   D' = f * S * srcCoeff + D * (1 - [f * (1 - dstCoeff)])
    221  *
    222  * To implement this formula, we output [f * (1 - dstCoeff)] for the secondary color and replace the
    223  * HW dst coeff with IS2C.
    224  *
    225  * Xfer modes: dst-atop (Sa!=1)
    226  */
    227 static constexpr BlendFormula MakeCoverageFormula(
    228         BlendFormula::OutputType oneMinusDstCoeffModulateOutput, GrBlendCoeff srcCoeff) {
    229     return BlendFormula(BlendFormula::kModulate_OutputType, oneMinusDstCoeffModulateOutput,
    230                         kAdd_GrBlendEquation, srcCoeff, kIS2C_GrBlendCoeff);
    231 }
    232 
    233 /**
    234  * When there is coverage and the src coeff is Zero, the equation with f=coverage becomes:
    235  *
    236  *   D' = f * D * dstCoeff + (1-f) * D
    237  *
    238  * This can be rewritten as:
    239  *
    240  *   D' = D - D * [f * (1 - dstCoeff)]
    241  *
    242  * To implement this formula, we output [f * (1 - dstCoeff)] for the primary color and use a reverse
    243  * subtract HW blend equation with coeffs of (DC, One).
    244  *
    245  * Xfer modes: clear, dst-out (Sa=1), dst-in (Sa!=1), modulate (Sc!=1)
    246  */
    247 static constexpr BlendFormula MakeCoverageSrcCoeffZeroFormula(
    248         BlendFormula::OutputType oneMinusDstCoeffModulateOutput) {
    249     return BlendFormula(oneMinusDstCoeffModulateOutput, BlendFormula::kNone_OutputType,
    250                         kReverseSubtract_GrBlendEquation, kDC_GrBlendCoeff, kOne_GrBlendCoeff);
    251 }
    252 
    253 /**
    254  * When there is coverage and the dst coeff is Zero, the equation with f=coverage becomes:
    255  *
    256  *   D' = f * S * srcCoeff + (1-f) * D
    257  *
    258  * To implement this formula, we output [f] for the secondary color and replace the HW dst coeff
    259  * with IS2A. (Note that we can avoid dual source blending when Sa=1 by using ISA.)
    260  *
    261  * Xfer modes (Sa!=1): src, src-in, src-out
    262  */
    263 static constexpr BlendFormula MakeCoverageDstCoeffZeroFormula(GrBlendCoeff srcCoeff) {
    264     return BlendFormula(BlendFormula::kModulate_OutputType, BlendFormula::kCoverage_OutputType,
    265                         kAdd_GrBlendEquation, srcCoeff, kIS2A_GrBlendCoeff);
    266 }
    267 
    268 // Older GCC won't like the constexpr arrays because of
    269 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61484.
    270 // MSVC 2015 crashes with an internal compiler error.
    271 #if !defined(__clang__) && ((defined(__GNUC__) && __GNUC__ < 5) || (defined(_MSC_VER) && _MSC_VER <= 1910))
    272 #   define MAYBE_CONSTEXPR const
    273 #else
    274 #   define MAYBE_CONSTEXPR constexpr
    275 #endif
    276 
    277 /**
    278  * This table outlines the blend formulas we will use with each xfermode, with and without coverage,
    279  * with and without an opaque input color. Optimization properties are deduced at compile time so we
    280  * can make runtime decisions quickly. RGB coverage is not supported.
    281  */
    282 static MAYBE_CONSTEXPR BlendFormula gBlendTable[2][2][(int)SkBlendMode::kLastCoeffMode + 1] = {
    283                      /*>> No coverage, input color unknown <<*/ {{
    284 
    285     /* clear */      MakeCoeffFormula(kZero_GrBlendCoeff, kZero_GrBlendCoeff),
    286     /* src */        MakeCoeffFormula(kOne_GrBlendCoeff,  kZero_GrBlendCoeff),
    287     /* dst */        MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
    288     /* src-over */   MakeCoeffFormula(kOne_GrBlendCoeff,  kISA_GrBlendCoeff),
    289     /* dst-over */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kOne_GrBlendCoeff),
    290     /* src-in */     MakeCoeffFormula(kDA_GrBlendCoeff,   kZero_GrBlendCoeff),
    291     /* dst-in */     MakeCoeffFormula(kZero_GrBlendCoeff, kSA_GrBlendCoeff),
    292     /* src-out */    MakeCoeffFormula(kIDA_GrBlendCoeff,  kZero_GrBlendCoeff),
    293     /* dst-out */    MakeCoeffFormula(kZero_GrBlendCoeff, kISA_GrBlendCoeff),
    294     /* src-atop */   MakeCoeffFormula(kDA_GrBlendCoeff,   kISA_GrBlendCoeff),
    295     /* dst-atop */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kSA_GrBlendCoeff),
    296     /* xor */        MakeCoeffFormula(kIDA_GrBlendCoeff,  kISA_GrBlendCoeff),
    297     /* plus */       MakeCoeffFormula(kOne_GrBlendCoeff,  kOne_GrBlendCoeff),
    298     /* modulate */   MakeCoeffFormula(kZero_GrBlendCoeff, kSC_GrBlendCoeff),
    299     /* screen */     MakeCoeffFormula(kOne_GrBlendCoeff,  kISC_GrBlendCoeff),
    300 
    301                      }, /*>> Has coverage, input color unknown <<*/ {
    302 
    303     /* clear */      MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType),
    304     /* src */        MakeCoverageDstCoeffZeroFormula(kOne_GrBlendCoeff),
    305     /* dst */        MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
    306     /* src-over */   MakeCoeffFormula(kOne_GrBlendCoeff,  kISA_GrBlendCoeff),
    307     /* dst-over */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kOne_GrBlendCoeff),
    308     /* src-in */     MakeCoverageDstCoeffZeroFormula(kDA_GrBlendCoeff),
    309     /* dst-in */     MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISAModulate_OutputType),
    310     /* src-out */    MakeCoverageDstCoeffZeroFormula(kIDA_GrBlendCoeff),
    311     /* dst-out */    MakeCoeffFormula(kZero_GrBlendCoeff, kISA_GrBlendCoeff),
    312     /* src-atop */   MakeCoeffFormula(kDA_GrBlendCoeff,   kISA_GrBlendCoeff),
    313     /* dst-atop */   MakeCoverageFormula(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff),
    314     /* xor */        MakeCoeffFormula(kIDA_GrBlendCoeff,  kISA_GrBlendCoeff),
    315     /* plus */       MakeCoeffFormula(kOne_GrBlendCoeff,  kOne_GrBlendCoeff),
    316     /* modulate */   MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISCModulate_OutputType),
    317     /* screen */     MakeCoeffFormula(kOne_GrBlendCoeff,  kISC_GrBlendCoeff),
    318 
    319                      }}, /*>> No coverage, input color opaque <<*/ {{
    320 
    321     /* clear */      MakeCoeffFormula(kZero_GrBlendCoeff, kZero_GrBlendCoeff),
    322     /* src */        MakeCoeffFormula(kOne_GrBlendCoeff,  kZero_GrBlendCoeff),
    323     /* dst */        MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
    324     /* src-over */   MakeCoeffFormula(kOne_GrBlendCoeff,  kISA_GrBlendCoeff), // see comment below
    325     /* dst-over */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kOne_GrBlendCoeff),
    326     /* src-in */     MakeCoeffFormula(kDA_GrBlendCoeff,   kZero_GrBlendCoeff),
    327     /* dst-in */     MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
    328     /* src-out */    MakeCoeffFormula(kIDA_GrBlendCoeff,  kZero_GrBlendCoeff),
    329     /* dst-out */    MakeCoeffFormula(kZero_GrBlendCoeff, kZero_GrBlendCoeff),
    330     /* src-atop */   MakeCoeffFormula(kDA_GrBlendCoeff,   kZero_GrBlendCoeff),
    331     /* dst-atop */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kOne_GrBlendCoeff),
    332     /* xor */        MakeCoeffFormula(kIDA_GrBlendCoeff,  kZero_GrBlendCoeff),
    333     /* plus */       MakeCoeffFormula(kOne_GrBlendCoeff,  kOne_GrBlendCoeff),
    334     /* modulate */   MakeCoeffFormula(kZero_GrBlendCoeff, kSC_GrBlendCoeff),
    335     /* screen */     MakeCoeffFormula(kOne_GrBlendCoeff,  kISC_GrBlendCoeff),
    336 
    337                      }, /*>> Has coverage, input color opaque <<*/ {
    338 
    339     /* clear */      MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType),
    340     /* src */        MakeCoeffFormula(kOne_GrBlendCoeff,  kISA_GrBlendCoeff),
    341     /* dst */        MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
    342     /* src-over */   MakeCoeffFormula(kOne_GrBlendCoeff,  kISA_GrBlendCoeff),
    343     /* dst-over */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kOne_GrBlendCoeff),
    344     /* src-in */     MakeCoeffFormula(kDA_GrBlendCoeff,   kISA_GrBlendCoeff),
    345     /* dst-in */     MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
    346     /* src-out */    MakeCoeffFormula(kIDA_GrBlendCoeff,  kISA_GrBlendCoeff),
    347     /* dst-out */    MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType),
    348     /* src-atop */   MakeCoeffFormula(kDA_GrBlendCoeff,   kISA_GrBlendCoeff),
    349     /* dst-atop */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kOne_GrBlendCoeff),
    350     /* xor */        MakeCoeffFormula(kIDA_GrBlendCoeff,  kISA_GrBlendCoeff),
    351     /* plus */       MakeCoeffFormula(kOne_GrBlendCoeff,  kOne_GrBlendCoeff),
    352     /* modulate */   MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISCModulate_OutputType),
    353     /* screen */     MakeCoeffFormula(kOne_GrBlendCoeff,  kISC_GrBlendCoeff),
    354 }}};
    355 // In the above table src-over is not optimized to src mode when the color is opaque because we
    356 // found no advantage to doing so. Also, we are using a global src-over XP in most cases which is
    357 // not specialized for opaque input. If the table were set to use the src formula then we'd have to
    358 // change when we use this global XP to keep analysis and practice in sync.
    359 
    360 static MAYBE_CONSTEXPR BlendFormula gLCDBlendTable[(int)SkBlendMode::kLastCoeffMode + 1] = {
    361     /* clear */      MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType),
    362     /* src */        MakeCoverageFormula(BlendFormula::kCoverage_OutputType, kOne_GrBlendCoeff),
    363     /* dst */        MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
    364     /* src-over */   MakeCoverageFormula(BlendFormula::kSAModulate_OutputType, kOne_GrBlendCoeff),
    365     /* dst-over */   MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
    366     /* src-in */     MakeCoverageFormula(BlendFormula::kCoverage_OutputType, kDA_GrBlendCoeff),
    367     /* dst-in */     MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISAModulate_OutputType),
    368     /* src-out */    MakeCoverageFormula(BlendFormula::kCoverage_OutputType, kIDA_GrBlendCoeff),
    369     /* dst-out */    MakeSAModulateFormula(kZero_GrBlendCoeff, kISC_GrBlendCoeff),
    370     /* src-atop */   MakeCoverageFormula(BlendFormula::kSAModulate_OutputType, kDA_GrBlendCoeff),
    371     /* dst-atop */   MakeCoverageFormula(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff),
    372     /* xor */        MakeCoverageFormula(BlendFormula::kSAModulate_OutputType, kIDA_GrBlendCoeff),
    373     /* plus */       MakeCoeffFormula(kOne_GrBlendCoeff, kOne_GrBlendCoeff),
    374     /* modulate */   MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISCModulate_OutputType),
    375     /* screen */     MakeCoeffFormula(kOne_GrBlendCoeff, kISC_GrBlendCoeff),
    376 };
    377 
    378 #undef MAYBE_CONSTEXPR
    379 
    380 static BlendFormula get_blend_formula(bool isOpaque,
    381                                       bool hasCoverage,
    382                                       bool hasMixedSamples,
    383                                       SkBlendMode xfermode) {
    384     SkASSERT((unsigned)xfermode <= (unsigned)SkBlendMode::kLastCoeffMode);
    385     bool conflatesCoverage = hasCoverage || hasMixedSamples;
    386     return gBlendTable[isOpaque][conflatesCoverage][(int)xfermode];
    387 }
    388 
    389 static BlendFormula get_lcd_blend_formula(SkBlendMode xfermode) {
    390     SkASSERT((unsigned)xfermode <= (unsigned)SkBlendMode::kLastCoeffMode);
    391 
    392     return gLCDBlendTable[(int)xfermode];
    393 }
    394 
    395 ///////////////////////////////////////////////////////////////////////////////
    396 
    397 class PorterDuffXferProcessor : public GrXferProcessor {
    398 public:
    399     PorterDuffXferProcessor(BlendFormula blendFormula, GrProcessorAnalysisCoverage coverage)
    400             : INHERITED(false, false, coverage)
    401             , fBlendFormula(blendFormula) {
    402         this->initClassID<PorterDuffXferProcessor>();
    403     }
    404 
    405     const char* name() const override { return "Porter Duff"; }
    406 
    407     GrGLSLXferProcessor* createGLSLInstance() const override;
    408 
    409     BlendFormula getBlendFormula() const { return fBlendFormula; }
    410 
    411 private:
    412     void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
    413 
    414     bool onHasSecondaryOutput() const override { return fBlendFormula.hasSecondaryOutput(); }
    415 
    416     void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override {
    417         blendInfo->fEquation = fBlendFormula.equation();
    418         blendInfo->fSrcBlend = fBlendFormula.srcCoeff();
    419         blendInfo->fDstBlend = fBlendFormula.dstCoeff();
    420         blendInfo->fWriteColor = fBlendFormula.modifiesDst();
    421     }
    422 
    423     bool onIsEqual(const GrXferProcessor& xpBase) const override {
    424         const PorterDuffXferProcessor& xp = xpBase.cast<PorterDuffXferProcessor>();
    425         return fBlendFormula == xp.fBlendFormula;
    426     }
    427 
    428     const BlendFormula fBlendFormula;
    429 
    430     typedef GrXferProcessor INHERITED;
    431 };
    432 
    433 ///////////////////////////////////////////////////////////////////////////////
    434 
    435 static void append_color_output(const PorterDuffXferProcessor& xp,
    436                                 GrGLSLXPFragmentBuilder* fragBuilder,
    437                                 BlendFormula::OutputType outputType, const char* output,
    438                                 const char* inColor, const char* inCoverage) {
    439     SkASSERT(inCoverage);
    440     SkASSERT(inColor);
    441     switch (outputType) {
    442         case BlendFormula::kNone_OutputType:
    443             fragBuilder->codeAppendf("%s = vec4(0.0);", output);
    444             break;
    445         case BlendFormula::kCoverage_OutputType:
    446             // We can have a coverage formula while not reading coverage if there are mixed samples.
    447             fragBuilder->codeAppendf("%s = %s;", output, inCoverage);
    448             break;
    449         case BlendFormula::kModulate_OutputType:
    450             fragBuilder->codeAppendf("%s = %s * %s;", output, inColor, inCoverage);
    451             break;
    452         case BlendFormula::kSAModulate_OutputType:
    453             fragBuilder->codeAppendf("%s = %s.a * %s;", output, inColor, inCoverage);
    454             break;
    455         case BlendFormula::kISAModulate_OutputType:
    456             fragBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", output, inColor, inCoverage);
    457             break;
    458         case BlendFormula::kISCModulate_OutputType:
    459             fragBuilder->codeAppendf("%s = (vec4(1.0) - %s) * %s;", output, inColor, inCoverage);
    460             break;
    461         default:
    462             SkFAIL("Unsupported output type.");
    463             break;
    464     }
    465 }
    466 
    467 class GLPorterDuffXferProcessor : public GrGLSLXferProcessor {
    468 public:
    469     static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) {
    470         const PorterDuffXferProcessor& xp = processor.cast<PorterDuffXferProcessor>();
    471         b->add32(xp.getBlendFormula().primaryOutput() |
    472                  (xp.getBlendFormula().secondaryOutput() << 3));
    473         GR_STATIC_ASSERT(BlendFormula::kLast_OutputType < 8);
    474     }
    475 
    476 private:
    477     void emitOutputsForBlendState(const EmitArgs& args) override {
    478         const PorterDuffXferProcessor& xp = args.fXP.cast<PorterDuffXferProcessor>();
    479         GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
    480 
    481         BlendFormula blendFormula = xp.getBlendFormula();
    482         if (blendFormula.hasSecondaryOutput()) {
    483             append_color_output(xp, fragBuilder, blendFormula.secondaryOutput(),
    484                                 args.fOutputSecondary, args.fInputColor, args.fInputCoverage);
    485         }
    486         append_color_output(xp, fragBuilder, blendFormula.primaryOutput(), args.fOutputPrimary,
    487                             args.fInputColor, args.fInputCoverage);
    488     }
    489 
    490     void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
    491 
    492     typedef GrGLSLXferProcessor INHERITED;
    493 };
    494 
    495 ///////////////////////////////////////////////////////////////////////////////
    496 
    497 void PorterDuffXferProcessor::onGetGLSLProcessorKey(const GrShaderCaps&,
    498                                                     GrProcessorKeyBuilder* b) const {
    499     GLPorterDuffXferProcessor::GenKey(*this, b);
    500 }
    501 
    502 GrGLSLXferProcessor* PorterDuffXferProcessor::createGLSLInstance() const {
    503     return new GLPorterDuffXferProcessor;
    504 }
    505 
    506 ///////////////////////////////////////////////////////////////////////////////
    507 
    508 class ShaderPDXferProcessor : public GrXferProcessor {
    509 public:
    510     ShaderPDXferProcessor(bool hasMixedSamples, SkBlendMode xfermode,
    511                           GrProcessorAnalysisCoverage coverage)
    512             : INHERITED(true, hasMixedSamples, coverage), fXfermode(xfermode) {
    513         this->initClassID<ShaderPDXferProcessor>();
    514     }
    515 
    516     const char* name() const override { return "Porter Duff Shader"; }
    517 
    518     GrGLSLXferProcessor* createGLSLInstance() const override;
    519 
    520     SkBlendMode getXfermode() const { return fXfermode; }
    521 
    522 private:
    523     void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
    524 
    525     bool onIsEqual(const GrXferProcessor& xpBase) const override {
    526         const ShaderPDXferProcessor& xp = xpBase.cast<ShaderPDXferProcessor>();
    527         return fXfermode == xp.fXfermode;
    528     }
    529 
    530     const SkBlendMode fXfermode;
    531 
    532     typedef GrXferProcessor INHERITED;
    533 };
    534 
    535 ///////////////////////////////////////////////////////////////////////////////
    536 
    537 class GLShaderPDXferProcessor : public GrGLSLXferProcessor {
    538 public:
    539     static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) {
    540         const ShaderPDXferProcessor& xp = processor.cast<ShaderPDXferProcessor>();
    541         b->add32((int)xp.getXfermode());
    542     }
    543 
    544 private:
    545     void emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder* fragBuilder,
    546                                  GrGLSLUniformHandler* uniformHandler,
    547                                  const char* srcColor,
    548                                  const char* srcCoverage,
    549                                  const char* dstColor,
    550                                  const char* outColor,
    551                                  const char* outColorSecondary,
    552                                  const GrXferProcessor& proc) override {
    553         const ShaderPDXferProcessor& xp = proc.cast<ShaderPDXferProcessor>();
    554 
    555         GrGLSLBlend::AppendMode(fragBuilder, srcColor, dstColor, outColor, xp.getXfermode());
    556 
    557         // Apply coverage.
    558         INHERITED::DefaultCoverageModulation(fragBuilder, srcCoverage, dstColor, outColor,
    559                                              outColorSecondary, xp);
    560     }
    561 
    562     void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
    563 
    564     typedef GrGLSLXferProcessor INHERITED;
    565 };
    566 
    567 ///////////////////////////////////////////////////////////////////////////////
    568 
    569 void ShaderPDXferProcessor::onGetGLSLProcessorKey(const GrShaderCaps&,
    570                                                   GrProcessorKeyBuilder* b) const {
    571     GLShaderPDXferProcessor::GenKey(*this, b);
    572 }
    573 
    574 GrGLSLXferProcessor* ShaderPDXferProcessor::createGLSLInstance() const {
    575     return new GLShaderPDXferProcessor;
    576 }
    577 
    578 ///////////////////////////////////////////////////////////////////////////////
    579 
    580 class PDLCDXferProcessor : public GrXferProcessor {
    581 public:
    582     static sk_sp<const GrXferProcessor> Make(SkBlendMode mode,
    583                                              const GrProcessorAnalysisColor& inputColor);
    584 
    585     ~PDLCDXferProcessor() override;
    586 
    587     const char* name() const override { return "Porter Duff LCD"; }
    588 
    589     GrGLSLXferProcessor* createGLSLInstance() const override;
    590 
    591     uint8_t alpha() const { return fAlpha; }
    592 
    593 private:
    594     PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha);
    595 
    596     void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
    597 
    598     void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override {
    599         blendInfo->fSrcBlend = kConstC_GrBlendCoeff;
    600         blendInfo->fDstBlend = kISC_GrBlendCoeff;
    601         blendInfo->fBlendConstant = fBlendConstant;
    602     }
    603 
    604     bool onIsEqual(const GrXferProcessor& xpBase) const override {
    605         const PDLCDXferProcessor& xp = xpBase.cast<PDLCDXferProcessor>();
    606         if (fBlendConstant != xp.fBlendConstant || fAlpha != xp.fAlpha) {
    607             return false;
    608         }
    609         return true;
    610     }
    611 
    612     GrColor fBlendConstant;
    613     uint8_t fAlpha;
    614 
    615     typedef GrXferProcessor INHERITED;
    616 };
    617 
    618 ///////////////////////////////////////////////////////////////////////////////
    619 
    620 class GLPDLCDXferProcessor : public GrGLSLXferProcessor {
    621 public:
    622     GLPDLCDXferProcessor(const GrProcessor&) : fLastAlpha(SK_MaxU32) {}
    623 
    624     ~GLPDLCDXferProcessor() override {}
    625 
    626     static void GenKey(const GrProcessor& processor, const GrShaderCaps& caps,
    627                        GrProcessorKeyBuilder* b) {}
    628 
    629 private:
    630     void emitOutputsForBlendState(const EmitArgs& args) override {
    631         const char* alpha;
    632         fAlphaUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat_GrSLType,
    633                                                          kDefault_GrSLPrecision, "alpha", &alpha);
    634         GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
    635         // We want to force our primary output to be alpha * Coverage, where alpha is the alpha
    636         // value of the src color. We know that there are no color stages (or we wouldn't have
    637         // created this xp) and the r,g, and b channels of the op's input color are baked into the
    638         // blend constant.
    639         SkASSERT(args.fInputCoverage);
    640         fragBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, alpha, args.fInputCoverage);
    641     }
    642 
    643     void onSetData(const GrGLSLProgramDataManager& pdm, const GrXferProcessor& xp) override {
    644         uint32_t alpha = SkToU32(xp.cast<PDLCDXferProcessor>().alpha());
    645         if (fLastAlpha != alpha) {
    646             pdm.set1f(fAlphaUniform, alpha / 255.f);
    647             fLastAlpha = alpha;
    648         }
    649     }
    650 
    651     GrGLSLUniformHandler::UniformHandle fAlphaUniform;
    652     uint32_t fLastAlpha;
    653     typedef GrGLSLXferProcessor INHERITED;
    654 };
    655 
    656 ///////////////////////////////////////////////////////////////////////////////
    657 
    658 PDLCDXferProcessor::PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha)
    659     : INHERITED(false, false, GrProcessorAnalysisCoverage::kLCD)
    660     , fBlendConstant(blendConstant)
    661     , fAlpha(alpha) {
    662     this->initClassID<PDLCDXferProcessor>();
    663 }
    664 
    665 sk_sp<const GrXferProcessor> PDLCDXferProcessor::Make(SkBlendMode mode,
    666                                                       const GrProcessorAnalysisColor& color) {
    667     if (SkBlendMode::kSrcOver != mode) {
    668         return nullptr;
    669     }
    670     GrColor blendConstant;
    671     if (!color.isConstant(&blendConstant)) {
    672         return nullptr;
    673     }
    674     blendConstant = GrUnpremulColor(blendConstant);
    675     uint8_t alpha = GrColorUnpackA(blendConstant);
    676     blendConstant |= (0xff << GrColor_SHIFT_A);
    677     return sk_sp<GrXferProcessor>(new PDLCDXferProcessor(blendConstant, alpha));
    678 }
    679 
    680 PDLCDXferProcessor::~PDLCDXferProcessor() {
    681 }
    682 
    683 void PDLCDXferProcessor::onGetGLSLProcessorKey(const GrShaderCaps& caps,
    684                                                GrProcessorKeyBuilder* b) const {
    685     GLPDLCDXferProcessor::GenKey(*this, caps, b);
    686 }
    687 
    688 GrGLSLXferProcessor* PDLCDXferProcessor::createGLSLInstance() const {
    689     return new GLPDLCDXferProcessor(*this);
    690 }
    691 
    692 ///////////////////////////////////////////////////////////////////////////////
    693 
    694 constexpr GrPorterDuffXPFactory::GrPorterDuffXPFactory(SkBlendMode xfermode)
    695         : fBlendMode(xfermode) {}
    696 
    697 const GrXPFactory* GrPorterDuffXPFactory::Get(SkBlendMode blendMode) {
    698     SkASSERT((unsigned)blendMode <= (unsigned)SkBlendMode::kLastCoeffMode);
    699 
    700     // If these objects are constructed as static constexpr by cl.exe (2015 SP2) the vtables are
    701     // null.
    702 #ifdef SK_BUILD_FOR_WIN
    703 #define _CONSTEXPR_
    704 #else
    705 #define _CONSTEXPR_ constexpr
    706 #endif
    707     static _CONSTEXPR_ const GrPorterDuffXPFactory gClearPDXPF(SkBlendMode::kClear);
    708     static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcPDXPF(SkBlendMode::kSrc);
    709     static _CONSTEXPR_ const GrPorterDuffXPFactory gDstPDXPF(SkBlendMode::kDst);
    710     static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcOverPDXPF(SkBlendMode::kSrcOver);
    711     static _CONSTEXPR_ const GrPorterDuffXPFactory gDstOverPDXPF(SkBlendMode::kDstOver);
    712     static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcInPDXPF(SkBlendMode::kSrcIn);
    713     static _CONSTEXPR_ const GrPorterDuffXPFactory gDstInPDXPF(SkBlendMode::kDstIn);
    714     static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcOutPDXPF(SkBlendMode::kSrcOut);
    715     static _CONSTEXPR_ const GrPorterDuffXPFactory gDstOutPDXPF(SkBlendMode::kDstOut);
    716     static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcATopPDXPF(SkBlendMode::kSrcATop);
    717     static _CONSTEXPR_ const GrPorterDuffXPFactory gDstATopPDXPF(SkBlendMode::kDstATop);
    718     static _CONSTEXPR_ const GrPorterDuffXPFactory gXorPDXPF(SkBlendMode::kXor);
    719     static _CONSTEXPR_ const GrPorterDuffXPFactory gPlusPDXPF(SkBlendMode::kPlus);
    720     static _CONSTEXPR_ const GrPorterDuffXPFactory gModulatePDXPF(SkBlendMode::kModulate);
    721     static _CONSTEXPR_ const GrPorterDuffXPFactory gScreenPDXPF(SkBlendMode::kScreen);
    722 #undef _CONSTEXPR_
    723 
    724     switch (blendMode) {
    725         case SkBlendMode::kClear:
    726             return &gClearPDXPF;
    727         case SkBlendMode::kSrc:
    728             return &gSrcPDXPF;
    729         case SkBlendMode::kDst:
    730             return &gDstPDXPF;
    731         case SkBlendMode::kSrcOver:
    732             return &gSrcOverPDXPF;
    733         case SkBlendMode::kDstOver:
    734             return &gDstOverPDXPF;
    735         case SkBlendMode::kSrcIn:
    736             return &gSrcInPDXPF;
    737         case SkBlendMode::kDstIn:
    738             return &gDstInPDXPF;
    739         case SkBlendMode::kSrcOut:
    740             return &gSrcOutPDXPF;
    741         case SkBlendMode::kDstOut:
    742             return &gDstOutPDXPF;
    743         case SkBlendMode::kSrcATop:
    744             return &gSrcATopPDXPF;
    745         case SkBlendMode::kDstATop:
    746             return &gDstATopPDXPF;
    747         case SkBlendMode::kXor:
    748             return &gXorPDXPF;
    749         case SkBlendMode::kPlus:
    750             return &gPlusPDXPF;
    751         case SkBlendMode::kModulate:
    752             return &gModulatePDXPF;
    753         case SkBlendMode::kScreen:
    754             return &gScreenPDXPF;
    755         default:
    756             SkFAIL("Unexpected blend mode.");
    757             return nullptr;
    758     }
    759 }
    760 
    761 sk_sp<const GrXferProcessor> GrPorterDuffXPFactory::makeXferProcessor(
    762         const GrProcessorAnalysisColor& color, GrProcessorAnalysisCoverage coverage,
    763         bool hasMixedSamples, const GrCaps& caps) const {
    764     BlendFormula blendFormula;
    765     bool isLCD = coverage == GrProcessorAnalysisCoverage::kLCD;
    766     if (isLCD) {
    767         // See comment in MakeSrcOverXferProcessor about color.isOpaque here
    768         if (SkBlendMode::kSrcOver == fBlendMode && color.isConstant() && /*color.isOpaque() &&*/
    769             !caps.shaderCaps()->dualSourceBlendingSupport() &&
    770             !caps.shaderCaps()->dstReadInShaderSupport()) {
    771             // If we don't have dual source blending or in shader dst reads, we fall back to this
    772             // trick for rendering SrcOver LCD text instead of doing a dst copy.
    773             return PDLCDXferProcessor::Make(fBlendMode, color);
    774         }
    775         blendFormula = get_lcd_blend_formula(fBlendMode);
    776     } else {
    777         blendFormula =
    778                 get_blend_formula(color.isOpaque(), GrProcessorAnalysisCoverage::kNone != coverage,
    779                                   hasMixedSamples, fBlendMode);
    780     }
    781 
    782     if ((blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) ||
    783         (isLCD && (SkBlendMode::kSrcOver != fBlendMode /*|| !color.isOpaque()*/))) {
    784         return sk_sp<const GrXferProcessor>(new ShaderPDXferProcessor(hasMixedSamples, fBlendMode,
    785                                                                       coverage));
    786     }
    787     return sk_sp<const GrXferProcessor>(new PorterDuffXferProcessor(blendFormula, coverage));
    788 }
    789 
    790 static inline GrXPFactory::AnalysisProperties analysis_properties(
    791         const GrProcessorAnalysisColor& color, const GrProcessorAnalysisCoverage& coverage,
    792         const GrCaps& caps, SkBlendMode mode) {
    793     using AnalysisProperties = GrXPFactory::AnalysisProperties;
    794     AnalysisProperties props = AnalysisProperties::kNone;
    795     bool hasCoverage = GrProcessorAnalysisCoverage::kNone != coverage;
    796     bool isLCD = GrProcessorAnalysisCoverage::kLCD == coverage;
    797     BlendFormula formula;
    798     if (isLCD) {
    799         formula = gLCDBlendTable[(int)mode];
    800     } else {
    801         formula = gBlendTable[color.isOpaque()][hasCoverage][(int)mode];
    802     }
    803 
    804     if (formula.canTweakAlphaForCoverage() && !isLCD) {
    805         props |= AnalysisProperties::kCompatibleWithAlphaAsCoverage;
    806     }
    807 
    808     if (isLCD) {
    809         // See comment in MakeSrcOverXferProcessor about color.isOpaque here
    810         if (SkBlendMode::kSrcOver == mode && color.isConstant() && /*color.isOpaque() &&*/
    811             !caps.shaderCaps()->dualSourceBlendingSupport() &&
    812             !caps.shaderCaps()->dstReadInShaderSupport()) {
    813             props |= AnalysisProperties::kIgnoresInputColor;
    814         } else {
    815             // For LCD blending, if the color is not opaque we must read the dst in shader even if
    816             // we have dual source blending. The opaqueness check must be done after blending so for
    817             // simplicity we only allow src-over to not take the dst read path (though src, src-in,
    818             // and DstATop would also work). We also fall into the dst read case for src-over if we
    819             // do not have dual source blending.
    820             if (SkBlendMode::kSrcOver != mode ||
    821                 /*!color.isOpaque() ||*/ // See comment in MakeSrcOverXferProcessor about isOpaque.
    822                 (formula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport())) {
    823                 props |= AnalysisProperties::kReadsDstInShader;
    824             }
    825         }
    826     } else {
    827         // With dual-source blending we never need the destination color in the shader.
    828         if (!caps.shaderCaps()->dualSourceBlendingSupport()) {
    829             // Mixed samples implicity computes a fractional coverage from sample coverage. This
    830             // could affect the formula used. However, we don't expect to have mixed samples without
    831             // dual source blending.
    832             SkASSERT(!caps.usesMixedSamples());
    833             if (formula.hasSecondaryOutput()) {
    834                 props |= AnalysisProperties::kReadsDstInShader;
    835             }
    836         }
    837     }
    838 
    839     if (!formula.modifiesDst() || !formula.usesInputColor()) {
    840         props |= AnalysisProperties::kIgnoresInputColor;
    841     }
    842     // Ignore the effect of coverage here for overlap stencil and cover property
    843     auto colorFormula = gBlendTable[color.isOpaque()][0][(int)mode];
    844     SkASSERT(kAdd_GrBlendEquation == colorFormula.equation());
    845     if (!colorFormula.usesDstColor()) {
    846         props |= AnalysisProperties::kCanCombineOverlappedStencilAndCover;
    847     }
    848     return props;
    849 }
    850 
    851 GrXPFactory::AnalysisProperties GrPorterDuffXPFactory::analysisProperties(
    852         const GrProcessorAnalysisColor& color,
    853         const GrProcessorAnalysisCoverage& coverage,
    854         const GrCaps& caps) const {
    855     return analysis_properties(color, coverage, caps, fBlendMode);
    856 }
    857 
    858 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory);
    859 
    860 #if GR_TEST_UTILS
    861 const GrXPFactory* GrPorterDuffXPFactory::TestGet(GrProcessorTestData* d) {
    862     SkBlendMode mode = SkBlendMode(d->fRandom->nextULessThan((int)SkBlendMode::kLastCoeffMode));
    863     return GrPorterDuffXPFactory::Get(mode);
    864 }
    865 #endif
    866 
    867 void GrPorterDuffXPFactory::TestGetXPOutputTypes(const GrXferProcessor* xp,
    868                                                  int* outPrimary,
    869                                                  int* outSecondary) {
    870     if (!!strcmp(xp->name(), "Porter Duff")) {
    871         *outPrimary = *outSecondary = -1;
    872         return;
    873     }
    874     BlendFormula blendFormula = static_cast<const PorterDuffXferProcessor*>(xp)->getBlendFormula();
    875     *outPrimary = blendFormula.primaryOutput();
    876     *outSecondary = blendFormula.secondaryOutput();
    877 }
    878 
    879 ////////////////////////////////////////////////////////////////////////////////////////////////
    880 // SrcOver Global functions
    881 ////////////////////////////////////////////////////////////////////////////////////////////////
    882 const GrXferProcessor& GrPorterDuffXPFactory::SimpleSrcOverXP() {
    883     static BlendFormula gSrcOverBlendFormula =
    884             MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff);
    885     static PorterDuffXferProcessor gSrcOverXP(gSrcOverBlendFormula,
    886                                               GrProcessorAnalysisCoverage::kSingleChannel);
    887     return gSrcOverXP;
    888 }
    889 
    890 sk_sp<const GrXferProcessor> GrPorterDuffXPFactory::MakeSrcOverXferProcessor(
    891         const GrProcessorAnalysisColor& color, GrProcessorAnalysisCoverage coverage,
    892         bool hasMixedSamples, const GrCaps& caps) {
    893     // We want to not make an xfer processor if possible. Thus for the simple case where we are not
    894     // doing lcd blending we will just use our global SimpleSrcOverXP. This slightly differs from
    895     // the general case where we convert a src-over blend that has solid coverage and an opaque
    896     // color to src-mode, which allows disabling of blending.
    897     if (coverage != GrProcessorAnalysisCoverage::kLCD) {
    898         // We return nullptr here, which our caller interprets as meaning "use SimpleSrcOverXP".
    899         // We don't simply return the address of that XP here because our caller would have to unref
    900         // it and since it is a global object and GrProgramElement's ref-cnting system is not thread
    901         // safe.
    902         return nullptr;
    903     }
    904 
    905     // Currently up the stack Skia is requiring that the dst is opaque or that the client has said
    906     // the opaqueness doesn't matter. Thus for src-over we don't need to worry about the src color
    907     // being opaque or not. This allows us to use faster code paths as well as avoid various bugs
    908     // that occur with dst reads in the shader blending. For now we disable the check for
    909     // opaqueness, but in the future we should pass down the knowledge about dst opaqueness and make
    910     // the correct decision here.
    911     //
    912     // This also fixes a chrome bug on macs where we are getting random fuzziness when doing
    913     // blending in the shader for non opaque sources.
    914     if (color.isConstant() && /*color.isOpaque() &&*/
    915         !caps.shaderCaps()->dualSourceBlendingSupport() &&
    916         !caps.shaderCaps()->dstReadInShaderSupport()) {
    917         // If we don't have dual source blending or in shader dst reads, we fall
    918         // back to this trick for rendering SrcOver LCD text instead of doing a
    919         // dst copy.
    920         return PDLCDXferProcessor::Make(SkBlendMode::kSrcOver, color);
    921     }
    922 
    923     BlendFormula blendFormula;
    924     blendFormula = get_lcd_blend_formula(SkBlendMode::kSrcOver);
    925     // See comment above regarding why the opaque check is commented out here.
    926     if (/*!color.isOpaque() ||*/
    927         (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport())) {
    928         return sk_sp<GrXferProcessor>(
    929                 new ShaderPDXferProcessor(hasMixedSamples, SkBlendMode::kSrcOver, coverage));
    930     }
    931     return sk_sp<GrXferProcessor>(new PorterDuffXferProcessor(blendFormula, coverage));
    932 }
    933 
    934 sk_sp<const GrXferProcessor> GrPorterDuffXPFactory::MakeNoCoverageXP(SkBlendMode blendmode) {
    935     BlendFormula formula = get_blend_formula(false, false, false, blendmode);
    936     return sk_make_sp<PorterDuffXferProcessor>(formula, GrProcessorAnalysisCoverage::kNone);
    937 }
    938 
    939 GrXPFactory::AnalysisProperties GrPorterDuffXPFactory::SrcOverAnalysisProperties(
    940         const GrProcessorAnalysisColor& color,
    941         const GrProcessorAnalysisCoverage& coverage,
    942         const GrCaps& caps) {
    943     return analysis_properties(color, coverage, caps, SkBlendMode::kSrcOver);
    944 }
    945