OLD | NEW |
---|---|
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" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
46 const char* name() const override { return "Porter Duff"; } | 46 const char* name() const override { return "Porter Duff"; } |
47 | 47 |
48 GrGLXferProcessor* createGLInstance() const override; | 48 GrGLXferProcessor* createGLInstance() const override; |
49 | 49 |
50 bool hasSecondaryOutput() const override; | 50 bool hasSecondaryOutput() const override; |
51 | 51 |
52 /////////////////////////////////////////////////////////////////////////// | 52 /////////////////////////////////////////////////////////////////////////// |
53 /// @name Stage Output Types | 53 /// @name Stage Output Types |
54 //// | 54 //// |
55 | 55 |
56 enum PrimaryOutputType { | 56 enum OutputType { |
57 kNone_PrimaryOutputType, | 57 kNone_OutputType, |
58 kColor_PrimaryOutputType, | 58 kColor_OutputType, |
59 kCoverage_PrimaryOutputType, | 59 kCoverage_OutputType, |
60 // Modulate color and coverage, write result as the color output. | 60 // Modulate color and coverage, write result as the color output. |
61 kModulate_PrimaryOutputType, | 61 kModulate_OutputType, |
62 // Write coverage * (1 - colorA) as the color output. | |
63 kCoverageISA_OutputType, | |
64 // Write coverage * (1 - colorRGBA) as the color output. | |
65 kCoverageISC_OutputType, | |
62 // Custom Porter-Duff output, used for when we explictly are reading the dst and blending | 66 // 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 | 67 // in the shader. This is only vaid for the primary output, and secondar y output is ignored |
64 // equation: cov * (coeffS * S + coeffD * D) + (1 - cov) * D | 68 // if you use this. Uses the equation: cov * (coeffS * S + coeffD * D) + (1 - cov) * D |
65 kCustom_PrimaryOutputType | 69 kCustom_OutputType |
66 }; | 70 }; |
67 | 71 |
68 enum SecondaryOutputType { | 72 OutputType primaryOutputType() const { return fPrimaryOutputType; } |
69 // There is no secondary output | 73 OutputType secondaryOutputType() const { return fSecondaryOutputType; } |
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 | 74 |
87 GrXferProcessor::OptFlags getOptimizations(const GrProcOptInfo& colorPOI, | 75 GrXferProcessor::OptFlags getOptimizations(const GrProcOptInfo& colorPOI, |
88 const GrProcOptInfo& coveragePOI, | 76 const GrProcOptInfo& coveragePOI, |
89 bool doesStencilWrite, | 77 bool doesStencilWrite, |
90 GrColor* overrideColor, | 78 GrColor* overrideColor, |
91 const GrDrawTargetCaps& caps) ove rride; | 79 const GrDrawTargetCaps& caps) ove rride; |
92 | 80 |
81 GrBlendEquation getBlendEquation() const { return fBlendEquation; } | |
93 GrBlendCoeff getSrcBlend() const { return fSrcBlend; } | 82 GrBlendCoeff getSrcBlend() const { return fSrcBlend; } |
94 GrBlendCoeff getDstBlend() const { return fDstBlend; } | 83 GrBlendCoeff getDstBlend() const { return fDstBlend; } |
95 | 84 |
96 private: | 85 private: |
97 PorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, GrColo r constant, | 86 PorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, GrColo r constant, |
98 const GrDeviceCoordTexture* dstCopy, bool willReadDs tColor); | 87 const GrDeviceCoordTexture* dstCopy, bool willReadDs tColor); |
99 | 88 |
100 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c onst override; | 89 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c onst override; |
101 | 90 |
102 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override { | 91 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override { |
103 if (!this->willReadDstColor()) { | 92 if (!this->willReadDstColor()) { |
93 blendInfo->fEquation = fBlendEquation; | |
104 blendInfo->fSrcBlend = fSrcBlend; | 94 blendInfo->fSrcBlend = fSrcBlend; |
105 blendInfo->fDstBlend = fDstBlend; | 95 blendInfo->fDstBlend = fDstBlend; |
106 } else { | |
107 blendInfo->fSrcBlend = kOne_GrBlendCoeff; | |
108 blendInfo->fDstBlend = kZero_GrBlendCoeff; | |
109 } | 96 } |
110 blendInfo->fBlendConstant = fBlendConstant; | 97 blendInfo->fBlendConstant = fBlendConstant; |
111 } | 98 } |
112 | 99 |
113 bool onIsEqual(const GrXferProcessor& xpBase) const override { | 100 bool onIsEqual(const GrXferProcessor& xpBase) const override { |
114 const PorterDuffXferProcessor& xp = xpBase.cast<PorterDuffXferProcessor> (); | 101 const PorterDuffXferProcessor& xp = xpBase.cast<PorterDuffXferProcessor> (); |
115 if (fSrcBlend != xp.fSrcBlend || | 102 if (fBlendEquation != xp.fBlendEquation || |
103 fSrcBlend != xp.fSrcBlend || | |
116 fDstBlend != xp.fDstBlend || | 104 fDstBlend != xp.fDstBlend || |
117 fBlendConstant != xp.fBlendConstant || | 105 fBlendConstant != xp.fBlendConstant || |
118 fPrimaryOutputType != xp.fPrimaryOutputType || | 106 fPrimaryOutputType != xp.fPrimaryOutputType || |
119 fSecondaryOutputType != xp.fSecondaryOutputType) { | 107 fSecondaryOutputType != xp.fSecondaryOutputType) { |
120 return false; | 108 return false; |
121 } | 109 } |
122 return true; | 110 return true; |
123 } | 111 } |
124 | 112 |
125 GrXferProcessor::OptFlags internalGetOptimizations(const GrProcOptInfo& colo rPOI, | 113 GrXferProcessor::OptFlags internalGetOptimizations(const GrProcOptInfo& colo rPOI, |
126 const GrProcOptInfo& cove ragePOI, | 114 const GrProcOptInfo& cove ragePOI, |
127 bool doesStencilWrite); | 115 bool doesStencilWrite); |
128 | 116 |
129 void calcOutputTypes(GrXferProcessor::OptFlags blendOpts, const GrDrawTarget Caps& caps, | 117 void calcOutputTypes(GrXferProcessor::OptFlags blendOpts, const GrDrawTarget Caps& caps, |
130 bool hasSolidCoverage); | 118 bool hasSolidCoverage); |
131 | 119 |
132 GrBlendCoeff fSrcBlend; | 120 GrBlendEquation fBlendEquation; |
133 GrBlendCoeff fDstBlend; | 121 GrBlendCoeff fSrcBlend; |
134 GrColor fBlendConstant; | 122 GrBlendCoeff fDstBlend; |
135 PrimaryOutputType fPrimaryOutputType; | 123 GrColor fBlendConstant; |
136 SecondaryOutputType fSecondaryOutputType; | 124 OutputType fPrimaryOutputType; |
125 OutputType fSecondaryOutputType; | |
137 | 126 |
138 typedef GrXferProcessor INHERITED; | 127 typedef GrXferProcessor INHERITED; |
139 }; | 128 }; |
140 | 129 |
141 /////////////////////////////////////////////////////////////////////////////// | 130 /////////////////////////////////////////////////////////////////////////////// |
142 | 131 |
132 static void append_color_output(GrGLXPFragmentBuilder* fsBuilder, | |
133 PorterDuffXferProcessor::OutputType outputType, | |
134 const char* outputName, const char* inputColor, | |
135 const char* inputCoverage) { | |
136 switch (outputType) { | |
137 case PorterDuffXferProcessor::kNone_OutputType: | |
138 fsBuilder->codeAppendf("%s = vec4(0);", outputName); | |
139 break; | |
140 case PorterDuffXferProcessor::kColor_OutputType: | |
141 fsBuilder->codeAppendf("%s = %s;", outputName, inputColor); | |
142 break; | |
143 case PorterDuffXferProcessor::kCoverage_OutputType: | |
144 fsBuilder->codeAppendf("%s = %s;", outputName, inputCoverage); | |
145 break; | |
146 case PorterDuffXferProcessor::kModulate_OutputType: | |
147 fsBuilder->codeAppendf("%s = %s * %s;", outputName, inputColor, inpu tCoverage); | |
148 break; | |
149 case PorterDuffXferProcessor::kCoverageISA_OutputType: | |
150 fsBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", | |
151 outputName, inputColor, inputCoverage); | |
152 break; | |
153 case PorterDuffXferProcessor::kCoverageISC_OutputType: | |
154 fsBuilder->codeAppendf("%s = (vec4(1.0) - %s) * %s;", | |
155 outputName, inputColor, inputCoverage); | |
156 break; | |
157 default: | |
158 SkFAIL("Unexpected Output"); | |
159 } | |
160 } | |
161 | |
143 bool append_porterduff_term(GrGLXPFragmentBuilder* fsBuilder, GrBlendCoeff coeff , | 162 bool append_porterduff_term(GrGLXPFragmentBuilder* fsBuilder, GrBlendCoeff coeff , |
144 const char* colorName, const char* srcColorName, | 163 const char* colorName, const char* srcColorName, |
145 const char* dstColorName, bool hasPrevious) { | 164 const char* dstColorName, bool hasPrevious) { |
146 if (kZero_GrBlendCoeff == coeff) { | 165 if (kZero_GrBlendCoeff == coeff) { |
147 return hasPrevious; | 166 return hasPrevious; |
148 } else { | 167 } else { |
149 if (hasPrevious) { | 168 if (hasPrevious) { |
150 fsBuilder->codeAppend(" + "); | 169 fsBuilder->codeAppend(" + "); |
151 } | 170 } |
152 fsBuilder->codeAppendf("%s", colorName); | 171 fsBuilder->codeAppendf("%s", colorName); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
198 if (xp.willReadDstColor()) { | 217 if (xp.willReadDstColor()) { |
199 b->add32(xp.getSrcBlend()); | 218 b->add32(xp.getSrcBlend()); |
200 b->add32(xp.getDstBlend()); | 219 b->add32(xp.getDstBlend()); |
201 } | 220 } |
202 }; | 221 }; |
203 | 222 |
204 private: | 223 private: |
205 void onEmitCode(const EmitArgs& args) override { | 224 void onEmitCode(const EmitArgs& args) override { |
206 const PorterDuffXferProcessor& xp = args.fXP.cast<PorterDuffXferProcesso r>(); | 225 const PorterDuffXferProcessor& xp = args.fXP.cast<PorterDuffXferProcesso r>(); |
207 GrGLXPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); | 226 GrGLXPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); |
208 if (PorterDuffXferProcessor::kCustom_PrimaryOutputType != xp.primaryOutp utType()) { | 227 if (PorterDuffXferProcessor::kCustom_OutputType != xp.primaryOutputType( )) { |
209 SkASSERT(!xp.willReadDstColor()); | 228 SkASSERT(!xp.willReadDstColor()); |
210 switch(xp.secondaryOutputType()) { | 229 if (PorterDuffXferProcessor::kNone_OutputType != xp.secondaryOutputT ype()) { |
211 case PorterDuffXferProcessor::kNone_SecondaryOutputType: | 230 append_color_output(fsBuilder, xp.secondaryOutputType(), args.fO utputSecondary, |
212 break; | 231 args.fInputColor, args.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 } | 232 } |
230 | 233 append_color_output(fsBuilder, xp.primaryOutputType(), args.fOutputP rimary, |
231 switch (xp.primaryOutputType()) { | 234 args.fInputColor, args.fInputCoverage); |
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 { | 235 } else { |
249 SkASSERT(xp.willReadDstColor()); | 236 SkASSERT(xp.willReadDstColor()); |
250 | 237 |
251 const char* dstColor = fsBuilder->dstColor(); | 238 const char* dstColor = fsBuilder->dstColor(); |
252 | 239 |
253 fsBuilder->codeAppend("vec4 colorBlend ="); | 240 fsBuilder->codeAppend("vec4 colorBlend ="); |
254 // append src blend | 241 // append src blend |
255 bool didAppend = append_porterduff_term(fsBuilder, xp.getSrcBlend(), | 242 bool didAppend = append_porterduff_term(fsBuilder, xp.getSrcBlend(), |
256 args.fInputColor, args.fInpu tColor, | 243 args.fInputColor, args.fInpu tColor, |
257 dstColor, false); | 244 dstColor, false); |
(...skipping 15 matching lines...) Expand all Loading... | |
273 }; | 260 }; |
274 | 261 |
275 /////////////////////////////////////////////////////////////////////////////// | 262 /////////////////////////////////////////////////////////////////////////////// |
276 | 263 |
277 PorterDuffXferProcessor::PorterDuffXferProcessor(GrBlendCoeff srcBlend, | 264 PorterDuffXferProcessor::PorterDuffXferProcessor(GrBlendCoeff srcBlend, |
278 GrBlendCoeff dstBlend, | 265 GrBlendCoeff dstBlend, |
279 GrColor constant, | 266 GrColor constant, |
280 const GrDeviceCoordTexture* dst Copy, | 267 const GrDeviceCoordTexture* dst Copy, |
281 bool willReadDstColor) | 268 bool willReadDstColor) |
282 : INHERITED(dstCopy, willReadDstColor) | 269 : INHERITED(dstCopy, willReadDstColor) |
270 , fBlendEquation(kAdd_GrBlendEquation) | |
283 , fSrcBlend(srcBlend) | 271 , fSrcBlend(srcBlend) |
284 , fDstBlend(dstBlend) | 272 , fDstBlend(dstBlend) |
285 , fBlendConstant(constant) | 273 , fBlendConstant(constant) |
286 , fPrimaryOutputType(kModulate_PrimaryOutputType) | 274 , fPrimaryOutputType(kModulate_OutputType) |
287 , fSecondaryOutputType(kNone_SecondaryOutputType) { | 275 , fSecondaryOutputType(kNone_OutputType) { |
288 this->initClassID<PorterDuffXferProcessor>(); | 276 this->initClassID<PorterDuffXferProcessor>(); |
289 } | 277 } |
290 | 278 |
291 PorterDuffXferProcessor::~PorterDuffXferProcessor() { | 279 PorterDuffXferProcessor::~PorterDuffXferProcessor() { |
292 } | 280 } |
293 | 281 |
294 void PorterDuffXferProcessor::onGetGLProcessorKey(const GrGLSLCaps& caps, | 282 void PorterDuffXferProcessor::onGetGLProcessorKey(const GrGLSLCaps& caps, |
295 GrProcessorKeyBuilder* b) cons t { | 283 GrProcessorKeyBuilder* b) cons t { |
296 GLPorterDuffXferProcessor::GenKey(*this, caps, b); | 284 GLPorterDuffXferProcessor::GenKey(*this, caps, b); |
297 } | 285 } |
(...skipping 24 matching lines...) Expand all Loading... | |
322 doesStencilWrite); | 310 doesStencilWrite); |
323 } | 311 } |
324 this->calcOutputTypes(optFlags, caps, coveragePOI.isSolidWhite()); | 312 this->calcOutputTypes(optFlags, caps, coveragePOI.isSolidWhite()); |
325 return optFlags; | 313 return optFlags; |
326 } | 314 } |
327 | 315 |
328 void PorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFlags , | 316 void PorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFlags , |
329 const GrDrawTargetCaps& caps, | 317 const GrDrawTargetCaps& caps, |
330 bool hasSolidCoverage) { | 318 bool hasSolidCoverage) { |
331 if (this->willReadDstColor()) { | 319 if (this->willReadDstColor()) { |
332 fPrimaryOutputType = kCustom_PrimaryOutputType; | 320 fPrimaryOutputType = kCustom_OutputType; |
333 return; | 321 return; |
334 } | 322 } |
335 | 323 |
336 if (optFlags & kIgnoreColor_OptFlag) { | 324 if (optFlags & kIgnoreColor_OptFlag) { |
337 if (optFlags & kIgnoreCoverage_OptFlag) { | 325 if (optFlags & kIgnoreCoverage_OptFlag) { |
338 fPrimaryOutputType = kNone_PrimaryOutputType; | 326 fPrimaryOutputType = kNone_OutputType; |
339 return; | 327 return; |
340 } else { | 328 } else { |
341 fPrimaryOutputType = kCoverage_PrimaryOutputType; | 329 fPrimaryOutputType = kCoverage_OutputType; |
342 return; | 330 return; |
343 } | 331 } |
344 } else if (optFlags & kIgnoreCoverage_OptFlag) { | 332 } else if (optFlags & kIgnoreCoverage_OptFlag) { |
345 fPrimaryOutputType = kColor_PrimaryOutputType; | 333 fPrimaryOutputType = kColor_OutputType; |
346 return; | 334 return; |
347 } | 335 } |
348 | 336 |
349 // If we do have coverage determine whether it matters. Dual source blendin g is expensive so | 337 // If we do have coverage determine whether it matters. Coverage drawing mod e "just works", |
350 // we don't do it if we are doing coverage drawing. If we aren't then We al ways do dual source | 338 // without the need for special handling. (We get coverage when there are an y effective coverage |
351 // blending if we have any effective coverage stages OR the geometry process or doesn't emits | 339 // stages OR the geometry processor doesn't emit solid coverage.) |
352 // solid coverage. | |
353 if (!(optFlags & kSetCoverageDrawing_OptFlag) && !hasSolidCoverage) { | 340 if (!(optFlags & kSetCoverageDrawing_OptFlag) && !hasSolidCoverage) { |
341 // Try to handle coverage using an alternate blend equation. Dual source blending is | |
342 // expensive and not supported on all platforms. | |
343 if (kZero_GrBlendCoeff == fSrcBlend) { | |
344 if (kSA_GrBlendCoeff == fDstBlend) { | |
345 // The formula with f=coverage is: f * D * Sa + (1-f) * D | |
346 // This can be rewritten as: D - [f * (1-Sa)] * D | |
347 fBlendEquation = kReverseSubtract_GrBlendEquation; | |
348 fDstBlend = kOne_GrBlendCoeff; | |
349 fSrcBlend = kDC_GrBlendCoeff; | |
350 fPrimaryOutputType = kCoverageISA_OutputType; | |
351 return; | |
352 } else if (kSC_GrBlendCoeff == fDstBlend) { | |
353 // The formula with f=coverage is: f * D * S + (1-f) * D | |
354 // This can be rewritten as: D - [f * (1-S)] * D | |
355 fBlendEquation = kReverseSubtract_GrBlendEquation; | |
356 fDstBlend = kOne_GrBlendCoeff; | |
357 fSrcBlend = kDC_GrBlendCoeff; | |
358 fPrimaryOutputType = kCoverageISC_OutputType; | |
359 return; | |
360 } | |
361 } | |
354 if (caps.shaderCaps()->dualSourceBlendingSupport()) { | 362 if (caps.shaderCaps()->dualSourceBlendingSupport()) { |
355 if (kZero_GrBlendCoeff == fDstBlend) { | 363 if (kZero_GrBlendCoeff == fDstBlend) { |
356 // write the coverage value to second color | 364 // write the coverage value to second color |
357 fSecondaryOutputType = kCoverage_SecondaryOutputType; | 365 fSecondaryOutputType = kCoverage_OutputType; |
358 fDstBlend = kIS2C_GrBlendCoeff; | 366 fDstBlend = kIS2C_GrBlendCoeff; |
367 return; | |
359 } else if (kSA_GrBlendCoeff == fDstBlend) { | 368 } else if (kSA_GrBlendCoeff == fDstBlend) { |
360 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered. | 369 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered. |
361 fSecondaryOutputType = kCoverageISA_SecondaryOutputType; | 370 fSecondaryOutputType = kCoverageISA_OutputType; |
362 fDstBlend = kIS2C_GrBlendCoeff; | 371 fDstBlend = kIS2C_GrBlendCoeff; |
363 } else if (kSC_GrBlendCoeff == fDstBlend) { | 372 return; |
364 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered. | |
365 fSecondaryOutputType = kCoverageISC_SecondaryOutputType; | |
366 fDstBlend = kIS2C_GrBlendCoeff; | |
Chris Dalton
2015/05/07 01:44:02
This branch is no longer used. Modulate was the on
| |
367 } | 373 } |
368 } | 374 } |
369 } | 375 } |
370 } | 376 } |
371 | 377 |
372 GrXferProcessor::OptFlags | 378 GrXferProcessor::OptFlags |
373 PorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPOI, | 379 PorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPOI, |
374 const GrProcOptInfo& coverageP OI, | 380 const GrProcOptInfo& coverageP OI, |
375 bool doesStencilWrite) { | 381 bool doesStencilWrite) { |
376 if (this->willReadDstColor()) { | 382 if (this->willReadDstColor()) { |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
462 | 468 |
463 } | 469 } |
464 return GrXferProcessor::kSetCoverageDrawing_OptFlag; | 470 return GrXferProcessor::kSetCoverageDrawing_OptFlag; |
465 } | 471 } |
466 } | 472 } |
467 | 473 |
468 return GrXferProcessor::kNone_Opt; | 474 return GrXferProcessor::kNone_Opt; |
469 } | 475 } |
470 | 476 |
471 bool PorterDuffXferProcessor::hasSecondaryOutput() const { | 477 bool PorterDuffXferProcessor::hasSecondaryOutput() const { |
472 return kNone_SecondaryOutputType != fSecondaryOutputType; | 478 return kNone_OutputType != fSecondaryOutputType; |
473 } | 479 } |
474 | 480 |
475 /////////////////////////////////////////////////////////////////////////////// | 481 /////////////////////////////////////////////////////////////////////////////// |
476 | 482 |
477 GrPorterDuffXPFactory::GrPorterDuffXPFactory(GrBlendCoeff src, GrBlendCoeff dst) | 483 GrPorterDuffXPFactory::GrPorterDuffXPFactory(GrBlendCoeff src, GrBlendCoeff dst) |
478 : fSrcCoeff(src), fDstCoeff(dst) { | 484 : fSrcCoeff(src), fDstCoeff(dst) { |
479 this->initClassID<GrPorterDuffXPFactory>(); | 485 this->initClassID<GrPorterDuffXPFactory>(); |
480 } | 486 } |
481 | 487 |
482 GrXPFactory* GrPorterDuffXPFactory::Create(SkXfermode::Mode mode) { | 488 GrXPFactory* GrPorterDuffXPFactory::Create(SkXfermode::Mode mode) { |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
667 if (caps.shaderCaps()->dualSourceBlendingSupport()) { | 673 if (caps.shaderCaps()->dualSourceBlendingSupport()) { |
668 return false; | 674 return false; |
669 } | 675 } |
670 | 676 |
671 if (can_tweak_alpha_for_coverage(fDstCoeff)) { | 677 if (can_tweak_alpha_for_coverage(fDstCoeff)) { |
672 return false; | 678 return false; |
673 } | 679 } |
674 | 680 |
675 bool srcAIsOne = colorPOI.isOpaque(); | 681 bool srcAIsOne = colorPOI.isOpaque(); |
676 | 682 |
677 if (kZero_GrBlendCoeff == fDstCoeff) { | 683 switch (fDstCoeff) { |
678 if (kZero_GrBlendCoeff == fSrcCoeff || srcAIsOne) { | 684 case kZero_GrBlendCoeff: |
679 return false; | 685 if (kZero_GrBlendCoeff == fSrcCoeff || srcAIsOne) { |
680 } | 686 return false; |
681 } | 687 } |
682 | 688 break; |
683 // Reduces to: coeffS * (Cov*S) + D | 689 case kSA_GrBlendCoeff: |
684 if (kSA_GrBlendCoeff == fDstCoeff && srcAIsOne) { | 690 // Reduces to: coeffS * (Cov*S) + D |
685 return false; | 691 if (srcAIsOne) { |
692 return false; | |
693 } | |
694 // fallthrough | |
695 case kSC_GrBlendCoeff: | |
696 // Can be implemented with kReverseSubtract_GrBlendEquation. | |
697 if (kZero_GrBlendCoeff == fSrcCoeff) { | |
698 return false; | |
699 } | |
700 break; | |
701 default: break; | |
686 } | 702 } |
687 | 703 |
688 // We can always blend correctly if we have solid coverage. | 704 // We can always blend correctly if we have solid coverage. |
689 if (coveragePOI.isSolidWhite()) { | 705 if (coveragePOI.isSolidWhite()) { |
690 return false; | 706 return false; |
691 } | 707 } |
692 | 708 |
693 return true; | 709 return true; |
694 } | 710 } |
695 | 711 |
696 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory); | 712 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory); |
697 | 713 |
698 GrXPFactory* GrPorterDuffXPFactory::TestCreate(SkRandom* random, | 714 GrXPFactory* GrPorterDuffXPFactory::TestCreate(SkRandom* random, |
699 GrContext*, | 715 GrContext*, |
700 const GrDrawTargetCaps&, | 716 const GrDrawTargetCaps&, |
701 GrTexture*[]) { | 717 GrTexture*[]) { |
702 SkXfermode::Mode mode = SkXfermode::Mode(random->nextULessThan(SkXfermode::k LastCoeffMode)); | 718 SkXfermode::Mode mode = SkXfermode::Mode(random->nextULessThan(SkXfermode::k LastCoeffMode)); |
703 return GrPorterDuffXPFactory::Create(mode); | 719 return GrPorterDuffXPFactory::Create(mode); |
704 } | 720 } |
705 | 721 |
OLD | NEW |