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 "SkTo.h"
     18 #include "glsl/GrGLSLBlend.h"
     19 #include "glsl/GrGLSLFragmentShaderBuilder.h"
     20 #include "glsl/GrGLSLProgramDataManager.h"
     21 #include "glsl/GrGLSLUniformHandler.h"
     22 #include "glsl/GrGLSLXferProcessor.h"
     23 
     24 /**
     25  * Wraps the shader outputs and HW blend state that comprise a Porter Duff blend mode with coverage.
     26  */
     27 class 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     BlendFormula() = default;
     45 
     46     constexpr BlendFormula(OutputType primaryOut, OutputType secondaryOut, GrBlendEquation equation,
     47                            GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff)
     48             : fPrimaryOutputType(primaryOut)
     49             , fSecondaryOutputType(secondaryOut)
     50             , fBlendEquation(equation)
     51             , fSrcCoeff(srcCoeff)
     52             , fDstCoeff(dstCoeff)
     53             , fProps(GetProperties(primaryOut, secondaryOut, equation, srcCoeff, dstCoeff)) {}
     54 
     55     BlendFormula& operator=(const BlendFormula& other) {
     56         SkDEBUGCODE(other.validatePreoptimized());
     57         fData = other.fData;
     58         return *this;
     59     }
     60 
     61     bool operator==(const BlendFormula& other) const {
     62         SkDEBUGCODE(this->validatePreoptimized());
     63         SkDEBUGCODE(other.validatePreoptimized());
     64         return fData == other.fData;
     65     }
     66 
     67     bool hasSecondaryOutput() const {
     68         SkDEBUGCODE(this->validatePreoptimized());
     69         return kNone_OutputType != fSecondaryOutputType;
     70     }
     71     bool modifiesDst() const {
     72         SkDEBUGCODE(this->validatePreoptimized());
     73         return SkToBool(fProps & kModifiesDst_Property);
     74     }
     75     bool usesDstColor() const {
     76         SkDEBUGCODE(this->validatePreoptimized());
     77         return SkToBool(fProps & kUsesDstColor_Property);
     78     }
     79     bool usesInputColor() const {
     80         SkDEBUGCODE(this->validatePreoptimized());
     81         return SkToBool(fProps & kUsesInputColor_Property);
     82     }
     83     bool canTweakAlphaForCoverage() const {
     84         SkDEBUGCODE(this->validatePreoptimized());
     85         return SkToBool(fProps & kCanTweakAlphaForCoverage_Property);
     86     }
     87 
     88     GrBlendEquation equation() const {
     89         SkDEBUGCODE(this->validatePreoptimized());
     90         return fBlendEquation;
     91     }
     92 
     93     GrBlendCoeff srcCoeff() const {
     94         SkDEBUGCODE(this->validatePreoptimized());
     95         return fSrcCoeff;
     96     }
     97 
     98     GrBlendCoeff dstCoeff() const {
     99         SkDEBUGCODE(this->validatePreoptimized());
    100         return fDstCoeff;
    101     }
    102 
    103     OutputType primaryOutput() const {
    104         SkDEBUGCODE(this->validatePreoptimized());
    105         return fPrimaryOutputType;
    106     }
    107 
    108     OutputType secondaryOutput() const {
    109         SkDEBUGCODE(this->validatePreoptimized());
    110         return fSecondaryOutputType;
    111     }
    112 
    113 private:
    114     enum Properties {
    115         kModifiesDst_Property              = 1,
    116         kUsesDstColor_Property             = 1 << 1,
    117         kUsesInputColor_Property           = 1 << 2,
    118         kCanTweakAlphaForCoverage_Property = 1 << 3,
    119 
    120         kLast_Property = kCanTweakAlphaForCoverage_Property
    121     };
    122     GR_DECL_BITFIELD_OPS_FRIENDS(Properties)
    123 
    124 #ifdef SK_DEBUG
    125     void validatePreoptimized() const {
    126         // The provided formula should already be optimized before a BlendFormula is constructed.
    127         // Preferably these asserts would be done statically in the constexpr constructor, but this
    128         // is not allowed in C++11.
    129         SkASSERT((kNone_OutputType == fPrimaryOutputType) ==
    130                  !GrBlendCoeffsUseSrcColor(fSrcCoeff, fDstCoeff));
    131         SkASSERT(!GrBlendCoeffRefsSrc2(fSrcCoeff));
    132         SkASSERT((kNone_OutputType == fSecondaryOutputType) == !GrBlendCoeffRefsSrc2(fDstCoeff));
    133         SkASSERT(fPrimaryOutputType != fSecondaryOutputType ||
    134                  kNone_OutputType == fPrimaryOutputType);
    135         SkASSERT(kNone_OutputType != fPrimaryOutputType ||
    136                  kNone_OutputType == fSecondaryOutputType);
    137     }
    138 #endif
    139 
    140     /**
    141      * Deduce the properties of a BlendFormula.
    142      */
    143     static constexpr Properties GetProperties(OutputType PrimaryOut, OutputType SecondaryOut,
    144                                               GrBlendEquation BlendEquation, GrBlendCoeff SrcCoeff,
    145                                               GrBlendCoeff DstCoeff);
    146 
    147     union {
    148         struct {
    149             // We allot the enums one more bit than they require because MSVC seems to sign-extend
    150             // them when the top bit is set. (This is in violation of the C++03 standard 9.6/4)
    151             OutputType        fPrimaryOutputType    : 4;
    152             OutputType        fSecondaryOutputType  : 4;
    153             GrBlendEquation   fBlendEquation        : 6;
    154             GrBlendCoeff      fSrcCoeff             : 6;
    155             GrBlendCoeff      fDstCoeff             : 6;
    156             Properties        fProps                : 32 - (4 + 4 + 6 + 6 + 6);
    157         };
    158         uint32_t fData;
    159     };
    160 
    161     GR_STATIC_ASSERT(kLast_OutputType      < (1 << 3));
    162     GR_STATIC_ASSERT(kLast_GrBlendEquation < (1 << 5));
    163     GR_STATIC_ASSERT(kLast_GrBlendCoeff    < (1 << 5));
    164     GR_STATIC_ASSERT(kLast_Property        < (1 << 6));
    165 };
    166 
    167 GR_STATIC_ASSERT(4 == sizeof(BlendFormula));
    168 
    169 GR_MAKE_BITFIELD_OPS(BlendFormula::Properties);
    170 
    171 constexpr BlendFormula::Properties BlendFormula::GetProperties(OutputType PrimaryOut,
    172                                                                OutputType SecondaryOut,
    173                                                                GrBlendEquation BlendEquation,
    174                                                                GrBlendCoeff SrcCoeff,
    175                                                                GrBlendCoeff DstCoeff) {
    176     return static_cast<Properties>(
    177             (GrBlendModifiesDst(BlendEquation, SrcCoeff, DstCoeff) ? kModifiesDst_Property : 0) |
    178             (GrBlendCoeffsUseDstColor(SrcCoeff, DstCoeff) ? kUsesDstColor_Property : 0) |
    179             ((PrimaryOut >= kModulate_OutputType && GrBlendCoeffsUseSrcColor(SrcCoeff, DstCoeff)) ||
    180                              (SecondaryOut >= kModulate_OutputType &&
    181                               GrBlendCoeffRefsSrc2(DstCoeff))
    182                      ? kUsesInputColor_Property
    183                      : 0) |  // We assert later that SrcCoeff doesn't ref src2.
    184             ((kModulate_OutputType == PrimaryOut || kNone_OutputType == PrimaryOut) &&
    185                              kNone_OutputType == SecondaryOut &&
    186                              GrBlendAllowsCoverageAsAlpha(BlendEquation, SrcCoeff, DstCoeff)
    187                      ? kCanTweakAlphaForCoverage_Property
    188                      : 0));
    189 }
    190 
    191 /**
    192  * When there is no coverage, or the blend mode can tweak alpha for coverage, we use the standard
    193  * Porter Duff formula.
    194  */
    195 static constexpr BlendFormula MakeCoeffFormula(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
    196     // When the coeffs are (Zero, Zero) or (Zero, One) we set the primary output to none.
    197     return (kZero_GrBlendCoeff == srcCoeff &&
    198             (kZero_GrBlendCoeff == dstCoeff || kOne_GrBlendCoeff == dstCoeff))
    199            ? BlendFormula(BlendFormula::kNone_OutputType, BlendFormula::kNone_OutputType,
    200                           kAdd_GrBlendEquation, kZero_GrBlendCoeff, dstCoeff)
    201            : BlendFormula(BlendFormula::kModulate_OutputType, BlendFormula::kNone_OutputType,
    202                         kAdd_GrBlendEquation, srcCoeff, dstCoeff);
    203 }
    204 
    205 /**
    206  * Basic coeff formula similar to MakeCoeffFormula but we will make the src f*Sa. This is used in
    207  * LCD dst-out.
    208  */
    209 static constexpr BlendFormula MakeSAModulateFormula(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
    210     return BlendFormula(BlendFormula::kSAModulate_OutputType, BlendFormula::kNone_OutputType,
    211                         kAdd_GrBlendEquation, srcCoeff, dstCoeff);
    212 }
    213 
    214 /**
    215  * When there is coverage, the equation with f=coverage is:
    216  *
    217  *   D' = f * (S * srcCoeff + D * dstCoeff) + (1-f) * D
    218  *
    219  * This can be rewritten as:
    220  *
    221  *   D' = f * S * srcCoeff + D * (1 - [f * (1 - dstCoeff)])
    222  *
    223  * To implement this formula, we output [f * (1 - dstCoeff)] for the secondary color and replace the
    224  * HW dst coeff with IS2C.
    225  *
    226  * Xfer modes: dst-atop (Sa!=1)
    227  */
    228 static constexpr BlendFormula MakeCoverageFormula(
    229         BlendFormula::OutputType oneMinusDstCoeffModulateOutput, GrBlendCoeff srcCoeff) {
    230     return BlendFormula(BlendFormula::kModulate_OutputType, oneMinusDstCoeffModulateOutput,
    231                         kAdd_GrBlendEquation, srcCoeff, kIS2C_GrBlendCoeff);
    232 }
    233 
    234 /**
    235  * When there is coverage and the src coeff is Zero, the equation with f=coverage becomes:
    236  *
    237  *   D' = f * D * dstCoeff + (1-f) * D
    238  *
    239  * This can be rewritten as:
    240  *
    241  *   D' = D - D * [f * (1 - dstCoeff)]
    242  *
    243  * To implement this formula, we output [f * (1 - dstCoeff)] for the primary color and use a reverse
    244  * subtract HW blend equation with coeffs of (DC, One).
    245  *
    246  * Xfer modes: clear, dst-out (Sa=1), dst-in (Sa!=1), modulate (Sc!=1)
    247  */
    248 static constexpr BlendFormula MakeCoverageSrcCoeffZeroFormula(
    249         BlendFormula::OutputType oneMinusDstCoeffModulateOutput) {
    250     return BlendFormula(oneMinusDstCoeffModulateOutput, BlendFormula::kNone_OutputType,
    251                         kReverseSubtract_GrBlendEquation, kDC_GrBlendCoeff, kOne_GrBlendCoeff);
    252 }
    253 
    254 /**
    255  * When there is coverage and the dst coeff is Zero, the equation with f=coverage becomes:
    256  *
    257  *   D' = f * S * srcCoeff + (1-f) * D
    258  *
    259  * To implement this formula, we output [f] for the secondary color and replace the HW dst coeff
    260  * with IS2A. (Note that we can avoid dual source blending when Sa=1 by using ISA.)
    261  *
    262  * Xfer modes (Sa!=1): src, src-in, src-out
    263  */
    264 static constexpr BlendFormula MakeCoverageDstCoeffZeroFormula(GrBlendCoeff srcCoeff) {
    265     return BlendFormula(BlendFormula::kModulate_OutputType, BlendFormula::kCoverage_OutputType,
    266                         kAdd_GrBlendEquation, srcCoeff, kIS2A_GrBlendCoeff);
    267 }
    268 
    269 // Older GCC won't like the constexpr arrays because of
    270 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61484.
    271 // MSVC 2015 crashes with an internal compiler error.
    272 #if !defined(__clang__) && ((defined(__GNUC__) && __GNUC__ < 5) || (defined(_MSC_VER) && _MSC_VER <= 1910))
    273 #   define MAYBE_CONSTEXPR const
    274 #else
    275 #   define MAYBE_CONSTEXPR constexpr
    276 #endif
    277 
    278 /**
    279  * This table outlines the blend formulas we will use with each xfermode, with and without coverage,
    280  * with and without an opaque input color. Optimization properties are deduced at compile time so we
    281  * can make runtime decisions quickly. RGB coverage is not supported.
    282  */
    283 static MAYBE_CONSTEXPR BlendFormula gBlendTable[2][2][(int)SkBlendMode::kLastCoeffMode + 1] = {
    284                      /*>> No coverage, input color unknown <<*/ {{
    285 
    286     /* clear */      MakeCoeffFormula(kZero_GrBlendCoeff, kZero_GrBlendCoeff),
    287     /* src */        MakeCoeffFormula(kOne_GrBlendCoeff,  kZero_GrBlendCoeff),
    288     /* dst */        MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
    289     /* src-over */   MakeCoeffFormula(kOne_GrBlendCoeff,  kISA_GrBlendCoeff),
    290     /* dst-over */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kOne_GrBlendCoeff),
    291     /* src-in */     MakeCoeffFormula(kDA_GrBlendCoeff,   kZero_GrBlendCoeff),
    292     /* dst-in */     MakeCoeffFormula(kZero_GrBlendCoeff, kSA_GrBlendCoeff),
    293     /* src-out */    MakeCoeffFormula(kIDA_GrBlendCoeff,  kZero_GrBlendCoeff),
    294     /* dst-out */    MakeCoeffFormula(kZero_GrBlendCoeff, kISA_GrBlendCoeff),
    295     /* src-atop */   MakeCoeffFormula(kDA_GrBlendCoeff,   kISA_GrBlendCoeff),
    296     /* dst-atop */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kSA_GrBlendCoeff),
    297     /* xor */        MakeCoeffFormula(kIDA_GrBlendCoeff,  kISA_GrBlendCoeff),
    298     /* plus */       MakeCoeffFormula(kOne_GrBlendCoeff,  kOne_GrBlendCoeff),
    299     /* modulate */   MakeCoeffFormula(kZero_GrBlendCoeff, kSC_GrBlendCoeff),
    300     /* screen */     MakeCoeffFormula(kOne_GrBlendCoeff,  kISC_GrBlendCoeff),
    301 
    302                      }, /*>> Has coverage, input color unknown <<*/ {
    303 
    304     /* clear */      MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType),
    305     /* src */        MakeCoverageDstCoeffZeroFormula(kOne_GrBlendCoeff),
    306     /* dst */        MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
    307     /* src-over */   MakeCoeffFormula(kOne_GrBlendCoeff,  kISA_GrBlendCoeff),
    308     /* dst-over */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kOne_GrBlendCoeff),
    309     /* src-in */     MakeCoverageDstCoeffZeroFormula(kDA_GrBlendCoeff),
    310     /* dst-in */     MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISAModulate_OutputType),
    311     /* src-out */    MakeCoverageDstCoeffZeroFormula(kIDA_GrBlendCoeff),
    312     /* dst-out */    MakeCoeffFormula(kZero_GrBlendCoeff, kISA_GrBlendCoeff),
    313     /* src-atop */   MakeCoeffFormula(kDA_GrBlendCoeff,   kISA_GrBlendCoeff),
    314     /* dst-atop */   MakeCoverageFormula(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff),
    315     /* xor */        MakeCoeffFormula(kIDA_GrBlendCoeff,  kISA_GrBlendCoeff),
    316     /* plus */       MakeCoeffFormula(kOne_GrBlendCoeff,  kOne_GrBlendCoeff),
    317     /* modulate */   MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISCModulate_OutputType),
    318     /* screen */     MakeCoeffFormula(kOne_GrBlendCoeff,  kISC_GrBlendCoeff),
    319 
    320                      }}, /*>> No coverage, input color opaque <<*/ {{
    321 
    322     /* clear */      MakeCoeffFormula(kZero_GrBlendCoeff, kZero_GrBlendCoeff),
    323     /* src */        MakeCoeffFormula(kOne_GrBlendCoeff,  kZero_GrBlendCoeff),
    324     /* dst */        MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
    325     /* src-over */   MakeCoeffFormula(kOne_GrBlendCoeff,  kISA_GrBlendCoeff), // see comment below
    326     /* dst-over */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kOne_GrBlendCoeff),
    327     /* src-in */     MakeCoeffFormula(kDA_GrBlendCoeff,   kZero_GrBlendCoeff),
    328     /* dst-in */     MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
    329     /* src-out */    MakeCoeffFormula(kIDA_GrBlendCoeff,  kZero_GrBlendCoeff),
    330     /* dst-out */    MakeCoeffFormula(kZero_GrBlendCoeff, kZero_GrBlendCoeff),
    331     /* src-atop */   MakeCoeffFormula(kDA_GrBlendCoeff,   kZero_GrBlendCoeff),
    332     /* dst-atop */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kOne_GrBlendCoeff),
    333     /* xor */        MakeCoeffFormula(kIDA_GrBlendCoeff,  kZero_GrBlendCoeff),
    334     /* plus */       MakeCoeffFormula(kOne_GrBlendCoeff,  kOne_GrBlendCoeff),
    335     /* modulate */   MakeCoeffFormula(kZero_GrBlendCoeff, kSC_GrBlendCoeff),
    336     /* screen */     MakeCoeffFormula(kOne_GrBlendCoeff,  kISC_GrBlendCoeff),
    337 
    338                      }, /*>> Has coverage, input color opaque <<*/ {
    339 
    340     /* clear */      MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType),
    341     /* src */        MakeCoeffFormula(kOne_GrBlendCoeff,  kISA_GrBlendCoeff),
    342     /* dst */        MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
    343     /* src-over */   MakeCoeffFormula(kOne_GrBlendCoeff,  kISA_GrBlendCoeff),
    344     /* dst-over */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kOne_GrBlendCoeff),
    345     /* src-in */     MakeCoeffFormula(kDA_GrBlendCoeff,   kISA_GrBlendCoeff),
    346     /* dst-in */     MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
    347     /* src-out */    MakeCoeffFormula(kIDA_GrBlendCoeff,  kISA_GrBlendCoeff),
    348     /* dst-out */    MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType),
    349     /* src-atop */   MakeCoeffFormula(kDA_GrBlendCoeff,   kISA_GrBlendCoeff),
    350     /* dst-atop */   MakeCoeffFormula(kIDA_GrBlendCoeff,  kOne_GrBlendCoeff),
    351     /* xor */        MakeCoeffFormula(kIDA_GrBlendCoeff,  kISA_GrBlendCoeff),
    352     /* plus */       MakeCoeffFormula(kOne_GrBlendCoeff,  kOne_GrBlendCoeff),
    353     /* modulate */   MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISCModulate_OutputType),
    354     /* screen */     MakeCoeffFormula(kOne_GrBlendCoeff,  kISC_GrBlendCoeff),
    355 }}};
    356 // In the above table src-over is not optimized to src mode when the color is opaque because we
    357 // found no advantage to doing so. Also, we are using a global src-over XP in most cases which is
    358 // not specialized for opaque input. If the table were set to use the src formula then we'd have to
    359 // change when we use this global XP to keep analysis and practice in sync.
    360 
    361 static MAYBE_CONSTEXPR BlendFormula gLCDBlendTable[(int)SkBlendMode::kLastCoeffMode + 1] = {
    362     /* clear */      MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType),
    363     /* src */        MakeCoverageFormula(BlendFormula::kCoverage_OutputType, kOne_GrBlendCoeff),
    364     /* dst */        MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff),
    365     /* src-over */   MakeCoverageFormula(BlendFormula::kSAModulate_OutputType, kOne_GrBlendCoeff),
    366     /* dst-over */   MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
    367     /* src-in */     MakeCoverageFormula(BlendFormula::kCoverage_OutputType, kDA_GrBlendCoeff),
    368     /* dst-in */     MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISAModulate_OutputType),
    369     /* src-out */    MakeCoverageFormula(BlendFormula::kCoverage_OutputType, kIDA_GrBlendCoeff),
    370     /* dst-out */    MakeSAModulateFormula(kZero_GrBlendCoeff, kISC_GrBlendCoeff),
    371     /* src-atop */   MakeCoverageFormula(BlendFormula::kSAModulate_OutputType, kDA_GrBlendCoeff),
    372     /* dst-atop */   MakeCoverageFormula(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff),
    373     /* xor */        MakeCoverageFormula(BlendFormula::kSAModulate_OutputType, kIDA_GrBlendCoeff),
    374     /* plus */       MakeCoeffFormula(kOne_GrBlendCoeff, kOne_GrBlendCoeff),
    375     /* modulate */   MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISCModulate_OutputType),
    376     /* screen */     MakeCoeffFormula(kOne_GrBlendCoeff, kISC_GrBlendCoeff),
    377 };
    378 
    379 #undef MAYBE_CONSTEXPR
    380 
    381 static BlendFormula get_blend_formula(bool isOpaque,
    382                                       bool hasCoverage,
    383                                       bool hasMixedSamples,
    384                                       SkBlendMode xfermode) {
    385     SkASSERT((unsigned)xfermode <= (unsigned)SkBlendMode::kLastCoeffMode);
    386     bool conflatesCoverage = hasCoverage || hasMixedSamples;
    387     return gBlendTable[isOpaque][conflatesCoverage][(int)xfermode];
    388 }
    389 
    390 static BlendFormula get_lcd_blend_formula(SkBlendMode xfermode) {
    391     SkASSERT((unsigned)xfermode <= (unsigned)SkBlendMode::kLastCoeffMode);
    392 
    393     return gLCDBlendTable[(int)xfermode];
    394 }
    395 
    396 ///////////////////////////////////////////////////////////////////////////////
    397 
    398 class PorterDuffXferProcessor : public GrXferProcessor {
    399 public:
    400     PorterDuffXferProcessor(BlendFormula blendFormula, GrProcessorAnalysisCoverage coverage)
    401             : INHERITED(kPorterDuffXferProcessor_ClassID, false, false, coverage)
    402             , fBlendFormula(blendFormula) {
    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 = half4(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 = (half4(1.0) - %s) * %s;", output, inColor, inCoverage);
    460             break;
    461         default:
    462             SK_ABORT("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(kShaderPDXferProcessor_ClassID, true, hasMixedSamples, coverage)
    513             , fXfermode(xfermode) {
    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     float alpha() const { return fAlpha; }
    592 
    593 private:
    594     PDLCDXferProcessor(const SkPMColor4f& blendConstant, float 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     SkPMColor4f fBlendConstant;
    613     float fAlpha;
    614 
    615     typedef GrXferProcessor INHERITED;
    616 };
    617 
    618 ///////////////////////////////////////////////////////////////////////////////
    619 
    620 class GLPDLCDXferProcessor : public GrGLSLXferProcessor {
    621 public:
    622     GLPDLCDXferProcessor(const GrProcessor&) : fLastAlpha(SK_FloatNaN) {}
    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, kHalf_GrSLType,
    633                                                          "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         float alpha = xp.cast<PDLCDXferProcessor>().alpha();
    645         if (fLastAlpha != alpha) {
    646             pdm.set1f(fAlphaUniform, alpha);
    647             fLastAlpha = alpha;
    648         }
    649     }
    650 
    651     GrGLSLUniformHandler::UniformHandle fAlphaUniform;
    652     float fLastAlpha;
    653     typedef GrGLSLXferProcessor INHERITED;
    654 };
    655 
    656 ///////////////////////////////////////////////////////////////////////////////
    657 
    658 PDLCDXferProcessor::PDLCDXferProcessor(const SkPMColor4f& blendConstant, float alpha)
    659     : INHERITED(kPDLCDXferProcessor_ClassID, false, false, GrProcessorAnalysisCoverage::kLCD)
    660     , fBlendConstant(blendConstant)
    661     , fAlpha(alpha) {
    662 }
    663 
    664 sk_sp<const GrXferProcessor> PDLCDXferProcessor::Make(SkBlendMode mode,
    665                                                       const GrProcessorAnalysisColor& color) {
    666     if (SkBlendMode::kSrcOver != mode) {
    667         return nullptr;
    668     }
    669     SkPMColor4f blendConstantPM;
    670     if (!color.isConstant(&blendConstantPM)) {
    671         return nullptr;
    672     }
    673     SkColor4f blendConstantUPM = blendConstantPM.unpremul();
    674     float alpha = blendConstantUPM.fA;
    675     blendConstantPM = { blendConstantUPM.fR, blendConstantUPM.fG, blendConstantUPM.fB, 1 };
    676     return sk_sp<GrXferProcessor>(new PDLCDXferProcessor(blendConstantPM, alpha));
    677 }
    678 
    679 PDLCDXferProcessor::~PDLCDXferProcessor() {
    680 }
    681 
    682 void PDLCDXferProcessor::onGetGLSLProcessorKey(const GrShaderCaps& caps,
    683                                                GrProcessorKeyBuilder* b) const {
    684     GLPDLCDXferProcessor::GenKey(*this, caps, b);
    685 }
    686 
    687 GrGLSLXferProcessor* PDLCDXferProcessor::createGLSLInstance() const {
    688     return new GLPDLCDXferProcessor(*this);
    689 }
    690 
    691 ///////////////////////////////////////////////////////////////////////////////
    692 
    693 constexpr GrPorterDuffXPFactory::GrPorterDuffXPFactory(SkBlendMode xfermode)
    694         : fBlendMode(xfermode) {}
    695 
    696 const GrXPFactory* GrPorterDuffXPFactory::Get(SkBlendMode blendMode) {
    697     SkASSERT((unsigned)blendMode <= (unsigned)SkBlendMode::kLastCoeffMode);
    698 
    699     // If these objects are constructed as static constexpr by cl.exe (2015 SP2) the vtables are
    700     // null.
    701 #ifdef SK_BUILD_FOR_WIN
    702 #define _CONSTEXPR_
    703 #else
    704 #define _CONSTEXPR_ constexpr
    705 #endif
    706     static _CONSTEXPR_ const GrPorterDuffXPFactory gClearPDXPF(SkBlendMode::kClear);
    707     static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcPDXPF(SkBlendMode::kSrc);
    708     static _CONSTEXPR_ const GrPorterDuffXPFactory gDstPDXPF(SkBlendMode::kDst);
    709     static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcOverPDXPF(SkBlendMode::kSrcOver);
    710     static _CONSTEXPR_ const GrPorterDuffXPFactory gDstOverPDXPF(SkBlendMode::kDstOver);
    711     static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcInPDXPF(SkBlendMode::kSrcIn);
    712     static _CONSTEXPR_ const GrPorterDuffXPFactory gDstInPDXPF(SkBlendMode::kDstIn);
    713     static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcOutPDXPF(SkBlendMode::kSrcOut);
    714     static _CONSTEXPR_ const GrPorterDuffXPFactory gDstOutPDXPF(SkBlendMode::kDstOut);
    715     static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcATopPDXPF(SkBlendMode::kSrcATop);
    716     static _CONSTEXPR_ const GrPorterDuffXPFactory gDstATopPDXPF(SkBlendMode::kDstATop);
    717     static _CONSTEXPR_ const GrPorterDuffXPFactory gXorPDXPF(SkBlendMode::kXor);
    718     static _CONSTEXPR_ const GrPorterDuffXPFactory gPlusPDXPF(SkBlendMode::kPlus);
    719     static _CONSTEXPR_ const GrPorterDuffXPFactory gModulatePDXPF(SkBlendMode::kModulate);
    720     static _CONSTEXPR_ const GrPorterDuffXPFactory gScreenPDXPF(SkBlendMode::kScreen);
    721 #undef _CONSTEXPR_
    722 
    723     switch (blendMode) {
    724         case SkBlendMode::kClear:
    725             return &gClearPDXPF;
    726         case SkBlendMode::kSrc:
    727             return &gSrcPDXPF;
    728         case SkBlendMode::kDst:
    729             return &gDstPDXPF;
    730         case SkBlendMode::kSrcOver:
    731             return &gSrcOverPDXPF;
    732         case SkBlendMode::kDstOver:
    733             return &gDstOverPDXPF;
    734         case SkBlendMode::kSrcIn:
    735             return &gSrcInPDXPF;
    736         case SkBlendMode::kDstIn:
    737             return &gDstInPDXPF;
    738         case SkBlendMode::kSrcOut:
    739             return &gSrcOutPDXPF;
    740         case SkBlendMode::kDstOut:
    741             return &gDstOutPDXPF;
    742         case SkBlendMode::kSrcATop:
    743             return &gSrcATopPDXPF;
    744         case SkBlendMode::kDstATop:
    745             return &gDstATopPDXPF;
    746         case SkBlendMode::kXor:
    747             return &gXorPDXPF;
    748         case SkBlendMode::kPlus:
    749             return &gPlusPDXPF;
    750         case SkBlendMode::kModulate:
    751             return &gModulatePDXPF;
    752         case SkBlendMode::kScreen:
    753             return &gScreenPDXPF;
    754         default:
    755             SK_ABORT("Unexpected blend mode.");
    756             return nullptr;
    757     }
    758 }
    759 
    760 sk_sp<const GrXferProcessor> GrPorterDuffXPFactory::makeXferProcessor(
    761         const GrProcessorAnalysisColor& color, GrProcessorAnalysisCoverage coverage,
    762         bool hasMixedSamples, const GrCaps& caps) const {
    763     BlendFormula blendFormula;
    764     bool isLCD = coverage == GrProcessorAnalysisCoverage::kLCD;
    765     if (isLCD) {
    766         // See comment in MakeSrcOverXferProcessor about color.isOpaque here
    767         if (SkBlendMode::kSrcOver == fBlendMode && color.isConstant() && /*color.isOpaque() &&*/
    768             !caps.shaderCaps()->dualSourceBlendingSupport() &&
    769             !caps.shaderCaps()->dstReadInShaderSupport()) {
    770             // If we don't have dual source blending or in shader dst reads, we fall back to this
    771             // trick for rendering SrcOver LCD text instead of doing a dst copy.
    772             return PDLCDXferProcessor::Make(fBlendMode, color);
    773         }
    774         blendFormula = get_lcd_blend_formula(fBlendMode);
    775     } else {
    776         blendFormula =
    777                 get_blend_formula(color.isOpaque(), GrProcessorAnalysisCoverage::kNone != coverage,
    778                                   hasMixedSamples, fBlendMode);
    779     }
    780 
    781     if ((blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) ||
    782         (isLCD && (SkBlendMode::kSrcOver != fBlendMode /*|| !color.isOpaque()*/))) {
    783         return sk_sp<const GrXferProcessor>(new ShaderPDXferProcessor(hasMixedSamples, fBlendMode,
    784                                                                       coverage));
    785     }
    786     return sk_sp<const GrXferProcessor>(new PorterDuffXferProcessor(blendFormula, coverage));
    787 }
    788 
    789 static inline GrXPFactory::AnalysisProperties analysis_properties(
    790         const GrProcessorAnalysisColor& color, const GrProcessorAnalysisCoverage& coverage,
    791         const GrCaps& caps, SkBlendMode mode) {
    792     using AnalysisProperties = GrXPFactory::AnalysisProperties;
    793     AnalysisProperties props = AnalysisProperties::kNone;
    794     bool hasCoverage = GrProcessorAnalysisCoverage::kNone != coverage;
    795     bool isLCD = GrProcessorAnalysisCoverage::kLCD == coverage;
    796     BlendFormula formula;
    797     if (isLCD) {
    798         formula = gLCDBlendTable[(int)mode];
    799     } else {
    800         formula = gBlendTable[color.isOpaque()][hasCoverage][(int)mode];
    801     }
    802 
    803     if (formula.canTweakAlphaForCoverage() && !isLCD) {
    804         props |= AnalysisProperties::kCompatibleWithAlphaAsCoverage;
    805     }
    806 
    807     if (isLCD) {
    808         // See comment in MakeSrcOverXferProcessor about color.isOpaque here
    809         if (SkBlendMode::kSrcOver == mode && color.isConstant() && /*color.isOpaque() &&*/
    810             !caps.shaderCaps()->dualSourceBlendingSupport() &&
    811             !caps.shaderCaps()->dstReadInShaderSupport()) {
    812             props |= AnalysisProperties::kIgnoresInputColor;
    813         } else {
    814             // For LCD blending, if the color is not opaque we must read the dst in shader even if
    815             // we have dual source blending. The opaqueness check must be done after blending so for
    816             // simplicity we only allow src-over to not take the dst read path (though src, src-in,
    817             // and DstATop would also work). We also fall into the dst read case for src-over if we
    818             // do not have dual source blending.
    819             if (SkBlendMode::kSrcOver != mode ||
    820                 /*!color.isOpaque() ||*/ // See comment in MakeSrcOverXferProcessor about isOpaque.
    821                 (formula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport())) {
    822                 props |= AnalysisProperties::kReadsDstInShader;
    823             }
    824         }
    825     } else {
    826         // With dual-source blending we never need the destination color in the shader.
    827         if (!caps.shaderCaps()->dualSourceBlendingSupport()) {
    828             // Mixed samples implicity computes a fractional coverage from sample coverage. This
    829             // could affect the formula used. However, we don't expect to have mixed samples without
    830             // dual source blending.
    831             SkASSERT(!caps.usesMixedSamples());
    832             if (formula.hasSecondaryOutput()) {
    833                 props |= AnalysisProperties::kReadsDstInShader;
    834             }
    835         }
    836     }
    837 
    838     if (!formula.modifiesDst() || !formula.usesInputColor()) {
    839         props |= AnalysisProperties::kIgnoresInputColor;
    840     }
    841     return props;
    842 }
    843 
    844 GrXPFactory::AnalysisProperties GrPorterDuffXPFactory::analysisProperties(
    845         const GrProcessorAnalysisColor& color,
    846         const GrProcessorAnalysisCoverage& coverage,
    847         const GrCaps& caps) const {
    848     return analysis_properties(color, coverage, caps, fBlendMode);
    849 }
    850 
    851 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory);
    852 
    853 #if GR_TEST_UTILS
    854 const GrXPFactory* GrPorterDuffXPFactory::TestGet(GrProcessorTestData* d) {
    855     SkBlendMode mode = SkBlendMode(d->fRandom->nextULessThan((int)SkBlendMode::kLastCoeffMode));
    856     return GrPorterDuffXPFactory::Get(mode);
    857 }
    858 #endif
    859 
    860 void GrPorterDuffXPFactory::TestGetXPOutputTypes(const GrXferProcessor* xp,
    861                                                  int* outPrimary,
    862                                                  int* outSecondary) {
    863     if (!!strcmp(xp->name(), "Porter Duff")) {
    864         *outPrimary = *outSecondary = -1;
    865         return;
    866     }
    867     BlendFormula blendFormula = static_cast<const PorterDuffXferProcessor*>(xp)->getBlendFormula();
    868     *outPrimary = blendFormula.primaryOutput();
    869     *outSecondary = blendFormula.secondaryOutput();
    870 }
    871 
    872 ////////////////////////////////////////////////////////////////////////////////////////////////
    873 // SrcOver Global functions
    874 ////////////////////////////////////////////////////////////////////////////////////////////////
    875 const GrXferProcessor& GrPorterDuffXPFactory::SimpleSrcOverXP() {
    876     static BlendFormula gSrcOverBlendFormula =
    877             MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff);
    878     static PorterDuffXferProcessor gSrcOverXP(gSrcOverBlendFormula,
    879                                               GrProcessorAnalysisCoverage::kSingleChannel);
    880     return gSrcOverXP;
    881 }
    882 
    883 sk_sp<const GrXferProcessor> GrPorterDuffXPFactory::MakeSrcOverXferProcessor(
    884         const GrProcessorAnalysisColor& color, GrProcessorAnalysisCoverage coverage,
    885         bool hasMixedSamples, const GrCaps& caps) {
    886     // We want to not make an xfer processor if possible. Thus for the simple case where we are not
    887     // doing lcd blending we will just use our global SimpleSrcOverXP. This slightly differs from
    888     // the general case where we convert a src-over blend that has solid coverage and an opaque
    889     // color to src-mode, which allows disabling of blending.
    890     if (coverage != GrProcessorAnalysisCoverage::kLCD) {
    891         // We return nullptr here, which our caller interprets as meaning "use SimpleSrcOverXP".
    892         // We don't simply return the address of that XP here because our caller would have to unref
    893         // it and since it is a global object and GrProgramElement's ref-cnting system is not thread
    894         // safe.
    895         return nullptr;
    896     }
    897 
    898     // Currently up the stack Skia is requiring that the dst is opaque or that the client has said
    899     // the opaqueness doesn't matter. Thus for src-over we don't need to worry about the src color
    900     // being opaque or not. This allows us to use faster code paths as well as avoid various bugs
    901     // that occur with dst reads in the shader blending. For now we disable the check for
    902     // opaqueness, but in the future we should pass down the knowledge about dst opaqueness and make
    903     // the correct decision here.
    904     //
    905     // This also fixes a chrome bug on macs where we are getting random fuzziness when doing
    906     // blending in the shader for non opaque sources.
    907     if (color.isConstant() && /*color.isOpaque() &&*/
    908         !caps.shaderCaps()->dualSourceBlendingSupport() &&
    909         !caps.shaderCaps()->dstReadInShaderSupport()) {
    910         // If we don't have dual source blending or in shader dst reads, we fall
    911         // back to this trick for rendering SrcOver LCD text instead of doing a
    912         // dst copy.
    913         return PDLCDXferProcessor::Make(SkBlendMode::kSrcOver, color);
    914     }
    915 
    916     BlendFormula blendFormula;
    917     blendFormula = get_lcd_blend_formula(SkBlendMode::kSrcOver);
    918     // See comment above regarding why the opaque check is commented out here.
    919     if (/*!color.isOpaque() ||*/
    920         (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport())) {
    921         return sk_sp<GrXferProcessor>(
    922                 new ShaderPDXferProcessor(hasMixedSamples, SkBlendMode::kSrcOver, coverage));
    923     }
    924     return sk_sp<GrXferProcessor>(new PorterDuffXferProcessor(blendFormula, coverage));
    925 }
    926 
    927 sk_sp<const GrXferProcessor> GrPorterDuffXPFactory::MakeNoCoverageXP(SkBlendMode blendmode) {
    928     BlendFormula formula = get_blend_formula(false, false, false, blendmode);
    929     return sk_make_sp<PorterDuffXferProcessor>(formula, GrProcessorAnalysisCoverage::kNone);
    930 }
    931 
    932 GrXPFactory::AnalysisProperties GrPorterDuffXPFactory::SrcOverAnalysisProperties(
    933         const GrProcessorAnalysisColor& color,
    934         const GrProcessorAnalysisCoverage& coverage,
    935         const GrCaps& caps) {
    936     return analysis_properties(color, coverage, caps, SkBlendMode::kSrcOver);
    937 }
    938