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