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