Chromium Code Reviews| 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 |