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