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

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: GrBlend.h bugs 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
« no previous file with comments | « src/gpu/GrBlend.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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,
egdaniel 2015/05/20 14:13:55 It doesn't necessarily use GrPaint's color, it jus
Chris Dalton 2015/05/20 16:11:22 Yeah, I like that name better.
Chris Dalton 2015/05/21 10:00:47 Done.
43 kCanTweakAlphaForCoverage_Property = 1 << 3,
44
45 kLast_Property = kCanTweakAlphaForCoverage_Property
46 };
47
48 bool hasSecondaryOutput() const { return kNone_OutputType != fSecondaryOutpu tType; }
49 bool modifiesDst() const { return fProps & kModifiesDst_Property; }
50 bool usesDstColor() const { return fProps & kUsesDstColor_Property; }
51 bool usesGrPaintColor() const { return fProps & kUsesGrPaintColor_Property; }
52 bool canTweakAlphaForCoverage() const { return fProps & kCanTweakAlphaForCov erage_Property; }
53
54 /**
55 * Deduce the properties of a compile-time constant BlendFormula.
56 */
57 template<OutputType PrimaryOut, OutputType SecondaryOut,
58 GrBlendEquation BlendEquation, GrBlendCoeff SrcCoeff, GrBlendCoeff DstCoeff>
59 struct get_properties : SkTIntegralConstant<Properties, static_cast<Properti es>(
60
61 (GR_BLEND_MODIFIES_DST(BlendEquation, SrcCoeff, DstCoeff) ?
62 kModifiesDst_Property : 0) |
63
64 (GR_BLEND_COEFFS_USE_DST_COLOR(SrcCoeff, DstCoeff) ?
65 kUsesDstColor_Property : 0) |
66
67 ((PrimaryOut >= kModulate_OutputType && GR_BLEND_COEFFS_USE_SRC_COLOR(Sr cCoeff,DstCoeff)) ||
68 (SecondaryOut >= kModulate_OutputType && GR_BLEND_COEFF_REFS_SRC2(DstCo eff)) ?
69 kUsesGrPaintColor_Property : 0) | // We assert later that SrcCoeff doesn't ref src2.
70
71 (kModulate_OutputType == PrimaryOut &&
72 kNone_OutputType == SecondaryOut &&
73 GR_BLEND_CAN_TWEAK_ALPHA_FOR_COVERAGE(BlendEquation, SrcCoeff, DstCoeff ) ?
74 kCanTweakAlphaForCoverage_Property : 0))> {
75
76 // The provided formula should already be optimized.
77 GR_STATIC_ASSERT((kNone_OutputType == PrimaryOut) ==
78 !GR_BLEND_COEFFS_USE_SRC_COLOR(SrcCoeff, DstCoeff));
79 GR_STATIC_ASSERT(!GR_BLEND_COEFF_REFS_SRC2(SrcCoeff));
80 GR_STATIC_ASSERT((kNone_OutputType == SecondaryOut) ==
81 !GR_BLEND_COEFF_REFS_SRC2(DstCoeff));
82 GR_STATIC_ASSERT(PrimaryOut != SecondaryOut || kNone_OutputType == Prima ryOut);
83 GR_STATIC_ASSERT(kNone_OutputType != PrimaryOut || kNone_OutputType == S econdaryOut);
84 };
85
86 OutputType fPrimaryOutputType : 3;
egdaniel 2015/05/20 14:13:55 should we have some static assert on the sizes her
Chris Dalton 2015/05/20 16:11:22 My reasoning for not including static asserts was
egdaniel 2015/05/20 18:59:42 I feel uneasy relying on an arbitrary compiler war
Chris Dalton 2015/05/21 10:00:47 Done.
87 OutputType fSecondaryOutputType : 3;
88 GrBlendEquation fBlendEquation : 5;
89 GrBlendCoeff fSrcCoeff : 5;
90 GrBlendCoeff fDstCoeff : 5;
91 Properties fProps : 4;
92 };
93
94 GR_MAKE_BITFIELD_OPS(BlendFormula::Properties);
95
96 /**
97 * Initialize a compile-time constant BlendFormula and automatically deduce fPro ps.
98 */
99 #define INIT_BLEND_FORMULA(PRIMARY_OUT, SECONDARY_OUT, BLEND_EQUATION, SRC_COEFF , DST_COEFF) \
100 {PRIMARY_OUT, \
101 SECONDARY_OUT, \
102 BLEND_EQUATION, SRC_COEFF, DST_COEFF, \
103 BlendFormula::get_properties<PRIMARY_OUT, SECONDARY_OUT, \
104 BLEND_EQUATION, SRC_COEFF, DST_COEFF>::value}
105
106 /**
107 * When there is no coverage, or the blend mode can tweak alpha for coverage, we use the standard
108 * Porter Duff formula.
109 */
110 #define COEFF_FORMULA(SRC_COEFF, DST_COEFF) \
111 INIT_BLEND_FORMULA(BlendFormula::kModulate_OutputType, \
112 BlendFormula::kNone_OutputType, \
113 kAdd_GrBlendEquation, SRC_COEFF, DST_COEFF)
114
115 /**
116 * When the coeffs are (Zero, Zero), we clear the dst. This formula has its own macro so we can set
117 * the primary output type to none.
118 *
119 * Xfer modes: clear, dst-out (Sa=1)
120 */
121 #define DST_CLEAR_FORMULA \
122 INIT_BLEND_FORMULA(BlendFormula::kNone_OutputType, \
123 BlendFormula::kNone_OutputType, \
124 kAdd_GrBlendEquation, kZero_GrBlendCoeff, kZero_GrBlendCo eff)
125
126 /**
127 * When the coeffs are (Zero, One), we don't write to the dst at all. This formu la has its own macro
128 * so we can set the primary output type to none.
129 *
130 * Xfer modes: dst, dst-in (Sa=1), modulate (Sc=1)
131 */
132 #define NO_DST_WRITE_FORMULA \
133 INIT_BLEND_FORMULA(BlendFormula::kNone_OutputType, \
134 BlendFormula::kNone_OutputType, \
135 kAdd_GrBlendEquation, kZero_GrBlendCoeff, kOne_GrBlendCoe ff)
136
137 /**
138 * When there is coverage, the equation with f=coverage is:
139 *
140 * D' = f * (S * srcCoeff + D * dstCoeff) + (1-f) * D
141 *
142 * This can be rewritten as:
143 *
144 * D' = f * S * srcCoeff + D * (1 - [f * (1 - dstCoeff)])
145 *
146 * To implement this formula, we output [f * (1 - dstCoeff)] for the secondary c olor and replace the
147 * HW dst coeff with IS2C.
148 *
149 * Xfer modes: dst-atop (Sa!=1)
150 */
151 #define COVERAGE_FORMULA(ONE_MINUS_DST_COEFF_MODULATE_OUTPUT, SRC_COEFF) \
152 INIT_BLEND_FORMULA(BlendFormula::kModulate_OutputType, \
153 ONE_MINUS_DST_COEFF_MODULATE_OUTPUT, \
154 kAdd_GrBlendEquation, SRC_COEFF, kIS2C_GrBlendCoeff)
155
156 /**
157 * When there is coverage and the src coeff is Zero, the equation with f=coverag e becomes:
158 *
159 * D' = f * D * dstCoeff + (1-f) * D
160 *
161 * This can be rewritten as:
162 *
163 * D' = D - D * [f * (1 - dstCoeff)]
164 *
165 * To implement this formula, we output [f * (1 - dstCoeff)] for the primary col or and use a reverse
166 * subtract HW blend equation with coeffs of (DC, One).
167 *
168 * Xfer modes: clear, dst-in (Sa!=1), modulate (Sc!=1)
169 */
170 #define COVERAGE_SRC_COEFF_ZERO_FORMULA(ONE_MINUS_DST_COEFF_MODULATE_OUTPUT) \
171 INIT_BLEND_FORMULA(ONE_MINUS_DST_COEFF_MODULATE_OUTPUT, \
172 BlendFormula::kNone_OutputType, \
173 kReverseSubtract_GrBlendEquation, kDC_GrBlendCoeff, kOne_ GrBlendCoeff)
174
175 /**
176 * When there is coverage and the dst coeff is Zero, the equation with f=coverag e becomes:
177 *
178 * D' = f * S * srcCoeff + (1-f) * D
179 *
180 * To implement this formula, we output [f] for the secondary color and replace the HW dst coeff
181 * with IS2A. (Note that we can avoid dual source blending when Sa=1 by using IS A.)
182 *
183 * Xfer modes (Sa!=1): src, src-in, src-out
184 */
185 #define COVERAGE_DST_COEFF_ZERO_FORMULA(SRC_COEFF) \
186 INIT_BLEND_FORMULA(BlendFormula::kModulate_OutputType, \
187 BlendFormula::kCoverage_OutputType, \
188 kAdd_GrBlendEquation, SRC_COEFF, kIS2A_GrBlendCoeff)
189
190 /**
191 * This table outlines the blend formulas we use with all combinations of color, coverage, and
192 * Xfermode. Optimization flags are deduced at compile so there is no need for r un-time analysis.
193 * RGB coverage is not supported. Each entry is 32 bits so the entire table only takes up 360 bytes.
194 */
195 static const BlendFormula gBlendTable[3][2][SkXfermode::kLastCoeffMode + 1] = {
egdaniel 2015/05/20 14:13:55 I don't this we are gaining much at all by also br
Chris Dalton 2015/05/20 16:11:22 Right I hear what you're saying. I actually did tr
egdaniel 2015/05/20 18:59:42 So in terms of dealing with coverage here I'm fine
Chris Dalton 2015/05/21 10:00:47 Done. I reduced it to just opaque and not. I was a
196
197 /*>> No coverage, input color unknown: <<*/ {{
egdaniel 2015/05/20 14:13:55 Would this look any clearer if we reordered the ta
Chris Dalton 2015/05/20 16:11:22 This is another one of those things I was on the f
egdaniel 2015/05/20 18:59:41 So IMO it comes down to how many optimization grou
Chris Dalton 2015/05/21 10:00:47 Done.
198
199 /* clear */ DST_CLEAR_FORMULA,
200 /* src */ COEFF_FORMULA( kOne_GrBlendCoeff, kZero_GrBlendCoeff),
201 /* dst */ NO_DST_WRITE_FORMULA,
202 /* src-over */ COEFF_FORMULA( kOne_GrBlendCoeff, kISA_GrBlendCoeff),
203 /* dst-over */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
204 /* src-in */ COEFF_FORMULA( kDA_GrBlendCoeff, kZero_GrBlendCoeff),
205 /* dst-in */ COEFF_FORMULA( kZero_GrBlendCoeff, kSA_GrBlendCoeff),
206 /* src-out */ COEFF_FORMULA( kIDA_GrBlendCoeff, kZero_GrBlendCoeff),
207 /* dst-out */ COEFF_FORMULA( kZero_GrBlendCoeff, kISA_GrBlendCoeff),
208 /* src-atop */ COEFF_FORMULA( kDA_GrBlendCoeff, kISA_GrBlendCoeff),
209 /* dst-atop */ COEFF_FORMULA( kIDA_GrBlendCoeff, kSA_GrBlendCoeff),
210 /* xor */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff),
211 /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff),
212 /* modulate */ COEFF_FORMULA( kZero_GrBlendCoeff, kSC_GrBlendCoeff),
213 /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff),
214
215 }, /*>> Has coverage, input color unknown: <<*/ {
216
217 /* clear */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_Out putType),
218 /* src */ COVERAGE_DST_COEFF_ZERO_FORMULA(kOne_GrBlendCoeff),
219 /* dst */ NO_DST_WRITE_FORMULA,
220 /* src-over */ COEFF_FORMULA( kOne_GrBlendCoeff, kISA_GrBlendCoeff),
221 /* dst-over */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
222 /* src-in */ COVERAGE_DST_COEFF_ZERO_FORMULA(kDA_GrBlendCoeff),
223 /* dst-in */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISAModulate_ OutputType),
224 /* src-out */ COVERAGE_DST_COEFF_ZERO_FORMULA(kIDA_GrBlendCoeff),
225 /* dst-out */ COEFF_FORMULA( kZero_GrBlendCoeff, kISA_GrBlendCoeff),
226 /* src-atop */ COEFF_FORMULA( kDA_GrBlendCoeff, kISA_GrBlendCoeff),
227 /* dst-atop */ COVERAGE_FORMULA(BlendFormula::kISAModulate_OutputType, kID A_GrBlendCoeff),
228 /* xor */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff),
229 /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff),
230 /* modulate */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISCModulate_ OutputType),
231 /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff),
232
233 }}, /*>> No coverage, input color opaque: <<*/ {{
234
235 /* clear */ DST_CLEAR_FORMULA,
236 /* src */ COEFF_FORMULA( kOne_GrBlendCoeff, kZero_GrBlendCoeff),
237 /* dst */ NO_DST_WRITE_FORMULA,
238 /* src-over */ COEFF_FORMULA( kOne_GrBlendCoeff, kZero_GrBlendCoeff),
239 /* dst-over */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
240 /* src-in */ COEFF_FORMULA( kDA_GrBlendCoeff, kZero_GrBlendCoeff),
241 /* dst-in */ NO_DST_WRITE_FORMULA,
242 /* src-out */ COEFF_FORMULA( kIDA_GrBlendCoeff, kZero_GrBlendCoeff),
243 /* dst-out */ DST_CLEAR_FORMULA,
244 /* src-atop */ COEFF_FORMULA( kDA_GrBlendCoeff, kZero_GrBlendCoeff),
245 /* dst-atop */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
246 /* xor */ COEFF_FORMULA( kIDA_GrBlendCoeff, kZero_GrBlendCoeff),
247 /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff),
248 /* modulate */ COEFF_FORMULA( kZero_GrBlendCoeff, kSC_GrBlendCoeff),
249 /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff),
250
251 }, /*>> Has coverage, input color opaque: <<*/ {
252
253 /* clear */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_Out putType),
254 /* src */ COEFF_FORMULA( kOne_GrBlendCoeff, kISA_GrBlendCoeff),
255 /* dst */ NO_DST_WRITE_FORMULA,
256 /* src-over */ COEFF_FORMULA( kOne_GrBlendCoeff, kISA_GrBlendCoeff),
257 /* dst-over */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
258 /* src-in */ COEFF_FORMULA( kDA_GrBlendCoeff, kISA_GrBlendCoeff),
259 /* dst-in */ NO_DST_WRITE_FORMULA,
260 /* src-out */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff),
261 /* dst-out */ COEFF_FORMULA( kZero_GrBlendCoeff, kISA_GrBlendCoeff),
262 /* src-atop */ COEFF_FORMULA( kDA_GrBlendCoeff, kISA_GrBlendCoeff),
263 /* dst-atop */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
264 /* xor */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff),
265 /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff),
266 /* modulate */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISCModulate_ OutputType),
267 /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff),
268
269 }}, /*>> No coverage, input solid white: <<*/ {{
270
271 /* clear */ DST_CLEAR_FORMULA,
272 /* src */ COEFF_FORMULA( kOne_GrBlendCoeff, kZero_GrBlendCoeff),
273 /* dst */ NO_DST_WRITE_FORMULA,
274 /* src-over */ COEFF_FORMULA( kOne_GrBlendCoeff, kZero_GrBlendCoeff),
275 /* dst-over */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
276 /* src-in */ COEFF_FORMULA( kDA_GrBlendCoeff, kZero_GrBlendCoeff),
277 /* dst-in */ NO_DST_WRITE_FORMULA,
278 /* src-out */ COEFF_FORMULA( kIDA_GrBlendCoeff, kZero_GrBlendCoeff),
279 /* dst-out */ DST_CLEAR_FORMULA,
280 /* src-atop */ COEFF_FORMULA( kDA_GrBlendCoeff, kZero_GrBlendCoeff),
281 /* dst-atop */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
282 /* xor */ COEFF_FORMULA( kIDA_GrBlendCoeff, kZero_GrBlendCoeff),
283 /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff),
284 /* modulate */ NO_DST_WRITE_FORMULA,
285 /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kZero_GrBlendCoeff),
286
287 }, /*>> Has coverage, input solid white: <<*/ {
288
289 /* clear */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_Out putType),
290 /* src */ COEFF_FORMULA( kOne_GrBlendCoeff, kISA_GrBlendCoeff),
291 /* dst */ NO_DST_WRITE_FORMULA,
292 /* src-over */ COEFF_FORMULA( kOne_GrBlendCoeff, kISA_GrBlendCoeff),
293 /* dst-over */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
294 /* src-in */ COEFF_FORMULA( kDA_GrBlendCoeff, kISA_GrBlendCoeff),
295 /* dst-in */ NO_DST_WRITE_FORMULA,
296 /* src-out */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff),
297 /* dst-out */ COEFF_FORMULA( kZero_GrBlendCoeff, kISA_GrBlendCoeff),
298 /* src-atop */ COEFF_FORMULA( kDA_GrBlendCoeff, kISA_GrBlendCoeff),
299 /* dst-atop */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
300 /* xor */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff),
301 /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff),
302 /* modulate */ NO_DST_WRITE_FORMULA,
303 /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff),
304 }}};
305
306 static const BlendFormula& get_blend_formula(const GrProcOptInfo& colorPOI,
307 const GrProcOptInfo& coveragePOI,
308 SkXfermode::Mode xfermode) {
309 SkASSERT(xfermode >= 0 && xfermode <= SkXfermode::kLastCoeffMode);
310 SkASSERT(!colorPOI.isSolidWhite() || colorPOI.isOpaque());
egdaniel 2015/05/20 14:13:55 What is this assert trying to check? This will tri
Chris Dalton 2015/05/20 16:11:22 Right, this is verifying that we can do "colorPOI.
egdaniel 2015/05/20 18:59:41 Ahhh okay I get it.
311 // inputColorTraits: 0 - unknown, 1 - opaque, 2 - solid white.
312 int inputColorTraits = colorPOI.isOpaque() + colorPOI.isSolidWhite();
313 bool hasCoverage = !coveragePOI.isSolidWhite();
314 return gBlendTable[inputColorTraits][hasCoverage][xfermode];
33 } 315 }
34 316
317 GR_STATIC_ASSERT(0 == SkXfermode::kClear_Mode);
318 GR_STATIC_ASSERT(1 == SkXfermode::kSrc_Mode);
319 GR_STATIC_ASSERT(2 == SkXfermode::kDst_Mode);
320 GR_STATIC_ASSERT(3 == SkXfermode::kSrcOver_Mode);
321 GR_STATIC_ASSERT(4 == SkXfermode::kDstOver_Mode);
322 GR_STATIC_ASSERT(5 == SkXfermode::kSrcIn_Mode);
323 GR_STATIC_ASSERT(6 == SkXfermode::kDstIn_Mode);
324 GR_STATIC_ASSERT(7 == SkXfermode::kSrcOut_Mode);
325 GR_STATIC_ASSERT(8 == SkXfermode::kDstOut_Mode);
326 GR_STATIC_ASSERT(9 == SkXfermode::kSrcATop_Mode);
327 GR_STATIC_ASSERT(10 == SkXfermode::kDstATop_Mode);
328 GR_STATIC_ASSERT(11 == SkXfermode::kXor_Mode);
329 GR_STATIC_ASSERT(12 == SkXfermode::kPlus_Mode);
330 GR_STATIC_ASSERT(13 == SkXfermode::kModulate_Mode);
331 GR_STATIC_ASSERT(14 == SkXfermode::kScreen_Mode);
332 GR_STATIC_ASSERT(15 * 2 * 3 * sizeof(BlendFormula) == sizeof(gBlendTable));
333
334 ///////////////////////////////////////////////////////////////////////////////
335
35 class PorterDuffXferProcessor : public GrXferProcessor { 336 class PorterDuffXferProcessor : public GrXferProcessor {
36 public: 337 public:
37 static GrXferProcessor* Create(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, 338 static GrXferProcessor* Create(SkXfermode::Mode xfermode, const GrDeviceCoor dTexture* dstCopy,
38 GrColor constant, const GrDeviceCoordTexture* dstCopy,
39 bool willReadDstColor) { 339 bool willReadDstColor) {
40 return SkNEW_ARGS(PorterDuffXferProcessor, (srcBlend, dstBlend, constant , dstCopy, 340 return SkNEW_ARGS(PorterDuffXferProcessor, (xfermode, dstCopy, willReadD stColor));
41 willReadDstColor));
42 } 341 }
43 342
44 ~PorterDuffXferProcessor() override; 343 ~PorterDuffXferProcessor() override;
45 344
46 const char* name() const override { return "Porter Duff"; } 345 const char* name() const override { return "Porter Duff"; }
47 346
48 GrGLXferProcessor* createGLInstance() const override; 347 GrGLXferProcessor* createGLInstance() const override;
49 348
50 bool hasSecondaryOutput() const override; 349 bool hasSecondaryOutput() const override {
350 return fBlendFormula && fBlendFormula->hasSecondaryOutput();
351 }
51 352
52 /////////////////////////////////////////////////////////////////////////// 353 SkXfermode::Mode getXfermode() const { return fXfermode; }
53 /// @name Stage Output Types 354 const 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 355
90 private: 356 private:
91 PorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, GrColo r constant, 357 PorterDuffXferProcessor(SkXfermode::Mode, const GrDeviceCoordTexture* dstCop y,
92 const GrDeviceCoordTexture* dstCopy, bool willReadDs tColor); 358 bool willReadDstColor);
93 359
94 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI, 360 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI,
95 const GrProcOptInfo& coveragePO I, 361 const GrProcOptInfo& coveragePO I,
96 bool doesStencilWrite, 362 bool doesStencilWrite,
97 GrColor* overrideColor, 363 GrColor* overrideColor,
98 const GrDrawTargetCaps& caps) o verride; 364 const GrDrawTargetCaps& caps) o verride;
99 365
100 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c onst override; 366 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c onst override;
101 367
102 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override { 368 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override {
103 if (!this->willReadDstColor()) { 369 if (fBlendFormula) {
104 blendInfo->fSrcBlend = fSrcBlend; 370 blendInfo->fEquation = fBlendFormula->fBlendEquation;
105 blendInfo->fDstBlend = fDstBlend; 371 blendInfo->fSrcBlend = fBlendFormula->fSrcCoeff;
106 } else { 372 blendInfo->fDstBlend = fBlendFormula->fDstCoeff;
107 blendInfo->fSrcBlend = kOne_GrBlendCoeff; 373 blendInfo->fWriteColor = fBlendFormula->modifiesDst();
108 blendInfo->fDstBlend = kZero_GrBlendCoeff;
109 } 374 }
110 blendInfo->fBlendConstant = fBlendConstant;
111 } 375 }
112 376
113 bool onIsEqual(const GrXferProcessor& xpBase) const override { 377 bool onIsEqual(const GrXferProcessor& xpBase) const override {
114 const PorterDuffXferProcessor& xp = xpBase.cast<PorterDuffXferProcessor> (); 378 const PorterDuffXferProcessor& xp = xpBase.cast<PorterDuffXferProcessor> ();
115 if (fSrcBlend != xp.fSrcBlend || 379 return fXfermode == xp.fXfermode &&
116 fDstBlend != xp.fDstBlend || 380 fBlendFormula == xp.fBlendFormula;
117 fBlendConstant != xp.fBlendConstant ||
118 fPrimaryOutputType != xp.fPrimaryOutputType ||
119 fSecondaryOutputType != xp.fSecondaryOutputType) {
120 return false;
121 }
122 return true;
123 } 381 }
124 382
125 GrXferProcessor::OptFlags internalGetOptimizations(const GrProcOptInfo& colo rPOI, 383 SkXfermode::Mode fXfermode;
126 const GrProcOptInfo& cove ragePOI, 384 const BlendFormula* fBlendFormula;
127 bool doesStencilWrite);
128
129 void calcOutputTypes(GrXferProcessor::OptFlags blendOpts, const GrDrawTarget Caps& caps,
130 bool hasSolidCoverage);
131
132 GrBlendCoeff fSrcBlend;
133 GrBlendCoeff fDstBlend;
134 GrColor fBlendConstant;
135 PrimaryOutputType fPrimaryOutputType;
136 SecondaryOutputType fSecondaryOutputType;
137 385
138 typedef GrXferProcessor INHERITED; 386 typedef GrXferProcessor INHERITED;
139 }; 387 };
140 388
141 /////////////////////////////////////////////////////////////////////////////// 389 ///////////////////////////////////////////////////////////////////////////////
142 390
143 bool append_porterduff_term(GrGLXPFragmentBuilder* fsBuilder, GrBlendCoeff coeff , 391 void append_color_output(const PorterDuffXferProcessor& xp, GrGLXPFragmentBuilde r* fsBuilder,
392 BlendFormula::OutputType outputType, const char* output ,
393 const char* inColor, const char* inCoverage) {
394 switch (outputType) {
395 case BlendFormula::kNone_OutputType:
396 fsBuilder->codeAppendf("%s = vec4(0.0);", output);
397 break;
398 case BlendFormula::kCoverage_OutputType:
399 fsBuilder->codeAppendf("%s = %s;",
400 output, xp.readsCoverage() ? inCoverage : "ve c4(1.0)");
egdaniel 2015/05/20 14:13:55 can we even get into this state? how can we be set
Chris Dalton 2015/05/20 16:11:22 Mixed samples :) (My motivation for this patch wa
egdaniel 2015/05/20 18:59:41 interesting
401 break;
402 case BlendFormula::kModulate_OutputType:
403 if (xp.readsCoverage()) {
404 fsBuilder->codeAppendf("%s = %s * %s;", output, inColor, inCover age);
405 } else {
406 fsBuilder->codeAppendf("%s = %s;", output, inColor);
407 }
408 break;
409 case BlendFormula::kISAModulate_OutputType:
410 if (xp.readsCoverage()) {
411 fsBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", output, inColo r, inCoverage);
412 } else {
413 fsBuilder->codeAppendf("%s = vec4(1.0 - %s.a);", output, inColor );
414 }
415 break;
416 case BlendFormula::kISCModulate_OutputType:
417 if (xp.readsCoverage()) {
418 fsBuilder->codeAppendf("%s = (vec4(1.0) - %s) * %s;", output, in Color, inCoverage);
419 } else {
420 fsBuilder->codeAppendf("%s = vec4(1.0) - %s;", output, inColor);
421 }
422 break;
423 default:
424 SkFAIL("Unsupported output type.");
425 break;
426 }
427 }
428
429 bool append_porterduff_term(GrGLXPFragmentBuilder* fsBuilder, SkXfermode::Coeff coeff,
144 const char* colorName, const char* srcColorName, 430 const char* colorName, const char* srcColorName,
145 const char* dstColorName, bool hasPrevious) { 431 const char* dstColorName, bool hasPrevious) {
146 if (kZero_GrBlendCoeff == coeff) { 432 if (SkXfermode::kZero_Coeff == coeff) {
147 return hasPrevious; 433 return hasPrevious;
148 } else { 434 } else {
149 if (hasPrevious) { 435 if (hasPrevious) {
150 fsBuilder->codeAppend(" + "); 436 fsBuilder->codeAppend(" + ");
151 } 437 }
152 fsBuilder->codeAppendf("%s", colorName); 438 fsBuilder->codeAppendf("%s", colorName);
153 switch (coeff) { 439 switch (coeff) {
154 case kOne_GrBlendCoeff: 440 case SkXfermode::kOne_Coeff:
155 break; 441 break;
156 case kSC_GrBlendCoeff: 442 case SkXfermode::kSC_Coeff:
157 fsBuilder->codeAppendf(" * %s", srcColorName); 443 fsBuilder->codeAppendf(" * %s", srcColorName);
158 break; 444 break;
159 case kISC_GrBlendCoeff: 445 case SkXfermode::kISC_Coeff:
160 fsBuilder->codeAppendf(" * (vec4(1.0) - %s)", srcColorName); 446 fsBuilder->codeAppendf(" * (vec4(1.0) - %s)", srcColorName);
161 break; 447 break;
162 case kDC_GrBlendCoeff: 448 case SkXfermode::kDC_Coeff:
163 fsBuilder->codeAppendf(" * %s", dstColorName); 449 fsBuilder->codeAppendf(" * %s", dstColorName);
164 break; 450 break;
165 case kIDC_GrBlendCoeff: 451 case SkXfermode::kIDC_Coeff:
166 fsBuilder->codeAppendf(" * (vec4(1.0) - %s)", dstColorName); 452 fsBuilder->codeAppendf(" * (vec4(1.0) - %s)", dstColorName);
167 break; 453 break;
168 case kSA_GrBlendCoeff: 454 case SkXfermode::kSA_Coeff:
169 fsBuilder->codeAppendf(" * %s.a", srcColorName); 455 fsBuilder->codeAppendf(" * %s.a", srcColorName);
170 break; 456 break;
171 case kISA_GrBlendCoeff: 457 case SkXfermode::kISA_Coeff:
172 fsBuilder->codeAppendf(" * (1.0 - %s.a)", srcColorName); 458 fsBuilder->codeAppendf(" * (1.0 - %s.a)", srcColorName);
173 break; 459 break;
174 case kDA_GrBlendCoeff: 460 case SkXfermode::kDA_Coeff:
175 fsBuilder->codeAppendf(" * %s.a", dstColorName); 461 fsBuilder->codeAppendf(" * %s.a", dstColorName);
176 break; 462 break;
177 case kIDA_GrBlendCoeff: 463 case SkXfermode::kIDA_Coeff:
178 fsBuilder->codeAppendf(" * (1.0 - %s.a)", dstColorName); 464 fsBuilder->codeAppendf(" * (1.0 - %s.a)", dstColorName);
179 break; 465 break;
180 default: 466 default:
181 SkFAIL("Unsupported Blend Coeff"); 467 SkFAIL("Unsupported Blend Coeff");
182 } 468 }
183 return true; 469 return true;
184 } 470 }
185 } 471 }
186 472
187 class GLPorterDuffXferProcessor : public GrGLXferProcessor { 473 class GLPorterDuffXferProcessor : public GrGLXferProcessor {
188 public: 474 public:
189 GLPorterDuffXferProcessor(const GrProcessor&) {} 475 GLPorterDuffXferProcessor(const GrProcessor&) {}
190 476
191 virtual ~GLPorterDuffXferProcessor() {} 477 virtual ~GLPorterDuffXferProcessor() {}
192 478
193 static void GenKey(const GrProcessor& processor, const GrGLSLCaps& caps, 479 static void GenKey(const GrProcessor& processor, const GrGLSLCaps& caps,
194 GrProcessorKeyBuilder* b) { 480 GrProcessorKeyBuilder* b) {
195 const PorterDuffXferProcessor& xp = processor.cast<PorterDuffXferProcess or>(); 481 const PorterDuffXferProcessor& xp = processor.cast<PorterDuffXferProcess or>();
196 b->add32(xp.primaryOutputType()); 482 uint32_t key = xp.willReadDstColor();
197 b->add32(xp.secondaryOutputType()); 483 if (key) {
198 if (xp.willReadDstColor()) { 484 SkASSERT(!xp.getBlendFormula());
199 b->add32(xp.getSrcBlend()); 485 key |= xp.getXfermode() << 1;
200 b->add32(xp.getDstBlend()); 486 } else {
487 const BlendFormula* blendFormula = xp.getBlendFormula();
488 SkASSERT(blendFormula);
489 GR_STATIC_ASSERT(BlendFormula::kLast_OutputType < 8);
490 key |= xp.readsCoverage() << 1;
491 key |= blendFormula->fSecondaryOutputType << 2;
492 key |= blendFormula->fPrimaryOutputType << 5;
egdaniel 2015/05/20 14:13:55 add some assert on max value of Output type?
Chris Dalton 2015/05/20 16:11:22 I think this already has what you are asking for?
egdaniel 2015/05/20 18:59:42 oh yeah, woops
Chris Dalton 2015/05/21 10:00:48 Done.
201 } 493 }
494 b->add32(key);
202 }; 495 };
203 496
204 private: 497 private:
205 void onEmitCode(const EmitArgs& args) override { 498 void onEmitCode(const EmitArgs& args) override {
206 const PorterDuffXferProcessor& xp = args.fXP.cast<PorterDuffXferProcesso r>(); 499 const PorterDuffXferProcessor& xp = args.fXP.cast<PorterDuffXferProcesso r>();
207 GrGLXPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); 500 GrGLXPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
208 if (PorterDuffXferProcessor::kCustom_PrimaryOutputType != xp.primaryOutp utType()) { 501 if (const BlendFormula* blendFormula = xp.getBlendFormula()) {
209 SkASSERT(!xp.willReadDstColor()); 502 SkASSERT(!xp.willReadDstColor());
210 switch(xp.secondaryOutputType()) { 503 if (blendFormula->hasSecondaryOutput()) {
211 case PorterDuffXferProcessor::kNone_SecondaryOutputType: 504 append_color_output(xp, fsBuilder, blendFormula->fSecondaryOutpu tType,
212 break; 505 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 } 506 }
230 507 append_color_output(xp, fsBuilder, blendFormula->fPrimaryOutputType,
231 switch (xp.primaryOutputType()) { 508 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 { 509 } else {
249 SkASSERT(xp.willReadDstColor()); 510 SkASSERT(xp.willReadDstColor());
250 511
512 SkXfermode::Coeff srcCoeff, dstCoeff;
513 SkXfermode::ModeAsCoeff(xp.getXfermode(), &srcCoeff, &dstCoeff);
514
251 const char* dstColor = fsBuilder->dstColor(); 515 const char* dstColor = fsBuilder->dstColor();
252 516
253 fsBuilder->codeAppend("vec4 colorBlend ="); 517 fsBuilder->codeAppend("vec4 colorBlend =");
254 // append src blend 518 // append src blend
255 bool didAppend = append_porterduff_term(fsBuilder, xp.getSrcBlend(), 519 bool didAppend = append_porterduff_term(fsBuilder, srcCoeff,
256 args.fInputColor, args.fInpu tColor, 520 args.fInputColor, args.fInpu tColor,
257 dstColor, false); 521 dstColor, false);
258 // append dst blend 522 // append dst blend
259 SkAssertResult(append_porterduff_term(fsBuilder, xp.getDstBlend(), 523 SkAssertResult(append_porterduff_term(fsBuilder, dstCoeff,
260 dstColor, args.fInputColor, 524 dstColor, args.fInputColor,
261 dstColor, didAppend)); 525 dstColor, didAppend));
262 fsBuilder->codeAppend(";"); 526 fsBuilder->codeAppend(";");
263 527
264 fsBuilder->codeAppendf("%s = %s * colorBlend + (vec4(1.0) - %s) * %s ;", 528 fsBuilder->codeAppendf("%s = %s * colorBlend + (vec4(1.0) - %s) * %s ;",
265 args.fOutputPrimary, args.fInputCoverage, arg s.fInputCoverage, 529 args.fOutputPrimary, args.fInputCoverage, arg s.fInputCoverage,
266 dstColor); 530 dstColor);
267 } 531 }
268 } 532 }
269 533
270 void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) overri de {}; 534 void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) overri de {};
271 535
272 typedef GrGLXferProcessor INHERITED; 536 typedef GrGLXferProcessor INHERITED;
273 }; 537 };
274 538
275 /////////////////////////////////////////////////////////////////////////////// 539 ///////////////////////////////////////////////////////////////////////////////
276 540
277 PorterDuffXferProcessor::PorterDuffXferProcessor(GrBlendCoeff srcBlend, 541 PorterDuffXferProcessor::PorterDuffXferProcessor(SkXfermode::Mode xfermode,
278 GrBlendCoeff dstBlend,
279 GrColor constant,
280 const GrDeviceCoordTexture* dst Copy, 542 const GrDeviceCoordTexture* dst Copy,
281 bool willReadDstColor) 543 bool willReadDstColor)
282 : INHERITED(dstCopy, willReadDstColor) 544 : INHERITED(dstCopy, willReadDstColor)
283 , fSrcBlend(srcBlend) 545 , fXfermode(xfermode)
284 , fDstBlend(dstBlend) 546 , fBlendFormula(NULL) {
285 , fBlendConstant(constant)
286 , fPrimaryOutputType(kModulate_PrimaryOutputType)
287 , fSecondaryOutputType(kNone_SecondaryOutputType) {
288 this->initClassID<PorterDuffXferProcessor>(); 547 this->initClassID<PorterDuffXferProcessor>();
289 } 548 }
290 549
291 PorterDuffXferProcessor::~PorterDuffXferProcessor() { 550 PorterDuffXferProcessor::~PorterDuffXferProcessor() {
292 } 551 }
293 552
294 void PorterDuffXferProcessor::onGetGLProcessorKey(const GrGLSLCaps& caps, 553 void PorterDuffXferProcessor::onGetGLProcessorKey(const GrGLSLCaps& caps,
295 GrProcessorKeyBuilder* b) cons t { 554 GrProcessorKeyBuilder* b) cons t {
296 GLPorterDuffXferProcessor::GenKey(*this, caps, b); 555 GLPorterDuffXferProcessor::GenKey(*this, caps, b);
297 } 556 }
298 557
299 GrGLXferProcessor* PorterDuffXferProcessor::createGLInstance() const { 558 GrGLXferProcessor* PorterDuffXferProcessor::createGLInstance() const {
300 return SkNEW_ARGS(GLPorterDuffXferProcessor, (*this)); 559 return SkNEW_ARGS(GLPorterDuffXferProcessor, (*this));
301 } 560 }
302 561
303 GrXferProcessor::OptFlags 562 GrXferProcessor::OptFlags
304 PorterDuffXferProcessor::onGetOptimizations(const GrProcOptInfo& colorPOI, 563 PorterDuffXferProcessor::onGetOptimizations(const GrProcOptInfo& colorPOI,
305 const GrProcOptInfo& coveragePOI, 564 const GrProcOptInfo& coveragePOI,
306 bool doesStencilWrite, 565 bool doesStencilWrite,
307 GrColor* overrideColor, 566 GrColor* overrideColor,
308 const GrDrawTargetCaps& caps) { 567 const GrDrawTargetCaps& 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 GrDrawTargetCaps& 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()) { 568 if (this->willReadDstColor()) {
365 return GrXferProcessor::kNone_Opt; 569 return GrXferProcessor::kNone_Opt;
366 } 570 }
367 571
368 bool srcAIsOne = colorPOI.isOpaque(); 572 fBlendFormula = &get_blend_formula(colorPOI, coveragePOI, fXfermode);
369 bool hasCoverage = !coveragePOI.isSolidWhite();
370 573
371 bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstBlend || 574 GrXferProcessor::OptFlags optFlags = GrXferProcessor::kNone_Opt;
372 (kSA_GrBlendCoeff == fDstBlend && srcAIsOne); 575 if (!fBlendFormula->modifiesDst()) {
373 bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstBlend || 576 if (!doesStencilWrite) {
374 (kISA_GrBlendCoeff == fDstBlend && srcAIsOne); 577 optFlags |= GrXferProcessor::kSkipDraw_OptFlag;
375 578 }
376 // When coeffs are (0,1) there is no reason to draw at all, unless 579 optFlags |= (GrXferProcessor::kIgnoreColor_OptFlag |
377 // stenciling is enabled. Having color writes disabled is effectively 580 GrXferProcessor::kIgnoreCoverage_OptFlag |
378 // (0,1). 581 GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag);
379 if ((kZero_GrBlendCoeff == fSrcBlend && dstCoeffIsOne)) { 582 } else {
380 if (doesStencilWrite) { 583 if (!fBlendFormula->usesGrPaintColor()) {
381 return GrXferProcessor::kIgnoreColor_OptFlag | 584 optFlags |= GrXferProcessor::kIgnoreColor_OptFlag;
382 GrXferProcessor::kSetCoverageDrawing_OptFlag; 585 }
383 } else { 586 if (coveragePOI.isSolidWhite()) {
384 fDstBlend = kOne_GrBlendCoeff; 587 optFlags |= GrXferProcessor::kIgnoreCoverage_OptFlag;
385 return GrXferProcessor::kSkipDraw_OptFlag; 588 }
589 if (colorPOI.allStagesMultiplyInput() && fBlendFormula->canTweakAlphaFor Coverage()) {
590 optFlags |= GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag;
386 } 591 }
387 } 592 }
388 593
389 // if we don't have coverage we can check whether the dst 594 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 } 595 }
464 596
465 /////////////////////////////////////////////////////////////////////////////// 597 ///////////////////////////////////////////////////////////////////////////////
466 598
467 class PDLCDXferProcessor : public GrXferProcessor { 599 class PDLCDXferProcessor : public GrXferProcessor {
468 public: 600 public:
469 static GrXferProcessor* Create(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, 601 static GrXferProcessor* Create(SkXfermode::Mode xfermode, const GrProcOptInf o& colorPOI);
470 const GrProcOptInfo& colorPOI);
471 602
472 ~PDLCDXferProcessor() override; 603 ~PDLCDXferProcessor() override;
473 604
474 const char* name() const override { return "Porter Duff LCD"; } 605 const char* name() const override { return "Porter Duff LCD"; }
475 606
476 GrGLXferProcessor* createGLInstance() const override; 607 GrGLXferProcessor* createGLInstance() const override;
477 608
478 bool hasSecondaryOutput() const override { return false; } 609 bool hasSecondaryOutput() const override { return false; }
479 610
480 private: 611 private:
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 }; 665 };
535 666
536 /////////////////////////////////////////////////////////////////////////////// 667 ///////////////////////////////////////////////////////////////////////////////
537 668
538 PDLCDXferProcessor::PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha) 669 PDLCDXferProcessor::PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha)
539 : fBlendConstant(blendConstant) 670 : fBlendConstant(blendConstant)
540 , fAlpha(alpha) { 671 , fAlpha(alpha) {
541 this->initClassID<PDLCDXferProcessor>(); 672 this->initClassID<PDLCDXferProcessor>();
542 } 673 }
543 674
544 GrXferProcessor* PDLCDXferProcessor::Create(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, 675 GrXferProcessor* PDLCDXferProcessor::Create(SkXfermode::Mode xfermode,
545 const GrProcOptInfo& colorPOI) { 676 const GrProcOptInfo& colorPOI) {
546 if (kOne_GrBlendCoeff != srcBlend || kISA_GrBlendCoeff != dstBlend) { 677 if (SkXfermode::kSrcOver_Mode != xfermode) {
547 return NULL; 678 return NULL;
548 } 679 }
549 680
550 if (kRGBA_GrColorComponentFlags != colorPOI.validFlags()) { 681 if (kRGBA_GrColorComponentFlags != colorPOI.validFlags()) {
551 return NULL; 682 return NULL;
552 } 683 }
553 684
554 GrColor blendConstant = GrUnPreMulColor(colorPOI.color()); 685 GrColor blendConstant = GrUnPreMulColor(colorPOI.color());
555 uint8_t alpha = GrColorUnpackA(blendConstant); 686 uint8_t alpha = GrColorUnpackA(blendConstant);
556 blendConstant |= (0xff << GrColor_SHIFT_A); 687 blendConstant |= (0xff << GrColor_SHIFT_A);
(...skipping 21 matching lines...) Expand all
578 const GrDrawTargetCaps& caps) { 709 const GrDrawTargetCaps& caps) {
579 // We want to force our primary output to be alpha * Coverage, where alp ha is the alpha 710 // 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 711 // 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 712 // 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. 713 // output is already baked into the blendConstant.
583 *overrideColor = GrColorPackRGBA(fAlpha, fAlpha, fAlpha, fAlpha); 714 *overrideColor = GrColorPackRGBA(fAlpha, fAlpha, fAlpha, fAlpha);
584 return GrXferProcessor::kOverrideColor_OptFlag; 715 return GrXferProcessor::kOverrideColor_OptFlag;
585 } 716 }
586 717
587 /////////////////////////////////////////////////////////////////////////////// 718 ///////////////////////////////////////////////////////////////////////////////
588 GrPorterDuffXPFactory::GrPorterDuffXPFactory(GrBlendCoeff src, GrBlendCoeff dst) 719
589 : fSrcCoeff(src), fDstCoeff(dst) { 720 GrPorterDuffXPFactory::GrPorterDuffXPFactory(SkXfermode::Mode xfermode)
721 : fXfermode(xfermode) {
590 this->initClassID<GrPorterDuffXPFactory>(); 722 this->initClassID<GrPorterDuffXPFactory>();
591 } 723 }
592 724
593 GrXPFactory* GrPorterDuffXPFactory::Create(SkXfermode::Mode mode) { 725 GrXPFactory* GrPorterDuffXPFactory::Create(SkXfermode::Mode xfermode) {
594 switch (mode) { 726 static GrPorterDuffXPFactory gClearPDXPF(SkXfermode::kClear_Mode);
595 case SkXfermode::kClear_Mode: { 727 static GrPorterDuffXPFactory gSrcPDXPF(SkXfermode::kSrc_Mode);
596 static GrPorterDuffXPFactory gClearPDXPF(kZero_GrBlendCoeff, kZero_G rBlendCoeff); 728 static GrPorterDuffXPFactory gDstPDXPF(SkXfermode::kDst_Mode);
597 return SkRef(&gClearPDXPF); 729 static GrPorterDuffXPFactory gSrcOverPDXPF(SkXfermode::kSrcOver_Mode);
598 break; 730 static GrPorterDuffXPFactory gDstOverPDXPF(SkXfermode::kDstOver_Mode);
599 } 731 static GrPorterDuffXPFactory gSrcInPDXPF(SkXfermode::kSrcIn_Mode);
600 case SkXfermode::kSrc_Mode: { 732 static GrPorterDuffXPFactory gDstInPDXPF(SkXfermode::kDstIn_Mode);
601 static GrPorterDuffXPFactory gSrcPDXPF(kOne_GrBlendCoeff, kZero_GrBl endCoeff); 733 static GrPorterDuffXPFactory gSrcOutPDXPF(SkXfermode::kSrcOut_Mode);
602 return SkRef(&gSrcPDXPF); 734 static GrPorterDuffXPFactory gDstOutPDXPF(SkXfermode::kDstOut_Mode);
603 break; 735 static GrPorterDuffXPFactory gSrcATopPDXPF(SkXfermode::kSrcATop_Mode);
604 } 736 static GrPorterDuffXPFactory gDstATopPDXPF(SkXfermode::kDstATop_Mode);
605 case SkXfermode::kDst_Mode: { 737 static GrPorterDuffXPFactory gXorPDXPF(SkXfermode::kXor_Mode);
606 static GrPorterDuffXPFactory gDstPDXPF(kZero_GrBlendCoeff, kOne_GrBl endCoeff); 738 static GrPorterDuffXPFactory gPlusPDXPF(SkXfermode::kPlus_Mode);
607 return SkRef(&gDstPDXPF); 739 static GrPorterDuffXPFactory gModulatePDXPF(SkXfermode::kModulate_Mode);
608 break; 740 static GrPorterDuffXPFactory gScreenPDXPF(SkXfermode::kScreen_Mode);
609 } 741
610 case SkXfermode::kSrcOver_Mode: { 742 static GrPorterDuffXPFactory* gFactories[] = {
611 static GrPorterDuffXPFactory gSrcOverPDXPF(kOne_GrBlendCoeff, kISA_G rBlendCoeff); 743 &gClearPDXPF, &gSrcPDXPF, &gDstPDXPF, &gSrcOverPDXPF, &gDstOverPDXPF, &g SrcInPDXPF,
612 return SkRef(&gSrcOverPDXPF); 744 &gDstInPDXPF, &gSrcOutPDXPF, &gDstOutPDXPF, &gSrcATopPDXPF, &gDstATopPDX PF, &gXorPDXPF,
613 break; 745 &gPlusPDXPF, &gModulatePDXPF, &gScreenPDXPF
614 } 746 };
615 case SkXfermode::kDstOver_Mode: { 747 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gFactories) == SkXfermode::kLastCoeffMode + 1);
616 static GrPorterDuffXPFactory gDstOverPDXPF(kIDA_GrBlendCoeff, kOne_G rBlendCoeff); 748
617 return SkRef(&gDstOverPDXPF); 749 if (xfermode < 0 || xfermode > SkXfermode::kLastCoeffMode) {
618 break; 750 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 } 751 }
752 return SkRef(gFactories[xfermode]);
673 } 753 }
674 754
675 GrXferProcessor* 755 GrXferProcessor*
676 GrPorterDuffXPFactory::onCreateXferProcessor(const GrDrawTargetCaps& caps, 756 GrPorterDuffXPFactory::onCreateXferProcessor(const GrDrawTargetCaps& caps,
677 const GrProcOptInfo& colorPOI, 757 const GrProcOptInfo& colorPOI,
678 const GrProcOptInfo& covPOI, 758 const GrProcOptInfo& covPOI,
679 const GrDeviceCoordTexture* dstCopy ) const { 759 const GrDeviceCoordTexture* dstCopy ) const {
680 if (covPOI.isFourChannelOutput()) { 760 if (covPOI.isFourChannelOutput()) {
681 return PDLCDXferProcessor::Create(fSrcCoeff, fDstCoeff, colorPOI); 761 return PDLCDXferProcessor::Create(fXfermode, colorPOI);
682 } else { 762 } else {
683 return PorterDuffXferProcessor::Create(fSrcCoeff, fDstCoeff, 0, dstCopy, 763 return PorterDuffXferProcessor::Create(fXfermode, dstCopy,
684 this->willReadDstColor(caps, colo rPOI, covPOI)); 764 this->willReadDstColor(caps, colo rPOI, covPOI));
685 } 765 }
686 } 766 }
687 767
688 bool GrPorterDuffXPFactory::supportsRGBCoverage(GrColor /*knownColor*/, 768 bool GrPorterDuffXPFactory::supportsRGBCoverage(GrColor /*knownColor*/,
689 uint32_t knownColorFlags) const { 769 uint32_t knownColorFlags) const {
690 if (kOne_GrBlendCoeff == fSrcCoeff && kISA_GrBlendCoeff == fDstCoeff && 770 if (SkXfermode::kSrcOver_Mode == fXfermode &&
691 kRGBA_GrColorComponentFlags == knownColorFlags) { 771 kRGBA_GrColorComponentFlags == knownColorFlags) {
692 return true; 772 return true;
693 } 773 }
694 return false; 774 return false;
695 } 775 }
696 776
697 void GrPorterDuffXPFactory::getInvariantOutput(const GrProcOptInfo& colorPOI, 777 void GrPorterDuffXPFactory::getInvariantOutput(const GrProcOptInfo& colorPOI,
698 const GrProcOptInfo& coveragePOI, 778 const GrProcOptInfo& coveragePOI,
699 GrXPFactory::InvariantOutput* out put) const { 779 GrXPFactory::InvariantOutput* out put) const {
700 if (!coveragePOI.isSolidWhite()) { 780 const BlendFormula& blendFormula = get_blend_formula(colorPOI, coveragePOI, fXfermode);
781
782 if (blendFormula.usesDstColor()) {
701 output->fWillBlendWithDst = true; 783 output->fWillBlendWithDst = true;
702 output->fBlendedColorFlags = 0; 784 output->fBlendedColorFlags = 0;
703 return; 785 return;
704 } 786 }
705 787
706 GrBlendCoeff srcCoeff = fSrcCoeff; 788 SkASSERT(coveragePOI.isSolidWhite());
707 GrBlendCoeff dstCoeff = fDstCoeff; 789 SkASSERT(kAdd_GrBlendEquation == blendFormula.fBlendEquation);
708 790
709 // TODO: figure out to merge this simplify with other current optimization c ode paths and 791 output->fWillBlendWithDst = false;
710 // eventually remove from GrBlend
711 GrSimplifyBlend(&srcCoeff, &dstCoeff, colorPOI.color(), colorPOI.validFlags( ),
712 0, 0, 0);
713 792
714 if (GrBlendCoeffRefsDst(srcCoeff)) { 793 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: 794 case kZero_GrBlendCoeff:
731 output->fBlendedColor = 0; 795 output->fBlendedColor = 0;
732 output->fBlendedColorFlags = kRGBA_GrColorComponentFlags; 796 output->fBlendedColorFlags = kRGBA_GrColorComponentFlags;
733 break; 797 return;
734 798
735 case kOne_GrBlendCoeff: 799 case kOne_GrBlendCoeff:
736 output->fBlendedColor = colorPOI.color(); 800 output->fBlendedColor = colorPOI.color();
737 output->fBlendedColorFlags = colorPOI.validFlags(); 801 output->fBlendedColorFlags = colorPOI.validFlags();
738 break; 802 return;
739 803
740 // The src coeff should never refer to the src and if it refers to d st then opaque 804 // 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: 805 default:
751 SkFAIL("srcCoeff should not refer to src or dst.");
752 break;
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; 806 output->fBlendedColorFlags = 0;
760 break; 807 return;
761 } 808 }
762
763 output->fWillBlendWithDst = false;
764 } 809 }
765 810
766 bool GrPorterDuffXPFactory::willReadDstColor(const GrDrawTargetCaps& caps, 811 bool GrPorterDuffXPFactory::willReadDstColor(const GrDrawTargetCaps& caps,
767 const GrProcOptInfo& colorPOI, 812 const GrProcOptInfo& colorPOI,
768 const GrProcOptInfo& coveragePOI) c onst { 813 const GrProcOptInfo& coveragePOI) c onst {
769 // We can always blend correctly if we have dual source blending. 814 // Some formulas use dual source blending, so we fall back if it is required but not supported.
770 if (caps.shaderCaps()->dualSourceBlendingSupport()) { 815 return !caps.shaderCaps()->dualSourceBlendingSupport() &&
771 return false; 816 get_blend_formula(colorPOI, coveragePOI, fXfermode).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 } 817 }
798 818
799 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory); 819 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory);
800 820
801 GrXPFactory* GrPorterDuffXPFactory::TestCreate(SkRandom* random, 821 GrXPFactory* GrPorterDuffXPFactory::TestCreate(SkRandom* random,
802 GrContext*, 822 GrContext*,
803 const GrDrawTargetCaps&, 823 const GrDrawTargetCaps&,
804 GrTexture*[]) { 824 GrTexture*[]) {
805 SkXfermode::Mode mode = SkXfermode::Mode(random->nextULessThan(SkXfermode::k LastCoeffMode)); 825 SkXfermode::Mode mode = SkXfermode::Mode(random->nextULessThan(SkXfermode::k LastCoeffMode));
806 return GrPorterDuffXPFactory::Create(mode); 826 return GrPorterDuffXPFactory::Create(mode);
807 } 827 }
808 828
OLDNEW
« no previous file with comments | « src/gpu/GrBlend.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698