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 "GrProcOptInfo.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 #include <utility>
     23 
     24 /**
     25  * Wraps the shader outputs and HW blend state that comprise a Porter Duff blend mode with coverage.
     26  */
     27 struct BlendFormula {
     28 public:
     29     /**
     30      * Values the shader can write to primary and secondary outputs. These must all be modulated by
     31      * coverage to support mixed samples. The XP will ignore the multiplies when not using coverage.
     32      */
     33     enum OutputType {
     34         kNone_OutputType,        //<! 0
     35         kCoverage_OutputType,    //<! inputCoverage
     36         kModulate_OutputType,    //<! inputColor * inputCoverage
     37         kSAModulate_OutputType,  //<! inputColor.a * inputCoverage
     38         kISAModulate_OutputType, //<! (1 - inputColor.a) * inputCoverage
     39         kISCModulate_OutputType, //<! (1 - inputColor) * inputCoverage
     40 
     41         kLast_OutputType = kISCModulate_OutputType
     42     };
     43 
     44     enum Properties {
     45         kModifiesDst_Property              = 1,
     46         kUsesDstColor_Property             = 1 << 1,
     47         kUsesInputColor_Property           = 1 << 2,
     48         kCanTweakAlphaForCoverage_Property = 1 << 3,
     49 
     50         kLast_Property = kCanTweakAlphaForCoverage_Property
     51     };
     52 
     53     BlendFormula& operator =(const BlendFormula& other) {
     54         fData = other.fData;
     55         return *this;
     56     }
     57 
     58     bool operator ==(const BlendFormula& other) const {
     59         return fData == other.fData;
     60     }
     61 
     62     bool hasSecondaryOutput() const { return kNone_OutputType != fSecondaryOutputType; }
     63     bool modifiesDst() const { return SkToBool(fProps & kModifiesDst_Property); }
     64     bool usesDstColor() const { return SkToBool(fProps & kUsesDstColor_Property); }
     65     bool usesInputColor() const { return SkToBool(fProps & kUsesInputColor_Property); }
     66     bool canTweakAlphaForCoverage() const {
     67         return SkToBool(fProps & kCanTweakAlphaForCoverage_Property);
     68     }
     69 
     70     /**
     71      * Deduce the properties of a compile-time constant BlendFormula.
     72      */
     73     template<OutputType PrimaryOut, OutputType SecondaryOut,
     74              GrBlendEquation BlendEquation, GrBlendCoeff SrcCoeff, GrBlendCoeff DstCoeff>
     75     struct get_properties : std::integral_constant<Properties, static_cast<Properties>(
     76 
     77         (GR_BLEND_MODIFIES_DST(BlendEquation, SrcCoeff, DstCoeff) ?
     78             kModifiesDst_Property : 0) |
     79 
     80         (GR_BLEND_COEFFS_USE_DST_COLOR(SrcCoeff, DstCoeff) ?
     81             kUsesDstColor_Property : 0) |
     82 
     83         ((PrimaryOut >= kModulate_OutputType && GR_BLEND_COEFFS_USE_SRC_COLOR(SrcCoeff,DstCoeff)) ||
     84          (SecondaryOut >= kModulate_OutputType && GR_BLEND_COEFF_REFS_SRC2(DstCoeff)) ?
     85             kUsesInputColor_Property : 0) |  // We assert later that SrcCoeff doesn't ref src2.
     86 
     87         (kModulate_OutputType == PrimaryOut &&
     88          kNone_OutputType == SecondaryOut &&
     89          GR_BLEND_CAN_TWEAK_ALPHA_FOR_COVERAGE(BlendEquation, SrcCoeff, DstCoeff) ?
     90             kCanTweakAlphaForCoverage_Property : 0))> {
     91 
     92         // The provided formula should already be optimized.
     93         GR_STATIC_ASSERT((kNone_OutputType == PrimaryOut) ==
     94                          !GR_BLEND_COEFFS_USE_SRC_COLOR(SrcCoeff, DstCoeff));
     95         GR_STATIC_ASSERT(!GR_BLEND_COEFF_REFS_SRC2(SrcCoeff));
     96         GR_STATIC_ASSERT((kNone_OutputType == SecondaryOut) ==
     97                          !GR_BLEND_COEFF_REFS_SRC2(DstCoeff));
     98         GR_STATIC_ASSERT(PrimaryOut != SecondaryOut || kNone_OutputType == PrimaryOut);
     99         GR_STATIC_ASSERT(kNone_OutputType != PrimaryOut || kNone_OutputType == SecondaryOut);
    100     };
    101 
    102     union {
    103         struct {
    104             // We allot the enums one more bit than they require because MSVC seems to sign-extend
    105             // them when the top bit is set. (This is in violation of the C++03 standard 9.6/4)
    106             OutputType        fPrimaryOutputType    : 4;
    107             OutputType        fSecondaryOutputType  : 4;
    108             GrBlendEquation   fBlendEquation        : 6;
    109             GrBlendCoeff      fSrcCoeff             : 6;
    110             GrBlendCoeff      fDstCoeff             : 6;
    111             Properties        fProps                : 32 - (4 + 4 + 6 + 6 + 6);
    112         };
    113         uint32_t fData;
    114     };
    115 
    116     GR_STATIC_ASSERT(kLast_OutputType      < (1 << 3));
    117     GR_STATIC_ASSERT(kLast_GrBlendEquation < (1 << 5));
    118     GR_STATIC_ASSERT(kLast_GrBlendCoeff    < (1 << 5));
    119     GR_STATIC_ASSERT(kLast_Property        < (1 << 6));
    120 };
    121 
    122 GR_STATIC_ASSERT(4 == sizeof(BlendFormula));
    123 
    124 GR_MAKE_BITFIELD_OPS(BlendFormula::Properties);
    125 
    126 /**
    127  * Initialize a compile-time constant BlendFormula and automatically deduce fProps.
    128  */
    129 #define INIT_BLEND_FORMULA(PRIMARY_OUT, SECONDARY_OUT, BLEND_EQUATION, SRC_COEFF, DST_COEFF) \
    130     {{{PRIMARY_OUT, \
    131        SECONDARY_OUT, \
    132        BLEND_EQUATION, SRC_COEFF, DST_COEFF, \
    133        BlendFormula::get_properties<PRIMARY_OUT, SECONDARY_OUT, \
    134                                     BLEND_EQUATION, SRC_COEFF, DST_COEFF>::value}}}
    135 
    136 /**
    137  * When there is no coverage, or the blend mode can tweak alpha for coverage, we use the standard
    138  * Porter Duff formula.
    139  */
    140 #define COEFF_FORMULA(SRC_COEFF, DST_COEFF) \
    141     INIT_BLEND_FORMULA(BlendFormula::kModulate_OutputType, \
    142                        BlendFormula::kNone_OutputType, \
    143                        kAdd_GrBlendEquation, SRC_COEFF, DST_COEFF)
    144 
    145 /**
    146  * Basic coeff formula similar to COEFF_FORMULA but we will make the src f*Sa. This is used in
    147  * LCD dst-out.
    148  */
    149 #define COEFF_FORMULA_SA_MODULATE(SRC_COEFF, DST_COEFF) \
    150     INIT_BLEND_FORMULA(BlendFormula::kSAModulate_OutputType, \
    151                        BlendFormula::kNone_OutputType, \
    152                        kAdd_GrBlendEquation, SRC_COEFF, DST_COEFF)
    153 
    154 /**
    155  * When the coeffs are (Zero, Zero), we clear the dst. This formula has its own macro so we can set
    156  * the primary output type to none.
    157  */
    158 #define DST_CLEAR_FORMULA \
    159     INIT_BLEND_FORMULA(BlendFormula::kNone_OutputType, \
    160                        BlendFormula::kNone_OutputType, \
    161                        kAdd_GrBlendEquation, kZero_GrBlendCoeff, kZero_GrBlendCoeff)
    162 
    163 /**
    164  * When the coeffs are (Zero, One), we don't write to the dst at all. This formula has its own macro
    165  * so we can set the primary output type to none.
    166  */
    167 #define NO_DST_WRITE_FORMULA \
    168     INIT_BLEND_FORMULA(BlendFormula::kNone_OutputType, \
    169                        BlendFormula::kNone_OutputType, \
    170                        kAdd_GrBlendEquation, kZero_GrBlendCoeff, kOne_GrBlendCoeff)
    171 
    172 /**
    173  * When there is coverage, the equation with f=coverage is:
    174  *
    175  *   D' = f * (S * srcCoeff + D * dstCoeff) + (1-f) * D
    176  *
    177  * This can be rewritten as:
    178  *
    179  *   D' = f * S * srcCoeff + D * (1 - [f * (1 - dstCoeff)])
    180  *
    181  * To implement this formula, we output [f * (1 - dstCoeff)] for the secondary color and replace the
    182  * HW dst coeff with IS2C.
    183  *
    184  * Xfer modes: dst-atop (Sa!=1)
    185  */
    186 #define COVERAGE_FORMULA(ONE_MINUS_DST_COEFF_MODULATE_OUTPUT, SRC_COEFF) \
    187     INIT_BLEND_FORMULA(BlendFormula::kModulate_OutputType, \
    188                        ONE_MINUS_DST_COEFF_MODULATE_OUTPUT, \
    189                        kAdd_GrBlendEquation, SRC_COEFF, kIS2C_GrBlendCoeff)
    190 
    191 /**
    192  * When there is coverage and the src coeff is Zero, the equation with f=coverage becomes:
    193  *
    194  *   D' = f * D * dstCoeff + (1-f) * D
    195  *
    196  * This can be rewritten as:
    197  *
    198  *   D' = D - D * [f * (1 - dstCoeff)]
    199  *
    200  * To implement this formula, we output [f * (1 - dstCoeff)] for the primary color and use a reverse
    201  * subtract HW blend equation with coeffs of (DC, One).
    202  *
    203  * Xfer modes: clear, dst-out (Sa=1), dst-in (Sa!=1), modulate (Sc!=1)
    204  */
    205 #define COVERAGE_SRC_COEFF_ZERO_FORMULA(ONE_MINUS_DST_COEFF_MODULATE_OUTPUT) \
    206     INIT_BLEND_FORMULA(ONE_MINUS_DST_COEFF_MODULATE_OUTPUT, \
    207                        BlendFormula::kNone_OutputType, \
    208                        kReverseSubtract_GrBlendEquation, kDC_GrBlendCoeff, kOne_GrBlendCoeff)
    209 
    210 /**
    211  * When there is coverage and the dst coeff is Zero, the equation with f=coverage becomes:
    212  *
    213  *   D' = f * S * srcCoeff + (1-f) * D
    214  *
    215  * To implement this formula, we output [f] for the secondary color and replace the HW dst coeff
    216  * with IS2A. (Note that we can avoid dual source blending when Sa=1 by using ISA.)
    217  *
    218  * Xfer modes (Sa!=1): src, src-in, src-out
    219  */
    220 #define COVERAGE_DST_COEFF_ZERO_FORMULA(SRC_COEFF) \
    221     INIT_BLEND_FORMULA(BlendFormula::kModulate_OutputType, \
    222                        BlendFormula::kCoverage_OutputType, \
    223                        kAdd_GrBlendEquation, SRC_COEFF, kIS2A_GrBlendCoeff)
    224 
    225 /**
    226  * This table outlines the blend formulas we will use with each xfermode, with and without coverage,
    227  * with and without an opaque input color. Optimization properties are deduced at compile time so we
    228  * can make runtime decisions quickly. RGB coverage is not supported.
    229  */
    230 static const BlendFormula gBlendTable[2][2][SkXfermode::kLastCoeffMode + 1] = {
    231 
    232                      /*>> No coverage, input color unknown <<*/ {{
    233 
    234     /* clear */      DST_CLEAR_FORMULA,
    235     /* src */        COEFF_FORMULA(   kOne_GrBlendCoeff,    kZero_GrBlendCoeff),
    236     /* dst */        NO_DST_WRITE_FORMULA,
    237     /* src-over */   COEFF_FORMULA(   kOne_GrBlendCoeff,    kISA_GrBlendCoeff),
    238     /* dst-over */   COEFF_FORMULA(   kIDA_GrBlendCoeff,    kOne_GrBlendCoeff),
    239     /* src-in */     COEFF_FORMULA(   kDA_GrBlendCoeff,     kZero_GrBlendCoeff),
    240     /* dst-in */     COEFF_FORMULA(   kZero_GrBlendCoeff,   kSA_GrBlendCoeff),
    241     /* src-out */    COEFF_FORMULA(   kIDA_GrBlendCoeff,    kZero_GrBlendCoeff),
    242     /* dst-out */    COEFF_FORMULA(   kZero_GrBlendCoeff,   kISA_GrBlendCoeff),
    243     /* src-atop */   COEFF_FORMULA(   kDA_GrBlendCoeff,     kISA_GrBlendCoeff),
    244     /* dst-atop */   COEFF_FORMULA(   kIDA_GrBlendCoeff,    kSA_GrBlendCoeff),
    245     /* xor */        COEFF_FORMULA(   kIDA_GrBlendCoeff,    kISA_GrBlendCoeff),
    246     /* plus */       COEFF_FORMULA(   kOne_GrBlendCoeff,    kOne_GrBlendCoeff),
    247     /* modulate */   COEFF_FORMULA(   kZero_GrBlendCoeff,   kSC_GrBlendCoeff),
    248     /* screen */     COEFF_FORMULA(   kOne_GrBlendCoeff,    kISC_GrBlendCoeff),
    249 
    250                      }, /*>> Has coverage, input color unknown <<*/ {
    251 
    252     /* clear */      COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_OutputType),
    253     /* src */        COVERAGE_DST_COEFF_ZERO_FORMULA(kOne_GrBlendCoeff),
    254     /* dst */        NO_DST_WRITE_FORMULA,
    255     /* src-over */   COEFF_FORMULA(   kOne_GrBlendCoeff,    kISA_GrBlendCoeff),
    256     /* dst-over */   COEFF_FORMULA(   kIDA_GrBlendCoeff,    kOne_GrBlendCoeff),
    257     /* src-in */     COVERAGE_DST_COEFF_ZERO_FORMULA(kDA_GrBlendCoeff),
    258     /* dst-in */     COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISAModulate_OutputType),
    259     /* src-out */    COVERAGE_DST_COEFF_ZERO_FORMULA(kIDA_GrBlendCoeff),
    260     /* dst-out */    COEFF_FORMULA(   kZero_GrBlendCoeff,   kISA_GrBlendCoeff),
    261     /* src-atop */   COEFF_FORMULA(   kDA_GrBlendCoeff,     kISA_GrBlendCoeff),
    262     /* dst-atop */   COVERAGE_FORMULA(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff),
    263     /* xor */        COEFF_FORMULA(   kIDA_GrBlendCoeff,    kISA_GrBlendCoeff),
    264     /* plus */       COEFF_FORMULA(   kOne_GrBlendCoeff,    kOne_GrBlendCoeff),
    265     /* modulate */   COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISCModulate_OutputType),
    266     /* screen */     COEFF_FORMULA(   kOne_GrBlendCoeff,    kISC_GrBlendCoeff),
    267 
    268                      }}, /*>> No coverage, input color opaque <<*/ {{
    269 
    270     /* clear */      DST_CLEAR_FORMULA,
    271     /* src */        COEFF_FORMULA(   kOne_GrBlendCoeff,    kZero_GrBlendCoeff),
    272     /* dst */        NO_DST_WRITE_FORMULA,
    273     /* src-over */   COEFF_FORMULA(   kOne_GrBlendCoeff,    kZero_GrBlendCoeff),
    274     /* dst-over */   COEFF_FORMULA(   kIDA_GrBlendCoeff,    kOne_GrBlendCoeff),
    275     /* src-in */     COEFF_FORMULA(   kDA_GrBlendCoeff,     kZero_GrBlendCoeff),
    276     /* dst-in */     NO_DST_WRITE_FORMULA,
    277     /* src-out */    COEFF_FORMULA(   kIDA_GrBlendCoeff,    kZero_GrBlendCoeff),
    278     /* dst-out */    DST_CLEAR_FORMULA,
    279     /* src-atop */   COEFF_FORMULA(   kDA_GrBlendCoeff,     kZero_GrBlendCoeff),
    280     /* dst-atop */   COEFF_FORMULA(   kIDA_GrBlendCoeff,    kOne_GrBlendCoeff),
    281     /* xor */        COEFF_FORMULA(   kIDA_GrBlendCoeff,    kZero_GrBlendCoeff),
    282     /* plus */       COEFF_FORMULA(   kOne_GrBlendCoeff,    kOne_GrBlendCoeff),
    283     /* modulate */   COEFF_FORMULA(   kZero_GrBlendCoeff,   kSC_GrBlendCoeff),
    284     /* screen */     COEFF_FORMULA(   kOne_GrBlendCoeff,    kISC_GrBlendCoeff),
    285 
    286                      }, /*>> Has coverage, input color opaque <<*/ {
    287 
    288     /* clear */      COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_OutputType),
    289     /* src */        COEFF_FORMULA(   kOne_GrBlendCoeff,    kISA_GrBlendCoeff),
    290     /* dst */        NO_DST_WRITE_FORMULA,
    291     /* src-over */   COEFF_FORMULA(   kOne_GrBlendCoeff,    kISA_GrBlendCoeff),
    292     /* dst-over */   COEFF_FORMULA(   kIDA_GrBlendCoeff,    kOne_GrBlendCoeff),
    293     /* src-in */     COEFF_FORMULA(   kDA_GrBlendCoeff,     kISA_GrBlendCoeff),
    294     /* dst-in */     NO_DST_WRITE_FORMULA,
    295     /* src-out */    COEFF_FORMULA(   kIDA_GrBlendCoeff,    kISA_GrBlendCoeff),
    296     /* dst-out */    COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_OutputType),
    297     /* src-atop */   COEFF_FORMULA(   kDA_GrBlendCoeff,     kISA_GrBlendCoeff),
    298     /* dst-atop */   COEFF_FORMULA(   kIDA_GrBlendCoeff,    kOne_GrBlendCoeff),
    299     /* xor */        COEFF_FORMULA(   kIDA_GrBlendCoeff,    kISA_GrBlendCoeff),
    300     /* plus */       COEFF_FORMULA(   kOne_GrBlendCoeff,    kOne_GrBlendCoeff),
    301     /* modulate */   COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISCModulate_OutputType),
    302     /* screen */     COEFF_FORMULA(   kOne_GrBlendCoeff,    kISC_GrBlendCoeff),
    303 }}};
    304 
    305 static const BlendFormula gLCDBlendTable[SkXfermode::kLastCoeffMode + 1] = {
    306     /* clear */      COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_OutputType),
    307     /* src */        COVERAGE_FORMULA(BlendFormula::kCoverage_OutputType, kOne_GrBlendCoeff),
    308     /* dst */        NO_DST_WRITE_FORMULA,
    309     /* src-over */   COVERAGE_FORMULA(BlendFormula::kSAModulate_OutputType, kOne_GrBlendCoeff),
    310     /* dst-over */   COEFF_FORMULA(   kIDA_GrBlendCoeff,    kOne_GrBlendCoeff),
    311     /* src-in */     COVERAGE_FORMULA(BlendFormula::kCoverage_OutputType, kDA_GrBlendCoeff),
    312     /* dst-in */     COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISAModulate_OutputType),
    313     /* src-out */    COVERAGE_FORMULA(BlendFormula::kCoverage_OutputType, kIDA_GrBlendCoeff),
    314     /* dst-out */    COEFF_FORMULA_SA_MODULATE(   kZero_GrBlendCoeff,   kISC_GrBlendCoeff),
    315     /* src-atop */   COVERAGE_FORMULA(BlendFormula::kSAModulate_OutputType, kDA_GrBlendCoeff),
    316     /* dst-atop */   COVERAGE_FORMULA(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff),
    317     /* xor */        COVERAGE_FORMULA(BlendFormula::kSAModulate_OutputType, kIDA_GrBlendCoeff),
    318     /* plus */       COEFF_FORMULA(   kOne_GrBlendCoeff,    kOne_GrBlendCoeff),
    319     /* modulate */   COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISCModulate_OutputType),
    320     /* screen */     COEFF_FORMULA(   kOne_GrBlendCoeff,    kISC_GrBlendCoeff),
    321 };
    322 
    323 static BlendFormula get_blend_formula(const GrProcOptInfo& colorPOI,
    324                                       const GrProcOptInfo& coveragePOI,
    325                                       bool hasMixedSamples,
    326                                       SkXfermode::Mode xfermode) {
    327     SkASSERT(xfermode >= 0 && xfermode <= SkXfermode::kLastCoeffMode);
    328     SkASSERT(!coveragePOI.isFourChannelOutput());
    329 
    330     bool conflatesCoverage = !coveragePOI.isSolidWhite() || hasMixedSamples;
    331     return gBlendTable[colorPOI.isOpaque()][conflatesCoverage][xfermode];
    332 }
    333 
    334 static BlendFormula get_lcd_blend_formula(const GrProcOptInfo& coveragePOI,
    335                                           SkXfermode::Mode xfermode) {
    336     SkASSERT(xfermode >= 0 && xfermode <= SkXfermode::kLastCoeffMode);
    337     SkASSERT(coveragePOI.isFourChannelOutput());
    338 
    339     return gLCDBlendTable[xfermode];
    340 }
    341 
    342 ///////////////////////////////////////////////////////////////////////////////
    343 
    344 class PorterDuffXferProcessor : public GrXferProcessor {
    345 public:
    346     PorterDuffXferProcessor(BlendFormula blendFormula) : fBlendFormula(blendFormula) {
    347         this->initClassID<PorterDuffXferProcessor>();
    348     }
    349 
    350     const char* name() const override { return "Porter Duff"; }
    351 
    352     GrGLSLXferProcessor* createGLSLInstance() const override;
    353 
    354     BlendFormula getBlendFormula() const { return fBlendFormula; }
    355 
    356 private:
    357     GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations& optimizations,
    358                                                  bool doesStencilWrite,
    359                                                  GrColor* overrideColor,
    360                                                  const GrCaps& caps) const override;
    361 
    362     void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
    363 
    364     bool onHasSecondaryOutput() const override { return fBlendFormula.hasSecondaryOutput(); }
    365 
    366     void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override {
    367         blendInfo->fEquation = fBlendFormula.fBlendEquation;
    368         blendInfo->fSrcBlend = fBlendFormula.fSrcCoeff;
    369         blendInfo->fDstBlend = fBlendFormula.fDstCoeff;
    370         blendInfo->fWriteColor = fBlendFormula.modifiesDst();
    371     }
    372 
    373     bool onIsEqual(const GrXferProcessor& xpBase) const override {
    374         const PorterDuffXferProcessor& xp = xpBase.cast<PorterDuffXferProcessor>();
    375         return fBlendFormula == xp.fBlendFormula;
    376     }
    377 
    378     const BlendFormula fBlendFormula;
    379 
    380     typedef GrXferProcessor INHERITED;
    381 };
    382 
    383 ///////////////////////////////////////////////////////////////////////////////
    384 
    385 static void append_color_output(const PorterDuffXferProcessor& xp,
    386                                 GrGLSLXPFragmentBuilder* fragBuilder,
    387                                 BlendFormula::OutputType outputType, const char* output,
    388                                 const char* inColor, const char* inCoverage) {
    389     switch (outputType) {
    390         case BlendFormula::kNone_OutputType:
    391             fragBuilder->codeAppendf("%s = vec4(0.0);", output);
    392             break;
    393         case BlendFormula::kCoverage_OutputType:
    394             // We can have a coverage formula while not reading coverage if there are mixed samples.
    395             if (inCoverage) {
    396                 fragBuilder->codeAppendf("%s = %s;", output, inCoverage);
    397             } else {
    398                 fragBuilder->codeAppendf("%s = vec4(1.0);", output);
    399             }
    400             break;
    401         case BlendFormula::kModulate_OutputType:
    402             if (inCoverage) {
    403                 fragBuilder->codeAppendf("%s = %s * %s;", output, inColor, inCoverage);
    404             } else {
    405                 fragBuilder->codeAppendf("%s = %s;", output, inColor);
    406             }
    407             break;
    408         case BlendFormula::kSAModulate_OutputType:
    409             if (inCoverage) {
    410                 fragBuilder->codeAppendf("%s = %s.a * %s;", output, inColor, inCoverage);
    411             } else {
    412                 fragBuilder->codeAppendf("%s = %s;", output, inColor);
    413             }
    414             break;
    415         case BlendFormula::kISAModulate_OutputType:
    416             if (inCoverage) {
    417                 fragBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", output, inColor, inCoverage);
    418             } else {
    419                 fragBuilder->codeAppendf("%s = vec4(1.0 - %s.a);", output, inColor);
    420             }
    421             break;
    422         case BlendFormula::kISCModulate_OutputType:
    423             if (inCoverage) {
    424                 fragBuilder->codeAppendf("%s = (vec4(1.0) - %s) * %s;", output, inColor, inCoverage);
    425             } else {
    426                 fragBuilder->codeAppendf("%s = vec4(1.0) - %s;", output, inColor);
    427             }
    428             break;
    429         default:
    430             SkFAIL("Unsupported output type.");
    431             break;
    432     }
    433 }
    434 
    435 class GLPorterDuffXferProcessor : public GrGLSLXferProcessor {
    436 public:
    437     static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) {
    438         const PorterDuffXferProcessor& xp = processor.cast<PorterDuffXferProcessor>();
    439         b->add32(xp.getBlendFormula().fPrimaryOutputType |
    440                  (xp.getBlendFormula().fSecondaryOutputType << 3));
    441         GR_STATIC_ASSERT(BlendFormula::kLast_OutputType < 8);
    442     };
    443 
    444 private:
    445     void emitOutputsForBlendState(const EmitArgs& args) override {
    446         const PorterDuffXferProcessor& xp = args.fXP.cast<PorterDuffXferProcessor>();
    447         GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
    448 
    449         BlendFormula blendFormula = xp.getBlendFormula();
    450         if (blendFormula.hasSecondaryOutput()) {
    451             append_color_output(xp, fragBuilder, blendFormula.fSecondaryOutputType,
    452                                 args.fOutputSecondary, args.fInputColor, args.fInputCoverage);
    453         }
    454         append_color_output(xp, fragBuilder, blendFormula.fPrimaryOutputType,
    455                             args.fOutputPrimary, args.fInputColor, args.fInputCoverage);
    456     }
    457 
    458     void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
    459 
    460     typedef GrGLSLXferProcessor INHERITED;
    461 };
    462 
    463 ///////////////////////////////////////////////////////////////////////////////
    464 
    465 void PorterDuffXferProcessor::onGetGLSLProcessorKey(const GrGLSLCaps&,
    466                                                     GrProcessorKeyBuilder* b) const {
    467     GLPorterDuffXferProcessor::GenKey(*this, b);
    468 }
    469 
    470 GrGLSLXferProcessor* PorterDuffXferProcessor::createGLSLInstance() const {
    471     return new GLPorterDuffXferProcessor;
    472 }
    473 
    474 GrXferProcessor::OptFlags
    475 PorterDuffXferProcessor::onGetOptimizations(const GrPipelineOptimizations& optimizations,
    476                                             bool doesStencilWrite,
    477                                             GrColor* overrideColor,
    478                                             const GrCaps& caps) const {
    479     GrXferProcessor::OptFlags optFlags = GrXferProcessor::kNone_OptFlags;
    480     if (!fBlendFormula.modifiesDst()) {
    481         if (!doesStencilWrite) {
    482             optFlags |= GrXferProcessor::kSkipDraw_OptFlag;
    483         }
    484         optFlags |= (GrXferProcessor::kIgnoreColor_OptFlag |
    485                      GrXferProcessor::kIgnoreCoverage_OptFlag |
    486                      GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag);
    487     } else {
    488         if (!fBlendFormula.usesInputColor()) {
    489             optFlags |= GrXferProcessor::kIgnoreColor_OptFlag;
    490         }
    491         if (optimizations.fCoveragePOI.isSolidWhite()) {
    492             optFlags |= GrXferProcessor::kIgnoreCoverage_OptFlag;
    493         }
    494         if (optimizations.fColorPOI.allStagesMultiplyInput() &&
    495             fBlendFormula.canTweakAlphaForCoverage() &&
    496             !optimizations.fCoveragePOI.isFourChannelOutput()) {
    497             optFlags |= GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag;
    498         }
    499     }
    500     return optFlags;
    501 }
    502 
    503 ///////////////////////////////////////////////////////////////////////////////
    504 
    505 class ShaderPDXferProcessor : public GrXferProcessor {
    506 public:
    507     ShaderPDXferProcessor(const DstTexture* dstTexture,
    508                           bool hasMixedSamples,
    509                           SkXfermode::Mode xfermode)
    510         : INHERITED(dstTexture, true, hasMixedSamples)
    511         , fXfermode(xfermode) {
    512         this->initClassID<ShaderPDXferProcessor>();
    513     }
    514 
    515     const char* name() const override { return "Porter Duff Shader"; }
    516 
    517     GrGLSLXferProcessor* createGLSLInstance() const override;
    518 
    519     SkXfermode::Mode getXfermode() const { return fXfermode; }
    520 
    521 private:
    522     GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations&, bool, GrColor*,
    523                                                  const GrCaps&) const override {
    524         return kNone_OptFlags;
    525     }
    526 
    527     void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
    528 
    529     bool onIsEqual(const GrXferProcessor& xpBase) const override {
    530         const ShaderPDXferProcessor& xp = xpBase.cast<ShaderPDXferProcessor>();
    531         return fXfermode == xp.fXfermode;
    532     }
    533 
    534     const SkXfermode::Mode fXfermode;
    535 
    536     typedef GrXferProcessor INHERITED;
    537 };
    538 
    539 ///////////////////////////////////////////////////////////////////////////////
    540 
    541 class GLShaderPDXferProcessor : public GrGLSLXferProcessor {
    542 public:
    543     static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) {
    544         const ShaderPDXferProcessor& xp = processor.cast<ShaderPDXferProcessor>();
    545         b->add32(xp.getXfermode());
    546     }
    547 
    548 private:
    549     void emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder* fragBuilder,
    550                                  GrGLSLUniformHandler* uniformHandler,
    551                                  const char* srcColor,
    552                                  const char* srcCoverage,
    553                                  const char* dstColor,
    554                                  const char* outColor,
    555                                  const char* outColorSecondary,
    556                                  const GrXferProcessor& proc) override {
    557         const ShaderPDXferProcessor& xp = proc.cast<ShaderPDXferProcessor>();
    558 
    559         GrGLSLBlend::AppendMode(fragBuilder, srcColor, dstColor, outColor, xp.getXfermode());
    560 
    561         // Apply coverage.
    562         INHERITED::DefaultCoverageModulation(fragBuilder, srcCoverage, dstColor, outColor,
    563                                              outColorSecondary, xp);
    564     }
    565 
    566     void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
    567 
    568     typedef GrGLSLXferProcessor INHERITED;
    569 };
    570 
    571 ///////////////////////////////////////////////////////////////////////////////
    572 
    573 void ShaderPDXferProcessor::onGetGLSLProcessorKey(const GrGLSLCaps&,
    574                                                   GrProcessorKeyBuilder* b) const {
    575     GLShaderPDXferProcessor::GenKey(*this, b);
    576 }
    577 
    578 GrGLSLXferProcessor* ShaderPDXferProcessor::createGLSLInstance() const {
    579     return new GLShaderPDXferProcessor;
    580 }
    581 
    582 ///////////////////////////////////////////////////////////////////////////////
    583 
    584 class PDLCDXferProcessor : public GrXferProcessor {
    585 public:
    586     static GrXferProcessor* Create(SkXfermode::Mode xfermode, const GrProcOptInfo& colorPOI);
    587 
    588     ~PDLCDXferProcessor() override;
    589 
    590     const char* name() const override { return "Porter Duff LCD"; }
    591 
    592     GrGLSLXferProcessor* createGLSLInstance() const override;
    593 
    594 private:
    595     PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha);
    596 
    597     GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations& optimizations,
    598                                                  bool doesStencilWrite,
    599                                                  GrColor* overrideColor,
    600                                                  const GrCaps& caps) const override;
    601 
    602     void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
    603 
    604     void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override {
    605         blendInfo->fSrcBlend = kConstC_GrBlendCoeff;
    606         blendInfo->fDstBlend = kISC_GrBlendCoeff;
    607         blendInfo->fBlendConstant = fBlendConstant;
    608     }
    609 
    610     bool onIsEqual(const GrXferProcessor& xpBase) const override {
    611         const PDLCDXferProcessor& xp = xpBase.cast<PDLCDXferProcessor>();
    612         if (fBlendConstant != xp.fBlendConstant ||
    613             fAlpha != xp.fAlpha) {
    614             return false;
    615         }
    616         return true;
    617     }
    618 
    619     GrColor      fBlendConstant;
    620     uint8_t      fAlpha;
    621 
    622     typedef GrXferProcessor INHERITED;
    623 };
    624 
    625 ///////////////////////////////////////////////////////////////////////////////
    626 
    627 class GLPDLCDXferProcessor : public GrGLSLXferProcessor {
    628 public:
    629     GLPDLCDXferProcessor(const GrProcessor&) {}
    630 
    631     virtual ~GLPDLCDXferProcessor() {}
    632 
    633     static void GenKey(const GrProcessor& processor, const GrGLSLCaps& caps,
    634                        GrProcessorKeyBuilder* b) {}
    635 
    636 private:
    637     void emitOutputsForBlendState(const EmitArgs& args) override {
    638         GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
    639         SkASSERT(args.fInputCoverage);
    640         fragBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, args.fInputColor,
    641                                  args.fInputCoverage);
    642     }
    643 
    644     void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {};
    645 
    646     typedef GrGLSLXferProcessor INHERITED;
    647 };
    648 
    649 ///////////////////////////////////////////////////////////////////////////////
    650 
    651 PDLCDXferProcessor::PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha)
    652     : fBlendConstant(blendConstant)
    653     , fAlpha(alpha) {
    654     this->initClassID<PDLCDXferProcessor>();
    655 }
    656 
    657 GrXferProcessor* PDLCDXferProcessor::Create(SkXfermode::Mode xfermode,
    658                                             const GrProcOptInfo& colorPOI) {
    659     if (SkXfermode::kSrcOver_Mode != xfermode) {
    660         return nullptr;
    661     }
    662 
    663     if (kRGBA_GrColorComponentFlags != colorPOI.validFlags()) {
    664         return nullptr;
    665     }
    666 
    667     GrColor blendConstant = GrUnpremulColor(colorPOI.color());
    668     uint8_t alpha = GrColorUnpackA(blendConstant);
    669     blendConstant |= (0xff << GrColor_SHIFT_A);
    670 
    671     return new PDLCDXferProcessor(blendConstant, alpha);
    672 }
    673 
    674 PDLCDXferProcessor::~PDLCDXferProcessor() {
    675 }
    676 
    677 void PDLCDXferProcessor::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
    678                                                GrProcessorKeyBuilder* b) const {
    679     GLPDLCDXferProcessor::GenKey(*this, caps, b);
    680 }
    681 
    682 GrGLSLXferProcessor* PDLCDXferProcessor::createGLSLInstance() const {
    683     return new GLPDLCDXferProcessor(*this);
    684 }
    685 
    686 GrXferProcessor::OptFlags
    687 PDLCDXferProcessor::onGetOptimizations(const GrPipelineOptimizations& optimizations,
    688                                        bool doesStencilWrite,
    689                                        GrColor* overrideColor,
    690                                        const GrCaps& caps) const {
    691         // We want to force our primary output to be alpha * Coverage, where alpha is the alpha
    692         // value of the blend the constant. We should already have valid blend coeff's if we are at
    693         // a point where we have RGB coverage. We don't need any color stages since the known color
    694         // output is already baked into the blendConstant.
    695         *overrideColor = GrColorPackRGBA(fAlpha, fAlpha, fAlpha, fAlpha);
    696         return GrXferProcessor::kOverrideColor_OptFlag;
    697 }
    698 
    699 ///////////////////////////////////////////////////////////////////////////////
    700 
    701 GrPorterDuffXPFactory::GrPorterDuffXPFactory(SkXfermode::Mode xfermode)
    702     : fXfermode(xfermode) {
    703     SkASSERT(fXfermode <= SkXfermode::kLastCoeffMode);
    704     this->initClassID<GrPorterDuffXPFactory>();
    705 }
    706 
    707 GrXPFactory* GrPorterDuffXPFactory::Create(SkXfermode::Mode xfermode) {
    708     static GrPorterDuffXPFactory gClearPDXPF(SkXfermode::kClear_Mode);
    709     static GrPorterDuffXPFactory gSrcPDXPF(SkXfermode::kSrc_Mode);
    710     static GrPorterDuffXPFactory gDstPDXPF(SkXfermode::kDst_Mode);
    711     static GrPorterDuffXPFactory gSrcOverPDXPF(SkXfermode::kSrcOver_Mode);
    712     static GrPorterDuffXPFactory gDstOverPDXPF(SkXfermode::kDstOver_Mode);
    713     static GrPorterDuffXPFactory gSrcInPDXPF(SkXfermode::kSrcIn_Mode);
    714     static GrPorterDuffXPFactory gDstInPDXPF(SkXfermode::kDstIn_Mode);
    715     static GrPorterDuffXPFactory gSrcOutPDXPF(SkXfermode::kSrcOut_Mode);
    716     static GrPorterDuffXPFactory gDstOutPDXPF(SkXfermode::kDstOut_Mode);
    717     static GrPorterDuffXPFactory gSrcATopPDXPF(SkXfermode::kSrcATop_Mode);
    718     static GrPorterDuffXPFactory gDstATopPDXPF(SkXfermode::kDstATop_Mode);
    719     static GrPorterDuffXPFactory gXorPDXPF(SkXfermode::kXor_Mode);
    720     static GrPorterDuffXPFactory gPlusPDXPF(SkXfermode::kPlus_Mode);
    721     static GrPorterDuffXPFactory gModulatePDXPF(SkXfermode::kModulate_Mode);
    722     static GrPorterDuffXPFactory gScreenPDXPF(SkXfermode::kScreen_Mode);
    723 
    724     static GrPorterDuffXPFactory* gFactories[] = {
    725         &gClearPDXPF, &gSrcPDXPF, &gDstPDXPF, &gSrcOverPDXPF, &gDstOverPDXPF, &gSrcInPDXPF,
    726         &gDstInPDXPF, &gSrcOutPDXPF, &gDstOutPDXPF, &gSrcATopPDXPF, &gDstATopPDXPF, &gXorPDXPF,
    727         &gPlusPDXPF, &gModulatePDXPF, &gScreenPDXPF
    728     };
    729     GR_STATIC_ASSERT(SK_ARRAY_COUNT(gFactories) == SkXfermode::kLastCoeffMode + 1);
    730 
    731     if (xfermode < 0 || xfermode > SkXfermode::kLastCoeffMode) {
    732         return nullptr;
    733     }
    734     return SkRef(gFactories[xfermode]);
    735 }
    736 
    737 GrXferProcessor*
    738 GrPorterDuffXPFactory::onCreateXferProcessor(const GrCaps& caps,
    739                                              const GrPipelineOptimizations& optimizations,
    740                                              bool hasMixedSamples,
    741                                              const DstTexture* dstTexture) const {
    742     if (optimizations.fOverrides.fUsePLSDstRead) {
    743         return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, fXfermode);
    744     }
    745     BlendFormula blendFormula;
    746     if (optimizations.fCoveragePOI.isFourChannelOutput()) {
    747         if (SkXfermode::kSrcOver_Mode == fXfermode &&
    748             kRGBA_GrColorComponentFlags == optimizations.fColorPOI.validFlags() &&
    749             !caps.shaderCaps()->dualSourceBlendingSupport() &&
    750             !caps.shaderCaps()->dstReadInShaderSupport()) {
    751             // If we don't have dual source blending or in shader dst reads, we fall back to this
    752             // trick for rendering SrcOver LCD text instead of doing a dst copy.
    753             SkASSERT(!dstTexture || !dstTexture->texture());
    754             return PDLCDXferProcessor::Create(fXfermode, optimizations.fColorPOI);
    755         }
    756         blendFormula = get_lcd_blend_formula(optimizations.fCoveragePOI, fXfermode);
    757     } else {
    758         blendFormula = get_blend_formula(optimizations.fColorPOI, optimizations.fCoveragePOI,
    759                                          hasMixedSamples, fXfermode);
    760     }
    761 
    762     if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) {
    763         return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, fXfermode);
    764     }
    765 
    766     SkASSERT(!dstTexture || !dstTexture->texture());
    767     return new PorterDuffXferProcessor(blendFormula);
    768 }
    769 
    770 void GrPorterDuffXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
    771                                                      InvariantBlendedColor* blendedColor) const {
    772     // Find the blended color info based on the formula that does not have coverage.
    773     BlendFormula colorFormula = gBlendTable[colorPOI.isOpaque()][0][fXfermode];
    774     if (colorFormula.usesDstColor()) {
    775         blendedColor->fWillBlendWithDst = true;
    776         blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags;
    777         return;
    778     }
    779 
    780     blendedColor->fWillBlendWithDst = false;
    781 
    782     SkASSERT(kAdd_GrBlendEquation == colorFormula.fBlendEquation);
    783 
    784     switch (colorFormula.fSrcCoeff) {
    785         case kZero_GrBlendCoeff:
    786             blendedColor->fKnownColor = 0;
    787             blendedColor->fKnownColorFlags = kRGBA_GrColorComponentFlags;
    788             return;
    789 
    790         case kOne_GrBlendCoeff:
    791             blendedColor->fKnownColor = colorPOI.color();
    792             blendedColor->fKnownColorFlags = colorPOI.validFlags();
    793             return;
    794 
    795         default:
    796             blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags;
    797             return;
    798     }
    799 }
    800 
    801 bool GrPorterDuffXPFactory::onWillReadDstColor(const GrCaps& caps,
    802                                                const GrPipelineOptimizations& optimizations,
    803                                                bool hasMixedSamples) const {
    804     if (caps.shaderCaps()->dualSourceBlendingSupport()) {
    805         return false;
    806     }
    807 
    808     // When we have four channel coverage we always need to read the dst in order to correctly
    809     // blend. The one exception is when we are using srcover mode and we know the input color into
    810     // the XP.
    811     if (optimizations.fCoveragePOI.isFourChannelOutput()) {
    812         if (SkXfermode::kSrcOver_Mode == fXfermode &&
    813             kRGBA_GrColorComponentFlags == optimizations.fColorPOI.validFlags() &&
    814             !caps.shaderCaps()->dstReadInShaderSupport()) {
    815             return false;
    816         }
    817         return get_lcd_blend_formula(optimizations.fCoveragePOI, fXfermode).hasSecondaryOutput();
    818     }
    819     // We fallback on the shader XP when the blend formula would use dual source blending but we
    820     // don't have support for it.
    821     return get_blend_formula(optimizations.fColorPOI, optimizations.fCoveragePOI, hasMixedSamples,
    822                              fXfermode).hasSecondaryOutput();
    823 }
    824 
    825 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory);
    826 
    827 const GrXPFactory* GrPorterDuffXPFactory::TestCreate(GrProcessorTestData* d) {
    828     SkXfermode::Mode mode = SkXfermode::Mode(d->fRandom->nextULessThan(SkXfermode::kLastCoeffMode));
    829     return GrPorterDuffXPFactory::Create(mode);
    830 }
    831 
    832 void GrPorterDuffXPFactory::TestGetXPOutputTypes(const GrXferProcessor* xp,
    833                                                  int* outPrimary,
    834                                                  int* outSecondary) {
    835     if (!!strcmp(xp->name(), "Porter Duff")) {
    836         *outPrimary = *outSecondary = -1;
    837         return;
    838     }
    839     BlendFormula blendFormula = static_cast<const PorterDuffXferProcessor*>(xp)->getBlendFormula();
    840     *outPrimary = blendFormula.fPrimaryOutputType;
    841     *outSecondary = blendFormula.fSecondaryOutputType;
    842 }
    843 
    844 
    845 ////////////////////////////////////////////////////////////////////////////////////////////////
    846 // SrcOver Global functions
    847 ////////////////////////////////////////////////////////////////////////////////////////////////
    848 const GrXferProcessor& GrPorterDuffXPFactory::SimpleSrcOverXP() {
    849     static BlendFormula gSrcOverBlendFormula = COEFF_FORMULA(kOne_GrBlendCoeff,
    850                                                              kISA_GrBlendCoeff);
    851     static PorterDuffXferProcessor gSrcOverXP(gSrcOverBlendFormula);
    852     return gSrcOverXP;
    853 }
    854 
    855 GrXferProcessor* GrPorterDuffXPFactory::CreateSrcOverXferProcessor(
    856         const GrCaps& caps,
    857         const GrPipelineOptimizations& optimizations,
    858         bool hasMixedSamples,
    859         const GrXferProcessor::DstTexture* dstTexture) {
    860     if (optimizations.fOverrides.fUsePLSDstRead) {
    861         return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, SkXfermode::kSrcOver_Mode);
    862     }
    863     if (!optimizations.fCoveragePOI.isFourChannelOutput() &&
    864         !(optimizations.fCoveragePOI.isSolidWhite() &&
    865           !hasMixedSamples &&
    866           optimizations.fColorPOI.isOpaque())) {
    867         // We return nullptr here, which our caller interprets as meaning "use SimpleSrcOverXP".
    868         // We don't simply return the address of that XP here because our caller would have to unref
    869         // it and since it is a global object and GrProgramElement's ref-cnting system is not thread
    870         // safe.
    871         return nullptr;
    872     }
    873 
    874     BlendFormula blendFormula;
    875     if (optimizations.fCoveragePOI.isFourChannelOutput()) {
    876         if (kRGBA_GrColorComponentFlags == optimizations.fColorPOI.validFlags() &&
    877             !caps.shaderCaps()->dualSourceBlendingSupport() &&
    878             !caps.shaderCaps()->dstReadInShaderSupport()) {
    879             // If we don't have dual source blending or in shader dst reads, we fall
    880             // back to this trick for rendering SrcOver LCD text instead of doing a
    881             // dst copy.
    882             SkASSERT(!dstTexture || !dstTexture->texture());
    883             return PDLCDXferProcessor::Create(SkXfermode::kSrcOver_Mode, optimizations.fColorPOI);
    884         }
    885         blendFormula = get_lcd_blend_formula(optimizations.fCoveragePOI, SkXfermode::kSrcOver_Mode);
    886     } else {
    887         blendFormula = get_blend_formula(optimizations.fColorPOI, optimizations.fCoveragePOI,
    888                                          hasMixedSamples, SkXfermode::kSrcOver_Mode);
    889     }
    890 
    891     if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) {
    892         return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, SkXfermode::kSrcOver_Mode);
    893     }
    894 
    895     SkASSERT(!dstTexture || !dstTexture->texture());
    896     return new PorterDuffXferProcessor(blendFormula);
    897 }
    898 
    899 bool GrPorterDuffXPFactory::SrcOverWillNeedDstTexture(const GrCaps& caps,
    900                                                       const GrPipelineOptimizations& optimizations,
    901                                                       bool hasMixedSamples) {
    902     if (caps.shaderCaps()->dstReadInShaderSupport() ||
    903         caps.shaderCaps()->dualSourceBlendingSupport()) {
    904         return false;
    905     }
    906 
    907     // When we have four channel coverage we always need to read the dst in order to correctly
    908     // blend. The one exception is when we are using srcover mode and we know the input color
    909     // into the XP.
    910     if (optimizations.fCoveragePOI.isFourChannelOutput()) {
    911         if (kRGBA_GrColorComponentFlags == optimizations.fColorPOI.validFlags() &&
    912             !caps.shaderCaps()->dstReadInShaderSupport()) {
    913             return false;
    914         }
    915         return get_lcd_blend_formula(optimizations.fCoveragePOI,
    916                                      SkXfermode::kSrcOver_Mode).hasSecondaryOutput();
    917     }
    918     // We fallback on the shader XP when the blend formula would use dual source blending but we
    919     // don't have support for it.
    920     return get_blend_formula(optimizations.fColorPOI, optimizations.fCoveragePOI,
    921                              hasMixedSamples, SkXfermode::kSrcOver_Mode).hasSecondaryOutput();
    922 }
    923 
    924