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 "GrPipelineAnalysis.h"
14 #include "GrProcessor.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 
operator =BlendFormula52     BlendFormula& operator =(const BlendFormula& other) {
53         fData = other.fData;
54         return *this;
55     }
56 
operator ==BlendFormula57     bool operator ==(const BlendFormula& other) const {
58         return fData == other.fData;
59     }
60 
hasSecondaryOutputBlendFormula61     bool hasSecondaryOutput() const { return kNone_OutputType != fSecondaryOutputType; }
modifiesDstBlendFormula62     bool modifiesDst() const { return SkToBool(fProps & kModifiesDst_Property); }
usesDstColorBlendFormula63     bool usesDstColor() const { return SkToBool(fProps & kUsesDstColor_Property); }
usesInputColorBlendFormula64     bool usesInputColor() const { return SkToBool(fProps & kUsesInputColor_Property); }
canTweakAlphaForCoverageBlendFormula65     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 : std::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][(int)SkBlendMode::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[(int)SkBlendMode::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 
get_blend_formula(bool isOpaque,bool hasCoverage,bool hasMixedSamples,SkBlendMode xfermode)322 static BlendFormula get_blend_formula(bool isOpaque,
323                                       bool hasCoverage,
324                                       bool hasMixedSamples,
325                                       SkBlendMode xfermode) {
326     SkASSERT((unsigned)xfermode <= (unsigned)SkBlendMode::kLastCoeffMode);
327     bool conflatesCoverage = hasCoverage || hasMixedSamples;
328     return gBlendTable[isOpaque][conflatesCoverage][(int)xfermode];
329 }
330 
get_lcd_blend_formula(SkBlendMode xfermode)331 static BlendFormula get_lcd_blend_formula(SkBlendMode xfermode) {
332     SkASSERT((unsigned)xfermode <= (unsigned)SkBlendMode::kLastCoeffMode);
333 
334     return gLCDBlendTable[(int)xfermode];
335 }
336 
337 ///////////////////////////////////////////////////////////////////////////////
338 
339 class PorterDuffXferProcessor : public GrXferProcessor {
340 public:
PorterDuffXferProcessor(BlendFormula blendFormula)341     PorterDuffXferProcessor(BlendFormula blendFormula) : fBlendFormula(blendFormula) {
342         this->initClassID<PorterDuffXferProcessor>();
343     }
344 
name() const345     const char* name() const override { return "Porter Duff"; }
346 
347     GrGLSLXferProcessor* createGLSLInstance() const override;
348 
getBlendFormula() const349     BlendFormula getBlendFormula() const { return fBlendFormula; }
350 
351 private:
352     GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&) const override;
353 
354     void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
355 
onHasSecondaryOutput() const356     bool onHasSecondaryOutput() const override { return fBlendFormula.hasSecondaryOutput(); }
357 
onGetBlendInfo(GrXferProcessor::BlendInfo * blendInfo) const358     void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override {
359         blendInfo->fEquation = fBlendFormula.fBlendEquation;
360         blendInfo->fSrcBlend = fBlendFormula.fSrcCoeff;
361         blendInfo->fDstBlend = fBlendFormula.fDstCoeff;
362         blendInfo->fWriteColor = fBlendFormula.modifiesDst();
363     }
364 
onIsEqual(const GrXferProcessor & xpBase) const365     bool onIsEqual(const GrXferProcessor& xpBase) const override {
366         const PorterDuffXferProcessor& xp = xpBase.cast<PorterDuffXferProcessor>();
367         return fBlendFormula == xp.fBlendFormula;
368     }
369 
370     const BlendFormula fBlendFormula;
371 
372     typedef GrXferProcessor INHERITED;
373 };
374 
375 ///////////////////////////////////////////////////////////////////////////////
376 
append_color_output(const PorterDuffXferProcessor & xp,GrGLSLXPFragmentBuilder * fragBuilder,BlendFormula::OutputType outputType,const char * output,const char * inColor,const char * inCoverage)377 static void append_color_output(const PorterDuffXferProcessor& xp,
378                                 GrGLSLXPFragmentBuilder* fragBuilder,
379                                 BlendFormula::OutputType outputType, const char* output,
380                                 const char* inColor, const char* inCoverage) {
381     SkASSERT(inCoverage);
382     SkASSERT(inColor);
383     switch (outputType) {
384         case BlendFormula::kNone_OutputType:
385             fragBuilder->codeAppendf("%s = vec4(0.0);", output);
386             break;
387         case BlendFormula::kCoverage_OutputType:
388             // We can have a coverage formula while not reading coverage if there are mixed samples.
389             fragBuilder->codeAppendf("%s = %s;", output, inCoverage);
390             break;
391         case BlendFormula::kModulate_OutputType:
392             fragBuilder->codeAppendf("%s = %s * %s;", output, inColor, inCoverage);
393             break;
394         case BlendFormula::kSAModulate_OutputType:
395             fragBuilder->codeAppendf("%s = %s.a * %s;", output, inColor, inCoverage);
396             break;
397         case BlendFormula::kISAModulate_OutputType:
398             fragBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", output, inColor, inCoverage);
399             break;
400         case BlendFormula::kISCModulate_OutputType:
401             fragBuilder->codeAppendf("%s = (vec4(1.0) - %s) * %s;", output, inColor, inCoverage);
402             break;
403         default:
404             SkFAIL("Unsupported output type.");
405             break;
406     }
407 }
408 
409 class GLPorterDuffXferProcessor : public GrGLSLXferProcessor {
410 public:
GenKey(const GrProcessor & processor,GrProcessorKeyBuilder * b)411     static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) {
412         const PorterDuffXferProcessor& xp = processor.cast<PorterDuffXferProcessor>();
413         b->add32(xp.getBlendFormula().fPrimaryOutputType |
414                  (xp.getBlendFormula().fSecondaryOutputType << 3));
415         GR_STATIC_ASSERT(BlendFormula::kLast_OutputType < 8);
416     }
417 
418 private:
emitOutputsForBlendState(const EmitArgs & args)419     void emitOutputsForBlendState(const EmitArgs& args) override {
420         const PorterDuffXferProcessor& xp = args.fXP.cast<PorterDuffXferProcessor>();
421         GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
422 
423         BlendFormula blendFormula = xp.getBlendFormula();
424         if (blendFormula.hasSecondaryOutput()) {
425             append_color_output(xp, fragBuilder, blendFormula.fSecondaryOutputType,
426                                 args.fOutputSecondary, args.fInputColor, args.fInputCoverage);
427         }
428         append_color_output(xp, fragBuilder, blendFormula.fPrimaryOutputType,
429                             args.fOutputPrimary, args.fInputColor, args.fInputCoverage);
430     }
431 
onSetData(const GrGLSLProgramDataManager &,const GrXferProcessor &)432     void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
433 
434     typedef GrGLSLXferProcessor INHERITED;
435 };
436 
437 ///////////////////////////////////////////////////////////////////////////////
438 
onGetGLSLProcessorKey(const GrShaderCaps &,GrProcessorKeyBuilder * b) const439 void PorterDuffXferProcessor::onGetGLSLProcessorKey(const GrShaderCaps&,
440                                                     GrProcessorKeyBuilder* b) const {
441     GLPorterDuffXferProcessor::GenKey(*this, b);
442 }
443 
createGLSLInstance() const444 GrGLSLXferProcessor* PorterDuffXferProcessor::createGLSLInstance() const {
445     return new GLPorterDuffXferProcessor;
446 }
447 
onGetOptimizations(const FragmentProcessorAnalysis & analysis) const448 GrXferProcessor::OptFlags PorterDuffXferProcessor::onGetOptimizations(
449         const FragmentProcessorAnalysis& analysis) const {
450     GrXferProcessor::OptFlags optFlags = GrXferProcessor::kNone_OptFlags;
451     if (!fBlendFormula.modifiesDst()) {
452         optFlags |= (GrXferProcessor::kIgnoreColor_OptFlag |
453                      GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag);
454     } else {
455         if (!fBlendFormula.usesInputColor()) {
456             optFlags |= GrXferProcessor::kIgnoreColor_OptFlag;
457         }
458         if (analysis.isCompatibleWithCoverageAsAlpha() &&
459             fBlendFormula.canTweakAlphaForCoverage()) {
460             optFlags |= GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag;
461         }
462     }
463     return optFlags;
464 }
465 
466 ///////////////////////////////////////////////////////////////////////////////
467 
468 class ShaderPDXferProcessor : public GrXferProcessor {
469 public:
ShaderPDXferProcessor(const DstTexture * dstTexture,bool hasMixedSamples,SkBlendMode xfermode)470     ShaderPDXferProcessor(const DstTexture* dstTexture,
471                           bool hasMixedSamples,
472                           SkBlendMode xfermode)
473         : INHERITED(dstTexture, true, hasMixedSamples)
474         , fXfermode(xfermode) {
475         this->initClassID<ShaderPDXferProcessor>();
476     }
477 
name() const478     const char* name() const override { return "Porter Duff Shader"; }
479 
480     GrGLSLXferProcessor* createGLSLInstance() const override;
481 
getXfermode() const482     SkBlendMode getXfermode() const { return fXfermode; }
483 
484 private:
onGetOptimizations(const FragmentProcessorAnalysis &) const485     GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&) const override {
486         return kNone_OptFlags;
487     }
488 
489     void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
490 
onIsEqual(const GrXferProcessor & xpBase) const491     bool onIsEqual(const GrXferProcessor& xpBase) const override {
492         const ShaderPDXferProcessor& xp = xpBase.cast<ShaderPDXferProcessor>();
493         return fXfermode == xp.fXfermode;
494     }
495 
496     const SkBlendMode fXfermode;
497 
498     typedef GrXferProcessor INHERITED;
499 };
500 
501 ///////////////////////////////////////////////////////////////////////////////
502 
503 class GLShaderPDXferProcessor : public GrGLSLXferProcessor {
504 public:
GenKey(const GrProcessor & processor,GrProcessorKeyBuilder * b)505     static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) {
506         const ShaderPDXferProcessor& xp = processor.cast<ShaderPDXferProcessor>();
507         b->add32((int)xp.getXfermode());
508     }
509 
510 private:
emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder * fragBuilder,GrGLSLUniformHandler * uniformHandler,const char * srcColor,const char * srcCoverage,const char * dstColor,const char * outColor,const char * outColorSecondary,const GrXferProcessor & proc)511     void emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder* fragBuilder,
512                                  GrGLSLUniformHandler* uniformHandler,
513                                  const char* srcColor,
514                                  const char* srcCoverage,
515                                  const char* dstColor,
516                                  const char* outColor,
517                                  const char* outColorSecondary,
518                                  const GrXferProcessor& proc) override {
519         const ShaderPDXferProcessor& xp = proc.cast<ShaderPDXferProcessor>();
520 
521         GrGLSLBlend::AppendMode(fragBuilder, srcColor, dstColor, outColor, xp.getXfermode());
522 
523         // Apply coverage.
524         INHERITED::DefaultCoverageModulation(fragBuilder, srcCoverage, dstColor, outColor,
525                                              outColorSecondary, xp);
526     }
527 
onSetData(const GrGLSLProgramDataManager &,const GrXferProcessor &)528     void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
529 
530     typedef GrGLSLXferProcessor INHERITED;
531 };
532 
533 ///////////////////////////////////////////////////////////////////////////////
534 
onGetGLSLProcessorKey(const GrShaderCaps &,GrProcessorKeyBuilder * b) const535 void ShaderPDXferProcessor::onGetGLSLProcessorKey(const GrShaderCaps&,
536                                                   GrProcessorKeyBuilder* b) const {
537     GLShaderPDXferProcessor::GenKey(*this, b);
538 }
539 
createGLSLInstance() const540 GrGLSLXferProcessor* ShaderPDXferProcessor::createGLSLInstance() const {
541     return new GLShaderPDXferProcessor;
542 }
543 
544 ///////////////////////////////////////////////////////////////////////////////
545 
546 class PDLCDXferProcessor : public GrXferProcessor {
547 public:
548     static GrXferProcessor* Create(SkBlendMode xfermode, const FragmentProcessorAnalysis& analysis);
549 
550     ~PDLCDXferProcessor() override;
551 
name() const552     const char* name() const override { return "Porter Duff LCD"; }
553 
554     GrGLSLXferProcessor* createGLSLInstance() const override;
555 
alpha() const556     uint8_t alpha() const { return fAlpha; }
557 
558 private:
559     PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha);
560 
561     GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&) const override;
562 
563     void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
564 
onGetBlendInfo(GrXferProcessor::BlendInfo * blendInfo) const565     void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override {
566         blendInfo->fSrcBlend = kConstC_GrBlendCoeff;
567         blendInfo->fDstBlend = kISC_GrBlendCoeff;
568         blendInfo->fBlendConstant = fBlendConstant;
569     }
570 
onIsEqual(const GrXferProcessor & xpBase) const571     bool onIsEqual(const GrXferProcessor& xpBase) const override {
572         const PDLCDXferProcessor& xp = xpBase.cast<PDLCDXferProcessor>();
573         if (fBlendConstant != xp.fBlendConstant || fAlpha != xp.fAlpha) {
574             return false;
575         }
576         return true;
577     }
578 
579     GrColor fBlendConstant;
580     uint8_t fAlpha;
581 
582     typedef GrXferProcessor INHERITED;
583 };
584 
585 ///////////////////////////////////////////////////////////////////////////////
586 
587 class GLPDLCDXferProcessor : public GrGLSLXferProcessor {
588 public:
GLPDLCDXferProcessor(const GrProcessor &)589     GLPDLCDXferProcessor(const GrProcessor&) : fLastAlpha(SK_MaxU32) {}
590 
~GLPDLCDXferProcessor()591     ~GLPDLCDXferProcessor() override {}
592 
GenKey(const GrProcessor & processor,const GrShaderCaps & caps,GrProcessorKeyBuilder * b)593     static void GenKey(const GrProcessor& processor, const GrShaderCaps& caps,
594                        GrProcessorKeyBuilder* b) {}
595 
596 private:
emitOutputsForBlendState(const EmitArgs & args)597     void emitOutputsForBlendState(const EmitArgs& args) override {
598         const char* alpha;
599         fAlphaUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat_GrSLType,
600                                                          kDefault_GrSLPrecision, "alpha", &alpha);
601         GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
602         // We want to force our primary output to be alpha * Coverage, where alpha is the alpha
603         // value of the src color. We know that there are no color stages (or we wouldn't have
604         // created this xp) and the r,g, and b channels of the op's input color are baked into the
605         // blend constant.
606         SkASSERT(args.fInputCoverage);
607         fragBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, alpha, args.fInputCoverage);
608     }
609 
onSetData(const GrGLSLProgramDataManager & pdm,const GrXferProcessor & xp)610     void onSetData(const GrGLSLProgramDataManager& pdm, const GrXferProcessor& xp) override {
611         uint32_t alpha = SkToU32(xp.cast<PDLCDXferProcessor>().alpha());
612         if (fLastAlpha != alpha) {
613             pdm.set1f(fAlphaUniform, alpha / 255.f);
614             fLastAlpha = alpha;
615         }
616     }
617 
618     GrGLSLUniformHandler::UniformHandle fAlphaUniform;
619     uint32_t fLastAlpha;
620     typedef GrGLSLXferProcessor INHERITED;
621 };
622 
623 ///////////////////////////////////////////////////////////////////////////////
624 
PDLCDXferProcessor(GrColor blendConstant,uint8_t alpha)625 PDLCDXferProcessor::PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha)
626     : fBlendConstant(blendConstant)
627     , fAlpha(alpha) {
628     this->initClassID<PDLCDXferProcessor>();
629 }
630 
Create(SkBlendMode xfermode,const FragmentProcessorAnalysis & analysis)631 GrXferProcessor* PDLCDXferProcessor::Create(SkBlendMode xfermode,
632                                             const FragmentProcessorAnalysis& analysis) {
633     if (SkBlendMode::kSrcOver != xfermode) {
634         return nullptr;
635     }
636     GrColor blendConstant;
637     if (!analysis.hasKnownOutputColor(&blendConstant)) {
638         return nullptr;
639     }
640     blendConstant = GrUnpremulColor(blendConstant);
641     uint8_t alpha = GrColorUnpackA(blendConstant);
642     blendConstant |= (0xff << GrColor_SHIFT_A);
643     return new PDLCDXferProcessor(blendConstant, alpha);
644 }
645 
~PDLCDXferProcessor()646 PDLCDXferProcessor::~PDLCDXferProcessor() {
647 }
648 
onGetGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const649 void PDLCDXferProcessor::onGetGLSLProcessorKey(const GrShaderCaps& caps,
650                                                GrProcessorKeyBuilder* b) const {
651     GLPDLCDXferProcessor::GenKey(*this, caps, b);
652 }
653 
createGLSLInstance() const654 GrGLSLXferProcessor* PDLCDXferProcessor::createGLSLInstance() const {
655     return new GLPDLCDXferProcessor(*this);
656 }
657 
onGetOptimizations(const FragmentProcessorAnalysis &) const658 GrXferProcessor::OptFlags PDLCDXferProcessor::onGetOptimizations(
659         const FragmentProcessorAnalysis&) const {
660     return GrXferProcessor::kIgnoreColor_OptFlag;
661 }
662 
663 ///////////////////////////////////////////////////////////////////////////////
664 
GrPorterDuffXPFactory(SkBlendMode xfermode)665 constexpr GrPorterDuffXPFactory::GrPorterDuffXPFactory(SkBlendMode xfermode)
666         : fBlendMode(xfermode) {}
667 
Get(SkBlendMode blendMode)668 const GrXPFactory* GrPorterDuffXPFactory::Get(SkBlendMode blendMode) {
669     SkASSERT((unsigned)blendMode <= (unsigned)SkBlendMode::kLastCoeffMode);
670 
671     // If these objects are constructed as static constexpr by cl.exe (2015 SP2) the vtables are
672     // null.
673 #ifdef SK_BUILD_FOR_WIN
674 #define _CONSTEXPR_
675 #else
676 #define _CONSTEXPR_ constexpr
677 #endif
678     static _CONSTEXPR_ const GrPorterDuffXPFactory gClearPDXPF(SkBlendMode::kClear);
679     static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcPDXPF(SkBlendMode::kSrc);
680     static _CONSTEXPR_ const GrPorterDuffXPFactory gDstPDXPF(SkBlendMode::kDst);
681     static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcOverPDXPF(SkBlendMode::kSrcOver);
682     static _CONSTEXPR_ const GrPorterDuffXPFactory gDstOverPDXPF(SkBlendMode::kDstOver);
683     static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcInPDXPF(SkBlendMode::kSrcIn);
684     static _CONSTEXPR_ const GrPorterDuffXPFactory gDstInPDXPF(SkBlendMode::kDstIn);
685     static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcOutPDXPF(SkBlendMode::kSrcOut);
686     static _CONSTEXPR_ const GrPorterDuffXPFactory gDstOutPDXPF(SkBlendMode::kDstOut);
687     static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcATopPDXPF(SkBlendMode::kSrcATop);
688     static _CONSTEXPR_ const GrPorterDuffXPFactory gDstATopPDXPF(SkBlendMode::kDstATop);
689     static _CONSTEXPR_ const GrPorterDuffXPFactory gXorPDXPF(SkBlendMode::kXor);
690     static _CONSTEXPR_ const GrPorterDuffXPFactory gPlusPDXPF(SkBlendMode::kPlus);
691     static _CONSTEXPR_ const GrPorterDuffXPFactory gModulatePDXPF(SkBlendMode::kModulate);
692     static _CONSTEXPR_ const GrPorterDuffXPFactory gScreenPDXPF(SkBlendMode::kScreen);
693 #undef _CONSTEXPR_
694 
695     switch (blendMode) {
696         case SkBlendMode::kClear:
697             return &gClearPDXPF;
698         case SkBlendMode::kSrc:
699             return &gSrcPDXPF;
700         case SkBlendMode::kDst:
701             return &gDstPDXPF;
702         case SkBlendMode::kSrcOver:
703             return &gSrcOverPDXPF;
704         case SkBlendMode::kDstOver:
705             return &gDstOverPDXPF;
706         case SkBlendMode::kSrcIn:
707             return &gSrcInPDXPF;
708         case SkBlendMode::kDstIn:
709             return &gDstInPDXPF;
710         case SkBlendMode::kSrcOut:
711             return &gSrcOutPDXPF;
712         case SkBlendMode::kDstOut:
713             return &gDstOutPDXPF;
714         case SkBlendMode::kSrcATop:
715             return &gSrcATopPDXPF;
716         case SkBlendMode::kDstATop:
717             return &gDstATopPDXPF;
718         case SkBlendMode::kXor:
719             return &gXorPDXPF;
720         case SkBlendMode::kPlus:
721             return &gPlusPDXPF;
722         case SkBlendMode::kModulate:
723             return &gModulatePDXPF;
724         case SkBlendMode::kScreen:
725             return &gScreenPDXPF;
726         default:
727             SkFAIL("Unexpected blend mode.");
728             return nullptr;
729     }
730 }
731 
onCreateXferProcessor(const GrCaps & caps,const FragmentProcessorAnalysis & analysis,bool hasMixedSamples,const DstTexture * dstTexture) const732 GrXferProcessor* GrPorterDuffXPFactory::onCreateXferProcessor(
733         const GrCaps& caps,
734         const FragmentProcessorAnalysis& analysis,
735         bool hasMixedSamples,
736         const DstTexture* dstTexture) const {
737     BlendFormula blendFormula;
738     if (analysis.outputCoverageType() == GrPipelineAnalysisCoverage::kLCD) {
739         if (SkBlendMode::kSrcOver == fBlendMode && analysis.hasKnownOutputColor() &&
740             !caps.shaderCaps()->dualSourceBlendingSupport() &&
741             !caps.shaderCaps()->dstReadInShaderSupport()) {
742             // If we don't have dual source blending or in shader dst reads, we fall back to this
743             // trick for rendering SrcOver LCD text instead of doing a dst copy.
744             SkASSERT(!dstTexture || !dstTexture->texture());
745             return PDLCDXferProcessor::Create(fBlendMode, analysis);
746         }
747         blendFormula = get_lcd_blend_formula(fBlendMode);
748     } else {
749         blendFormula = get_blend_formula(analysis.isOutputColorOpaque(), analysis.hasCoverage(),
750                                          hasMixedSamples, fBlendMode);
751     }
752 
753     if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) {
754         return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, fBlendMode);
755     }
756 
757     SkASSERT(!dstTexture || !dstTexture->texture());
758     return new PorterDuffXferProcessor(blendFormula);
759 }
760 
canCombineOverlappedStencilAndCover(bool colorIsOpaque) const761 bool GrPorterDuffXPFactory::canCombineOverlappedStencilAndCover(bool colorIsOpaque) const {
762     // Ignore the effect of coverage here.
763     BlendFormula colorFormula = gBlendTable[colorIsOpaque][0][(int)fBlendMode];
764     SkASSERT(kAdd_GrBlendEquation == colorFormula.fBlendEquation);
765     return !colorFormula.usesDstColor();
766 }
767 
willReadDstInShader(const GrCaps & caps,const FragmentProcessorAnalysis & analysis) const768 bool GrPorterDuffXPFactory::willReadDstInShader(const GrCaps& caps,
769                                                 const FragmentProcessorAnalysis& analysis) const {
770     if (caps.shaderCaps()->dualSourceBlendingSupport()) {
771         return false;
772     }
773 
774     // When we have four channel coverage we always need to read the dst in order to correctly
775     // blend. The one exception is when we are using srcover mode and we know the input color into
776     // the XP.
777     if (analysis.outputCoverageType() == GrPipelineAnalysisCoverage::kLCD) {
778         if (SkBlendMode::kSrcOver == fBlendMode && analysis.hasKnownOutputColor() &&
779             !caps.shaderCaps()->dstReadInShaderSupport()) {
780             return false;
781         }
782         return get_lcd_blend_formula(fBlendMode).hasSecondaryOutput();
783     }
784 
785     // We fallback on the shader XP when the blend formula would use dual source blending but we
786     // don't have support for it.
787     static const bool kHasMixedSamples = false;
788     SkASSERT(!caps.usesMixedSamples()); // We never use mixed samples without dual source blending.
789     auto formula = get_blend_formula(analysis.isOutputColorOpaque(), analysis.hasCoverage(),
790                                      kHasMixedSamples, fBlendMode);
791     return formula.hasSecondaryOutput();
792 }
793 
compatibleWithCoverageAsAlpha(bool colorIsOpaque) const794 bool GrPorterDuffXPFactory::compatibleWithCoverageAsAlpha(bool colorIsOpaque) const {
795     // We assume we have coverage (or else this doesn't matter).
796     return gBlendTable[colorIsOpaque][1][(int)fBlendMode].canTweakAlphaForCoverage();
797 }
798 
799 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory);
800 
801 #if GR_TEST_UTILS
TestGet(GrProcessorTestData * d)802 const GrXPFactory* GrPorterDuffXPFactory::TestGet(GrProcessorTestData* d) {
803     SkBlendMode mode = SkBlendMode(d->fRandom->nextULessThan((int)SkBlendMode::kLastCoeffMode));
804     return GrPorterDuffXPFactory::Get(mode);
805 }
806 #endif
807 
TestGetXPOutputTypes(const GrXferProcessor * xp,int * outPrimary,int * outSecondary)808 void GrPorterDuffXPFactory::TestGetXPOutputTypes(const GrXferProcessor* xp,
809                                                  int* outPrimary,
810                                                  int* outSecondary) {
811     if (!!strcmp(xp->name(), "Porter Duff")) {
812         *outPrimary = *outSecondary = -1;
813         return;
814     }
815     BlendFormula blendFormula = static_cast<const PorterDuffXferProcessor*>(xp)->getBlendFormula();
816     *outPrimary = blendFormula.fPrimaryOutputType;
817     *outSecondary = blendFormula.fSecondaryOutputType;
818 }
819 
820 ////////////////////////////////////////////////////////////////////////////////////////////////
821 // SrcOver Global functions
822 ////////////////////////////////////////////////////////////////////////////////////////////////
SimpleSrcOverXP()823 const GrXferProcessor& GrPorterDuffXPFactory::SimpleSrcOverXP() {
824     static BlendFormula gSrcOverBlendFormula = COEFF_FORMULA(kOne_GrBlendCoeff,
825                                                              kISA_GrBlendCoeff);
826     static PorterDuffXferProcessor gSrcOverXP(gSrcOverBlendFormula);
827     return gSrcOverXP;
828 }
829 
CreateSrcOverXferProcessor(const GrCaps & caps,const FragmentProcessorAnalysis & analysis,bool hasMixedSamples,const GrXferProcessor::DstTexture * dstTexture)830 GrXferProcessor* GrPorterDuffXPFactory::CreateSrcOverXferProcessor(
831         const GrCaps& caps,
832         const FragmentProcessorAnalysis& analysis,
833         bool hasMixedSamples,
834         const GrXferProcessor::DstTexture* dstTexture) {
835 
836     // We want to not make an xfer processor if possible. Thus for the simple case where we are not
837     // doing lcd blending we will just use our global SimpleSrcOverXP. This slightly differs from
838     // the general case where we convert a src-over blend that has solid coverage and an opaque
839     // color to src-mode, which allows disabling of blending.
840     if (analysis.outputCoverageType() != GrPipelineAnalysisCoverage::kLCD) {
841         // We return nullptr here, which our caller interprets as meaning "use SimpleSrcOverXP".
842         // We don't simply return the address of that XP here because our caller would have to unref
843         // it and since it is a global object and GrProgramElement's ref-cnting system is not thread
844         // safe.
845         return nullptr;
846     }
847 
848     if (analysis.hasKnownOutputColor() && !caps.shaderCaps()->dualSourceBlendingSupport() &&
849         !caps.shaderCaps()->dstReadInShaderSupport()) {
850         // If we don't have dual source blending or in shader dst reads, we fall
851         // back to this trick for rendering SrcOver LCD text instead of doing a
852         // dst copy.
853         SkASSERT(!dstTexture || !dstTexture->texture());
854         return PDLCDXferProcessor::Create(SkBlendMode::kSrcOver, analysis);
855     }
856 
857     BlendFormula blendFormula;
858     blendFormula = get_lcd_blend_formula(SkBlendMode::kSrcOver);
859     if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) {
860         return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, SkBlendMode::kSrcOver);
861     }
862 
863     SkASSERT(!dstTexture || !dstTexture->texture());
864     return new PorterDuffXferProcessor(blendFormula);
865 }
866 
CreateNoCoverageXP(SkBlendMode blendmode)867 sk_sp<GrXferProcessor> GrPorterDuffXPFactory::CreateNoCoverageXP(SkBlendMode blendmode) {
868     BlendFormula formula = get_blend_formula(false, false, false, blendmode);
869     return sk_make_sp<PorterDuffXferProcessor>(formula);
870 }
871 
WillSrcOverNeedDstTexture(const GrCaps & caps,const FragmentProcessorAnalysis & analysis)872 bool GrPorterDuffXPFactory::WillSrcOverNeedDstTexture(const GrCaps& caps,
873                                                       const FragmentProcessorAnalysis& analysis) {
874     if (caps.shaderCaps()->dstReadInShaderSupport() ||
875         caps.shaderCaps()->dualSourceBlendingSupport()) {
876         return false;
877     }
878 
879     // When we have four channel coverage we always need to read the dst in order to correctly
880     // blend. The one exception is when we are using srcover mode and we know the input color
881     // into the XP.
882     if (analysis.outputCoverageType() == GrPipelineAnalysisCoverage::kLCD) {
883         if (analysis.hasKnownOutputColor() && !caps.shaderCaps()->dstReadInShaderSupport()) {
884             return false;
885         }
886         auto formula = get_lcd_blend_formula(SkBlendMode::kSrcOver);
887         return formula.hasSecondaryOutput();
888     }
889 
890     // We fallback on the shader XP when the blend formula would use dual source blending but we
891     // don't have support for it.
892     static const bool kHasMixedSamples = false;
893     bool isOpaque = analysis.isOutputColorOpaque();
894     bool hasCoverage = analysis.hasCoverage();
895     SkASSERT(!caps.usesMixedSamples()); // We never use mixed samples without dual source blending.
896     auto formula =
897             get_blend_formula(isOpaque, hasCoverage, kHasMixedSamples, SkBlendMode::kSrcOver);
898     return formula.hasSecondaryOutput();
899 }
900