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 "GrPipelineAnalysis.h"
14 #include "GrProcessor.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
23 /**
24 * Wraps the shader outputs and HW blend state that comprise a Porter Duff blend mode with coverage.
25 */
26 struct BlendFormula {
27 public:
28 /**
29 * Values the shader can write to primary and secondary outputs. These must all be modulated by
30 * coverage to support mixed samples. The XP will ignore the multiplies when not using coverage.
31 */
32 enum OutputType {
33 kNone_OutputType, //<! 0
34 kCoverage_OutputType, //<! inputCoverage
35 kModulate_OutputType, //<! inputColor * inputCoverage
36 kSAModulate_OutputType, //<! inputColor.a * inputCoverage
37 kISAModulate_OutputType, //<! (1 - inputColor.a) * inputCoverage
38 kISCModulate_OutputType, //<! (1 - inputColor) * inputCoverage
39
40 kLast_OutputType = kISCModulate_OutputType
41 };
42
43 enum Properties {
44 kModifiesDst_Property = 1,
45 kUsesDstColor_Property = 1 << 1,
46 kUsesInputColor_Property = 1 << 2,
47 kCanTweakAlphaForCoverage_Property = 1 << 3,
48
49 kLast_Property = kCanTweakAlphaForCoverage_Property
50 };
51
operator =BlendFormula52 BlendFormula& operator =(const BlendFormula& other) {
53 fData = other.fData;
54 return *this;
55 }
56
operator ==BlendFormula57 bool operator ==(const BlendFormula& other) const {
58 return fData == other.fData;
59 }
60
hasSecondaryOutputBlendFormula61 bool hasSecondaryOutput() const { return kNone_OutputType != fSecondaryOutputType; }
modifiesDstBlendFormula62 bool modifiesDst() const { return SkToBool(fProps & kModifiesDst_Property); }
usesDstColorBlendFormula63 bool usesDstColor() const { return SkToBool(fProps & kUsesDstColor_Property); }
usesInputColorBlendFormula64 bool usesInputColor() const { return SkToBool(fProps & kUsesInputColor_Property); }
canTweakAlphaForCoverageBlendFormula65 bool canTweakAlphaForCoverage() const {
66 return SkToBool(fProps & kCanTweakAlphaForCoverage_Property);
67 }
68
69 /**
70 * Deduce the properties of a compile-time constant BlendFormula.
71 */
72 template<OutputType PrimaryOut, OutputType SecondaryOut,
73 GrBlendEquation BlendEquation, GrBlendCoeff SrcCoeff, GrBlendCoeff DstCoeff>
74 struct get_properties : std::integral_constant<Properties, static_cast<Properties>(
75
76 (GR_BLEND_MODIFIES_DST(BlendEquation, SrcCoeff, DstCoeff) ?
77 kModifiesDst_Property : 0) |
78
79 (GR_BLEND_COEFFS_USE_DST_COLOR(SrcCoeff, DstCoeff) ?
80 kUsesDstColor_Property : 0) |
81
82 ((PrimaryOut >= kModulate_OutputType && GR_BLEND_COEFFS_USE_SRC_COLOR(SrcCoeff,DstCoeff)) ||
83 (SecondaryOut >= kModulate_OutputType && GR_BLEND_COEFF_REFS_SRC2(DstCoeff)) ?
84 kUsesInputColor_Property : 0) | // We assert later that SrcCoeff doesn't ref src2.
85
86 (kModulate_OutputType == PrimaryOut &&
87 kNone_OutputType == SecondaryOut &&
88 GR_BLEND_CAN_TWEAK_ALPHA_FOR_COVERAGE(BlendEquation, SrcCoeff, DstCoeff) ?
89 kCanTweakAlphaForCoverage_Property : 0))> {
90
91 // The provided formula should already be optimized.
92 GR_STATIC_ASSERT((kNone_OutputType == PrimaryOut) ==
93 !GR_BLEND_COEFFS_USE_SRC_COLOR(SrcCoeff, DstCoeff));
94 GR_STATIC_ASSERT(!GR_BLEND_COEFF_REFS_SRC2(SrcCoeff));
95 GR_STATIC_ASSERT((kNone_OutputType == SecondaryOut) ==
96 !GR_BLEND_COEFF_REFS_SRC2(DstCoeff));
97 GR_STATIC_ASSERT(PrimaryOut != SecondaryOut || kNone_OutputType == PrimaryOut);
98 GR_STATIC_ASSERT(kNone_OutputType != PrimaryOut || kNone_OutputType == SecondaryOut);
99 };
100
101 union {
102 struct {
103 // We allot the enums one more bit than they require because MSVC seems to sign-extend
104 // them when the top bit is set. (This is in violation of the C++03 standard 9.6/4)
105 OutputType fPrimaryOutputType : 4;
106 OutputType fSecondaryOutputType : 4;
107 GrBlendEquation fBlendEquation : 6;
108 GrBlendCoeff fSrcCoeff : 6;
109 GrBlendCoeff fDstCoeff : 6;
110 Properties fProps : 32 - (4 + 4 + 6 + 6 + 6);
111 };
112 uint32_t fData;
113 };
114
115 GR_STATIC_ASSERT(kLast_OutputType < (1 << 3));
116 GR_STATIC_ASSERT(kLast_GrBlendEquation < (1 << 5));
117 GR_STATIC_ASSERT(kLast_GrBlendCoeff < (1 << 5));
118 GR_STATIC_ASSERT(kLast_Property < (1 << 6));
119 };
120
121 GR_STATIC_ASSERT(4 == sizeof(BlendFormula));
122
123 GR_MAKE_BITFIELD_OPS(BlendFormula::Properties);
124
125 /**
126 * Initialize a compile-time constant BlendFormula and automatically deduce fProps.
127 */
128 #define INIT_BLEND_FORMULA(PRIMARY_OUT, SECONDARY_OUT, BLEND_EQUATION, SRC_COEFF, DST_COEFF) \
129 {{{PRIMARY_OUT, \
130 SECONDARY_OUT, \
131 BLEND_EQUATION, SRC_COEFF, DST_COEFF, \
132 BlendFormula::get_properties<PRIMARY_OUT, SECONDARY_OUT, \
133 BLEND_EQUATION, SRC_COEFF, DST_COEFF>::value}}}
134
135 /**
136 * When there is no coverage, or the blend mode can tweak alpha for coverage, we use the standard
137 * Porter Duff formula.
138 */
139 #define COEFF_FORMULA(SRC_COEFF, DST_COEFF) \
140 INIT_BLEND_FORMULA(BlendFormula::kModulate_OutputType, \
141 BlendFormula::kNone_OutputType, \
142 kAdd_GrBlendEquation, SRC_COEFF, DST_COEFF)
143
144 /**
145 * Basic coeff formula similar to COEFF_FORMULA but we will make the src f*Sa. This is used in
146 * LCD dst-out.
147 */
148 #define COEFF_FORMULA_SA_MODULATE(SRC_COEFF, DST_COEFF) \
149 INIT_BLEND_FORMULA(BlendFormula::kSAModulate_OutputType, \
150 BlendFormula::kNone_OutputType, \
151 kAdd_GrBlendEquation, SRC_COEFF, DST_COEFF)
152
153 /**
154 * When the coeffs are (Zero, Zero), we clear the dst. This formula has its own macro so we can set
155 * the primary output type to none.
156 */
157 #define DST_CLEAR_FORMULA \
158 INIT_BLEND_FORMULA(BlendFormula::kNone_OutputType, \
159 BlendFormula::kNone_OutputType, \
160 kAdd_GrBlendEquation, kZero_GrBlendCoeff, kZero_GrBlendCoeff)
161
162 /**
163 * When the coeffs are (Zero, One), we don't write to the dst at all. This formula has its own macro
164 * so we can set the primary output type to none.
165 */
166 #define NO_DST_WRITE_FORMULA \
167 INIT_BLEND_FORMULA(BlendFormula::kNone_OutputType, \
168 BlendFormula::kNone_OutputType, \
169 kAdd_GrBlendEquation, kZero_GrBlendCoeff, kOne_GrBlendCoeff)
170
171 /**
172 * When there is coverage, the equation with f=coverage is:
173 *
174 * D' = f * (S * srcCoeff + D * dstCoeff) + (1-f) * D
175 *
176 * This can be rewritten as:
177 *
178 * D' = f * S * srcCoeff + D * (1 - [f * (1 - dstCoeff)])
179 *
180 * To implement this formula, we output [f * (1 - dstCoeff)] for the secondary color and replace the
181 * HW dst coeff with IS2C.
182 *
183 * Xfer modes: dst-atop (Sa!=1)
184 */
185 #define COVERAGE_FORMULA(ONE_MINUS_DST_COEFF_MODULATE_OUTPUT, SRC_COEFF) \
186 INIT_BLEND_FORMULA(BlendFormula::kModulate_OutputType, \
187 ONE_MINUS_DST_COEFF_MODULATE_OUTPUT, \
188 kAdd_GrBlendEquation, SRC_COEFF, kIS2C_GrBlendCoeff)
189
190 /**
191 * When there is coverage and the src coeff is Zero, the equation with f=coverage becomes:
192 *
193 * D' = f * D * dstCoeff + (1-f) * D
194 *
195 * This can be rewritten as:
196 *
197 * D' = D - D * [f * (1 - dstCoeff)]
198 *
199 * To implement this formula, we output [f * (1 - dstCoeff)] for the primary color and use a reverse
200 * subtract HW blend equation with coeffs of (DC, One).
201 *
202 * Xfer modes: clear, dst-out (Sa=1), dst-in (Sa!=1), modulate (Sc!=1)
203 */
204 #define COVERAGE_SRC_COEFF_ZERO_FORMULA(ONE_MINUS_DST_COEFF_MODULATE_OUTPUT) \
205 INIT_BLEND_FORMULA(ONE_MINUS_DST_COEFF_MODULATE_OUTPUT, \
206 BlendFormula::kNone_OutputType, \
207 kReverseSubtract_GrBlendEquation, kDC_GrBlendCoeff, kOne_GrBlendCoeff)
208
209 /**
210 * When there is coverage and the dst coeff is Zero, the equation with f=coverage becomes:
211 *
212 * D' = f * S * srcCoeff + (1-f) * D
213 *
214 * To implement this formula, we output [f] for the secondary color and replace the HW dst coeff
215 * with IS2A. (Note that we can avoid dual source blending when Sa=1 by using ISA.)
216 *
217 * Xfer modes (Sa!=1): src, src-in, src-out
218 */
219 #define COVERAGE_DST_COEFF_ZERO_FORMULA(SRC_COEFF) \
220 INIT_BLEND_FORMULA(BlendFormula::kModulate_OutputType, \
221 BlendFormula::kCoverage_OutputType, \
222 kAdd_GrBlendEquation, SRC_COEFF, kIS2A_GrBlendCoeff)
223
224 /**
225 * This table outlines the blend formulas we will use with each xfermode, with and without coverage,
226 * with and without an opaque input color. Optimization properties are deduced at compile time so we
227 * can make runtime decisions quickly. RGB coverage is not supported.
228 */
229 static const BlendFormula gBlendTable[2][2][(int)SkBlendMode::kLastCoeffMode + 1] = {
230
231 /*>> No coverage, input color unknown <<*/ {{
232
233 /* clear */ DST_CLEAR_FORMULA,
234 /* src */ COEFF_FORMULA( kOne_GrBlendCoeff, kZero_GrBlendCoeff),
235 /* dst */ NO_DST_WRITE_FORMULA,
236 /* src-over */ COEFF_FORMULA( kOne_GrBlendCoeff, kISA_GrBlendCoeff),
237 /* dst-over */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
238 /* src-in */ COEFF_FORMULA( kDA_GrBlendCoeff, kZero_GrBlendCoeff),
239 /* dst-in */ COEFF_FORMULA( kZero_GrBlendCoeff, kSA_GrBlendCoeff),
240 /* src-out */ COEFF_FORMULA( kIDA_GrBlendCoeff, kZero_GrBlendCoeff),
241 /* dst-out */ COEFF_FORMULA( kZero_GrBlendCoeff, kISA_GrBlendCoeff),
242 /* src-atop */ COEFF_FORMULA( kDA_GrBlendCoeff, kISA_GrBlendCoeff),
243 /* dst-atop */ COEFF_FORMULA( kIDA_GrBlendCoeff, kSA_GrBlendCoeff),
244 /* xor */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff),
245 /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff),
246 /* modulate */ COEFF_FORMULA( kZero_GrBlendCoeff, kSC_GrBlendCoeff),
247 /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff),
248
249 }, /*>> Has coverage, input color unknown <<*/ {
250
251 /* clear */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_OutputType),
252 /* src */ COVERAGE_DST_COEFF_ZERO_FORMULA(kOne_GrBlendCoeff),
253 /* dst */ NO_DST_WRITE_FORMULA,
254 /* src-over */ COEFF_FORMULA( kOne_GrBlendCoeff, kISA_GrBlendCoeff),
255 /* dst-over */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
256 /* src-in */ COVERAGE_DST_COEFF_ZERO_FORMULA(kDA_GrBlendCoeff),
257 /* dst-in */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISAModulate_OutputType),
258 /* src-out */ COVERAGE_DST_COEFF_ZERO_FORMULA(kIDA_GrBlendCoeff),
259 /* dst-out */ COEFF_FORMULA( kZero_GrBlendCoeff, kISA_GrBlendCoeff),
260 /* src-atop */ COEFF_FORMULA( kDA_GrBlendCoeff, kISA_GrBlendCoeff),
261 /* dst-atop */ COVERAGE_FORMULA(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff),
262 /* xor */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff),
263 /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff),
264 /* modulate */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISCModulate_OutputType),
265 /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff),
266
267 }}, /*>> No coverage, input color opaque <<*/ {{
268
269 /* clear */ DST_CLEAR_FORMULA,
270 /* src */ COEFF_FORMULA( kOne_GrBlendCoeff, kZero_GrBlendCoeff),
271 /* dst */ NO_DST_WRITE_FORMULA,
272 /* src-over */ COEFF_FORMULA( kOne_GrBlendCoeff, kZero_GrBlendCoeff),
273 /* dst-over */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
274 /* src-in */ COEFF_FORMULA( kDA_GrBlendCoeff, kZero_GrBlendCoeff),
275 /* dst-in */ NO_DST_WRITE_FORMULA,
276 /* src-out */ COEFF_FORMULA( kIDA_GrBlendCoeff, kZero_GrBlendCoeff),
277 /* dst-out */ DST_CLEAR_FORMULA,
278 /* src-atop */ COEFF_FORMULA( kDA_GrBlendCoeff, kZero_GrBlendCoeff),
279 /* dst-atop */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
280 /* xor */ COEFF_FORMULA( kIDA_GrBlendCoeff, kZero_GrBlendCoeff),
281 /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff),
282 /* modulate */ COEFF_FORMULA( kZero_GrBlendCoeff, kSC_GrBlendCoeff),
283 /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff),
284
285 }, /*>> Has coverage, input color opaque <<*/ {
286
287 /* clear */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_OutputType),
288 /* src */ COEFF_FORMULA( kOne_GrBlendCoeff, kISA_GrBlendCoeff),
289 /* dst */ NO_DST_WRITE_FORMULA,
290 /* src-over */ COEFF_FORMULA( kOne_GrBlendCoeff, kISA_GrBlendCoeff),
291 /* dst-over */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
292 /* src-in */ COEFF_FORMULA( kDA_GrBlendCoeff, kISA_GrBlendCoeff),
293 /* dst-in */ NO_DST_WRITE_FORMULA,
294 /* src-out */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff),
295 /* dst-out */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_OutputType),
296 /* src-atop */ COEFF_FORMULA( kDA_GrBlendCoeff, kISA_GrBlendCoeff),
297 /* dst-atop */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
298 /* xor */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff),
299 /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff),
300 /* modulate */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISCModulate_OutputType),
301 /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff),
302 }}};
303
304 static const BlendFormula gLCDBlendTable[(int)SkBlendMode::kLastCoeffMode + 1] = {
305 /* clear */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_OutputType),
306 /* src */ COVERAGE_FORMULA(BlendFormula::kCoverage_OutputType, kOne_GrBlendCoeff),
307 /* dst */ NO_DST_WRITE_FORMULA,
308 /* src-over */ COVERAGE_FORMULA(BlendFormula::kSAModulate_OutputType, kOne_GrBlendCoeff),
309 /* dst-over */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
310 /* src-in */ COVERAGE_FORMULA(BlendFormula::kCoverage_OutputType, kDA_GrBlendCoeff),
311 /* dst-in */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISAModulate_OutputType),
312 /* src-out */ COVERAGE_FORMULA(BlendFormula::kCoverage_OutputType, kIDA_GrBlendCoeff),
313 /* dst-out */ COEFF_FORMULA_SA_MODULATE( kZero_GrBlendCoeff, kISC_GrBlendCoeff),
314 /* src-atop */ COVERAGE_FORMULA(BlendFormula::kSAModulate_OutputType, kDA_GrBlendCoeff),
315 /* dst-atop */ COVERAGE_FORMULA(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff),
316 /* xor */ COVERAGE_FORMULA(BlendFormula::kSAModulate_OutputType, kIDA_GrBlendCoeff),
317 /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff),
318 /* modulate */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISCModulate_OutputType),
319 /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff),
320 };
321
get_blend_formula(bool isOpaque,bool hasCoverage,bool hasMixedSamples,SkBlendMode xfermode)322 static BlendFormula get_blend_formula(bool isOpaque,
323 bool hasCoverage,
324 bool hasMixedSamples,
325 SkBlendMode xfermode) {
326 SkASSERT((unsigned)xfermode <= (unsigned)SkBlendMode::kLastCoeffMode);
327 bool conflatesCoverage = hasCoverage || hasMixedSamples;
328 return gBlendTable[isOpaque][conflatesCoverage][(int)xfermode];
329 }
330
get_lcd_blend_formula(SkBlendMode xfermode)331 static BlendFormula get_lcd_blend_formula(SkBlendMode xfermode) {
332 SkASSERT((unsigned)xfermode <= (unsigned)SkBlendMode::kLastCoeffMode);
333
334 return gLCDBlendTable[(int)xfermode];
335 }
336
337 ///////////////////////////////////////////////////////////////////////////////
338
339 class PorterDuffXferProcessor : public GrXferProcessor {
340 public:
PorterDuffXferProcessor(BlendFormula blendFormula)341 PorterDuffXferProcessor(BlendFormula blendFormula) : fBlendFormula(blendFormula) {
342 this->initClassID<PorterDuffXferProcessor>();
343 }
344
name() const345 const char* name() const override { return "Porter Duff"; }
346
347 GrGLSLXferProcessor* createGLSLInstance() const override;
348
getBlendFormula() const349 BlendFormula getBlendFormula() const { return fBlendFormula; }
350
351 private:
352 GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&) const override;
353
354 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
355
onHasSecondaryOutput() const356 bool onHasSecondaryOutput() const override { return fBlendFormula.hasSecondaryOutput(); }
357
onGetBlendInfo(GrXferProcessor::BlendInfo * blendInfo) const358 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override {
359 blendInfo->fEquation = fBlendFormula.fBlendEquation;
360 blendInfo->fSrcBlend = fBlendFormula.fSrcCoeff;
361 blendInfo->fDstBlend = fBlendFormula.fDstCoeff;
362 blendInfo->fWriteColor = fBlendFormula.modifiesDst();
363 }
364
onIsEqual(const GrXferProcessor & xpBase) const365 bool onIsEqual(const GrXferProcessor& xpBase) const override {
366 const PorterDuffXferProcessor& xp = xpBase.cast<PorterDuffXferProcessor>();
367 return fBlendFormula == xp.fBlendFormula;
368 }
369
370 const BlendFormula fBlendFormula;
371
372 typedef GrXferProcessor INHERITED;
373 };
374
375 ///////////////////////////////////////////////////////////////////////////////
376
append_color_output(const PorterDuffXferProcessor & xp,GrGLSLXPFragmentBuilder * fragBuilder,BlendFormula::OutputType outputType,const char * output,const char * inColor,const char * inCoverage)377 static void append_color_output(const PorterDuffXferProcessor& xp,
378 GrGLSLXPFragmentBuilder* fragBuilder,
379 BlendFormula::OutputType outputType, const char* output,
380 const char* inColor, const char* inCoverage) {
381 SkASSERT(inCoverage);
382 SkASSERT(inColor);
383 switch (outputType) {
384 case BlendFormula::kNone_OutputType:
385 fragBuilder->codeAppendf("%s = vec4(0.0);", output);
386 break;
387 case BlendFormula::kCoverage_OutputType:
388 // We can have a coverage formula while not reading coverage if there are mixed samples.
389 fragBuilder->codeAppendf("%s = %s;", output, inCoverage);
390 break;
391 case BlendFormula::kModulate_OutputType:
392 fragBuilder->codeAppendf("%s = %s * %s;", output, inColor, inCoverage);
393 break;
394 case BlendFormula::kSAModulate_OutputType:
395 fragBuilder->codeAppendf("%s = %s.a * %s;", output, inColor, inCoverage);
396 break;
397 case BlendFormula::kISAModulate_OutputType:
398 fragBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", output, inColor, inCoverage);
399 break;
400 case BlendFormula::kISCModulate_OutputType:
401 fragBuilder->codeAppendf("%s = (vec4(1.0) - %s) * %s;", output, inColor, inCoverage);
402 break;
403 default:
404 SkFAIL("Unsupported output type.");
405 break;
406 }
407 }
408
409 class GLPorterDuffXferProcessor : public GrGLSLXferProcessor {
410 public:
GenKey(const GrProcessor & processor,GrProcessorKeyBuilder * b)411 static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) {
412 const PorterDuffXferProcessor& xp = processor.cast<PorterDuffXferProcessor>();
413 b->add32(xp.getBlendFormula().fPrimaryOutputType |
414 (xp.getBlendFormula().fSecondaryOutputType << 3));
415 GR_STATIC_ASSERT(BlendFormula::kLast_OutputType < 8);
416 }
417
418 private:
emitOutputsForBlendState(const EmitArgs & args)419 void emitOutputsForBlendState(const EmitArgs& args) override {
420 const PorterDuffXferProcessor& xp = args.fXP.cast<PorterDuffXferProcessor>();
421 GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
422
423 BlendFormula blendFormula = xp.getBlendFormula();
424 if (blendFormula.hasSecondaryOutput()) {
425 append_color_output(xp, fragBuilder, blendFormula.fSecondaryOutputType,
426 args.fOutputSecondary, args.fInputColor, args.fInputCoverage);
427 }
428 append_color_output(xp, fragBuilder, blendFormula.fPrimaryOutputType,
429 args.fOutputPrimary, args.fInputColor, args.fInputCoverage);
430 }
431
onSetData(const GrGLSLProgramDataManager &,const GrXferProcessor &)432 void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
433
434 typedef GrGLSLXferProcessor INHERITED;
435 };
436
437 ///////////////////////////////////////////////////////////////////////////////
438
onGetGLSLProcessorKey(const GrShaderCaps &,GrProcessorKeyBuilder * b) const439 void PorterDuffXferProcessor::onGetGLSLProcessorKey(const GrShaderCaps&,
440 GrProcessorKeyBuilder* b) const {
441 GLPorterDuffXferProcessor::GenKey(*this, b);
442 }
443
createGLSLInstance() const444 GrGLSLXferProcessor* PorterDuffXferProcessor::createGLSLInstance() const {
445 return new GLPorterDuffXferProcessor;
446 }
447
onGetOptimizations(const FragmentProcessorAnalysis & analysis) const448 GrXferProcessor::OptFlags PorterDuffXferProcessor::onGetOptimizations(
449 const FragmentProcessorAnalysis& analysis) const {
450 GrXferProcessor::OptFlags optFlags = GrXferProcessor::kNone_OptFlags;
451 if (!fBlendFormula.modifiesDst()) {
452 optFlags |= (GrXferProcessor::kIgnoreColor_OptFlag |
453 GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag);
454 } else {
455 if (!fBlendFormula.usesInputColor()) {
456 optFlags |= GrXferProcessor::kIgnoreColor_OptFlag;
457 }
458 if (analysis.isCompatibleWithCoverageAsAlpha() &&
459 fBlendFormula.canTweakAlphaForCoverage()) {
460 optFlags |= GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag;
461 }
462 }
463 return optFlags;
464 }
465
466 ///////////////////////////////////////////////////////////////////////////////
467
468 class ShaderPDXferProcessor : public GrXferProcessor {
469 public:
ShaderPDXferProcessor(const DstTexture * dstTexture,bool hasMixedSamples,SkBlendMode xfermode)470 ShaderPDXferProcessor(const DstTexture* dstTexture,
471 bool hasMixedSamples,
472 SkBlendMode xfermode)
473 : INHERITED(dstTexture, true, hasMixedSamples)
474 , fXfermode(xfermode) {
475 this->initClassID<ShaderPDXferProcessor>();
476 }
477
name() const478 const char* name() const override { return "Porter Duff Shader"; }
479
480 GrGLSLXferProcessor* createGLSLInstance() const override;
481
getXfermode() const482 SkBlendMode getXfermode() const { return fXfermode; }
483
484 private:
onGetOptimizations(const FragmentProcessorAnalysis &) const485 GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&) const override {
486 return kNone_OptFlags;
487 }
488
489 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
490
onIsEqual(const GrXferProcessor & xpBase) const491 bool onIsEqual(const GrXferProcessor& xpBase) const override {
492 const ShaderPDXferProcessor& xp = xpBase.cast<ShaderPDXferProcessor>();
493 return fXfermode == xp.fXfermode;
494 }
495
496 const SkBlendMode fXfermode;
497
498 typedef GrXferProcessor INHERITED;
499 };
500
501 ///////////////////////////////////////////////////////////////////////////////
502
503 class GLShaderPDXferProcessor : public GrGLSLXferProcessor {
504 public:
GenKey(const GrProcessor & processor,GrProcessorKeyBuilder * b)505 static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) {
506 const ShaderPDXferProcessor& xp = processor.cast<ShaderPDXferProcessor>();
507 b->add32((int)xp.getXfermode());
508 }
509
510 private:
emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder * fragBuilder,GrGLSLUniformHandler * uniformHandler,const char * srcColor,const char * srcCoverage,const char * dstColor,const char * outColor,const char * outColorSecondary,const GrXferProcessor & proc)511 void emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder* fragBuilder,
512 GrGLSLUniformHandler* uniformHandler,
513 const char* srcColor,
514 const char* srcCoverage,
515 const char* dstColor,
516 const char* outColor,
517 const char* outColorSecondary,
518 const GrXferProcessor& proc) override {
519 const ShaderPDXferProcessor& xp = proc.cast<ShaderPDXferProcessor>();
520
521 GrGLSLBlend::AppendMode(fragBuilder, srcColor, dstColor, outColor, xp.getXfermode());
522
523 // Apply coverage.
524 INHERITED::DefaultCoverageModulation(fragBuilder, srcCoverage, dstColor, outColor,
525 outColorSecondary, xp);
526 }
527
onSetData(const GrGLSLProgramDataManager &,const GrXferProcessor &)528 void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
529
530 typedef GrGLSLXferProcessor INHERITED;
531 };
532
533 ///////////////////////////////////////////////////////////////////////////////
534
onGetGLSLProcessorKey(const GrShaderCaps &,GrProcessorKeyBuilder * b) const535 void ShaderPDXferProcessor::onGetGLSLProcessorKey(const GrShaderCaps&,
536 GrProcessorKeyBuilder* b) const {
537 GLShaderPDXferProcessor::GenKey(*this, b);
538 }
539
createGLSLInstance() const540 GrGLSLXferProcessor* ShaderPDXferProcessor::createGLSLInstance() const {
541 return new GLShaderPDXferProcessor;
542 }
543
544 ///////////////////////////////////////////////////////////////////////////////
545
546 class PDLCDXferProcessor : public GrXferProcessor {
547 public:
548 static GrXferProcessor* Create(SkBlendMode xfermode, const FragmentProcessorAnalysis& analysis);
549
550 ~PDLCDXferProcessor() override;
551
name() const552 const char* name() const override { return "Porter Duff LCD"; }
553
554 GrGLSLXferProcessor* createGLSLInstance() const override;
555
alpha() const556 uint8_t alpha() const { return fAlpha; }
557
558 private:
559 PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha);
560
561 GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&) const override;
562
563 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
564
onGetBlendInfo(GrXferProcessor::BlendInfo * blendInfo) const565 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override {
566 blendInfo->fSrcBlend = kConstC_GrBlendCoeff;
567 blendInfo->fDstBlend = kISC_GrBlendCoeff;
568 blendInfo->fBlendConstant = fBlendConstant;
569 }
570
onIsEqual(const GrXferProcessor & xpBase) const571 bool onIsEqual(const GrXferProcessor& xpBase) const override {
572 const PDLCDXferProcessor& xp = xpBase.cast<PDLCDXferProcessor>();
573 if (fBlendConstant != xp.fBlendConstant || fAlpha != xp.fAlpha) {
574 return false;
575 }
576 return true;
577 }
578
579 GrColor fBlendConstant;
580 uint8_t fAlpha;
581
582 typedef GrXferProcessor INHERITED;
583 };
584
585 ///////////////////////////////////////////////////////////////////////////////
586
587 class GLPDLCDXferProcessor : public GrGLSLXferProcessor {
588 public:
GLPDLCDXferProcessor(const GrProcessor &)589 GLPDLCDXferProcessor(const GrProcessor&) : fLastAlpha(SK_MaxU32) {}
590
~GLPDLCDXferProcessor()591 ~GLPDLCDXferProcessor() override {}
592
GenKey(const GrProcessor & processor,const GrShaderCaps & caps,GrProcessorKeyBuilder * b)593 static void GenKey(const GrProcessor& processor, const GrShaderCaps& caps,
594 GrProcessorKeyBuilder* b) {}
595
596 private:
emitOutputsForBlendState(const EmitArgs & args)597 void emitOutputsForBlendState(const EmitArgs& args) override {
598 const char* alpha;
599 fAlphaUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat_GrSLType,
600 kDefault_GrSLPrecision, "alpha", &alpha);
601 GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
602 // We want to force our primary output to be alpha * Coverage, where alpha is the alpha
603 // value of the src color. We know that there are no color stages (or we wouldn't have
604 // created this xp) and the r,g, and b channels of the op's input color are baked into the
605 // blend constant.
606 SkASSERT(args.fInputCoverage);
607 fragBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, alpha, args.fInputCoverage);
608 }
609
onSetData(const GrGLSLProgramDataManager & pdm,const GrXferProcessor & xp)610 void onSetData(const GrGLSLProgramDataManager& pdm, const GrXferProcessor& xp) override {
611 uint32_t alpha = SkToU32(xp.cast<PDLCDXferProcessor>().alpha());
612 if (fLastAlpha != alpha) {
613 pdm.set1f(fAlphaUniform, alpha / 255.f);
614 fLastAlpha = alpha;
615 }
616 }
617
618 GrGLSLUniformHandler::UniformHandle fAlphaUniform;
619 uint32_t fLastAlpha;
620 typedef GrGLSLXferProcessor INHERITED;
621 };
622
623 ///////////////////////////////////////////////////////////////////////////////
624
PDLCDXferProcessor(GrColor blendConstant,uint8_t alpha)625 PDLCDXferProcessor::PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha)
626 : fBlendConstant(blendConstant)
627 , fAlpha(alpha) {
628 this->initClassID<PDLCDXferProcessor>();
629 }
630
Create(SkBlendMode xfermode,const FragmentProcessorAnalysis & analysis)631 GrXferProcessor* PDLCDXferProcessor::Create(SkBlendMode xfermode,
632 const FragmentProcessorAnalysis& analysis) {
633 if (SkBlendMode::kSrcOver != xfermode) {
634 return nullptr;
635 }
636 GrColor blendConstant;
637 if (!analysis.hasKnownOutputColor(&blendConstant)) {
638 return nullptr;
639 }
640 blendConstant = GrUnpremulColor(blendConstant);
641 uint8_t alpha = GrColorUnpackA(blendConstant);
642 blendConstant |= (0xff << GrColor_SHIFT_A);
643 return new PDLCDXferProcessor(blendConstant, alpha);
644 }
645
~PDLCDXferProcessor()646 PDLCDXferProcessor::~PDLCDXferProcessor() {
647 }
648
onGetGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const649 void PDLCDXferProcessor::onGetGLSLProcessorKey(const GrShaderCaps& caps,
650 GrProcessorKeyBuilder* b) const {
651 GLPDLCDXferProcessor::GenKey(*this, caps, b);
652 }
653
createGLSLInstance() const654 GrGLSLXferProcessor* PDLCDXferProcessor::createGLSLInstance() const {
655 return new GLPDLCDXferProcessor(*this);
656 }
657
onGetOptimizations(const FragmentProcessorAnalysis &) const658 GrXferProcessor::OptFlags PDLCDXferProcessor::onGetOptimizations(
659 const FragmentProcessorAnalysis&) const {
660 return GrXferProcessor::kIgnoreColor_OptFlag;
661 }
662
663 ///////////////////////////////////////////////////////////////////////////////
664
GrPorterDuffXPFactory(SkBlendMode xfermode)665 constexpr GrPorterDuffXPFactory::GrPorterDuffXPFactory(SkBlendMode xfermode)
666 : fBlendMode(xfermode) {}
667
Get(SkBlendMode blendMode)668 const GrXPFactory* GrPorterDuffXPFactory::Get(SkBlendMode blendMode) {
669 SkASSERT((unsigned)blendMode <= (unsigned)SkBlendMode::kLastCoeffMode);
670
671 // If these objects are constructed as static constexpr by cl.exe (2015 SP2) the vtables are
672 // null.
673 #ifdef SK_BUILD_FOR_WIN
674 #define _CONSTEXPR_
675 #else
676 #define _CONSTEXPR_ constexpr
677 #endif
678 static _CONSTEXPR_ const GrPorterDuffXPFactory gClearPDXPF(SkBlendMode::kClear);
679 static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcPDXPF(SkBlendMode::kSrc);
680 static _CONSTEXPR_ const GrPorterDuffXPFactory gDstPDXPF(SkBlendMode::kDst);
681 static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcOverPDXPF(SkBlendMode::kSrcOver);
682 static _CONSTEXPR_ const GrPorterDuffXPFactory gDstOverPDXPF(SkBlendMode::kDstOver);
683 static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcInPDXPF(SkBlendMode::kSrcIn);
684 static _CONSTEXPR_ const GrPorterDuffXPFactory gDstInPDXPF(SkBlendMode::kDstIn);
685 static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcOutPDXPF(SkBlendMode::kSrcOut);
686 static _CONSTEXPR_ const GrPorterDuffXPFactory gDstOutPDXPF(SkBlendMode::kDstOut);
687 static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcATopPDXPF(SkBlendMode::kSrcATop);
688 static _CONSTEXPR_ const GrPorterDuffXPFactory gDstATopPDXPF(SkBlendMode::kDstATop);
689 static _CONSTEXPR_ const GrPorterDuffXPFactory gXorPDXPF(SkBlendMode::kXor);
690 static _CONSTEXPR_ const GrPorterDuffXPFactory gPlusPDXPF(SkBlendMode::kPlus);
691 static _CONSTEXPR_ const GrPorterDuffXPFactory gModulatePDXPF(SkBlendMode::kModulate);
692 static _CONSTEXPR_ const GrPorterDuffXPFactory gScreenPDXPF(SkBlendMode::kScreen);
693 #undef _CONSTEXPR_
694
695 switch (blendMode) {
696 case SkBlendMode::kClear:
697 return &gClearPDXPF;
698 case SkBlendMode::kSrc:
699 return &gSrcPDXPF;
700 case SkBlendMode::kDst:
701 return &gDstPDXPF;
702 case SkBlendMode::kSrcOver:
703 return &gSrcOverPDXPF;
704 case SkBlendMode::kDstOver:
705 return &gDstOverPDXPF;
706 case SkBlendMode::kSrcIn:
707 return &gSrcInPDXPF;
708 case SkBlendMode::kDstIn:
709 return &gDstInPDXPF;
710 case SkBlendMode::kSrcOut:
711 return &gSrcOutPDXPF;
712 case SkBlendMode::kDstOut:
713 return &gDstOutPDXPF;
714 case SkBlendMode::kSrcATop:
715 return &gSrcATopPDXPF;
716 case SkBlendMode::kDstATop:
717 return &gDstATopPDXPF;
718 case SkBlendMode::kXor:
719 return &gXorPDXPF;
720 case SkBlendMode::kPlus:
721 return &gPlusPDXPF;
722 case SkBlendMode::kModulate:
723 return &gModulatePDXPF;
724 case SkBlendMode::kScreen:
725 return &gScreenPDXPF;
726 default:
727 SkFAIL("Unexpected blend mode.");
728 return nullptr;
729 }
730 }
731
onCreateXferProcessor(const GrCaps & caps,const FragmentProcessorAnalysis & analysis,bool hasMixedSamples,const DstTexture * dstTexture) const732 GrXferProcessor* GrPorterDuffXPFactory::onCreateXferProcessor(
733 const GrCaps& caps,
734 const FragmentProcessorAnalysis& analysis,
735 bool hasMixedSamples,
736 const DstTexture* dstTexture) const {
737 BlendFormula blendFormula;
738 if (analysis.outputCoverageType() == GrPipelineAnalysisCoverage::kLCD) {
739 if (SkBlendMode::kSrcOver == fBlendMode && analysis.hasKnownOutputColor() &&
740 !caps.shaderCaps()->dualSourceBlendingSupport() &&
741 !caps.shaderCaps()->dstReadInShaderSupport()) {
742 // If we don't have dual source blending or in shader dst reads, we fall back to this
743 // trick for rendering SrcOver LCD text instead of doing a dst copy.
744 SkASSERT(!dstTexture || !dstTexture->texture());
745 return PDLCDXferProcessor::Create(fBlendMode, analysis);
746 }
747 blendFormula = get_lcd_blend_formula(fBlendMode);
748 } else {
749 blendFormula = get_blend_formula(analysis.isOutputColorOpaque(), analysis.hasCoverage(),
750 hasMixedSamples, fBlendMode);
751 }
752
753 if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) {
754 return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, fBlendMode);
755 }
756
757 SkASSERT(!dstTexture || !dstTexture->texture());
758 return new PorterDuffXferProcessor(blendFormula);
759 }
760
canCombineOverlappedStencilAndCover(bool colorIsOpaque) const761 bool GrPorterDuffXPFactory::canCombineOverlappedStencilAndCover(bool colorIsOpaque) const {
762 // Ignore the effect of coverage here.
763 BlendFormula colorFormula = gBlendTable[colorIsOpaque][0][(int)fBlendMode];
764 SkASSERT(kAdd_GrBlendEquation == colorFormula.fBlendEquation);
765 return !colorFormula.usesDstColor();
766 }
767
willReadDstInShader(const GrCaps & caps,const FragmentProcessorAnalysis & analysis) const768 bool GrPorterDuffXPFactory::willReadDstInShader(const GrCaps& caps,
769 const FragmentProcessorAnalysis& analysis) const {
770 if (caps.shaderCaps()->dualSourceBlendingSupport()) {
771 return false;
772 }
773
774 // When we have four channel coverage we always need to read the dst in order to correctly
775 // blend. The one exception is when we are using srcover mode and we know the input color into
776 // the XP.
777 if (analysis.outputCoverageType() == GrPipelineAnalysisCoverage::kLCD) {
778 if (SkBlendMode::kSrcOver == fBlendMode && analysis.hasKnownOutputColor() &&
779 !caps.shaderCaps()->dstReadInShaderSupport()) {
780 return false;
781 }
782 return get_lcd_blend_formula(fBlendMode).hasSecondaryOutput();
783 }
784
785 // We fallback on the shader XP when the blend formula would use dual source blending but we
786 // don't have support for it.
787 static const bool kHasMixedSamples = false;
788 SkASSERT(!caps.usesMixedSamples()); // We never use mixed samples without dual source blending.
789 auto formula = get_blend_formula(analysis.isOutputColorOpaque(), analysis.hasCoverage(),
790 kHasMixedSamples, fBlendMode);
791 return formula.hasSecondaryOutput();
792 }
793
compatibleWithCoverageAsAlpha(bool colorIsOpaque) const794 bool GrPorterDuffXPFactory::compatibleWithCoverageAsAlpha(bool colorIsOpaque) const {
795 // We assume we have coverage (or else this doesn't matter).
796 return gBlendTable[colorIsOpaque][1][(int)fBlendMode].canTweakAlphaForCoverage();
797 }
798
799 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory);
800
801 #if GR_TEST_UTILS
TestGet(GrProcessorTestData * d)802 const GrXPFactory* GrPorterDuffXPFactory::TestGet(GrProcessorTestData* d) {
803 SkBlendMode mode = SkBlendMode(d->fRandom->nextULessThan((int)SkBlendMode::kLastCoeffMode));
804 return GrPorterDuffXPFactory::Get(mode);
805 }
806 #endif
807
TestGetXPOutputTypes(const GrXferProcessor * xp,int * outPrimary,int * outSecondary)808 void GrPorterDuffXPFactory::TestGetXPOutputTypes(const GrXferProcessor* xp,
809 int* outPrimary,
810 int* outSecondary) {
811 if (!!strcmp(xp->name(), "Porter Duff")) {
812 *outPrimary = *outSecondary = -1;
813 return;
814 }
815 BlendFormula blendFormula = static_cast<const PorterDuffXferProcessor*>(xp)->getBlendFormula();
816 *outPrimary = blendFormula.fPrimaryOutputType;
817 *outSecondary = blendFormula.fSecondaryOutputType;
818 }
819
820 ////////////////////////////////////////////////////////////////////////////////////////////////
821 // SrcOver Global functions
822 ////////////////////////////////////////////////////////////////////////////////////////////////
SimpleSrcOverXP()823 const GrXferProcessor& GrPorterDuffXPFactory::SimpleSrcOverXP() {
824 static BlendFormula gSrcOverBlendFormula = COEFF_FORMULA(kOne_GrBlendCoeff,
825 kISA_GrBlendCoeff);
826 static PorterDuffXferProcessor gSrcOverXP(gSrcOverBlendFormula);
827 return gSrcOverXP;
828 }
829
CreateSrcOverXferProcessor(const GrCaps & caps,const FragmentProcessorAnalysis & analysis,bool hasMixedSamples,const GrXferProcessor::DstTexture * dstTexture)830 GrXferProcessor* GrPorterDuffXPFactory::CreateSrcOverXferProcessor(
831 const GrCaps& caps,
832 const FragmentProcessorAnalysis& analysis,
833 bool hasMixedSamples,
834 const GrXferProcessor::DstTexture* dstTexture) {
835
836 // We want to not make an xfer processor if possible. Thus for the simple case where we are not
837 // doing lcd blending we will just use our global SimpleSrcOverXP. This slightly differs from
838 // the general case where we convert a src-over blend that has solid coverage and an opaque
839 // color to src-mode, which allows disabling of blending.
840 if (analysis.outputCoverageType() != GrPipelineAnalysisCoverage::kLCD) {
841 // We return nullptr here, which our caller interprets as meaning "use SimpleSrcOverXP".
842 // We don't simply return the address of that XP here because our caller would have to unref
843 // it and since it is a global object and GrProgramElement's ref-cnting system is not thread
844 // safe.
845 return nullptr;
846 }
847
848 if (analysis.hasKnownOutputColor() && !caps.shaderCaps()->dualSourceBlendingSupport() &&
849 !caps.shaderCaps()->dstReadInShaderSupport()) {
850 // If we don't have dual source blending or in shader dst reads, we fall
851 // back to this trick for rendering SrcOver LCD text instead of doing a
852 // dst copy.
853 SkASSERT(!dstTexture || !dstTexture->texture());
854 return PDLCDXferProcessor::Create(SkBlendMode::kSrcOver, analysis);
855 }
856
857 BlendFormula blendFormula;
858 blendFormula = get_lcd_blend_formula(SkBlendMode::kSrcOver);
859 if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) {
860 return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, SkBlendMode::kSrcOver);
861 }
862
863 SkASSERT(!dstTexture || !dstTexture->texture());
864 return new PorterDuffXferProcessor(blendFormula);
865 }
866
CreateNoCoverageXP(SkBlendMode blendmode)867 sk_sp<GrXferProcessor> GrPorterDuffXPFactory::CreateNoCoverageXP(SkBlendMode blendmode) {
868 BlendFormula formula = get_blend_formula(false, false, false, blendmode);
869 return sk_make_sp<PorterDuffXferProcessor>(formula);
870 }
871
WillSrcOverNeedDstTexture(const GrCaps & caps,const FragmentProcessorAnalysis & analysis)872 bool GrPorterDuffXPFactory::WillSrcOverNeedDstTexture(const GrCaps& caps,
873 const FragmentProcessorAnalysis& analysis) {
874 if (caps.shaderCaps()->dstReadInShaderSupport() ||
875 caps.shaderCaps()->dualSourceBlendingSupport()) {
876 return false;
877 }
878
879 // When we have four channel coverage we always need to read the dst in order to correctly
880 // blend. The one exception is when we are using srcover mode and we know the input color
881 // into the XP.
882 if (analysis.outputCoverageType() == GrPipelineAnalysisCoverage::kLCD) {
883 if (analysis.hasKnownOutputColor() && !caps.shaderCaps()->dstReadInShaderSupport()) {
884 return false;
885 }
886 auto formula = get_lcd_blend_formula(SkBlendMode::kSrcOver);
887 return formula.hasSecondaryOutput();
888 }
889
890 // We fallback on the shader XP when the blend formula would use dual source blending but we
891 // don't have support for it.
892 static const bool kHasMixedSamples = false;
893 bool isOpaque = analysis.isOutputColorOpaque();
894 bool hasCoverage = analysis.hasCoverage();
895 SkASSERT(!caps.usesMixedSamples()); // We never use mixed samples without dual source blending.
896 auto formula =
897 get_blend_formula(isOpaque, hasCoverage, kHasMixedSamples, SkBlendMode::kSrcOver);
898 return formula.hasSecondaryOutput();
899 }
900