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

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: comment 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 | « no previous file | 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"
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698