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