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