1 /*
2  * Copyright 2014 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "effects/GrPorterDuffXferProcessor.h"
9 
10 #include "GrBlend.h"
11 #include "GrCaps.h"
12 #include "GrPipeline.h"
13 #include "GrProcessor.h"
14 #include "GrProcOptInfo.h"
15 #include "GrTypes.h"
16 #include "GrXferProcessor.h"
17 #include "glsl/GrGLSLBlend.h"
18 #include "glsl/GrGLSLFragmentShaderBuilder.h"
19 #include "glsl/GrGLSLProgramDataManager.h"
20 #include "glsl/GrGLSLUniformHandler.h"
21 #include "glsl/GrGLSLXferProcessor.h"
22 #include <utility>
23 
24 /**
25  * Wraps the shader outputs and HW blend state that comprise a Porter Duff blend mode with coverage.
26  */
27 struct 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     enum Properties {
45         kModifiesDst_Property              = 1,
46         kUsesDstColor_Property             = 1 << 1,
47         kUsesInputColor_Property           = 1 << 2,
48         kCanTweakAlphaForCoverage_Property = 1 << 3,
49 
50         kLast_Property = kCanTweakAlphaForCoverage_Property
51     };
52 
operator =BlendFormula53     BlendFormula& operator =(const BlendFormula& other) {
54         fData = other.fData;
55         return *this;
56     }
57 
operator ==BlendFormula58     bool operator ==(const BlendFormula& other) const {
59         return fData == other.fData;
60     }
61 
hasSecondaryOutputBlendFormula62     bool hasSecondaryOutput() const { return kNone_OutputType != fSecondaryOutputType; }
modifiesDstBlendFormula63     bool modifiesDst() const { return SkToBool(fProps & kModifiesDst_Property); }
usesDstColorBlendFormula64     bool usesDstColor() const { return SkToBool(fProps & kUsesDstColor_Property); }
usesInputColorBlendFormula65     bool usesInputColor() const { return SkToBool(fProps & kUsesInputColor_Property); }
canTweakAlphaForCoverageBlendFormula66     bool canTweakAlphaForCoverage() const {
67         return SkToBool(fProps & kCanTweakAlphaForCoverage_Property);
68     }
69 
70     /**
71      * Deduce the properties of a compile-time constant BlendFormula.
72      */
73     template<OutputType PrimaryOut, OutputType SecondaryOut,
74              GrBlendEquation BlendEquation, GrBlendCoeff SrcCoeff, GrBlendCoeff DstCoeff>
75     struct get_properties : std::integral_constant<Properties, static_cast<Properties>(
76 
77         (GR_BLEND_MODIFIES_DST(BlendEquation, SrcCoeff, DstCoeff) ?
78             kModifiesDst_Property : 0) |
79 
80         (GR_BLEND_COEFFS_USE_DST_COLOR(SrcCoeff, DstCoeff) ?
81             kUsesDstColor_Property : 0) |
82 
83         ((PrimaryOut >= kModulate_OutputType && GR_BLEND_COEFFS_USE_SRC_COLOR(SrcCoeff,DstCoeff)) ||
84          (SecondaryOut >= kModulate_OutputType && GR_BLEND_COEFF_REFS_SRC2(DstCoeff)) ?
85             kUsesInputColor_Property : 0) |  // We assert later that SrcCoeff doesn't ref src2.
86 
87         (kModulate_OutputType == PrimaryOut &&
88          kNone_OutputType == SecondaryOut &&
89          GR_BLEND_CAN_TWEAK_ALPHA_FOR_COVERAGE(BlendEquation, SrcCoeff, DstCoeff) ?
90             kCanTweakAlphaForCoverage_Property : 0))> {
91 
92         // The provided formula should already be optimized.
93         GR_STATIC_ASSERT((kNone_OutputType == PrimaryOut) ==
94                          !GR_BLEND_COEFFS_USE_SRC_COLOR(SrcCoeff, DstCoeff));
95         GR_STATIC_ASSERT(!GR_BLEND_COEFF_REFS_SRC2(SrcCoeff));
96         GR_STATIC_ASSERT((kNone_OutputType == SecondaryOut) ==
97                          !GR_BLEND_COEFF_REFS_SRC2(DstCoeff));
98         GR_STATIC_ASSERT(PrimaryOut != SecondaryOut || kNone_OutputType == PrimaryOut);
99         GR_STATIC_ASSERT(kNone_OutputType != PrimaryOut || kNone_OutputType == SecondaryOut);
100     };
101 
102     union {
103         struct {
104             // We allot the enums one more bit than they require because MSVC seems to sign-extend
105             // them when the top bit is set. (This is in violation of the C++03 standard 9.6/4)
106             OutputType        fPrimaryOutputType    : 4;
107             OutputType        fSecondaryOutputType  : 4;
108             GrBlendEquation   fBlendEquation        : 6;
109             GrBlendCoeff      fSrcCoeff             : 6;
110             GrBlendCoeff      fDstCoeff             : 6;
111             Properties        fProps                : 32 - (4 + 4 + 6 + 6 + 6);
112         };
113         uint32_t fData;
114     };
115 
116     GR_STATIC_ASSERT(kLast_OutputType      < (1 << 3));
117     GR_STATIC_ASSERT(kLast_GrBlendEquation < (1 << 5));
118     GR_STATIC_ASSERT(kLast_GrBlendCoeff    < (1 << 5));
119     GR_STATIC_ASSERT(kLast_Property        < (1 << 6));
120 };
121 
122 GR_STATIC_ASSERT(4 == sizeof(BlendFormula));
123 
124 GR_MAKE_BITFIELD_OPS(BlendFormula::Properties);
125 
126 /**
127  * Initialize a compile-time constant BlendFormula and automatically deduce fProps.
128  */
129 #define INIT_BLEND_FORMULA(PRIMARY_OUT, SECONDARY_OUT, BLEND_EQUATION, SRC_COEFF, DST_COEFF) \
130     {{{PRIMARY_OUT, \
131        SECONDARY_OUT, \
132        BLEND_EQUATION, SRC_COEFF, DST_COEFF, \
133        BlendFormula::get_properties<PRIMARY_OUT, SECONDARY_OUT, \
134                                     BLEND_EQUATION, SRC_COEFF, DST_COEFF>::value}}}
135 
136 /**
137  * When there is no coverage, or the blend mode can tweak alpha for coverage, we use the standard
138  * Porter Duff formula.
139  */
140 #define COEFF_FORMULA(SRC_COEFF, DST_COEFF) \
141     INIT_BLEND_FORMULA(BlendFormula::kModulate_OutputType, \
142                        BlendFormula::kNone_OutputType, \
143                        kAdd_GrBlendEquation, SRC_COEFF, DST_COEFF)
144 
145 /**
146  * Basic coeff formula similar to COEFF_FORMULA but we will make the src f*Sa. This is used in
147  * LCD dst-out.
148  */
149 #define COEFF_FORMULA_SA_MODULATE(SRC_COEFF, DST_COEFF) \
150     INIT_BLEND_FORMULA(BlendFormula::kSAModulate_OutputType, \
151                        BlendFormula::kNone_OutputType, \
152                        kAdd_GrBlendEquation, SRC_COEFF, DST_COEFF)
153 
154 /**
155  * When the coeffs are (Zero, Zero), we clear the dst. This formula has its own macro so we can set
156  * the primary output type to none.
157  */
158 #define DST_CLEAR_FORMULA \
159     INIT_BLEND_FORMULA(BlendFormula::kNone_OutputType, \
160                        BlendFormula::kNone_OutputType, \
161                        kAdd_GrBlendEquation, kZero_GrBlendCoeff, kZero_GrBlendCoeff)
162 
163 /**
164  * When the coeffs are (Zero, One), we don't write to the dst at all. This formula has its own macro
165  * so we can set the primary output type to none.
166  */
167 #define NO_DST_WRITE_FORMULA \
168     INIT_BLEND_FORMULA(BlendFormula::kNone_OutputType, \
169                        BlendFormula::kNone_OutputType, \
170                        kAdd_GrBlendEquation, kZero_GrBlendCoeff, kOne_GrBlendCoeff)
171 
172 /**
173  * When there is coverage, the equation with f=coverage is:
174  *
175  *   D' = f * (S * srcCoeff + D * dstCoeff) + (1-f) * D
176  *
177  * This can be rewritten as:
178  *
179  *   D' = f * S * srcCoeff + D * (1 - [f * (1 - dstCoeff)])
180  *
181  * To implement this formula, we output [f * (1 - dstCoeff)] for the secondary color and replace the
182  * HW dst coeff with IS2C.
183  *
184  * Xfer modes: dst-atop (Sa!=1)
185  */
186 #define COVERAGE_FORMULA(ONE_MINUS_DST_COEFF_MODULATE_OUTPUT, SRC_COEFF) \
187     INIT_BLEND_FORMULA(BlendFormula::kModulate_OutputType, \
188                        ONE_MINUS_DST_COEFF_MODULATE_OUTPUT, \
189                        kAdd_GrBlendEquation, SRC_COEFF, kIS2C_GrBlendCoeff)
190 
191 /**
192  * When there is coverage and the src coeff is Zero, the equation with f=coverage becomes:
193  *
194  *   D' = f * D * dstCoeff + (1-f) * D
195  *
196  * This can be rewritten as:
197  *
198  *   D' = D - D * [f * (1 - dstCoeff)]
199  *
200  * To implement this formula, we output [f * (1 - dstCoeff)] for the primary color and use a reverse
201  * subtract HW blend equation with coeffs of (DC, One).
202  *
203  * Xfer modes: clear, dst-out (Sa=1), dst-in (Sa!=1), modulate (Sc!=1)
204  */
205 #define COVERAGE_SRC_COEFF_ZERO_FORMULA(ONE_MINUS_DST_COEFF_MODULATE_OUTPUT) \
206     INIT_BLEND_FORMULA(ONE_MINUS_DST_COEFF_MODULATE_OUTPUT, \
207                        BlendFormula::kNone_OutputType, \
208                        kReverseSubtract_GrBlendEquation, kDC_GrBlendCoeff, kOne_GrBlendCoeff)
209 
210 /**
211  * When there is coverage and the dst coeff is Zero, the equation with f=coverage becomes:
212  *
213  *   D' = f * S * srcCoeff + (1-f) * D
214  *
215  * To implement this formula, we output [f] for the secondary color and replace the HW dst coeff
216  * with IS2A. (Note that we can avoid dual source blending when Sa=1 by using ISA.)
217  *
218  * Xfer modes (Sa!=1): src, src-in, src-out
219  */
220 #define COVERAGE_DST_COEFF_ZERO_FORMULA(SRC_COEFF) \
221     INIT_BLEND_FORMULA(BlendFormula::kModulate_OutputType, \
222                        BlendFormula::kCoverage_OutputType, \
223                        kAdd_GrBlendEquation, SRC_COEFF, kIS2A_GrBlendCoeff)
224 
225 /**
226  * This table outlines the blend formulas we will use with each xfermode, with and without coverage,
227  * with and without an opaque input color. Optimization properties are deduced at compile time so we
228  * can make runtime decisions quickly. RGB coverage is not supported.
229  */
230 static const BlendFormula gBlendTable[2][2][SkXfermode::kLastCoeffMode + 1] = {
231 
232                      /*>> No coverage, input color unknown <<*/ {{
233 
234     /* clear */      DST_CLEAR_FORMULA,
235     /* src */        COEFF_FORMULA(   kOne_GrBlendCoeff,    kZero_GrBlendCoeff),
236     /* dst */        NO_DST_WRITE_FORMULA,
237     /* src-over */   COEFF_FORMULA(   kOne_GrBlendCoeff,    kISA_GrBlendCoeff),
238     /* dst-over */   COEFF_FORMULA(   kIDA_GrBlendCoeff,    kOne_GrBlendCoeff),
239     /* src-in */     COEFF_FORMULA(   kDA_GrBlendCoeff,     kZero_GrBlendCoeff),
240     /* dst-in */     COEFF_FORMULA(   kZero_GrBlendCoeff,   kSA_GrBlendCoeff),
241     /* src-out */    COEFF_FORMULA(   kIDA_GrBlendCoeff,    kZero_GrBlendCoeff),
242     /* dst-out */    COEFF_FORMULA(   kZero_GrBlendCoeff,   kISA_GrBlendCoeff),
243     /* src-atop */   COEFF_FORMULA(   kDA_GrBlendCoeff,     kISA_GrBlendCoeff),
244     /* dst-atop */   COEFF_FORMULA(   kIDA_GrBlendCoeff,    kSA_GrBlendCoeff),
245     /* xor */        COEFF_FORMULA(   kIDA_GrBlendCoeff,    kISA_GrBlendCoeff),
246     /* plus */       COEFF_FORMULA(   kOne_GrBlendCoeff,    kOne_GrBlendCoeff),
247     /* modulate */   COEFF_FORMULA(   kZero_GrBlendCoeff,   kSC_GrBlendCoeff),
248     /* screen */     COEFF_FORMULA(   kOne_GrBlendCoeff,    kISC_GrBlendCoeff),
249 
250                      }, /*>> Has coverage, input color unknown <<*/ {
251 
252     /* clear */      COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_OutputType),
253     /* src */        COVERAGE_DST_COEFF_ZERO_FORMULA(kOne_GrBlendCoeff),
254     /* dst */        NO_DST_WRITE_FORMULA,
255     /* src-over */   COEFF_FORMULA(   kOne_GrBlendCoeff,    kISA_GrBlendCoeff),
256     /* dst-over */   COEFF_FORMULA(   kIDA_GrBlendCoeff,    kOne_GrBlendCoeff),
257     /* src-in */     COVERAGE_DST_COEFF_ZERO_FORMULA(kDA_GrBlendCoeff),
258     /* dst-in */     COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISAModulate_OutputType),
259     /* src-out */    COVERAGE_DST_COEFF_ZERO_FORMULA(kIDA_GrBlendCoeff),
260     /* dst-out */    COEFF_FORMULA(   kZero_GrBlendCoeff,   kISA_GrBlendCoeff),
261     /* src-atop */   COEFF_FORMULA(   kDA_GrBlendCoeff,     kISA_GrBlendCoeff),
262     /* dst-atop */   COVERAGE_FORMULA(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff),
263     /* xor */        COEFF_FORMULA(   kIDA_GrBlendCoeff,    kISA_GrBlendCoeff),
264     /* plus */       COEFF_FORMULA(   kOne_GrBlendCoeff,    kOne_GrBlendCoeff),
265     /* modulate */   COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISCModulate_OutputType),
266     /* screen */     COEFF_FORMULA(   kOne_GrBlendCoeff,    kISC_GrBlendCoeff),
267 
268                      }}, /*>> No coverage, input color opaque <<*/ {{
269 
270     /* clear */      DST_CLEAR_FORMULA,
271     /* src */        COEFF_FORMULA(   kOne_GrBlendCoeff,    kZero_GrBlendCoeff),
272     /* dst */        NO_DST_WRITE_FORMULA,
273     /* src-over */   COEFF_FORMULA(   kOne_GrBlendCoeff,    kZero_GrBlendCoeff),
274     /* dst-over */   COEFF_FORMULA(   kIDA_GrBlendCoeff,    kOne_GrBlendCoeff),
275     /* src-in */     COEFF_FORMULA(   kDA_GrBlendCoeff,     kZero_GrBlendCoeff),
276     /* dst-in */     NO_DST_WRITE_FORMULA,
277     /* src-out */    COEFF_FORMULA(   kIDA_GrBlendCoeff,    kZero_GrBlendCoeff),
278     /* dst-out */    DST_CLEAR_FORMULA,
279     /* src-atop */   COEFF_FORMULA(   kDA_GrBlendCoeff,     kZero_GrBlendCoeff),
280     /* dst-atop */   COEFF_FORMULA(   kIDA_GrBlendCoeff,    kOne_GrBlendCoeff),
281     /* xor */        COEFF_FORMULA(   kIDA_GrBlendCoeff,    kZero_GrBlendCoeff),
282     /* plus */       COEFF_FORMULA(   kOne_GrBlendCoeff,    kOne_GrBlendCoeff),
283     /* modulate */   COEFF_FORMULA(   kZero_GrBlendCoeff,   kSC_GrBlendCoeff),
284     /* screen */     COEFF_FORMULA(   kOne_GrBlendCoeff,    kISC_GrBlendCoeff),
285 
286                      }, /*>> Has coverage, input color opaque <<*/ {
287 
288     /* clear */      COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_OutputType),
289     /* src */        COEFF_FORMULA(   kOne_GrBlendCoeff,    kISA_GrBlendCoeff),
290     /* dst */        NO_DST_WRITE_FORMULA,
291     /* src-over */   COEFF_FORMULA(   kOne_GrBlendCoeff,    kISA_GrBlendCoeff),
292     /* dst-over */   COEFF_FORMULA(   kIDA_GrBlendCoeff,    kOne_GrBlendCoeff),
293     /* src-in */     COEFF_FORMULA(   kDA_GrBlendCoeff,     kISA_GrBlendCoeff),
294     /* dst-in */     NO_DST_WRITE_FORMULA,
295     /* src-out */    COEFF_FORMULA(   kIDA_GrBlendCoeff,    kISA_GrBlendCoeff),
296     /* dst-out */    COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_OutputType),
297     /* src-atop */   COEFF_FORMULA(   kDA_GrBlendCoeff,     kISA_GrBlendCoeff),
298     /* dst-atop */   COEFF_FORMULA(   kIDA_GrBlendCoeff,    kOne_GrBlendCoeff),
299     /* xor */        COEFF_FORMULA(   kIDA_GrBlendCoeff,    kISA_GrBlendCoeff),
300     /* plus */       COEFF_FORMULA(   kOne_GrBlendCoeff,    kOne_GrBlendCoeff),
301     /* modulate */   COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISCModulate_OutputType),
302     /* screen */     COEFF_FORMULA(   kOne_GrBlendCoeff,    kISC_GrBlendCoeff),
303 }}};
304 
305 static const BlendFormula gLCDBlendTable[SkXfermode::kLastCoeffMode + 1] = {
306     /* clear */      COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_OutputType),
307     /* src */        COVERAGE_FORMULA(BlendFormula::kCoverage_OutputType, kOne_GrBlendCoeff),
308     /* dst */        NO_DST_WRITE_FORMULA,
309     /* src-over */   COVERAGE_FORMULA(BlendFormula::kSAModulate_OutputType, kOne_GrBlendCoeff),
310     /* dst-over */   COEFF_FORMULA(   kIDA_GrBlendCoeff,    kOne_GrBlendCoeff),
311     /* src-in */     COVERAGE_FORMULA(BlendFormula::kCoverage_OutputType, kDA_GrBlendCoeff),
312     /* dst-in */     COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISAModulate_OutputType),
313     /* src-out */    COVERAGE_FORMULA(BlendFormula::kCoverage_OutputType, kIDA_GrBlendCoeff),
314     /* dst-out */    COEFF_FORMULA_SA_MODULATE(   kZero_GrBlendCoeff,   kISC_GrBlendCoeff),
315     /* src-atop */   COVERAGE_FORMULA(BlendFormula::kSAModulate_OutputType, kDA_GrBlendCoeff),
316     /* dst-atop */   COVERAGE_FORMULA(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff),
317     /* xor */        COVERAGE_FORMULA(BlendFormula::kSAModulate_OutputType, kIDA_GrBlendCoeff),
318     /* plus */       COEFF_FORMULA(   kOne_GrBlendCoeff,    kOne_GrBlendCoeff),
319     /* modulate */   COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISCModulate_OutputType),
320     /* screen */     COEFF_FORMULA(   kOne_GrBlendCoeff,    kISC_GrBlendCoeff),
321 };
322 
get_blend_formula(const GrProcOptInfo & colorPOI,const GrProcOptInfo & coveragePOI,bool hasMixedSamples,SkXfermode::Mode xfermode)323 static BlendFormula get_blend_formula(const GrProcOptInfo& colorPOI,
324                                       const GrProcOptInfo& coveragePOI,
325                                       bool hasMixedSamples,
326                                       SkXfermode::Mode xfermode) {
327     SkASSERT(xfermode >= 0 && xfermode <= SkXfermode::kLastCoeffMode);
328     SkASSERT(!coveragePOI.isFourChannelOutput());
329 
330     bool conflatesCoverage = !coveragePOI.isSolidWhite() || hasMixedSamples;
331     return gBlendTable[colorPOI.isOpaque()][conflatesCoverage][xfermode];
332 }
333 
get_lcd_blend_formula(const GrProcOptInfo & coveragePOI,SkXfermode::Mode xfermode)334 static BlendFormula get_lcd_blend_formula(const GrProcOptInfo& coveragePOI,
335                                           SkXfermode::Mode xfermode) {
336     SkASSERT(xfermode >= 0 && xfermode <= SkXfermode::kLastCoeffMode);
337     SkASSERT(coveragePOI.isFourChannelOutput());
338 
339     return gLCDBlendTable[xfermode];
340 }
341 
342 ///////////////////////////////////////////////////////////////////////////////
343 
344 class PorterDuffXferProcessor : public GrXferProcessor {
345 public:
PorterDuffXferProcessor(BlendFormula blendFormula)346     PorterDuffXferProcessor(BlendFormula blendFormula) : fBlendFormula(blendFormula) {
347         this->initClassID<PorterDuffXferProcessor>();
348     }
349 
name() const350     const char* name() const override { return "Porter Duff"; }
351 
352     GrGLSLXferProcessor* createGLSLInstance() const override;
353 
getBlendFormula() const354     BlendFormula getBlendFormula() const { return fBlendFormula; }
355 
356 private:
357     GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations& optimizations,
358                                                  bool doesStencilWrite,
359                                                  GrColor* overrideColor,
360                                                  const GrCaps& caps) const override;
361 
362     void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
363 
onHasSecondaryOutput() const364     bool onHasSecondaryOutput() const override { return fBlendFormula.hasSecondaryOutput(); }
365 
onGetBlendInfo(GrXferProcessor::BlendInfo * blendInfo) const366     void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override {
367         blendInfo->fEquation = fBlendFormula.fBlendEquation;
368         blendInfo->fSrcBlend = fBlendFormula.fSrcCoeff;
369         blendInfo->fDstBlend = fBlendFormula.fDstCoeff;
370         blendInfo->fWriteColor = fBlendFormula.modifiesDst();
371     }
372 
onIsEqual(const GrXferProcessor & xpBase) const373     bool onIsEqual(const GrXferProcessor& xpBase) const override {
374         const PorterDuffXferProcessor& xp = xpBase.cast<PorterDuffXferProcessor>();
375         return fBlendFormula == xp.fBlendFormula;
376     }
377 
378     const BlendFormula fBlendFormula;
379 
380     typedef GrXferProcessor INHERITED;
381 };
382 
383 ///////////////////////////////////////////////////////////////////////////////
384 
append_color_output(const PorterDuffXferProcessor & xp,GrGLSLXPFragmentBuilder * fragBuilder,BlendFormula::OutputType outputType,const char * output,const char * inColor,const char * inCoverage)385 static void append_color_output(const PorterDuffXferProcessor& xp,
386                                 GrGLSLXPFragmentBuilder* fragBuilder,
387                                 BlendFormula::OutputType outputType, const char* output,
388                                 const char* inColor, const char* inCoverage) {
389     switch (outputType) {
390         case BlendFormula::kNone_OutputType:
391             fragBuilder->codeAppendf("%s = vec4(0.0);", output);
392             break;
393         case BlendFormula::kCoverage_OutputType:
394             // We can have a coverage formula while not reading coverage if there are mixed samples.
395             if (inCoverage) {
396                 fragBuilder->codeAppendf("%s = %s;", output, inCoverage);
397             } else {
398                 fragBuilder->codeAppendf("%s = vec4(1.0);", output);
399             }
400             break;
401         case BlendFormula::kModulate_OutputType:
402             if (inCoverage) {
403                 fragBuilder->codeAppendf("%s = %s * %s;", output, inColor, inCoverage);
404             } else {
405                 fragBuilder->codeAppendf("%s = %s;", output, inColor);
406             }
407             break;
408         case BlendFormula::kSAModulate_OutputType:
409             if (inCoverage) {
410                 fragBuilder->codeAppendf("%s = %s.a * %s;", output, inColor, inCoverage);
411             } else {
412                 fragBuilder->codeAppendf("%s = %s;", output, inColor);
413             }
414             break;
415         case BlendFormula::kISAModulate_OutputType:
416             if (inCoverage) {
417                 fragBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", output, inColor, inCoverage);
418             } else {
419                 fragBuilder->codeAppendf("%s = vec4(1.0 - %s.a);", output, inColor);
420             }
421             break;
422         case BlendFormula::kISCModulate_OutputType:
423             if (inCoverage) {
424                 fragBuilder->codeAppendf("%s = (vec4(1.0) - %s) * %s;", output, inColor, inCoverage);
425             } else {
426                 fragBuilder->codeAppendf("%s = vec4(1.0) - %s;", output, inColor);
427             }
428             break;
429         default:
430             SkFAIL("Unsupported output type.");
431             break;
432     }
433 }
434 
435 class GLPorterDuffXferProcessor : public GrGLSLXferProcessor {
436 public:
GenKey(const GrProcessor & processor,GrProcessorKeyBuilder * b)437     static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) {
438         const PorterDuffXferProcessor& xp = processor.cast<PorterDuffXferProcessor>();
439         b->add32(xp.getBlendFormula().fPrimaryOutputType |
440                  (xp.getBlendFormula().fSecondaryOutputType << 3));
441         GR_STATIC_ASSERT(BlendFormula::kLast_OutputType < 8);
442     }
443 
444 private:
emitOutputsForBlendState(const EmitArgs & args)445     void emitOutputsForBlendState(const EmitArgs& args) override {
446         const PorterDuffXferProcessor& xp = args.fXP.cast<PorterDuffXferProcessor>();
447         GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
448 
449         BlendFormula blendFormula = xp.getBlendFormula();
450         if (blendFormula.hasSecondaryOutput()) {
451             append_color_output(xp, fragBuilder, blendFormula.fSecondaryOutputType,
452                                 args.fOutputSecondary, args.fInputColor, args.fInputCoverage);
453         }
454         append_color_output(xp, fragBuilder, blendFormula.fPrimaryOutputType,
455                             args.fOutputPrimary, args.fInputColor, args.fInputCoverage);
456     }
457 
onSetData(const GrGLSLProgramDataManager &,const GrXferProcessor &)458     void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
459 
460     typedef GrGLSLXferProcessor INHERITED;
461 };
462 
463 ///////////////////////////////////////////////////////////////////////////////
464 
onGetGLSLProcessorKey(const GrGLSLCaps &,GrProcessorKeyBuilder * b) const465 void PorterDuffXferProcessor::onGetGLSLProcessorKey(const GrGLSLCaps&,
466                                                     GrProcessorKeyBuilder* b) const {
467     GLPorterDuffXferProcessor::GenKey(*this, b);
468 }
469 
createGLSLInstance() const470 GrGLSLXferProcessor* PorterDuffXferProcessor::createGLSLInstance() const {
471     return new GLPorterDuffXferProcessor;
472 }
473 
474 GrXferProcessor::OptFlags
onGetOptimizations(const GrPipelineOptimizations & optimizations,bool doesStencilWrite,GrColor * overrideColor,const GrCaps & caps) const475 PorterDuffXferProcessor::onGetOptimizations(const GrPipelineOptimizations& optimizations,
476                                             bool doesStencilWrite,
477                                             GrColor* overrideColor,
478                                             const GrCaps& caps) const {
479     GrXferProcessor::OptFlags optFlags = GrXferProcessor::kNone_OptFlags;
480     if (!fBlendFormula.modifiesDst()) {
481         if (!doesStencilWrite) {
482             optFlags |= GrXferProcessor::kSkipDraw_OptFlag;
483         }
484         optFlags |= (GrXferProcessor::kIgnoreColor_OptFlag |
485                      GrXferProcessor::kIgnoreCoverage_OptFlag |
486                      GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag);
487     } else {
488         if (!fBlendFormula.usesInputColor()) {
489             optFlags |= GrXferProcessor::kIgnoreColor_OptFlag;
490         }
491         if (optimizations.fCoveragePOI.isSolidWhite()) {
492             optFlags |= GrXferProcessor::kIgnoreCoverage_OptFlag;
493         }
494         if (optimizations.fColorPOI.allStagesMultiplyInput() &&
495             fBlendFormula.canTweakAlphaForCoverage() &&
496             !optimizations.fCoveragePOI.isFourChannelOutput()) {
497             optFlags |= GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag;
498         }
499     }
500     return optFlags;
501 }
502 
503 ///////////////////////////////////////////////////////////////////////////////
504 
505 class ShaderPDXferProcessor : public GrXferProcessor {
506 public:
ShaderPDXferProcessor(const DstTexture * dstTexture,bool hasMixedSamples,SkXfermode::Mode xfermode)507     ShaderPDXferProcessor(const DstTexture* dstTexture,
508                           bool hasMixedSamples,
509                           SkXfermode::Mode xfermode)
510         : INHERITED(dstTexture, true, hasMixedSamples)
511         , fXfermode(xfermode) {
512         this->initClassID<ShaderPDXferProcessor>();
513     }
514 
name() const515     const char* name() const override { return "Porter Duff Shader"; }
516 
517     GrGLSLXferProcessor* createGLSLInstance() const override;
518 
getXfermode() const519     SkXfermode::Mode getXfermode() const { return fXfermode; }
520 
521 private:
onGetOptimizations(const GrPipelineOptimizations &,bool,GrColor *,const GrCaps &) const522     GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations&, bool, GrColor*,
523                                                  const GrCaps&) const override {
524         return kNone_OptFlags;
525     }
526 
527     void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
528 
onIsEqual(const GrXferProcessor & xpBase) const529     bool onIsEqual(const GrXferProcessor& xpBase) const override {
530         const ShaderPDXferProcessor& xp = xpBase.cast<ShaderPDXferProcessor>();
531         return fXfermode == xp.fXfermode;
532     }
533 
534     const SkXfermode::Mode fXfermode;
535 
536     typedef GrXferProcessor INHERITED;
537 };
538 
539 ///////////////////////////////////////////////////////////////////////////////
540 
541 class GLShaderPDXferProcessor : public GrGLSLXferProcessor {
542 public:
GenKey(const GrProcessor & processor,GrProcessorKeyBuilder * b)543     static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) {
544         const ShaderPDXferProcessor& xp = processor.cast<ShaderPDXferProcessor>();
545         b->add32(xp.getXfermode());
546     }
547 
548 private:
emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder * fragBuilder,GrGLSLUniformHandler * uniformHandler,const char * srcColor,const char * srcCoverage,const char * dstColor,const char * outColor,const char * outColorSecondary,const GrXferProcessor & proc)549     void emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder* fragBuilder,
550                                  GrGLSLUniformHandler* uniformHandler,
551                                  const char* srcColor,
552                                  const char* srcCoverage,
553                                  const char* dstColor,
554                                  const char* outColor,
555                                  const char* outColorSecondary,
556                                  const GrXferProcessor& proc) override {
557         const ShaderPDXferProcessor& xp = proc.cast<ShaderPDXferProcessor>();
558 
559         GrGLSLBlend::AppendMode(fragBuilder, srcColor, dstColor, outColor, xp.getXfermode());
560 
561         // Apply coverage.
562         INHERITED::DefaultCoverageModulation(fragBuilder, srcCoverage, dstColor, outColor,
563                                              outColorSecondary, xp);
564     }
565 
onSetData(const GrGLSLProgramDataManager &,const GrXferProcessor &)566     void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
567 
568     typedef GrGLSLXferProcessor INHERITED;
569 };
570 
571 ///////////////////////////////////////////////////////////////////////////////
572 
onGetGLSLProcessorKey(const GrGLSLCaps &,GrProcessorKeyBuilder * b) const573 void ShaderPDXferProcessor::onGetGLSLProcessorKey(const GrGLSLCaps&,
574                                                   GrProcessorKeyBuilder* b) const {
575     GLShaderPDXferProcessor::GenKey(*this, b);
576 }
577 
createGLSLInstance() const578 GrGLSLXferProcessor* ShaderPDXferProcessor::createGLSLInstance() const {
579     return new GLShaderPDXferProcessor;
580 }
581 
582 ///////////////////////////////////////////////////////////////////////////////
583 
584 class PDLCDXferProcessor : public GrXferProcessor {
585 public:
586     static GrXferProcessor* Create(SkXfermode::Mode xfermode, const GrProcOptInfo& colorPOI);
587 
588     ~PDLCDXferProcessor() override;
589 
name() const590     const char* name() const override { return "Porter Duff LCD"; }
591 
592     GrGLSLXferProcessor* createGLSLInstance() const override;
593 
594 private:
595     PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha);
596 
597     GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations& optimizations,
598                                                  bool doesStencilWrite,
599                                                  GrColor* overrideColor,
600                                                  const GrCaps& caps) const override;
601 
602     void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
603 
onGetBlendInfo(GrXferProcessor::BlendInfo * blendInfo) const604     void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override {
605         blendInfo->fSrcBlend = kConstC_GrBlendCoeff;
606         blendInfo->fDstBlend = kISC_GrBlendCoeff;
607         blendInfo->fBlendConstant = fBlendConstant;
608     }
609 
onIsEqual(const GrXferProcessor & xpBase) const610     bool onIsEqual(const GrXferProcessor& xpBase) const override {
611         const PDLCDXferProcessor& xp = xpBase.cast<PDLCDXferProcessor>();
612         if (fBlendConstant != xp.fBlendConstant ||
613             fAlpha != xp.fAlpha) {
614             return false;
615         }
616         return true;
617     }
618 
619     GrColor      fBlendConstant;
620     uint8_t      fAlpha;
621 
622     typedef GrXferProcessor INHERITED;
623 };
624 
625 ///////////////////////////////////////////////////////////////////////////////
626 
627 class GLPDLCDXferProcessor : public GrGLSLXferProcessor {
628 public:
GLPDLCDXferProcessor(const GrProcessor &)629     GLPDLCDXferProcessor(const GrProcessor&) {}
630 
~GLPDLCDXferProcessor()631     virtual ~GLPDLCDXferProcessor() {}
632 
GenKey(const GrProcessor & processor,const GrGLSLCaps & caps,GrProcessorKeyBuilder * b)633     static void GenKey(const GrProcessor& processor, const GrGLSLCaps& caps,
634                        GrProcessorKeyBuilder* b) {}
635 
636 private:
emitOutputsForBlendState(const EmitArgs & args)637     void emitOutputsForBlendState(const EmitArgs& args) override {
638         GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
639         SkASSERT(args.fInputCoverage);
640         fragBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, args.fInputColor,
641                                  args.fInputCoverage);
642     }
643 
onSetData(const GrGLSLProgramDataManager &,const GrXferProcessor &)644     void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
645 
646     typedef GrGLSLXferProcessor INHERITED;
647 };
648 
649 ///////////////////////////////////////////////////////////////////////////////
650 
PDLCDXferProcessor(GrColor blendConstant,uint8_t alpha)651 PDLCDXferProcessor::PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha)
652     : fBlendConstant(blendConstant)
653     , fAlpha(alpha) {
654     this->initClassID<PDLCDXferProcessor>();
655 }
656 
Create(SkXfermode::Mode xfermode,const GrProcOptInfo & colorPOI)657 GrXferProcessor* PDLCDXferProcessor::Create(SkXfermode::Mode xfermode,
658                                             const GrProcOptInfo& colorPOI) {
659     if (SkXfermode::kSrcOver_Mode != xfermode) {
660         return nullptr;
661     }
662 
663     if (kRGBA_GrColorComponentFlags != colorPOI.validFlags()) {
664         return nullptr;
665     }
666 
667     GrColor blendConstant = GrUnpremulColor(colorPOI.color());
668     uint8_t alpha = GrColorUnpackA(blendConstant);
669     blendConstant |= (0xff << GrColor_SHIFT_A);
670 
671     return new PDLCDXferProcessor(blendConstant, alpha);
672 }
673 
~PDLCDXferProcessor()674 PDLCDXferProcessor::~PDLCDXferProcessor() {
675 }
676 
onGetGLSLProcessorKey(const GrGLSLCaps & caps,GrProcessorKeyBuilder * b) const677 void PDLCDXferProcessor::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
678                                                GrProcessorKeyBuilder* b) const {
679     GLPDLCDXferProcessor::GenKey(*this, caps, b);
680 }
681 
createGLSLInstance() const682 GrGLSLXferProcessor* PDLCDXferProcessor::createGLSLInstance() const {
683     return new GLPDLCDXferProcessor(*this);
684 }
685 
686 GrXferProcessor::OptFlags
onGetOptimizations(const GrPipelineOptimizations & optimizations,bool doesStencilWrite,GrColor * overrideColor,const GrCaps & caps) const687 PDLCDXferProcessor::onGetOptimizations(const GrPipelineOptimizations& optimizations,
688                                        bool doesStencilWrite,
689                                        GrColor* overrideColor,
690                                        const GrCaps& caps) const {
691         // We want to force our primary output to be alpha * Coverage, where alpha is the alpha
692         // value of the blend the constant. We should already have valid blend coeff's if we are at
693         // a point where we have RGB coverage. We don't need any color stages since the known color
694         // output is already baked into the blendConstant.
695         *overrideColor = GrColorPackRGBA(fAlpha, fAlpha, fAlpha, fAlpha);
696         return GrXferProcessor::kOverrideColor_OptFlag;
697 }
698 
699 ///////////////////////////////////////////////////////////////////////////////
700 
GrPorterDuffXPFactory(SkXfermode::Mode xfermode)701 GrPorterDuffXPFactory::GrPorterDuffXPFactory(SkXfermode::Mode xfermode)
702     : fXfermode(xfermode) {
703     SkASSERT(fXfermode <= SkXfermode::kLastCoeffMode);
704     this->initClassID<GrPorterDuffXPFactory>();
705 }
706 
Make(SkXfermode::Mode xfermode)707 sk_sp<GrXPFactory> GrPorterDuffXPFactory::Make(SkXfermode::Mode xfermode) {
708     static GrPorterDuffXPFactory gClearPDXPF(SkXfermode::kClear_Mode);
709     static GrPorterDuffXPFactory gSrcPDXPF(SkXfermode::kSrc_Mode);
710     static GrPorterDuffXPFactory gDstPDXPF(SkXfermode::kDst_Mode);
711     static GrPorterDuffXPFactory gSrcOverPDXPF(SkXfermode::kSrcOver_Mode);
712     static GrPorterDuffXPFactory gDstOverPDXPF(SkXfermode::kDstOver_Mode);
713     static GrPorterDuffXPFactory gSrcInPDXPF(SkXfermode::kSrcIn_Mode);
714     static GrPorterDuffXPFactory gDstInPDXPF(SkXfermode::kDstIn_Mode);
715     static GrPorterDuffXPFactory gSrcOutPDXPF(SkXfermode::kSrcOut_Mode);
716     static GrPorterDuffXPFactory gDstOutPDXPF(SkXfermode::kDstOut_Mode);
717     static GrPorterDuffXPFactory gSrcATopPDXPF(SkXfermode::kSrcATop_Mode);
718     static GrPorterDuffXPFactory gDstATopPDXPF(SkXfermode::kDstATop_Mode);
719     static GrPorterDuffXPFactory gXorPDXPF(SkXfermode::kXor_Mode);
720     static GrPorterDuffXPFactory gPlusPDXPF(SkXfermode::kPlus_Mode);
721     static GrPorterDuffXPFactory gModulatePDXPF(SkXfermode::kModulate_Mode);
722     static GrPorterDuffXPFactory gScreenPDXPF(SkXfermode::kScreen_Mode);
723 
724     static GrPorterDuffXPFactory* gFactories[] = {
725         &gClearPDXPF, &gSrcPDXPF, &gDstPDXPF, &gSrcOverPDXPF, &gDstOverPDXPF, &gSrcInPDXPF,
726         &gDstInPDXPF, &gSrcOutPDXPF, &gDstOutPDXPF, &gSrcATopPDXPF, &gDstATopPDXPF, &gXorPDXPF,
727         &gPlusPDXPF, &gModulatePDXPF, &gScreenPDXPF
728     };
729     GR_STATIC_ASSERT(SK_ARRAY_COUNT(gFactories) == SkXfermode::kLastCoeffMode + 1);
730 
731     if (xfermode < 0 || xfermode > SkXfermode::kLastCoeffMode) {
732         return nullptr;
733     }
734     return sk_sp<GrXPFactory>(SkRef(gFactories[xfermode]));
735 }
736 
737 GrXferProcessor*
onCreateXferProcessor(const GrCaps & caps,const GrPipelineOptimizations & optimizations,bool hasMixedSamples,const DstTexture * dstTexture) const738 GrPorterDuffXPFactory::onCreateXferProcessor(const GrCaps& caps,
739                                              const GrPipelineOptimizations& optimizations,
740                                              bool hasMixedSamples,
741                                              const DstTexture* dstTexture) const {
742     if (optimizations.fOverrides.fUsePLSDstRead) {
743         return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, fXfermode);
744     }
745     BlendFormula blendFormula;
746     if (optimizations.fCoveragePOI.isFourChannelOutput()) {
747         if (SkXfermode::kSrcOver_Mode == fXfermode &&
748             kRGBA_GrColorComponentFlags == optimizations.fColorPOI.validFlags() &&
749             !caps.shaderCaps()->dualSourceBlendingSupport() &&
750             !caps.shaderCaps()->dstReadInShaderSupport()) {
751             // If we don't have dual source blending or in shader dst reads, we fall back to this
752             // trick for rendering SrcOver LCD text instead of doing a dst copy.
753             SkASSERT(!dstTexture || !dstTexture->texture());
754             return PDLCDXferProcessor::Create(fXfermode, optimizations.fColorPOI);
755         }
756         blendFormula = get_lcd_blend_formula(optimizations.fCoveragePOI, fXfermode);
757     } else {
758         blendFormula = get_blend_formula(optimizations.fColorPOI, optimizations.fCoveragePOI,
759                                          hasMixedSamples, fXfermode);
760     }
761 
762     if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) {
763         return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, fXfermode);
764     }
765 
766     SkASSERT(!dstTexture || !dstTexture->texture());
767     return new PorterDuffXferProcessor(blendFormula);
768 }
769 
getInvariantBlendedColor(const GrProcOptInfo & colorPOI,InvariantBlendedColor * blendedColor) const770 void GrPorterDuffXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
771                                                      InvariantBlendedColor* blendedColor) const {
772     // Find the blended color info based on the formula that does not have coverage.
773     BlendFormula colorFormula = gBlendTable[colorPOI.isOpaque()][0][fXfermode];
774     if (colorFormula.usesDstColor()) {
775         blendedColor->fWillBlendWithDst = true;
776         blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags;
777         return;
778     }
779 
780     blendedColor->fWillBlendWithDst = false;
781 
782     SkASSERT(kAdd_GrBlendEquation == colorFormula.fBlendEquation);
783 
784     switch (colorFormula.fSrcCoeff) {
785         case kZero_GrBlendCoeff:
786             blendedColor->fKnownColor = 0;
787             blendedColor->fKnownColorFlags = kRGBA_GrColorComponentFlags;
788             return;
789 
790         case kOne_GrBlendCoeff:
791             blendedColor->fKnownColor = colorPOI.color();
792             blendedColor->fKnownColorFlags = colorPOI.validFlags();
793             return;
794 
795         default:
796             blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags;
797             return;
798     }
799 }
800 
onWillReadDstColor(const GrCaps & caps,const GrPipelineOptimizations & optimizations) const801 bool GrPorterDuffXPFactory::onWillReadDstColor(const GrCaps& caps,
802                                                const GrPipelineOptimizations& optimizations) const {
803     if (caps.shaderCaps()->dualSourceBlendingSupport()) {
804         return false;
805     }
806 
807     // When we have four channel coverage we always need to read the dst in order to correctly
808     // blend. The one exception is when we are using srcover mode and we know the input color into
809     // the XP.
810     if (optimizations.fCoveragePOI.isFourChannelOutput()) {
811         if (SkXfermode::kSrcOver_Mode == fXfermode &&
812             kRGBA_GrColorComponentFlags == optimizations.fColorPOI.validFlags() &&
813             !caps.shaderCaps()->dstReadInShaderSupport()) {
814             return false;
815         }
816         return get_lcd_blend_formula(optimizations.fCoveragePOI, fXfermode).hasSecondaryOutput();
817     }
818 
819     // We fallback on the shader XP when the blend formula would use dual source blending but we
820     // don't have support for it.
821     static const bool kHasMixedSamples = false;
822     SkASSERT(!caps.usesMixedSamples()); // We never use mixed samples without dual source blending.
823     return get_blend_formula(optimizations.fColorPOI, optimizations.fCoveragePOI, kHasMixedSamples,
824                              fXfermode).hasSecondaryOutput();
825 }
826 
827 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory);
828 
TestCreate(GrProcessorTestData * d)829 sk_sp<GrXPFactory> GrPorterDuffXPFactory::TestCreate(GrProcessorTestData* d) {
830     SkXfermode::Mode mode = SkXfermode::Mode(d->fRandom->nextULessThan(SkXfermode::kLastCoeffMode));
831     return GrPorterDuffXPFactory::Make(mode);
832 }
833 
TestGetXPOutputTypes(const GrXferProcessor * xp,int * outPrimary,int * outSecondary)834 void GrPorterDuffXPFactory::TestGetXPOutputTypes(const GrXferProcessor* xp,
835                                                  int* outPrimary,
836                                                  int* outSecondary) {
837     if (!!strcmp(xp->name(), "Porter Duff")) {
838         *outPrimary = *outSecondary = -1;
839         return;
840     }
841     BlendFormula blendFormula = static_cast<const PorterDuffXferProcessor*>(xp)->getBlendFormula();
842     *outPrimary = blendFormula.fPrimaryOutputType;
843     *outSecondary = blendFormula.fSecondaryOutputType;
844 }
845 
846 
847 ////////////////////////////////////////////////////////////////////////////////////////////////
848 // SrcOver Global functions
849 ////////////////////////////////////////////////////////////////////////////////////////////////
SimpleSrcOverXP()850 const GrXferProcessor& GrPorterDuffXPFactory::SimpleSrcOverXP() {
851     static BlendFormula gSrcOverBlendFormula = COEFF_FORMULA(kOne_GrBlendCoeff,
852                                                              kISA_GrBlendCoeff);
853     static PorterDuffXferProcessor gSrcOverXP(gSrcOverBlendFormula);
854     return gSrcOverXP;
855 }
856 
CreateSrcOverXferProcessor(const GrCaps & caps,const GrPipelineOptimizations & optimizations,bool hasMixedSamples,const GrXferProcessor::DstTexture * dstTexture)857 GrXferProcessor* GrPorterDuffXPFactory::CreateSrcOverXferProcessor(
858         const GrCaps& caps,
859         const GrPipelineOptimizations& optimizations,
860         bool hasMixedSamples,
861         const GrXferProcessor::DstTexture* dstTexture) {
862     if (optimizations.fOverrides.fUsePLSDstRead) {
863         return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, SkXfermode::kSrcOver_Mode);
864     }
865 
866     // We want to not make an xfer processor if possible. Thus for the simple case where we are not
867     // doing lcd blending we will just use our global SimpleSrcOverXP. This slightly differs from
868     // the general case where we convert a src-over blend that has solid coverage and an opaque
869     // color to src-mode, which allows disabling of blending.
870     if (!optimizations.fCoveragePOI.isFourChannelOutput()) {
871         // We return nullptr here, which our caller interprets as meaning "use SimpleSrcOverXP".
872         // We don't simply return the address of that XP here because our caller would have to unref
873         // it and since it is a global object and GrProgramElement's ref-cnting system is not thread
874         // safe.
875         return nullptr;
876     }
877 
878     if (kRGBA_GrColorComponentFlags == optimizations.fColorPOI.validFlags() &&
879         !caps.shaderCaps()->dualSourceBlendingSupport() &&
880         !caps.shaderCaps()->dstReadInShaderSupport()) {
881         // If we don't have dual source blending or in shader dst reads, we fall
882         // back to this trick for rendering SrcOver LCD text instead of doing a
883         // dst copy.
884         SkASSERT(!dstTexture || !dstTexture->texture());
885         return PDLCDXferProcessor::Create(SkXfermode::kSrcOver_Mode, optimizations.fColorPOI);
886     }
887 
888     BlendFormula blendFormula;
889     blendFormula = get_lcd_blend_formula(optimizations.fCoveragePOI, SkXfermode::kSrcOver_Mode);
890     if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) {
891         return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, SkXfermode::kSrcOver_Mode);
892     }
893 
894     SkASSERT(!dstTexture || !dstTexture->texture());
895     return new PorterDuffXferProcessor(blendFormula);
896 }
897 
SrcOverWillNeedDstTexture(const GrCaps & caps,const GrPipelineOptimizations & optimizations)898 bool GrPorterDuffXPFactory::SrcOverWillNeedDstTexture(const GrCaps& caps,
899                                                      const GrPipelineOptimizations& optimizations) {
900     if (caps.shaderCaps()->dstReadInShaderSupport() ||
901         caps.shaderCaps()->dualSourceBlendingSupport()) {
902         return false;
903     }
904 
905     // When we have four channel coverage we always need to read the dst in order to correctly
906     // blend. The one exception is when we are using srcover mode and we know the input color
907     // into the XP.
908     if (optimizations.fCoveragePOI.isFourChannelOutput()) {
909         if (kRGBA_GrColorComponentFlags == optimizations.fColorPOI.validFlags() &&
910             !caps.shaderCaps()->dstReadInShaderSupport()) {
911             return false;
912         }
913         return get_lcd_blend_formula(optimizations.fCoveragePOI,
914                                      SkXfermode::kSrcOver_Mode).hasSecondaryOutput();
915     }
916 
917     // We fallback on the shader XP when the blend formula would use dual source blending but we
918     // don't have support for it.
919     static const bool kHasMixedSamples = false;
920     SkASSERT(!caps.usesMixedSamples()); // We never use mixed samples without dual source blending.
921     return get_blend_formula(optimizations.fColorPOI, optimizations.fCoveragePOI,
922                              kHasMixedSamples, SkXfermode::kSrcOver_Mode).hasSecondaryOutput();
923 }
924