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