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