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