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 | 74 |
| 81 kSecondaryOutputTypeCnt, | 75 GrBlendEquation getBlendEquation() const { return fBlendEquation; } |
| 82 }; | |
| 83 | |
| 84 PrimaryOutputType primaryOutputType() const { return fPrimaryOutputType; } | |
| 85 SecondaryOutputType secondaryOutputType() const { return fSecondaryOutputTyp e; } | |
| 86 | |
| 87 GrBlendCoeff getSrcBlend() const { return fSrcBlend; } | 76 GrBlendCoeff getSrcBlend() const { return fSrcBlend; } |
| 88 GrBlendCoeff getDstBlend() const { return fDstBlend; } | 77 GrBlendCoeff getDstBlend() const { return fDstBlend; } |
| 89 | 78 |
| 90 private: | 79 private: |
| 91 PorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, GrColo r constant, | 80 PorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, GrColo r constant, |
| 92 const GrDeviceCoordTexture* dstCopy, bool willReadDs tColor); | 81 const GrDeviceCoordTexture* dstCopy, bool willReadDs tColor); |
| 93 | 82 |
| 94 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI, | 83 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI, |
| 95 const GrProcOptInfo& coveragePO I, | 84 const GrProcOptInfo& coveragePO I, |
| 96 bool doesStencilWrite, | 85 bool doesStencilWrite, |
| 97 GrColor* overrideColor, | 86 GrColor* overrideColor, |
| 98 const GrDrawTargetCaps& caps) o verride; | 87 const GrDrawTargetCaps& caps) o verride; |
| 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 12 matching lines...) Expand all Loading... | |
| 310 coverage POI, | 298 coverage POI, |
| 311 doesSten cilWrite); | 299 doesSten cilWrite); |
| 312 this->calcOutputTypes(optFlags, caps, coveragePOI.isSolidWhite()); | 300 this->calcOutputTypes(optFlags, caps, coveragePOI.isSolidWhite()); |
| 313 return optFlags; | 301 return optFlags; |
| 314 } | 302 } |
| 315 | 303 |
| 316 void PorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFlags , | 304 void PorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFlags , |
| 317 const GrDrawTargetCaps& caps, | 305 const GrDrawTargetCaps& caps, |
| 318 bool hasSolidCoverage) { | 306 bool hasSolidCoverage) { |
| 319 if (this->willReadDstColor()) { | 307 if (this->willReadDstColor()) { |
| 320 fPrimaryOutputType = kCustom_PrimaryOutputType; | 308 fPrimaryOutputType = kCustom_OutputType; |
| 321 return; | 309 return; |
| 322 } | 310 } |
| 323 | 311 |
| 324 if (optFlags & kIgnoreColor_OptFlag) { | 312 if (optFlags & kIgnoreColor_OptFlag) { |
| 325 if (optFlags & kIgnoreCoverage_OptFlag) { | 313 if (optFlags & kIgnoreCoverage_OptFlag) { |
| 326 fPrimaryOutputType = kNone_PrimaryOutputType; | 314 fPrimaryOutputType = kNone_OutputType; |
| 327 return; | 315 return; |
| 328 } else { | 316 } else { |
| 329 fPrimaryOutputType = kCoverage_PrimaryOutputType; | 317 fPrimaryOutputType = kCoverage_OutputType; |
| 330 return; | 318 return; |
| 331 } | 319 } |
| 332 } else if (optFlags & kIgnoreCoverage_OptFlag) { | 320 } else if (optFlags & kIgnoreCoverage_OptFlag) { |
| 333 fPrimaryOutputType = kColor_PrimaryOutputType; | 321 fPrimaryOutputType = kColor_OutputType; |
| 334 return; | 322 return; |
| 335 } | 323 } |
| 336 | 324 |
| 337 // If we do have coverage determine whether it matters. Dual source blendin g is expensive so | 325 // If we do have coverage determine whether it matters. Coverage drawing mod e "just works", |
| 338 // we don't do it if we are doing coverage drawing. If we aren't then We al ways do dual source | 326 // without the need for special handling. (We get coverage when there are an y effective coverage |
| 339 // blending if we have any effective coverage stages OR the geometry process or doesn't emits | 327 // stages OR the geometry processor doesn't emit solid coverage.) |
| 340 // solid coverage. | |
| 341 if (!(optFlags & kSetCoverageDrawing_OptFlag) && !hasSolidCoverage) { | 328 if (!(optFlags & kSetCoverageDrawing_OptFlag) && !hasSolidCoverage) { |
| 329 // Try to handle coverage using an alternate blend equation. Dual source blending is | |
| 330 // expensive and not supported on all platforms. | |
| 331 if (kZero_GrBlendCoeff == fSrcBlend) { | |
|
egdaniel
2015/05/15 14:58:03
I wonder if it is time to merge getInternalOptimiz
| |
| 332 if (kSA_GrBlendCoeff == fDstBlend) { | |
| 333 // The formula with f=coverage is: f * D * Sa + (1-f) * D | |
| 334 // This can be rewritten as: D - [f * (1-Sa)] * D | |
| 335 fBlendEquation = kReverseSubtract_GrBlendEquation; | |
| 336 fDstBlend = kOne_GrBlendCoeff; | |
| 337 fSrcBlend = kDC_GrBlendCoeff; | |
| 338 fPrimaryOutputType = kCoverageISA_OutputType; | |
| 339 return; | |
| 340 } else if (kSC_GrBlendCoeff == fDstBlend) { | |
| 341 // The formula with f=coverage is: f * D * S + (1-f) * D | |
| 342 // This can be rewritten as: D - [f * (1-S)] * D | |
| 343 fBlendEquation = kReverseSubtract_GrBlendEquation; | |
| 344 fDstBlend = kOne_GrBlendCoeff; | |
| 345 fSrcBlend = kDC_GrBlendCoeff; | |
| 346 fPrimaryOutputType = kCoverageISC_OutputType; | |
| 347 return; | |
| 348 } | |
| 349 } | |
| 342 if (caps.shaderCaps()->dualSourceBlendingSupport()) { | 350 if (caps.shaderCaps()->dualSourceBlendingSupport()) { |
| 343 if (kZero_GrBlendCoeff == fDstBlend) { | 351 if (kZero_GrBlendCoeff == fDstBlend) { |
| 344 // write the coverage value to second color | 352 // write the coverage value to second color |
| 345 fSecondaryOutputType = kCoverage_SecondaryOutputType; | 353 fSecondaryOutputType = kCoverage_OutputType; |
| 346 fDstBlend = kIS2C_GrBlendCoeff; | 354 fDstBlend = kIS2C_GrBlendCoeff; |
| 355 return; | |
| 347 } else if (kSA_GrBlendCoeff == fDstBlend) { | 356 } else if (kSA_GrBlendCoeff == fDstBlend) { |
| 348 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered. | 357 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered. |
| 349 fSecondaryOutputType = kCoverageISA_SecondaryOutputType; | 358 fSecondaryOutputType = kCoverageISA_OutputType; |
| 350 fDstBlend = kIS2C_GrBlendCoeff; | 359 fDstBlend = kIS2C_GrBlendCoeff; |
| 351 } else if (kSC_GrBlendCoeff == fDstBlend) { | 360 return; |
| 352 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered. | |
| 353 fSecondaryOutputType = kCoverageISC_SecondaryOutputType; | |
| 354 fDstBlend = kIS2C_GrBlendCoeff; | |
| 355 } | 361 } |
| 356 } | 362 } |
| 357 } | 363 } |
| 358 } | 364 } |
| 359 | 365 |
| 360 GrXferProcessor::OptFlags | 366 GrXferProcessor::OptFlags |
| 361 PorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPOI, | 367 PorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPOI, |
| 362 const GrProcOptInfo& coverageP OI, | 368 const GrProcOptInfo& coverageP OI, |
| 363 bool doesStencilWrite) { | 369 bool doesStencilWrite) { |
| 364 if (this->willReadDstColor()) { | 370 if (this->willReadDstColor()) { |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 452 return GrXferProcessor::kSetCoverageDrawing_OptFlag; | 458 return GrXferProcessor::kSetCoverageDrawing_OptFlag; |
| 453 | 459 |
| 454 } | 460 } |
| 455 return GrXferProcessor::kSetCoverageDrawing_OptFlag; | 461 return GrXferProcessor::kSetCoverageDrawing_OptFlag; |
| 456 } | 462 } |
| 457 | 463 |
| 458 return GrXferProcessor::kNone_Opt; | 464 return GrXferProcessor::kNone_Opt; |
| 459 } | 465 } |
| 460 | 466 |
| 461 bool PorterDuffXferProcessor::hasSecondaryOutput() const { | 467 bool PorterDuffXferProcessor::hasSecondaryOutput() const { |
| 462 return kNone_SecondaryOutputType != fSecondaryOutputType; | 468 return kNone_OutputType != fSecondaryOutputType; |
| 463 } | 469 } |
| 464 | 470 |
| 465 /////////////////////////////////////////////////////////////////////////////// | 471 /////////////////////////////////////////////////////////////////////////////// |
| 466 | 472 |
| 467 class PDLCDXferProcessor : public GrXferProcessor { | 473 class PDLCDXferProcessor : public GrXferProcessor { |
| 468 public: | 474 public: |
| 469 static GrXferProcessor* Create(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, | 475 static GrXferProcessor* Create(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, |
| 470 const GrProcOptInfo& colorPOI); | 476 const GrProcOptInfo& colorPOI); |
| 471 | 477 |
| 472 ~PDLCDXferProcessor() override; | 478 ~PDLCDXferProcessor() override; |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 770 if (caps.shaderCaps()->dualSourceBlendingSupport()) { | 776 if (caps.shaderCaps()->dualSourceBlendingSupport()) { |
| 771 return false; | 777 return false; |
| 772 } | 778 } |
| 773 | 779 |
| 774 if (can_tweak_alpha_for_coverage(fDstCoeff)) { | 780 if (can_tweak_alpha_for_coverage(fDstCoeff)) { |
| 775 return false; | 781 return false; |
| 776 } | 782 } |
| 777 | 783 |
| 778 bool srcAIsOne = colorPOI.isOpaque(); | 784 bool srcAIsOne = colorPOI.isOpaque(); |
| 779 | 785 |
| 780 if (kZero_GrBlendCoeff == fDstCoeff) { | 786 switch (fDstCoeff) { |
| 781 if (kZero_GrBlendCoeff == fSrcCoeff || srcAIsOne) { | 787 case kZero_GrBlendCoeff: |
| 782 return false; | 788 if (kZero_GrBlendCoeff == fSrcCoeff || srcAIsOne) { |
| 783 } | 789 return false; |
| 784 } | 790 } |
| 785 | 791 break; |
| 786 // Reduces to: coeffS * (Cov*S) + D | 792 case kSA_GrBlendCoeff: |
| 787 if (kSA_GrBlendCoeff == fDstCoeff && srcAIsOne) { | 793 // Reduces to: coeffS * (Cov*S) + D |
| 788 return false; | 794 if (srcAIsOne) { |
| 795 return false; | |
| 796 } | |
| 797 // fallthrough | |
| 798 case kSC_GrBlendCoeff: | |
| 799 // Can be implemented with kReverseSubtract_GrBlendEquation. | |
| 800 if (kZero_GrBlendCoeff == fSrcCoeff) { | |
| 801 return false; | |
| 802 } | |
| 803 break; | |
| 804 default: break; | |
| 789 } | 805 } |
| 790 | 806 |
| 791 // We can always blend correctly if we have solid coverage. | 807 // We can always blend correctly if we have solid coverage. |
| 792 if (coveragePOI.isSolidWhite()) { | 808 if (coveragePOI.isSolidWhite()) { |
| 793 return false; | 809 return false; |
| 794 } | 810 } |
| 795 | 811 |
| 796 return true; | 812 return true; |
| 797 } | 813 } |
| 798 | 814 |
| 799 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory); | 815 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory); |
| 800 | 816 |
| 801 GrXPFactory* GrPorterDuffXPFactory::TestCreate(SkRandom* random, | 817 GrXPFactory* GrPorterDuffXPFactory::TestCreate(SkRandom* random, |
| 802 GrContext*, | 818 GrContext*, |
| 803 const GrDrawTargetCaps&, | 819 const GrDrawTargetCaps&, |
| 804 GrTexture*[]) { | 820 GrTexture*[]) { |
| 805 SkXfermode::Mode mode = SkXfermode::Mode(random->nextULessThan(SkXfermode::k LastCoeffMode)); | 821 SkXfermode::Mode mode = SkXfermode::Mode(random->nextULessThan(SkXfermode::k LastCoeffMode)); |
| 806 return GrPorterDuffXPFactory::Create(mode); | 822 return GrPorterDuffXPFactory::Create(mode); |
| 807 } | 823 } |
| 808 | 824 |
| OLD | NEW |