Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(102)

Side by Side Diff: src/gpu/effects/GrPorterDuffXferProcessor.cpp

Issue 1124373002: Implement Porter Duff XP with a blend table (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: var names Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2014 Google Inc. 2 * Copyright 2014 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "effects/GrPorterDuffXferProcessor.h" 8 #include "effects/GrPorterDuffXferProcessor.h"
9 9
10 #include "GrBlend.h" 10 #include "GrBlend.h"
11 #include "GrDrawTargetCaps.h" 11 #include "GrDrawTargetCaps.h"
12 #include "GrProcessor.h" 12 #include "GrProcessor.h"
13 #include "GrProcOptInfo.h" 13 #include "GrProcOptInfo.h"
14 #include "GrTypes.h" 14 #include "GrTypes.h"
15 #include "GrXferProcessor.h" 15 #include "GrXferProcessor.h"
16 #include "gl/GrGLXferProcessor.h" 16 #include "gl/GrGLXferProcessor.h"
17 #include "gl/builders/GrGLFragmentShaderBuilder.h" 17 #include "gl/builders/GrGLFragmentShaderBuilder.h"
18 #include "gl/builders/GrGLProgramBuilder.h" 18 #include "gl/builders/GrGLProgramBuilder.h"
19 19
20 static bool can_tweak_alpha_for_coverage(GrBlendCoeff dstCoeff) { 20 /**
21 /* 21 * Wraps the shader outputs and HW blend state that comprise a Porter Duff blend mode with coverage.
22 The fractional coverage is f. 22 */
23 The src and dst coeffs are Cs and Cd. 23 struct BlendFormula {
24 The dst and src colors are S and D. 24 public:
25 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the sou rce color's alpha 25 /**
26 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second 26 * Values the shader can write to primary and secondary outputs. These must all be modulated by
27 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various poss ibilities for Cd we 27 * coverage to support mixed samples. The XP will ignore the multiplies when not using coverage.
28 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
29 */ 28 */
30 return kOne_GrBlendCoeff == dstCoeff || 29 enum OutputType {
31 kISA_GrBlendCoeff == dstCoeff || 30 kNone_OutputType, //<! 0
32 kISC_GrBlendCoeff == dstCoeff; 31 kCoverage_OutputType, //<! inputCoverage
32 kModulate_OutputType, //<! inputColor * inputCoverage
33 kISAModulate_OutputType, //<! (1 - inputColor.a) * inputCoverage
34 kISCModulate_OutputType, //<! (1 - inputColor) * inputCoverage
35
36 kLast_OutputType = kISCModulate_OutputType
37 };
38
39 enum Properties {
40 kModifiesDst_Property = 1,
41 kUsesDstColor_Property = 1 << 1,
42 kUsesGrPaintColor_Property = 1 << 2,
43 kCanTweakAlphaForCoverage_Property = 1 << 3,
44
45 kLast_Property = kCanTweakAlphaForCoverage_Property
46 };
47
48 BlendFormula& operator =(const BlendFormula& other) {
49 fData = other.fData;
50 return *this;
51 }
52
53 bool operator ==(const BlendFormula& other) const {
54 return fData == other.fData;
55 }
56
57 bool hasSecondaryOutput() const { return kNone_OutputType != fSecondaryOutpu tType; }
58 bool modifiesDst() const { return fProps & kModifiesDst_Property; }
59 bool usesDstColor() const { return fProps & kUsesDstColor_Property; }
60 bool usesGrPaintColor() const { return fProps & kUsesGrPaintColor_Property; }
61 bool canTweakAlphaForCoverage() const { return fProps & kCanTweakAlphaForCov erage_Property; }
62
63 /**
64 * Deduce the properties of a compile-time constant BlendFormula.
65 */
66 template<OutputType PrimaryOut, OutputType SecondaryOut,
67 GrBlendEquation BlendEquation, GrBlendCoeff SrcCoeff, GrBlendCoeff DstCoeff>
68 struct get_properties : SkTIntegralConstant<Properties, static_cast<Properti es>(
69
70 (GR_BLEND_MODIFIES_DST(BlendEquation, SrcCoeff, DstCoeff) ?
71 kModifiesDst_Property : 0) |
72
73 (GR_BLEND_COEFFS_USE_DST_COLOR(SrcCoeff, DstCoeff) ?
74 kUsesDstColor_Property : 0) |
75
76 ((PrimaryOut >= kModulate_OutputType && GR_BLEND_COEFFS_USE_SRC_COLOR(Sr cCoeff,DstCoeff)) ||
77 (SecondaryOut >= kModulate_OutputType && GR_BLEND_COEFF_REFS_SRC2(DstCo eff)) ?
78 kUsesGrPaintColor_Property : 0) | // We assert later that SrcCoeff doesn't ref src2.
79
80 (kModulate_OutputType == PrimaryOut &&
81 kNone_OutputType == SecondaryOut &&
82 GR_BLEND_CAN_TWEAK_ALPHA_FOR_COVERAGE(BlendEquation, SrcCoeff, DstCoeff ) ?
83 kCanTweakAlphaForCoverage_Property : 0))> {
84
85 // The provided formula should already be optimized.
86 GR_STATIC_ASSERT((kNone_OutputType == PrimaryOut) ==
87 !GR_BLEND_COEFFS_USE_SRC_COLOR(SrcCoeff, DstCoeff));
88 GR_STATIC_ASSERT(!GR_BLEND_COEFF_REFS_SRC2(SrcCoeff));
89 GR_STATIC_ASSERT((kNone_OutputType == SecondaryOut) ==
90 !GR_BLEND_COEFF_REFS_SRC2(DstCoeff));
91 GR_STATIC_ASSERT(PrimaryOut != SecondaryOut || kNone_OutputType == Prima ryOut);
92 GR_STATIC_ASSERT(kNone_OutputType != PrimaryOut || kNone_OutputType == S econdaryOut);
93 };
94
95 union {
96 struct {
97 OutputType fPrimaryOutputType : 3;
98 OutputType fSecondaryOutputType : 3;
99 GrBlendEquation fBlendEquation : 5;
100 GrBlendCoeff fSrcCoeff : 5;
101 GrBlendCoeff fDstCoeff : 5;
102 Properties fProps : (32 - 3 - 3 - 5 - 5 - 5);
103 };
104 uint32_t fData;
105 };
106 };
107
108 GR_STATIC_ASSERT(4 == sizeof(BlendFormula));
109
110 GR_MAKE_BITFIELD_OPS(BlendFormula::Properties);
111
112 /**
113 * Initialize a compile-time constant BlendFormula and automatically deduce fPro ps.
114 */
115 #define INIT_BLEND_FORMULA(PRIMARY_OUT, SECONDARY_OUT, BLEND_EQUATION, SRC_COEFF , DST_COEFF) \
116 {PRIMARY_OUT, \
117 SECONDARY_OUT, \
118 BLEND_EQUATION, SRC_COEFF, DST_COEFF, \
119 BlendFormula::get_properties<PRIMARY_OUT, SECONDARY_OUT, \
120 BLEND_EQUATION, SRC_COEFF, DST_COEFF>::value}
121
122 /**
123 * When there is no coverage, or the blend mode can tweak alpha for coverage, we use the standard
124 * Porter Duff formula.
125 */
126 #define COEFF_FORMULA(SRC_COEFF, DST_COEFF) \
127 INIT_BLEND_FORMULA(BlendFormula::kModulate_OutputType, \
128 BlendFormula::kNone_OutputType, \
129 kAdd_GrBlendEquation, SRC_COEFF, DST_COEFF)
130
131 /**
132 * When the coeffs are (Zero, Zero), we clear the dst. This formula has its own macro so we can set
133 * the primary output type to none.
Chris Dalton 2015/05/19 21:47:13 <copying this comment from before so it doesn't ge
134 *
135 * Xfer modes: clear, dst-out (Sa=1)
136 */
137 #define DST_CLEAR_FORMULA \
138 INIT_BLEND_FORMULA(BlendFormula::kNone_OutputType, \
139 BlendFormula::kNone_OutputType, \
140 kAdd_GrBlendEquation, kZero_GrBlendCoeff, kZero_GrBlendCo eff)
141
142 /**
143 * When the coeffs are (Zero, One), we don't write to the dst at all. This formu la has its own macro
144 * so we can set the primary output type to none.
145 *
146 * Xfer modes: dst, dst-in (Sa=1), modulate (Sc=1)
147 */
148 #define NO_DST_WRITE_FORMULA \
149 INIT_BLEND_FORMULA(BlendFormula::kNone_OutputType, \
150 BlendFormula::kNone_OutputType, \
151 kAdd_GrBlendEquation, kZero_GrBlendCoeff, kOne_GrBlendCoe ff)
152
153 /**
154 * When there is coverage, the equation with f=coverage is:
155 *
156 * D' = f * (S * srcCoeff + D * dstCoeff) + (1-f) * D
157 *
158 * This can be rewritten as:
159 *
160 * D' = f * S * srcCoeff + D * (1 - [f * (1 - dstCoeff)])
161 *
162 * To implement this formula, we output [f * (1 - dstCoeff)] for the secondary c olor and replace the
163 * HW dst coeff with IS2C.
164 *
165 * Xfer modes: dst-atop (Sa!=1)
166 */
167 #define COVERAGE_FORMULA(ONE_MINUS_DST_COEFF_MODULATE_OUTPUT, SRC_COEFF) \
168 INIT_BLEND_FORMULA(BlendFormula::kModulate_OutputType, \
169 ONE_MINUS_DST_COEFF_MODULATE_OUTPUT, \
170 kAdd_GrBlendEquation, SRC_COEFF, kIS2C_GrBlendCoeff)
171
172 /**
173 * When there is coverage and the src coeff is Zero, the equation with f=coverag e becomes:
174 *
175 * D' = f * D * dstCoeff + (1-f) * D
176 *
177 * This can be rewritten as:
178 *
179 * D' = D - D * [f * (1 - dstCoeff)]
180 *
181 * To implement this formula, we output [f * (1 - dstCoeff)] for the primary col or and use a reverse
182 * subtract HW blend equation with coeffs of (DC, One).
183 *
184 * Xfer modes: clear, dst-in (Sa!=1), modulate (Sc!=1)
185 */
186 #define COVERAGE_SRC_COEFF_ZERO_FORMULA(ONE_MINUS_DST_COEFF_MODULATE_OUTPUT) \
187 INIT_BLEND_FORMULA(ONE_MINUS_DST_COEFF_MODULATE_OUTPUT, \
188 BlendFormula::kNone_OutputType, \
189 kReverseSubtract_GrBlendEquation, kDC_GrBlendCoeff, kOne_ GrBlendCoeff)
190
191 /**
192 * When there is coverage and the dst coeff is Zero, the equation with f=coverag e becomes:
193 *
194 * D' = f * S * srcCoeff + (1-f) * D
195 *
196 * To implement this formula, we output [f] for the secondary color and replace the HW dst coeff
197 * with IS2A. (Note that we can avoid dual source blending when Sa=1 by using IS A.)
198 *
199 * Xfer modes (Sa!=1): src, src-in, src-out
200 */
201 #define COVERAGE_DST_COEFF_ZERO_FORMULA(SRC_COEFF) \
202 INIT_BLEND_FORMULA(BlendFormula::kModulate_OutputType, \
203 BlendFormula::kCoverage_OutputType, \
204 kAdd_GrBlendEquation, SRC_COEFF, kIS2A_GrBlendCoeff)
205
206 /**
207 * This table outlines the blend formulas we use with all combinations of color, coverage, and
208 * Xfermode. Optimization flags are deduced at compile so there is no need for r un-time analysis.
209 * RGB coverage is not supported. Each entry is 32 bits so the entire table only takes up 360 bytes.
210 */
211 static const BlendFormula gBlendTable[3][2][SkXfermode::kLastCoeffMode + 1] = {
212
213 /*>> Has coverage, input color unknown: <<*/ {{
214
215 /* clear */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_Out putType),
216 /* src */ COVERAGE_DST_COEFF_ZERO_FORMULA(kOne_GrBlendCoeff),
217 /* dst */ NO_DST_WRITE_FORMULA,
218 /* src-over */ COEFF_FORMULA( kOne_GrBlendCoeff, kISA_GrBlendCoeff),
219 /* dst-over */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
220 /* src-in */ COVERAGE_DST_COEFF_ZERO_FORMULA(kDA_GrBlendCoeff),
221 /* dst-in */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISAModulate_ OutputType),
222 /* src-out */ COVERAGE_DST_COEFF_ZERO_FORMULA(kIDA_GrBlendCoeff),
223 /* dst-out */ COEFF_FORMULA( kZero_GrBlendCoeff, kISA_GrBlendCoeff),
224 /* src-atop */ COEFF_FORMULA( kDA_GrBlendCoeff, kISA_GrBlendCoeff),
225 /* dst-atop */ COVERAGE_FORMULA(BlendFormula::kISAModulate_OutputType, kID A_GrBlendCoeff),
226 /* xor */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff),
227 /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff),
228 /* modulate */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISCModulate_ OutputType),
229 /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff),
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 opaque: <<*/ {{
250
251 /* clear */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_Out putType),
252 /* src */ COEFF_FORMULA( kOne_GrBlendCoeff, kISA_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 */ COEFF_FORMULA( kDA_GrBlendCoeff, kISA_GrBlendCoeff),
257 /* dst-in */ NO_DST_WRITE_FORMULA,
258 /* src-out */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff),
259 /* dst-out */ COEFF_FORMULA( kZero_GrBlendCoeff, kISA_GrBlendCoeff),
260 /* src-atop */ COEFF_FORMULA( kDA_GrBlendCoeff, kISA_GrBlendCoeff),
261 /* dst-atop */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_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 solid white: <<*/ {{
286
287 /* clear */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_Out putType),
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 */ COEFF_FORMULA( kZero_GrBlendCoeff, kISA_GrBlendCoeff),
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 */ NO_DST_WRITE_FORMULA,
301 /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff),
302
303 }, /*>> No coverage, input solid white: <<*/ {
304
305 /* clear */ DST_CLEAR_FORMULA,
306 /* src */ COEFF_FORMULA( kOne_GrBlendCoeff, kZero_GrBlendCoeff),
307 /* dst */ NO_DST_WRITE_FORMULA,
308 /* src-over */ COEFF_FORMULA( kOne_GrBlendCoeff, kZero_GrBlendCoeff),
309 /* dst-over */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
310 /* src-in */ COEFF_FORMULA( kDA_GrBlendCoeff, kZero_GrBlendCoeff),
311 /* dst-in */ NO_DST_WRITE_FORMULA,
312 /* src-out */ COEFF_FORMULA( kIDA_GrBlendCoeff, kZero_GrBlendCoeff),
313 /* dst-out */ DST_CLEAR_FORMULA,
314 /* src-atop */ COEFF_FORMULA( kDA_GrBlendCoeff, kZero_GrBlendCoeff),
315 /* dst-atop */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
316 /* xor */ COEFF_FORMULA( kIDA_GrBlendCoeff, kZero_GrBlendCoeff),
317 /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff),
318 /* modulate */ NO_DST_WRITE_FORMULA,
319 /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kZero_GrBlendCoeff),
320 }}};
321
322 static BlendFormula get_unoptimized_blend_formula(SkXfermode::Mode xfermode) {
323 SkASSERT(xfermode >= 0 && xfermode <= SkXfermode::kLastCoeffMode);
324 return gBlendTable[0][0][xfermode];
33 } 325 }
34 326
327 static BlendFormula get_blend_formula(SkXfermode::Mode xfermode,
328 const GrProcOptInfo& colorPOI,
329 const GrProcOptInfo& coveragePOI) {
330 SkASSERT(xfermode >= 0 && xfermode <= SkXfermode::kLastCoeffMode);
331 SkASSERT(!colorPOI.isSolidWhite() || colorPOI.isOpaque());
332 SkASSERT(!coveragePOI.isFourChannelOutput());
333
334 // colorTraits: 0 - unknown, 1 - opaque, 2 - solid white.
335 int colorTraits = colorPOI.isOpaque() + colorPOI.isSolidWhite();
336 bool fullCoverage = coveragePOI.isSolidWhite();
337 return gBlendTable[colorTraits][fullCoverage][xfermode];
338 }
339
340 GR_STATIC_ASSERT(0 == SkXfermode::kClear_Mode);
341 GR_STATIC_ASSERT(1 == SkXfermode::kSrc_Mode);
342 GR_STATIC_ASSERT(2 == SkXfermode::kDst_Mode);
343 GR_STATIC_ASSERT(3 == SkXfermode::kSrcOver_Mode);
344 GR_STATIC_ASSERT(4 == SkXfermode::kDstOver_Mode);
345 GR_STATIC_ASSERT(5 == SkXfermode::kSrcIn_Mode);
346 GR_STATIC_ASSERT(6 == SkXfermode::kDstIn_Mode);
347 GR_STATIC_ASSERT(7 == SkXfermode::kSrcOut_Mode);
348 GR_STATIC_ASSERT(8 == SkXfermode::kDstOut_Mode);
349 GR_STATIC_ASSERT(9 == SkXfermode::kSrcATop_Mode);
350 GR_STATIC_ASSERT(10 == SkXfermode::kDstATop_Mode);
351 GR_STATIC_ASSERT(11 == SkXfermode::kXor_Mode);
352 GR_STATIC_ASSERT(12 == SkXfermode::kPlus_Mode);
353 GR_STATIC_ASSERT(13 == SkXfermode::kModulate_Mode);
354 GR_STATIC_ASSERT(14 == SkXfermode::kScreen_Mode);
355 GR_STATIC_ASSERT(15 * 2 * 3 * sizeof(BlendFormula) == sizeof(gBlendTable));
356
357 ///////////////////////////////////////////////////////////////////////////////
358
35 class PorterDuffXferProcessor : public GrXferProcessor { 359 class PorterDuffXferProcessor : public GrXferProcessor {
36 public: 360 public:
37 static GrXferProcessor* Create(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, 361 static GrXferProcessor* Create(SkXfermode::Mode xfermode, const GrDeviceCoor dTexture* dstCopy,
38 GrColor constant, const GrDeviceCoordTexture* dstCopy,
39 bool willReadDstColor) { 362 bool willReadDstColor) {
40 return SkNEW_ARGS(PorterDuffXferProcessor, (srcBlend, dstBlend, constant , dstCopy, 363 return SkNEW_ARGS(PorterDuffXferProcessor, (xfermode, dstCopy, willReadD stColor));
41 willReadDstColor));
42 } 364 }
43 365
44 ~PorterDuffXferProcessor() override; 366 ~PorterDuffXferProcessor() override;
45 367
46 const char* name() const override { return "Porter Duff"; } 368 const char* name() const override { return "Porter Duff"; }
47 369
48 GrGLXferProcessor* createGLInstance() const override; 370 GrGLXferProcessor* createGLInstance() const override;
49 371
50 bool hasSecondaryOutput() const override; 372 bool hasSecondaryOutput() const override {
373 return fBlendFormula.hasSecondaryOutput();
374 }
51 375
52 /////////////////////////////////////////////////////////////////////////// 376 SkXfermode::Mode getXfermode() const { return fXfermode; }
53 /// @name Stage Output Types 377 BlendFormula getBlendFormula() const { return fBlendFormula; }
54 ////
55
56 enum PrimaryOutputType {
57 kNone_PrimaryOutputType,
58 kColor_PrimaryOutputType,
59 kCoverage_PrimaryOutputType,
60 // Modulate color and coverage, write result as the color output.
61 kModulate_PrimaryOutputType,
62 // Custom Porter-Duff output, used for when we explictly are reading the dst and blending
63 // in the shader. Secondary Output must be none if you use this. The cus tom blend uses the
64 // equation: cov * (coeffS * S + coeffD * D) + (1 - cov) * D
65 kCustom_PrimaryOutputType
66 };
67
68 enum SecondaryOutputType {
69 // There is no secondary output
70 kNone_SecondaryOutputType,
71 // Writes coverage as the secondary output. Only set if dual source blen ding is supported
72 // and primary output is kModulate.
73 kCoverage_SecondaryOutputType,
74 // Writes coverage * (1 - colorA) as the secondary output. Only set if d ual source blending
75 // is supported and primary output is kModulate.
76 kCoverageISA_SecondaryOutputType,
77 // Writes coverage * (1 - colorRGBA) as the secondary output. Only set i f dual source
78 // blending is supported and primary output is kModulate.
79 kCoverageISC_SecondaryOutputType,
80
81 kSecondaryOutputTypeCnt,
82 };
83
84 PrimaryOutputType primaryOutputType() const { return fPrimaryOutputType; }
85 SecondaryOutputType secondaryOutputType() const { return fSecondaryOutputTyp e; }
86
87 GrBlendCoeff getSrcBlend() const { return fSrcBlend; }
88 GrBlendCoeff getDstBlend() const { return fDstBlend; }
89 378
90 private: 379 private:
91 PorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, GrColo r constant, 380 PorterDuffXferProcessor(SkXfermode::Mode, const GrDeviceCoordTexture* dstCop y,
92 const GrDeviceCoordTexture* dstCopy, bool willReadDs tColor); 381 bool willReadDstColor);
93 382
94 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI, 383 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI,
95 const GrProcOptInfo& coveragePO I, 384 const GrProcOptInfo& coveragePO I,
96 bool doesStencilWrite, 385 bool doesStencilWrite,
97 GrColor* overrideColor, 386 GrColor* overrideColor,
98 const GrCaps& caps) override; 387 const GrCaps& caps) override;
99 388
100 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c onst override; 389 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c onst override;
101 390
102 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override { 391 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override {
103 if (!this->willReadDstColor()) { 392 if (!this->willReadDstColor()) {
104 blendInfo->fSrcBlend = fSrcBlend; 393 blendInfo->fEquation = fBlendFormula.fBlendEquation;
105 blendInfo->fDstBlend = fDstBlend; 394 blendInfo->fSrcBlend = fBlendFormula.fSrcCoeff;
106 } else { 395 blendInfo->fDstBlend = fBlendFormula.fDstCoeff;
107 blendInfo->fSrcBlend = kOne_GrBlendCoeff; 396 blendInfo->fWriteColor = fBlendFormula.modifiesDst();
108 blendInfo->fDstBlend = kZero_GrBlendCoeff;
109 } 397 }
110 blendInfo->fBlendConstant = fBlendConstant;
111 } 398 }
112 399
113 bool onIsEqual(const GrXferProcessor& xpBase) const override { 400 bool onIsEqual(const GrXferProcessor& xpBase) const override {
114 const PorterDuffXferProcessor& xp = xpBase.cast<PorterDuffXferProcessor> (); 401 const PorterDuffXferProcessor& xp = xpBase.cast<PorterDuffXferProcessor> ();
115 if (fSrcBlend != xp.fSrcBlend || 402 return fXfermode == xp.fXfermode &&
116 fDstBlend != xp.fDstBlend || 403 fBlendFormula == xp.fBlendFormula;
117 fBlendConstant != xp.fBlendConstant ||
118 fPrimaryOutputType != xp.fPrimaryOutputType ||
119 fSecondaryOutputType != xp.fSecondaryOutputType) {
120 return false;
121 }
122 return true;
123 } 404 }
124 405
125 GrXferProcessor::OptFlags internalGetOptimizations(const GrProcOptInfo& colo rPOI, 406 SkXfermode::Mode fXfermode;
126 const GrProcOptInfo& cove ragePOI, 407 BlendFormula fBlendFormula;
127 bool doesStencilWrite);
128
129 void calcOutputTypes(GrXferProcessor::OptFlags blendOpts, const GrCaps& caps ,
130 bool hasSolidCoverage);
131
132 GrBlendCoeff fSrcBlend;
133 GrBlendCoeff fDstBlend;
134 GrColor fBlendConstant;
135 PrimaryOutputType fPrimaryOutputType;
136 SecondaryOutputType fSecondaryOutputType;
137 408
138 typedef GrXferProcessor INHERITED; 409 typedef GrXferProcessor INHERITED;
139 }; 410 };
140 411
141 /////////////////////////////////////////////////////////////////////////////// 412 ///////////////////////////////////////////////////////////////////////////////
142 413
143 bool append_porterduff_term(GrGLXPFragmentBuilder* fsBuilder, GrBlendCoeff coeff , 414 void append_color_output(const PorterDuffXferProcessor& xp, GrGLXPFragmentBuilde r* fsBuilder,
415 BlendFormula::OutputType outputType, const char* output ,
416 const char* inColor, const char* inCoverage) {
417 switch (outputType) {
418 case BlendFormula::kNone_OutputType:
419 fsBuilder->codeAppendf("%s = vec4(0.0);", output);
420 break;
421 case BlendFormula::kCoverage_OutputType:
422 fsBuilder->codeAppendf("%s = %s;",
423 output, xp.readsCoverage() ? inCoverage : "ve c4(1.0)");
424 break;
425 case BlendFormula::kModulate_OutputType:
426 if (xp.readsCoverage()) {
427 fsBuilder->codeAppendf("%s = %s * %s;", output, inColor, inCover age);
428 } else {
429 fsBuilder->codeAppendf("%s = %s;", output, inColor);
430 }
431 break;
432 case BlendFormula::kISAModulate_OutputType:
433 if (xp.readsCoverage()) {
434 fsBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", output, inColo r, inCoverage);
435 } else {
436 fsBuilder->codeAppendf("%s = vec4(1.0 - %s.a);", output, inColor );
437 }
438 break;
439 case BlendFormula::kISCModulate_OutputType:
440 if (xp.readsCoverage()) {
441 fsBuilder->codeAppendf("%s = (vec4(1.0) - %s) * %s;", output, in Color, inCoverage);
442 } else {
443 fsBuilder->codeAppendf("%s = vec4(1.0) - %s;", output, inColor);
444 }
445 break;
446 default:
447 SkFAIL("Unsupported output type.");
448 break;
449 }
450 }
451
452 bool append_porterduff_term(GrGLXPFragmentBuilder* fsBuilder, SkXfermode::Coeff coeff,
144 const char* colorName, const char* srcColorName, 453 const char* colorName, const char* srcColorName,
145 const char* dstColorName, bool hasPrevious) { 454 const char* dstColorName, bool hasPrevious) {
146 if (kZero_GrBlendCoeff == coeff) { 455 if (SkXfermode::kZero_Coeff == coeff) {
147 return hasPrevious; 456 return hasPrevious;
148 } else { 457 } else {
149 if (hasPrevious) { 458 if (hasPrevious) {
150 fsBuilder->codeAppend(" + "); 459 fsBuilder->codeAppend(" + ");
151 } 460 }
152 fsBuilder->codeAppendf("%s", colorName); 461 fsBuilder->codeAppendf("%s", colorName);
153 switch (coeff) { 462 switch (coeff) {
154 case kOne_GrBlendCoeff: 463 case SkXfermode::kOne_Coeff:
155 break; 464 break;
156 case kSC_GrBlendCoeff: 465 case SkXfermode::kSC_Coeff:
157 fsBuilder->codeAppendf(" * %s", srcColorName); 466 fsBuilder->codeAppendf(" * %s", srcColorName);
158 break; 467 break;
159 case kISC_GrBlendCoeff: 468 case SkXfermode::kISC_Coeff:
160 fsBuilder->codeAppendf(" * (vec4(1.0) - %s)", srcColorName); 469 fsBuilder->codeAppendf(" * (vec4(1.0) - %s)", srcColorName);
161 break; 470 break;
162 case kDC_GrBlendCoeff: 471 case SkXfermode::kDC_Coeff:
163 fsBuilder->codeAppendf(" * %s", dstColorName); 472 fsBuilder->codeAppendf(" * %s", dstColorName);
164 break; 473 break;
165 case kIDC_GrBlendCoeff: 474 case SkXfermode::kIDC_Coeff:
166 fsBuilder->codeAppendf(" * (vec4(1.0) - %s)", dstColorName); 475 fsBuilder->codeAppendf(" * (vec4(1.0) - %s)", dstColorName);
167 break; 476 break;
168 case kSA_GrBlendCoeff: 477 case SkXfermode::kSA_Coeff:
169 fsBuilder->codeAppendf(" * %s.a", srcColorName); 478 fsBuilder->codeAppendf(" * %s.a", srcColorName);
170 break; 479 break;
171 case kISA_GrBlendCoeff: 480 case SkXfermode::kISA_Coeff:
172 fsBuilder->codeAppendf(" * (1.0 - %s.a)", srcColorName); 481 fsBuilder->codeAppendf(" * (1.0 - %s.a)", srcColorName);
173 break; 482 break;
174 case kDA_GrBlendCoeff: 483 case SkXfermode::kDA_Coeff:
175 fsBuilder->codeAppendf(" * %s.a", dstColorName); 484 fsBuilder->codeAppendf(" * %s.a", dstColorName);
176 break; 485 break;
177 case kIDA_GrBlendCoeff: 486 case SkXfermode::kIDA_Coeff:
178 fsBuilder->codeAppendf(" * (1.0 - %s.a)", dstColorName); 487 fsBuilder->codeAppendf(" * (1.0 - %s.a)", dstColorName);
179 break; 488 break;
180 default: 489 default:
181 SkFAIL("Unsupported Blend Coeff"); 490 SkFAIL("Unsupported Blend Coeff");
182 } 491 }
183 return true; 492 return true;
184 } 493 }
185 } 494 }
186 495
187 class GLPorterDuffXferProcessor : public GrGLXferProcessor { 496 class GLPorterDuffXferProcessor : public GrGLXferProcessor {
188 public: 497 public:
189 GLPorterDuffXferProcessor(const GrProcessor&) {} 498 GLPorterDuffXferProcessor(const GrProcessor&) {}
190 499
191 virtual ~GLPorterDuffXferProcessor() {} 500 virtual ~GLPorterDuffXferProcessor() {}
192 501
193 static void GenKey(const GrProcessor& processor, const GrGLSLCaps& caps, 502 static void GenKey(const GrProcessor& processor, const GrGLSLCaps& caps,
194 GrProcessorKeyBuilder* b) { 503 GrProcessorKeyBuilder* b) {
195 const PorterDuffXferProcessor& xp = processor.cast<PorterDuffXferProcess or>(); 504 const PorterDuffXferProcessor& xp = processor.cast<PorterDuffXferProcess or>();
196 b->add32(xp.primaryOutputType());
197 b->add32(xp.secondaryOutputType());
198 if (xp.willReadDstColor()) { 505 if (xp.willReadDstColor()) {
199 b->add32(xp.getSrcBlend()); 506 b->add32(xp.getXfermode()); // Parent class includes willReadDstCol or() in key.
200 b->add32(xp.getDstBlend()); 507 } else {
508 GR_STATIC_ASSERT(BlendFormula::kLast_OutputType < 8);
509 b->add32(xp.readsCoverage() |
510 (xp.getBlendFormula().fPrimaryOutputType << 1) |
511 (xp.getBlendFormula().fSecondaryOutputType << 4));
201 } 512 }
202 }; 513 };
203 514
204 private: 515 private:
205 void onEmitCode(const EmitArgs& args) override { 516 void onEmitCode(const EmitArgs& args) override {
206 const PorterDuffXferProcessor& xp = args.fXP.cast<PorterDuffXferProcesso r>(); 517 const PorterDuffXferProcessor& xp = args.fXP.cast<PorterDuffXferProcesso r>();
207 GrGLXPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); 518 GrGLXPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
208 if (PorterDuffXferProcessor::kCustom_PrimaryOutputType != xp.primaryOutp utType()) { 519 if (!xp.willReadDstColor()) {
209 SkASSERT(!xp.willReadDstColor()); 520 BlendFormula blendFormula = xp.getBlendFormula();
210 switch(xp.secondaryOutputType()) { 521 if (blendFormula.hasSecondaryOutput()) {
211 case PorterDuffXferProcessor::kNone_SecondaryOutputType: 522 append_color_output(xp, fsBuilder, blendFormula.fSecondaryOutput Type,
212 break; 523 args.fOutputSecondary, args.fInputColor, arg s.fInputCoverage);
213 case PorterDuffXferProcessor::kCoverage_SecondaryOutputType:
214 fsBuilder->codeAppendf("%s = %s;", args.fOutputSecondary,
215 args.fInputCoverage);
216 break;
217 case PorterDuffXferProcessor::kCoverageISA_SecondaryOutputType:
218 fsBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;",
219 args.fOutputSecondary, args.fInputCol or,
220 args.fInputCoverage);
221 break;
222 case PorterDuffXferProcessor::kCoverageISC_SecondaryOutputType:
223 fsBuilder->codeAppendf("%s = (vec4(1.0) - %s) * %s;",
224 args.fOutputSecondary, args.fInputCol or,
225 args.fInputCoverage);
226 break;
227 default:
228 SkFAIL("Unexpected Secondary Output");
229 } 524 }
230 525 append_color_output(xp, fsBuilder, blendFormula.fPrimaryOutputType,
231 switch (xp.primaryOutputType()) { 526 args.fOutputPrimary, args.fInputColor, args.fInp utCoverage);
232 case PorterDuffXferProcessor::kNone_PrimaryOutputType:
233 fsBuilder->codeAppendf("%s = vec4(0);", args.fOutputPrimary) ;
234 break;
235 case PorterDuffXferProcessor::kColor_PrimaryOutputType:
236 fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args .fInputColor);
237 break;
238 case PorterDuffXferProcessor::kCoverage_PrimaryOutputType:
239 fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args .fInputCoverage);
240 break;
241 case PorterDuffXferProcessor::kModulate_PrimaryOutputType:
242 fsBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, args.fInputColor,
243 args.fInputCoverage);
244 break;
245 default:
246 SkFAIL("Unexpected Primary Output");
247 }
248 } else { 527 } else {
249 SkASSERT(xp.willReadDstColor()); 528 SkASSERT(xp.willReadDstColor());
250 529
530 SkXfermode::Coeff srcCoeff, dstCoeff;
531 SkXfermode::ModeAsCoeff(xp.getXfermode(), &srcCoeff, &dstCoeff);
532
251 const char* dstColor = fsBuilder->dstColor(); 533 const char* dstColor = fsBuilder->dstColor();
252 534
253 fsBuilder->codeAppend("vec4 colorBlend ="); 535 fsBuilder->codeAppend("vec4 colorBlend =");
254 // append src blend 536 // append src blend
255 bool didAppend = append_porterduff_term(fsBuilder, xp.getSrcBlend(), 537 bool didAppend = append_porterduff_term(fsBuilder, srcCoeff,
256 args.fInputColor, args.fInpu tColor, 538 args.fInputColor, args.fInpu tColor,
257 dstColor, false); 539 dstColor, false);
258 // append dst blend 540 // append dst blend
259 SkAssertResult(append_porterduff_term(fsBuilder, xp.getDstBlend(), 541 SkAssertResult(append_porterduff_term(fsBuilder, dstCoeff,
260 dstColor, args.fInputColor, 542 dstColor, args.fInputColor,
261 dstColor, didAppend)); 543 dstColor, didAppend));
262 fsBuilder->codeAppend(";"); 544 fsBuilder->codeAppend(";");
263 545
264 fsBuilder->codeAppendf("%s = %s * colorBlend + (vec4(1.0) - %s) * %s ;", 546 fsBuilder->codeAppendf("%s = %s * colorBlend + (vec4(1.0) - %s) * %s ;",
265 args.fOutputPrimary, args.fInputCoverage, arg s.fInputCoverage, 547 args.fOutputPrimary, args.fInputCoverage, arg s.fInputCoverage,
266 dstColor); 548 dstColor);
267 } 549 }
268 } 550 }
269 551
270 void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) overri de {}; 552 void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) overri de {};
271 553
272 typedef GrGLXferProcessor INHERITED; 554 typedef GrGLXferProcessor INHERITED;
273 }; 555 };
274 556
275 /////////////////////////////////////////////////////////////////////////////// 557 ///////////////////////////////////////////////////////////////////////////////
276 558
277 PorterDuffXferProcessor::PorterDuffXferProcessor(GrBlendCoeff srcBlend, 559 PorterDuffXferProcessor::PorterDuffXferProcessor(SkXfermode::Mode xfermode,
278 GrBlendCoeff dstBlend,
279 GrColor constant,
280 const GrDeviceCoordTexture* dst Copy, 560 const GrDeviceCoordTexture* dst Copy,
281 bool willReadDstColor) 561 bool willReadDstColor)
282 : INHERITED(dstCopy, willReadDstColor) 562 : INHERITED(dstCopy, willReadDstColor)
283 , fSrcBlend(srcBlend) 563 , fXfermode(xfermode)
284 , fDstBlend(dstBlend) 564 , fBlendFormula(get_unoptimized_blend_formula(xfermode)) {
egdaniel 2015/05/20 18:59:42 so what did we gain with the get_unoptimized? Seem
Chris Dalton 2015/05/21 04:00:36 That's right.. BlendFormula is 32 bits, so it prob
egdaniel 2015/05/21 18:36:45 Okay yeah I think you were right before. Our curre
Chris Dalton 2015/05/21 23:14:49 Done. Went with the coverage by default. It's slow
285 , fBlendConstant(constant)
286 , fPrimaryOutputType(kModulate_PrimaryOutputType)
287 , fSecondaryOutputType(kNone_SecondaryOutputType) {
288 this->initClassID<PorterDuffXferProcessor>(); 565 this->initClassID<PorterDuffXferProcessor>();
289 } 566 }
290 567
291 PorterDuffXferProcessor::~PorterDuffXferProcessor() { 568 PorterDuffXferProcessor::~PorterDuffXferProcessor() {
292 } 569 }
293 570
294 void PorterDuffXferProcessor::onGetGLProcessorKey(const GrGLSLCaps& caps, 571 void PorterDuffXferProcessor::onGetGLProcessorKey(const GrGLSLCaps& caps,
295 GrProcessorKeyBuilder* b) cons t { 572 GrProcessorKeyBuilder* b) cons t {
296 GLPorterDuffXferProcessor::GenKey(*this, caps, b); 573 GLPorterDuffXferProcessor::GenKey(*this, caps, b);
297 } 574 }
298 575
299 GrGLXferProcessor* PorterDuffXferProcessor::createGLInstance() const { 576 GrGLXferProcessor* PorterDuffXferProcessor::createGLInstance() const {
300 return SkNEW_ARGS(GLPorterDuffXferProcessor, (*this)); 577 return SkNEW_ARGS(GLPorterDuffXferProcessor, (*this));
301 } 578 }
302 579
303 GrXferProcessor::OptFlags 580 GrXferProcessor::OptFlags
304 PorterDuffXferProcessor::onGetOptimizations(const GrProcOptInfo& colorPOI, 581 PorterDuffXferProcessor::onGetOptimizations(const GrProcOptInfo& colorPOI,
305 const GrProcOptInfo& coveragePOI, 582 const GrProcOptInfo& coveragePOI,
306 bool doesStencilWrite, 583 bool doesStencilWrite,
307 GrColor* overrideColor, 584 GrColor* overrideColor,
308 const GrCaps& caps) { 585 const GrCaps& caps) {
309 GrXferProcessor::OptFlags optFlags = this->internalGetOptimizations(colorPOI ,
310 coverage POI,
311 doesSten cilWrite);
312 this->calcOutputTypes(optFlags, caps, coveragePOI.isSolidWhite());
313 return optFlags;
314 }
315
316 void PorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFlags ,
317 const GrCaps& caps,
318 bool hasSolidCoverage) {
319 if (this->willReadDstColor()) {
320 fPrimaryOutputType = kCustom_PrimaryOutputType;
321 return;
322 }
323
324 if (optFlags & kIgnoreColor_OptFlag) {
325 if (optFlags & kIgnoreCoverage_OptFlag) {
326 fPrimaryOutputType = kNone_PrimaryOutputType;
327 return;
328 } else {
329 fPrimaryOutputType = kCoverage_PrimaryOutputType;
330 return;
331 }
332 } else if (optFlags & kIgnoreCoverage_OptFlag) {
333 fPrimaryOutputType = kColor_PrimaryOutputType;
334 return;
335 }
336
337 // If we do have coverage determine whether it matters. Dual source blendin g is expensive so
338 // we don't do it if we are doing coverage drawing. If we aren't then We al ways do dual source
339 // blending if we have any effective coverage stages OR the geometry process or doesn't emits
340 // solid coverage.
341 if (!(optFlags & kSetCoverageDrawing_OptFlag) && !hasSolidCoverage) {
342 if (caps.shaderCaps()->dualSourceBlendingSupport()) {
343 if (kZero_GrBlendCoeff == fDstBlend) {
344 // write the coverage value to second color
345 fSecondaryOutputType = kCoverage_SecondaryOutputType;
346 fDstBlend = kIS2C_GrBlendCoeff;
347 } else if (kSA_GrBlendCoeff == fDstBlend) {
348 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
349 fSecondaryOutputType = kCoverageISA_SecondaryOutputType;
350 fDstBlend = kIS2C_GrBlendCoeff;
351 } else if (kSC_GrBlendCoeff == fDstBlend) {
352 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
353 fSecondaryOutputType = kCoverageISC_SecondaryOutputType;
354 fDstBlend = kIS2C_GrBlendCoeff;
355 }
356 }
357 }
358 }
359
360 GrXferProcessor::OptFlags
361 PorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPOI,
362 const GrProcOptInfo& coverageP OI,
363 bool doesStencilWrite) {
364 if (this->willReadDstColor()) { 586 if (this->willReadDstColor()) {
365 return GrXferProcessor::kNone_Opt; 587 return GrXferProcessor::kNone_Opt;
366 } 588 }
367 589
368 bool srcAIsOne = colorPOI.isOpaque(); 590 fBlendFormula = get_blend_formula(fXfermode, colorPOI, coveragePOI);
369 bool hasCoverage = !coveragePOI.isSolidWhite();
370 591
371 bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstBlend || 592 GrXferProcessor::OptFlags optFlags = GrXferProcessor::kNone_Opt;
372 (kSA_GrBlendCoeff == fDstBlend && srcAIsOne); 593 if (!fBlendFormula.modifiesDst()) {
373 bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstBlend || 594 if (!doesStencilWrite) {
374 (kISA_GrBlendCoeff == fDstBlend && srcAIsOne); 595 optFlags |= GrXferProcessor::kSkipDraw_OptFlag;
375 596 }
376 // When coeffs are (0,1) there is no reason to draw at all, unless 597 optFlags |= (GrXferProcessor::kIgnoreColor_OptFlag |
377 // stenciling is enabled. Having color writes disabled is effectively 598 GrXferProcessor::kIgnoreCoverage_OptFlag |
378 // (0,1). 599 GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag);
379 if ((kZero_GrBlendCoeff == fSrcBlend && dstCoeffIsOne)) { 600 } else {
380 if (doesStencilWrite) { 601 if (!fBlendFormula.usesGrPaintColor()) {
381 return GrXferProcessor::kIgnoreColor_OptFlag | 602 optFlags |= GrXferProcessor::kIgnoreColor_OptFlag;
382 GrXferProcessor::kSetCoverageDrawing_OptFlag; 603 }
383 } else { 604 if (coveragePOI.isSolidWhite()) {
384 fDstBlend = kOne_GrBlendCoeff; 605 optFlags |= GrXferProcessor::kIgnoreCoverage_OptFlag;
385 return GrXferProcessor::kSkipDraw_OptFlag; 606 }
607 if (colorPOI.allStagesMultiplyInput() && fBlendFormula.canTweakAlphaForC overage()) {
608 optFlags |= GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag;
386 } 609 }
387 } 610 }
388 611
389 // if we don't have coverage we can check whether the dst 612 return optFlags;
390 // has to read at all. If not, we'll disable blending.
391 if (!hasCoverage) {
392 if (dstCoeffIsZero) {
393 if (kOne_GrBlendCoeff == fSrcBlend) {
394 // if there is no coverage and coeffs are (1,0) then we
395 // won't need to read the dst at all, it gets replaced by src
396 fDstBlend = kZero_GrBlendCoeff;
397 return GrXferProcessor::kNone_Opt |
398 GrXferProcessor::kIgnoreCoverage_OptFlag;
399 } else if (kZero_GrBlendCoeff == fSrcBlend) {
400 // if the op is "clear" then we don't need to emit a color
401 // or blend, just write transparent black into the dst.
402 fSrcBlend = kOne_GrBlendCoeff;
403 fDstBlend = kZero_GrBlendCoeff;
404 return GrXferProcessor::kIgnoreColor_OptFlag |
405 GrXferProcessor::kIgnoreCoverage_OptFlag;
406 }
407 }
408 return GrXferProcessor::kIgnoreCoverage_OptFlag;
409 }
410
411 // check whether coverage can be safely rolled into alpha
412 // of if we can skip color computation and just emit coverage
413 if (can_tweak_alpha_for_coverage(fDstBlend)) {
414 if (colorPOI.allStagesMultiplyInput()) {
415 return GrXferProcessor::kSetCoverageDrawing_OptFlag |
416 GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag;
417 } else {
418 return GrXferProcessor::kSetCoverageDrawing_OptFlag;
419
420 }
421 }
422 if (dstCoeffIsZero) {
423 if (kZero_GrBlendCoeff == fSrcBlend) {
424 // the source color is not included in the blend
425 // the dst coeff is effectively zero so blend works out to:
426 // (c)(0)D + (1-c)D = (1-c)D.
427 fDstBlend = kISA_GrBlendCoeff;
428 return GrXferProcessor::kIgnoreColor_OptFlag |
429 GrXferProcessor::kSetCoverageDrawing_OptFlag;
430 } else if (srcAIsOne) {
431 // the dst coeff is effectively zero so blend works out to:
432 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
433 // If Sa is 1 then we can replace Sa with c
434 // and set dst coeff to 1-Sa.
435 fDstBlend = kISA_GrBlendCoeff;
436 if (colorPOI.allStagesMultiplyInput()) {
437 return GrXferProcessor::kSetCoverageDrawing_OptFlag |
438 GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag;
439 } else {
440 return GrXferProcessor::kSetCoverageDrawing_OptFlag;
441
442 }
443 }
444 } else if (dstCoeffIsOne) {
445 // the dst coeff is effectively one so blend works out to:
446 // cS + (c)(1)D + (1-c)D = cS + D.
447 fDstBlend = kOne_GrBlendCoeff;
448 if (colorPOI.allStagesMultiplyInput()) {
449 return GrXferProcessor::kSetCoverageDrawing_OptFlag |
450 GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag;
451 } else {
452 return GrXferProcessor::kSetCoverageDrawing_OptFlag;
453
454 }
455 return GrXferProcessor::kSetCoverageDrawing_OptFlag;
456 }
457
458 return GrXferProcessor::kNone_Opt;
459 }
460
461 bool PorterDuffXferProcessor::hasSecondaryOutput() const {
462 return kNone_SecondaryOutputType != fSecondaryOutputType;
463 } 613 }
464 614
465 /////////////////////////////////////////////////////////////////////////////// 615 ///////////////////////////////////////////////////////////////////////////////
466 616
467 class PDLCDXferProcessor : public GrXferProcessor { 617 class PDLCDXferProcessor : public GrXferProcessor {
468 public: 618 public:
469 static GrXferProcessor* Create(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, 619 static GrXferProcessor* Create(SkXfermode::Mode xfermode, const GrProcOptInf o& colorPOI);
470 const GrProcOptInfo& colorPOI);
471 620
472 ~PDLCDXferProcessor() override; 621 ~PDLCDXferProcessor() override;
473 622
474 const char* name() const override { return "Porter Duff LCD"; } 623 const char* name() const override { return "Porter Duff LCD"; }
475 624
476 GrGLXferProcessor* createGLInstance() const override; 625 GrGLXferProcessor* createGLInstance() const override;
477 626
478 bool hasSecondaryOutput() const override { return false; } 627 bool hasSecondaryOutput() const override { return false; }
479 628
480 private: 629 private:
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 }; 683 };
535 684
536 /////////////////////////////////////////////////////////////////////////////// 685 ///////////////////////////////////////////////////////////////////////////////
537 686
538 PDLCDXferProcessor::PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha) 687 PDLCDXferProcessor::PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha)
539 : fBlendConstant(blendConstant) 688 : fBlendConstant(blendConstant)
540 , fAlpha(alpha) { 689 , fAlpha(alpha) {
541 this->initClassID<PDLCDXferProcessor>(); 690 this->initClassID<PDLCDXferProcessor>();
542 } 691 }
543 692
544 GrXferProcessor* PDLCDXferProcessor::Create(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, 693 GrXferProcessor* PDLCDXferProcessor::Create(SkXfermode::Mode xfermode,
545 const GrProcOptInfo& colorPOI) { 694 const GrProcOptInfo& colorPOI) {
546 if (kOne_GrBlendCoeff != srcBlend || kISA_GrBlendCoeff != dstBlend) { 695 if (SkXfermode::kSrcOver_Mode != xfermode) {
547 return NULL; 696 return NULL;
548 } 697 }
549 698
550 if (kRGBA_GrColorComponentFlags != colorPOI.validFlags()) { 699 if (kRGBA_GrColorComponentFlags != colorPOI.validFlags()) {
551 return NULL; 700 return NULL;
552 } 701 }
553 702
554 GrColor blendConstant = GrUnPreMulColor(colorPOI.color()); 703 GrColor blendConstant = GrUnPreMulColor(colorPOI.color());
555 uint8_t alpha = GrColorUnpackA(blendConstant); 704 uint8_t alpha = GrColorUnpackA(blendConstant);
556 blendConstant |= (0xff << GrColor_SHIFT_A); 705 blendConstant |= (0xff << GrColor_SHIFT_A);
(...skipping 21 matching lines...) Expand all
578 const GrCaps& caps) { 727 const GrCaps& caps) {
579 // We want to force our primary output to be alpha * Coverage, where alp ha is the alpha 728 // We want to force our primary output to be alpha * Coverage, where alp ha is the alpha
580 // value of the blend the constant. We should already have valid blend c oeff's if we are at 729 // value of the blend the constant. We should already have valid blend c oeff's if we are at
581 // a point where we have RGB coverage. We don't need any color stages si nce the known color 730 // a point where we have RGB coverage. We don't need any color stages si nce the known color
582 // output is already baked into the blendConstant. 731 // output is already baked into the blendConstant.
583 *overrideColor = GrColorPackRGBA(fAlpha, fAlpha, fAlpha, fAlpha); 732 *overrideColor = GrColorPackRGBA(fAlpha, fAlpha, fAlpha, fAlpha);
584 return GrXferProcessor::kOverrideColor_OptFlag; 733 return GrXferProcessor::kOverrideColor_OptFlag;
585 } 734 }
586 735
587 /////////////////////////////////////////////////////////////////////////////// 736 ///////////////////////////////////////////////////////////////////////////////
588 GrPorterDuffXPFactory::GrPorterDuffXPFactory(GrBlendCoeff src, GrBlendCoeff dst) 737
589 : fSrcCoeff(src), fDstCoeff(dst) { 738 GrPorterDuffXPFactory::GrPorterDuffXPFactory(SkXfermode::Mode xfermode)
739 : fXfermode(xfermode) {
590 this->initClassID<GrPorterDuffXPFactory>(); 740 this->initClassID<GrPorterDuffXPFactory>();
591 } 741 }
592 742
593 GrXPFactory* GrPorterDuffXPFactory::Create(SkXfermode::Mode mode) { 743 GrXPFactory* GrPorterDuffXPFactory::Create(SkXfermode::Mode xfermode) {
594 switch (mode) { 744 static GrPorterDuffXPFactory gClearPDXPF(SkXfermode::kClear_Mode);
595 case SkXfermode::kClear_Mode: { 745 static GrPorterDuffXPFactory gSrcPDXPF(SkXfermode::kSrc_Mode);
596 static GrPorterDuffXPFactory gClearPDXPF(kZero_GrBlendCoeff, kZero_G rBlendCoeff); 746 static GrPorterDuffXPFactory gDstPDXPF(SkXfermode::kDst_Mode);
597 return SkRef(&gClearPDXPF); 747 static GrPorterDuffXPFactory gSrcOverPDXPF(SkXfermode::kSrcOver_Mode);
598 break; 748 static GrPorterDuffXPFactory gDstOverPDXPF(SkXfermode::kDstOver_Mode);
599 } 749 static GrPorterDuffXPFactory gSrcInPDXPF(SkXfermode::kSrcIn_Mode);
600 case SkXfermode::kSrc_Mode: { 750 static GrPorterDuffXPFactory gDstInPDXPF(SkXfermode::kDstIn_Mode);
601 static GrPorterDuffXPFactory gSrcPDXPF(kOne_GrBlendCoeff, kZero_GrBl endCoeff); 751 static GrPorterDuffXPFactory gSrcOutPDXPF(SkXfermode::kSrcOut_Mode);
602 return SkRef(&gSrcPDXPF); 752 static GrPorterDuffXPFactory gDstOutPDXPF(SkXfermode::kDstOut_Mode);
603 break; 753 static GrPorterDuffXPFactory gSrcATopPDXPF(SkXfermode::kSrcATop_Mode);
604 } 754 static GrPorterDuffXPFactory gDstATopPDXPF(SkXfermode::kDstATop_Mode);
605 case SkXfermode::kDst_Mode: { 755 static GrPorterDuffXPFactory gXorPDXPF(SkXfermode::kXor_Mode);
606 static GrPorterDuffXPFactory gDstPDXPF(kZero_GrBlendCoeff, kOne_GrBl endCoeff); 756 static GrPorterDuffXPFactory gPlusPDXPF(SkXfermode::kPlus_Mode);
607 return SkRef(&gDstPDXPF); 757 static GrPorterDuffXPFactory gModulatePDXPF(SkXfermode::kModulate_Mode);
608 break; 758 static GrPorterDuffXPFactory gScreenPDXPF(SkXfermode::kScreen_Mode);
609 } 759
610 case SkXfermode::kSrcOver_Mode: { 760 static GrPorterDuffXPFactory* gFactories[] = {
611 static GrPorterDuffXPFactory gSrcOverPDXPF(kOne_GrBlendCoeff, kISA_G rBlendCoeff); 761 &gClearPDXPF, &gSrcPDXPF, &gDstPDXPF, &gSrcOverPDXPF, &gDstOverPDXPF, &g SrcInPDXPF,
612 return SkRef(&gSrcOverPDXPF); 762 &gDstInPDXPF, &gSrcOutPDXPF, &gDstOutPDXPF, &gSrcATopPDXPF, &gDstATopPDX PF, &gXorPDXPF,
613 break; 763 &gPlusPDXPF, &gModulatePDXPF, &gScreenPDXPF
614 } 764 };
615 case SkXfermode::kDstOver_Mode: { 765 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gFactories) == SkXfermode::kLastCoeffMode + 1);
616 static GrPorterDuffXPFactory gDstOverPDXPF(kIDA_GrBlendCoeff, kOne_G rBlendCoeff); 766
617 return SkRef(&gDstOverPDXPF); 767 if (xfermode < 0 || xfermode > SkXfermode::kLastCoeffMode) {
618 break; 768 return NULL;
619 }
620 case SkXfermode::kSrcIn_Mode: {
621 static GrPorterDuffXPFactory gSrcInPDXPF(kDA_GrBlendCoeff, kZero_GrB lendCoeff);
622 return SkRef(&gSrcInPDXPF);
623 break;
624 }
625 case SkXfermode::kDstIn_Mode: {
626 static GrPorterDuffXPFactory gDstInPDXPF(kZero_GrBlendCoeff, kSA_GrB lendCoeff);
627 return SkRef(&gDstInPDXPF);
628 break;
629 }
630 case SkXfermode::kSrcOut_Mode: {
631 static GrPorterDuffXPFactory gSrcOutPDXPF(kIDA_GrBlendCoeff, kZero_G rBlendCoeff);
632 return SkRef(&gSrcOutPDXPF);
633 break;
634 }
635 case SkXfermode::kDstOut_Mode: {
636 static GrPorterDuffXPFactory gDstOutPDXPF(kZero_GrBlendCoeff, kISA_G rBlendCoeff);
637 return SkRef(&gDstOutPDXPF);
638 break;
639 }
640 case SkXfermode::kSrcATop_Mode: {
641 static GrPorterDuffXPFactory gSrcATopPDXPF(kDA_GrBlendCoeff, kISA_Gr BlendCoeff);
642 return SkRef(&gSrcATopPDXPF);
643 break;
644 }
645 case SkXfermode::kDstATop_Mode: {
646 static GrPorterDuffXPFactory gDstATopPDXPF(kIDA_GrBlendCoeff, kSA_Gr BlendCoeff);
647 return SkRef(&gDstATopPDXPF);
648 break;
649 }
650 case SkXfermode::kXor_Mode: {
651 static GrPorterDuffXPFactory gXorPDXPF(kIDA_GrBlendCoeff, kISA_GrBle ndCoeff);
652 return SkRef(&gXorPDXPF);
653 break;
654 }
655 case SkXfermode::kPlus_Mode: {
656 static GrPorterDuffXPFactory gPlusPDXPF(kOne_GrBlendCoeff, kOne_GrBl endCoeff);
657 return SkRef(&gPlusPDXPF);
658 break;
659 }
660 case SkXfermode::kModulate_Mode: {
661 static GrPorterDuffXPFactory gModulatePDXPF(kZero_GrBlendCoeff, kSC_ GrBlendCoeff);
662 return SkRef(&gModulatePDXPF);
663 break;
664 }
665 case SkXfermode::kScreen_Mode: {
666 static GrPorterDuffXPFactory gScreenPDXPF(kOne_GrBlendCoeff, kISC_Gr BlendCoeff);
667 return SkRef(&gScreenPDXPF);
668 break;
669 }
670 default:
671 return NULL;
672 } 769 }
770 return SkRef(gFactories[xfermode]);
673 } 771 }
674 772
675 GrXferProcessor* 773 GrXferProcessor*
676 GrPorterDuffXPFactory::onCreateXferProcessor(const GrCaps& caps, 774 GrPorterDuffXPFactory::onCreateXferProcessor(const GrCaps& caps,
677 const GrProcOptInfo& colorPOI, 775 const GrProcOptInfo& colorPOI,
678 const GrProcOptInfo& covPOI, 776 const GrProcOptInfo& covPOI,
679 const GrDeviceCoordTexture* dstCopy ) const { 777 const GrDeviceCoordTexture* dstCopy ) const {
680 if (covPOI.isFourChannelOutput()) { 778 if (covPOI.isFourChannelOutput()) {
681 return PDLCDXferProcessor::Create(fSrcCoeff, fDstCoeff, colorPOI); 779 return PDLCDXferProcessor::Create(fXfermode, colorPOI);
682 } else { 780 } else {
683 return PorterDuffXferProcessor::Create(fSrcCoeff, fDstCoeff, 0, dstCopy, 781 return PorterDuffXferProcessor::Create(fXfermode, dstCopy,
684 this->willReadDstColor(caps, colo rPOI, covPOI)); 782 this->willReadDstColor(caps, colo rPOI, covPOI));
685 } 783 }
686 } 784 }
687 785
688 bool GrPorterDuffXPFactory::supportsRGBCoverage(GrColor /*knownColor*/, 786 bool GrPorterDuffXPFactory::supportsRGBCoverage(GrColor /*knownColor*/,
689 uint32_t knownColorFlags) const { 787 uint32_t knownColorFlags) const {
690 if (kOne_GrBlendCoeff == fSrcCoeff && kISA_GrBlendCoeff == fDstCoeff && 788 if (SkXfermode::kSrcOver_Mode == fXfermode &&
691 kRGBA_GrColorComponentFlags == knownColorFlags) { 789 kRGBA_GrColorComponentFlags == knownColorFlags) {
692 return true; 790 return true;
693 } 791 }
694 return false; 792 return false;
695 } 793 }
696 794
697 void GrPorterDuffXPFactory::getInvariantOutput(const GrProcOptInfo& colorPOI, 795 void GrPorterDuffXPFactory::getInvariantOutput(const GrProcOptInfo& colorPOI,
698 const GrProcOptInfo& coveragePOI, 796 const GrProcOptInfo& coveragePOI,
699 GrXPFactory::InvariantOutput* out put) const { 797 GrXPFactory::InvariantOutput* out put) const {
700 if (!coveragePOI.isSolidWhite()) { 798 BlendFormula blendFormula = get_blend_formula(fXfermode, colorPOI, coverageP OI);
799
800 if (blendFormula.usesDstColor()) {
701 output->fWillBlendWithDst = true; 801 output->fWillBlendWithDst = true;
702 output->fBlendedColorFlags = 0; 802 output->fBlendedColorFlags = kNone_GrColorComponentFlags;
703 return; 803 return;
704 } 804 }
705 805
706 GrBlendCoeff srcCoeff = fSrcCoeff; 806 SkASSERT(coveragePOI.isSolidWhite());
707 GrBlendCoeff dstCoeff = fDstCoeff; 807 SkASSERT(kAdd_GrBlendEquation == blendFormula.fBlendEquation);
708 808
709 // TODO: figure out to merge this simplify with other current optimization c ode paths and 809 output->fWillBlendWithDst = false;
710 // eventually remove from GrBlend
711 GrSimplifyBlend(&srcCoeff, &dstCoeff, colorPOI.color(), colorPOI.validFlags( ),
712 0, 0, 0);
713 810
714 if (GrBlendCoeffRefsDst(srcCoeff)) { 811 switch (blendFormula.fSrcCoeff) {
715 output->fWillBlendWithDst = true;
716 output->fBlendedColorFlags = 0;
717 return;
718 }
719
720 if (kZero_GrBlendCoeff != dstCoeff) {
721 bool srcAIsOne = colorPOI.isOpaque();
722 if (kISA_GrBlendCoeff != dstCoeff || !srcAIsOne) {
723 output->fWillBlendWithDst = true;
724 }
725 output->fBlendedColorFlags = 0;
726 return;
727 }
728
729 switch (srcCoeff) {
730 case kZero_GrBlendCoeff: 812 case kZero_GrBlendCoeff:
731 output->fBlendedColor = 0; 813 output->fBlendedColor = 0;
732 output->fBlendedColorFlags = kRGBA_GrColorComponentFlags; 814 output->fBlendedColorFlags = kRGBA_GrColorComponentFlags;
733 break; 815 return;
734 816
735 case kOne_GrBlendCoeff: 817 case kOne_GrBlendCoeff:
736 output->fBlendedColor = colorPOI.color(); 818 output->fBlendedColor = colorPOI.color();
737 output->fBlendedColorFlags = colorPOI.validFlags(); 819 output->fBlendedColorFlags = colorPOI.validFlags();
738 break; 820 return;
739 821
740 // The src coeff should never refer to the src and if it refers to d st then opaque 822 // TODO: update if we ever use const color.
741 // should have been false.
742 case kSC_GrBlendCoeff:
743 case kISC_GrBlendCoeff:
744 case kDC_GrBlendCoeff:
745 case kIDC_GrBlendCoeff:
746 case kSA_GrBlendCoeff:
747 case kISA_GrBlendCoeff:
748 case kDA_GrBlendCoeff:
749 case kIDA_GrBlendCoeff:
750 default: 823 default:
751 SkFAIL("srcCoeff should not refer to src or dst."); 824 output->fBlendedColorFlags = kNone_GrColorComponentFlags;
752 break; 825 return;
753
754 // TODO: update this once GrPaint actually has a const color.
755 case kConstC_GrBlendCoeff:
756 case kIConstC_GrBlendCoeff:
757 case kConstA_GrBlendCoeff:
758 case kIConstA_GrBlendCoeff:
759 output->fBlendedColorFlags = 0;
760 break;
761 } 826 }
762
763 output->fWillBlendWithDst = false;
764 } 827 }
765 828
766 bool GrPorterDuffXPFactory::willReadDstColor(const GrCaps& caps, 829 bool GrPorterDuffXPFactory::willReadDstColor(const GrCaps& caps,
767 const GrProcOptInfo& colorPOI, 830 const GrProcOptInfo& colorPOI,
768 const GrProcOptInfo& coveragePOI) c onst { 831 const GrProcOptInfo& coveragePOI) c onst {
769 // We can always blend correctly if we have dual source blending. 832 // Some formulas use dual source blending, so we fall back if it is required but not supported.
770 if (caps.shaderCaps()->dualSourceBlendingSupport()) { 833 return !caps.shaderCaps()->dualSourceBlendingSupport() &&
771 return false; 834 get_blend_formula(fXfermode, colorPOI, coveragePOI).hasSecondaryOutpu t();
772 }
773
774 if (can_tweak_alpha_for_coverage(fDstCoeff)) {
775 return false;
776 }
777
778 bool srcAIsOne = colorPOI.isOpaque();
779
780 if (kZero_GrBlendCoeff == fDstCoeff) {
781 if (kZero_GrBlendCoeff == fSrcCoeff || srcAIsOne) {
782 return false;
783 }
784 }
785
786 // Reduces to: coeffS * (Cov*S) + D
787 if (kSA_GrBlendCoeff == fDstCoeff && srcAIsOne) {
788 return false;
789 }
790
791 // We can always blend correctly if we have solid coverage.
792 if (coveragePOI.isSolidWhite()) {
793 return false;
794 }
795
796 return true;
797 } 835 }
798 836
799 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory); 837 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory);
800 838
801 GrXPFactory* GrPorterDuffXPFactory::TestCreate(SkRandom* random, 839 GrXPFactory* GrPorterDuffXPFactory::TestCreate(SkRandom* random,
802 GrContext*, 840 GrContext*,
803 const GrCaps&, 841 const GrCaps&,
804 GrTexture*[]) { 842 GrTexture*[]) {
805 SkXfermode::Mode mode = SkXfermode::Mode(random->nextULessThan(SkXfermode::k LastCoeffMode)); 843 SkXfermode::Mode mode = SkXfermode::Mode(random->nextULessThan(SkXfermode::k LastCoeffMode));
806 return GrPorterDuffXPFactory::Create(mode); 844 return GrPorterDuffXPFactory::Create(mode);
807 } 845 }
808 846
847 int GrPorterDuffXPFactory::TestGetXPOutputPrimay(const GrXferProcessor* xp) {
egdaniel 2015/05/20 18:59:42 missing an r in Primay
Chris Dalton 2015/05/21 10:00:48 Done.
848 if (!!strcmp(xp->name(), "Porter Duff")) {
849 return -1;
850 }
851 return static_cast<const PorterDuffXferProcessor*>(xp)->getBlendFormula().fP rimaryOutputType;
852 }
853
854 int GrPorterDuffXPFactory::TestGetXPOutputSecondary(const GrXferProcessor* xp) {
855 if (!!strcmp(xp->name(), "Porter Duff")) {
856 return -1;
857 }
858 return static_cast<const PorterDuffXferProcessor*>(xp)->getBlendFormula().fS econdaryOutputType;
859 }
860
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698