| 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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 /////////////////////////////////////////////////////////////////////////// | 52 /////////////////////////////////////////////////////////////////////////// |
| 53 /// @name Stage Output Types | 53 /// @name Stage Output Types |
| 54 //// | 54 //// |
| 55 | 55 |
| 56 enum PrimaryOutputType { | 56 enum PrimaryOutputType { |
| 57 kNone_PrimaryOutputType, | 57 kNone_PrimaryOutputType, |
| 58 kColor_PrimaryOutputType, | 58 kColor_PrimaryOutputType, |
| 59 kCoverage_PrimaryOutputType, | 59 kCoverage_PrimaryOutputType, |
| 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_PrimaryOutputType, |
| 62 // Custom Porter-Duff output, used for when we explictly are reading the
dst and blending |
| 63 // in the shader. Secondary Output must be none if you use this. The cus
tom blend uses the |
| 64 // equation: cov * (coeffS * S + coeffD * D) + (1 - cov) * D |
| 65 kCustom_PrimaryOutputType |
| 62 }; | 66 }; |
| 63 | 67 |
| 64 enum SecondaryOutputType { | 68 enum SecondaryOutputType { |
| 65 // There is no secondary output | 69 // There is no secondary output |
| 66 kNone_SecondaryOutputType, | 70 kNone_SecondaryOutputType, |
| 67 // Writes coverage as the secondary output. Only set if dual source blen
ding is supported | 71 // Writes coverage as the secondary output. Only set if dual source blen
ding is supported |
| 68 // and primary output is kModulate. | 72 // and primary output is kModulate. |
| 69 kCoverage_SecondaryOutputType, | 73 kCoverage_SecondaryOutputType, |
| 70 // Writes coverage * (1 - colorA) as the secondary output. Only set if d
ual source blending | 74 // Writes coverage * (1 - colorA) as the secondary output. Only set if d
ual source blending |
| 71 // is supported and primary output is kModulate. | 75 // is supported and primary output is kModulate. |
| 72 kCoverageISA_SecondaryOutputType, | 76 kCoverageISA_SecondaryOutputType, |
| 73 // Writes coverage * (1 - colorRGBA) as the secondary output. Only set i
f dual source | 77 // Writes coverage * (1 - colorRGBA) as the secondary output. Only set i
f dual source |
| 74 // blending is supported and primary output is kModulate. | 78 // blending is supported and primary output is kModulate. |
| 75 kCoverageISC_SecondaryOutputType, | 79 kCoverageISC_SecondaryOutputType, |
| 76 | 80 |
| 77 kSecondaryOutputTypeCnt, | 81 kSecondaryOutputTypeCnt, |
| 78 }; | 82 }; |
| 79 | 83 |
| 80 PrimaryOutputType primaryOutputType() const { return fPrimaryOutputType; } | 84 PrimaryOutputType primaryOutputType() const { return fPrimaryOutputType; } |
| 81 SecondaryOutputType secondaryOutputType() const { return fSecondaryOutputTyp
e; } | 85 SecondaryOutputType secondaryOutputType() const { return fSecondaryOutputTyp
e; } |
| 82 | 86 |
| 83 GrXferProcessor::OptFlags getOptimizations(const GrProcOptInfo& colorPOI, | 87 GrXferProcessor::OptFlags getOptimizations(const GrProcOptInfo& colorPOI, |
| 84 const GrProcOptInfo& coveragePOI, | 88 const GrProcOptInfo& coveragePOI, |
| 85 bool doesStencilWrite, | 89 bool doesStencilWrite, |
| 86 GrColor* overrideColor, | 90 GrColor* overrideColor, |
| 87 const GrDrawTargetCaps& caps) SK_
OVERRIDE; | 91 const GrDrawTargetCaps& caps) SK_
OVERRIDE; |
| 88 | 92 |
| 89 void getBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const SK_OVERRIDE { | 93 void getBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const SK_OVERRIDE { |
| 90 blendInfo->fSrcBlend = fSrcBlend; | 94 if (!this->willReadDstColor()) { |
| 91 blendInfo->fDstBlend = fDstBlend; | 95 blendInfo->fSrcBlend = fSrcBlend; |
| 96 blendInfo->fDstBlend = fDstBlend; |
| 97 } else { |
| 98 blendInfo->fSrcBlend = kOne_GrBlendCoeff; |
| 99 blendInfo->fDstBlend = kZero_GrBlendCoeff; |
| 100 } |
| 92 blendInfo->fBlendConstant = fBlendConstant; | 101 blendInfo->fBlendConstant = fBlendConstant; |
| 93 } | 102 } |
| 94 | 103 |
| 104 GrBlendCoeff getSrcBlend() const { return fSrcBlend; } |
| 105 GrBlendCoeff getDstBlend() const { return fDstBlend; } |
| 106 |
| 95 private: | 107 private: |
| 96 PorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, GrColo
r constant, | 108 PorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, GrColo
r constant, |
| 97 const GrDeviceCoordTexture* dstCopy, bool willReadDs
tColor); | 109 const GrDeviceCoordTexture* dstCopy, bool willReadDs
tColor); |
| 98 | 110 |
| 99 void onGetGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) con
st SK_OVERRIDE; | 111 void onGetGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) con
st SK_OVERRIDE; |
| 100 | 112 |
| 101 bool onIsEqual(const GrXferProcessor& xpBase) const SK_OVERRIDE { | 113 bool onIsEqual(const GrXferProcessor& xpBase) const SK_OVERRIDE { |
| 102 const PorterDuffXferProcessor& xp = xpBase.cast<PorterDuffXferProcessor>
(); | 114 const PorterDuffXferProcessor& xp = xpBase.cast<PorterDuffXferProcessor>
(); |
| 103 if (fSrcBlend != xp.fSrcBlend || | 115 if (fSrcBlend != xp.fSrcBlend || |
| 104 fDstBlend != xp.fDstBlend || | 116 fDstBlend != xp.fDstBlend || |
| (...skipping 16 matching lines...) Expand all Loading... |
| 121 GrBlendCoeff fDstBlend; | 133 GrBlendCoeff fDstBlend; |
| 122 GrColor fBlendConstant; | 134 GrColor fBlendConstant; |
| 123 PrimaryOutputType fPrimaryOutputType; | 135 PrimaryOutputType fPrimaryOutputType; |
| 124 SecondaryOutputType fSecondaryOutputType; | 136 SecondaryOutputType fSecondaryOutputType; |
| 125 | 137 |
| 126 typedef GrXferProcessor INHERITED; | 138 typedef GrXferProcessor INHERITED; |
| 127 }; | 139 }; |
| 128 | 140 |
| 129 /////////////////////////////////////////////////////////////////////////////// | 141 /////////////////////////////////////////////////////////////////////////////// |
| 130 | 142 |
| 143 bool append_porterduff_term(GrGLFPFragmentBuilder* fsBuilder, GrBlendCoeff coeff
, |
| 144 const char* colorName, const char* srcColorName, |
| 145 const char* dstColorName, bool hasPrevious) { |
| 146 if (kZero_GrBlendCoeff == coeff) { |
| 147 return hasPrevious; |
| 148 } else { |
| 149 if (hasPrevious) { |
| 150 fsBuilder->codeAppend(" + "); |
| 151 } |
| 152 fsBuilder->codeAppendf("%s", colorName); |
| 153 switch (coeff) { |
| 154 case kOne_GrBlendCoeff: |
| 155 break; |
| 156 case kSC_GrBlendCoeff: |
| 157 fsBuilder->codeAppendf(" * %s", srcColorName); |
| 158 break; |
| 159 case kISC_GrBlendCoeff: |
| 160 fsBuilder->codeAppendf(" * (vec4(1.0) - %s)", srcColorName); |
| 161 break; |
| 162 case kDC_GrBlendCoeff: |
| 163 fsBuilder->codeAppendf(" * %s", dstColorName); |
| 164 break; |
| 165 case kIDC_GrBlendCoeff: |
| 166 fsBuilder->codeAppendf(" * (vec4(1.0) - %s)", dstColorName); |
| 167 break; |
| 168 case kSA_GrBlendCoeff: |
| 169 fsBuilder->codeAppendf(" * %s.a", srcColorName); |
| 170 break; |
| 171 case kISA_GrBlendCoeff: |
| 172 fsBuilder->codeAppendf(" * (1.0 - %s.a)", srcColorName); |
| 173 break; |
| 174 case kDA_GrBlendCoeff: |
| 175 fsBuilder->codeAppendf(" * %s.a", dstColorName); |
| 176 break; |
| 177 case kIDA_GrBlendCoeff: |
| 178 fsBuilder->codeAppendf(" * (1.0 - %s.a)", dstColorName); |
| 179 break; |
| 180 default: |
| 181 SkFAIL("Unsupported Blend Coeff"); |
| 182 } |
| 183 return true; |
| 184 } |
| 185 } |
| 186 |
| 131 class GLPorterDuffXferProcessor : public GrGLXferProcessor { | 187 class GLPorterDuffXferProcessor : public GrGLXferProcessor { |
| 132 public: | 188 public: |
| 133 GLPorterDuffXferProcessor(const GrProcessor&) {} | 189 GLPorterDuffXferProcessor(const GrProcessor&) {} |
| 134 | 190 |
| 135 virtual ~GLPorterDuffXferProcessor() {} | 191 virtual ~GLPorterDuffXferProcessor() {} |
| 136 | 192 |
| 137 static void GenKey(const GrProcessor& processor, const GrGLCaps& caps, | 193 static void GenKey(const GrProcessor& processor, const GrGLCaps& caps, |
| 138 GrProcessorKeyBuilder* b) { | 194 GrProcessorKeyBuilder* b) { |
| 139 const PorterDuffXferProcessor& xp = processor.cast<PorterDuffXferProcess
or>(); | 195 const PorterDuffXferProcessor& xp = processor.cast<PorterDuffXferProcess
or>(); |
| 140 b->add32(xp.primaryOutputType()); | 196 b->add32(xp.primaryOutputType()); |
| 141 b->add32(xp.secondaryOutputType()); | 197 b->add32(xp.secondaryOutputType()); |
| 198 if (xp.willReadDstColor()) { |
| 199 b->add32(xp.getSrcBlend()); |
| 200 b->add32(xp.getDstBlend()); |
| 201 } |
| 142 }; | 202 }; |
| 143 | 203 |
| 144 private: | 204 private: |
| 145 void onEmitCode(const EmitArgs& args) SK_OVERRIDE { | 205 void onEmitCode(const EmitArgs& args) SK_OVERRIDE { |
| 146 const PorterDuffXferProcessor& xp = args.fXP.cast<PorterDuffXferProcesso
r>(); | 206 const PorterDuffXferProcessor& xp = args.fXP.cast<PorterDuffXferProcesso
r>(); |
| 147 GrGLFPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); | 207 GrGLFPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); |
| 148 if (xp.hasSecondaryOutput()) { | 208 if (PorterDuffXferProcessor::kCustom_PrimaryOutputType != xp.primaryOutp
utType()) { |
| 209 SkASSERT(!xp.willReadDstColor()); |
| 149 switch(xp.secondaryOutputType()) { | 210 switch(xp.secondaryOutputType()) { |
| 211 case PorterDuffXferProcessor::kNone_SecondaryOutputType: |
| 212 break; |
| 150 case PorterDuffXferProcessor::kCoverage_SecondaryOutputType: | 213 case PorterDuffXferProcessor::kCoverage_SecondaryOutputType: |
| 151 fsBuilder->codeAppendf("%s = %s;", args.fOutputSecondary, ar
gs.fInputCoverage); | 214 fsBuilder->codeAppendf("%s = %s;", args.fOutputSecondary, |
| 215 args.fInputCoverage); |
| 152 break; | 216 break; |
| 153 case PorterDuffXferProcessor::kCoverageISA_SecondaryOutputType: | 217 case PorterDuffXferProcessor::kCoverageISA_SecondaryOutputType: |
| 154 fsBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", | 218 fsBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", |
| 155 args.fOutputSecondary, args.fInputCol
or, | 219 args.fOutputSecondary, args.fInputCol
or, |
| 156 args.fInputCoverage); | 220 args.fInputCoverage); |
| 157 break; | 221 break; |
| 158 case PorterDuffXferProcessor::kCoverageISC_SecondaryOutputType: | 222 case PorterDuffXferProcessor::kCoverageISC_SecondaryOutputType: |
| 159 fsBuilder->codeAppendf("%s = (vec4(1.0) - %s) * %s;", | 223 fsBuilder->codeAppendf("%s = (vec4(1.0) - %s) * %s;", |
| 160 args.fOutputSecondary, args.fInputCol
or, | 224 args.fOutputSecondary, args.fInputCol
or, |
| 161 args.fInputCoverage); | 225 args.fInputCoverage); |
| 162 break; | 226 break; |
| 163 default: | 227 default: |
| 164 SkFAIL("Unexpected Secondary Output"); | 228 SkFAIL("Unexpected Secondary Output"); |
| 165 } | 229 } |
| 166 } | 230 |
| 167 | 231 switch (xp.primaryOutputType()) { |
| 168 switch (xp.primaryOutputType()) { | 232 case PorterDuffXferProcessor::kNone_PrimaryOutputType: |
| 169 case PorterDuffXferProcessor::kNone_PrimaryOutputType: | 233 fsBuilder->codeAppendf("%s = vec4(0);", args.fOutputPrimary)
; |
| 170 fsBuilder->codeAppendf("%s = vec4(0);", args.fOutputPrimary); | 234 break; |
| 171 break; | 235 case PorterDuffXferProcessor::kColor_PrimaryOutputType: |
| 172 case PorterDuffXferProcessor::kColor_PrimaryOutputType: | 236 fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args
.fInputColor); |
| 173 fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fIn
putColor); | 237 break; |
| 174 break; | 238 case PorterDuffXferProcessor::kCoverage_PrimaryOutputType: |
| 175 case PorterDuffXferProcessor::kCoverage_PrimaryOutputType: | 239 fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args
.fInputCoverage); |
| 176 fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fIn
putCoverage); | 240 break; |
| 177 break; | 241 case PorterDuffXferProcessor::kModulate_PrimaryOutputType: |
| 178 case PorterDuffXferProcessor::kModulate_PrimaryOutputType: | 242 fsBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary,
args.fInputColor, |
| 179 fsBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, arg
s.fInputColor, | 243 args.fInputCoverage); |
| 180 args.fInputCoverage); | 244 break; |
| 181 break; | 245 default: |
| 182 default: | 246 SkFAIL("Unexpected Primary Output"); |
| 183 SkFAIL("Unexpected Primary Output"); | 247 } |
| 248 } else { |
| 249 SkASSERT(xp.willReadDstColor()); |
| 250 |
| 251 const char* dstColor = fsBuilder->dstColor(); |
| 252 |
| 253 fsBuilder->codeAppend("vec4 colorBlend ="); |
| 254 // append src blend |
| 255 bool didAppend = append_porterduff_term(fsBuilder, xp.getSrcBlend(), |
| 256 args.fInputColor, args.fInpu
tColor, |
| 257 dstColor, false); |
| 258 // append dst blend |
| 259 SkAssertResult(append_porterduff_term(fsBuilder, xp.getDstBlend(), |
| 260 dstColor, args.fInputColor, |
| 261 dstColor, didAppend)); |
| 262 fsBuilder->codeAppend(";"); |
| 263 |
| 264 fsBuilder->codeAppendf("%s = %s * colorBlend + (vec4(1.0) - %s) * %s
;", |
| 265 args.fOutputPrimary, args.fInputCoverage, arg
s.fInputCoverage, |
| 266 dstColor); |
| 184 } | 267 } |
| 185 } | 268 } |
| 186 | 269 |
| 187 void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVE
RRIDE {}; | 270 void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVE
RRIDE {}; |
| 188 | 271 |
| 189 typedef GrGLXferProcessor INHERITED; | 272 typedef GrGLXferProcessor INHERITED; |
| 190 }; | 273 }; |
| 191 | 274 |
| 192 /////////////////////////////////////////////////////////////////////////////// | 275 /////////////////////////////////////////////////////////////////////////////// |
| 193 | 276 |
| 194 PorterDuffXferProcessor::PorterDuffXferProcessor(GrBlendCoeff srcBlend, | 277 PorterDuffXferProcessor::PorterDuffXferProcessor(GrBlendCoeff srcBlend, |
| 195 GrBlendCoeff dstBlend, | 278 GrBlendCoeff dstBlend, |
| 196 GrColor constant, | 279 GrColor constant, |
| 197 const GrDeviceCoordTexture* dst
Copy, | 280 const GrDeviceCoordTexture* dst
Copy, |
| 198 bool willReadDstColor) | 281 bool willReadDstColor) |
| 199 : fSrcBlend(srcBlend) | 282 : INHERITED(dstCopy, willReadDstColor) |
| 283 , fSrcBlend(srcBlend) |
| 200 , fDstBlend(dstBlend) | 284 , fDstBlend(dstBlend) |
| 201 , fBlendConstant(constant) | 285 , fBlendConstant(constant) |
| 202 , fPrimaryOutputType(kModulate_PrimaryOutputType) | 286 , fPrimaryOutputType(kModulate_PrimaryOutputType) |
| 203 , fSecondaryOutputType(kNone_SecondaryOutputType) { | 287 , fSecondaryOutputType(kNone_SecondaryOutputType) { |
| 204 this->initClassID<PorterDuffXferProcessor>(); | 288 this->initClassID<PorterDuffXferProcessor>(); |
| 205 } | 289 } |
| 206 | 290 |
| 207 PorterDuffXferProcessor::~PorterDuffXferProcessor() { | 291 PorterDuffXferProcessor::~PorterDuffXferProcessor() { |
| 208 } | 292 } |
| 209 | 293 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 237 coveragePOI, | 321 coveragePOI, |
| 238 doesStencilWrite); | 322 doesStencilWrite); |
| 239 } | 323 } |
| 240 this->calcOutputTypes(optFlags, caps, coveragePOI.isSolidWhite()); | 324 this->calcOutputTypes(optFlags, caps, coveragePOI.isSolidWhite()); |
| 241 return optFlags; | 325 return optFlags; |
| 242 } | 326 } |
| 243 | 327 |
| 244 void PorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFlags
, | 328 void PorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFlags
, |
| 245 const GrDrawTargetCaps& caps, | 329 const GrDrawTargetCaps& caps, |
| 246 bool hasSolidCoverage) { | 330 bool hasSolidCoverage) { |
| 331 if (this->willReadDstColor()) { |
| 332 fPrimaryOutputType = kCustom_PrimaryOutputType; |
| 333 return; |
| 334 } |
| 335 |
| 247 if (optFlags & kIgnoreColor_OptFlag) { | 336 if (optFlags & kIgnoreColor_OptFlag) { |
| 248 if (optFlags & kIgnoreCoverage_OptFlag) { | 337 if (optFlags & kIgnoreCoverage_OptFlag) { |
| 249 fPrimaryOutputType = kNone_PrimaryOutputType; | 338 fPrimaryOutputType = kNone_PrimaryOutputType; |
| 250 return; | 339 return; |
| 251 } else { | 340 } else { |
| 252 fPrimaryOutputType = kCoverage_PrimaryOutputType; | 341 fPrimaryOutputType = kCoverage_PrimaryOutputType; |
| 253 return; | 342 return; |
| 254 } | 343 } |
| 255 } else if (optFlags & kIgnoreCoverage_OptFlag) { | 344 } else if (optFlags & kIgnoreCoverage_OptFlag) { |
| 256 fPrimaryOutputType = kColor_PrimaryOutputType; | 345 fPrimaryOutputType = kColor_PrimaryOutputType; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 277 fDstBlend = kIS2C_GrBlendCoeff; | 366 fDstBlend = kIS2C_GrBlendCoeff; |
| 278 } | 367 } |
| 279 } | 368 } |
| 280 } | 369 } |
| 281 } | 370 } |
| 282 | 371 |
| 283 GrXferProcessor::OptFlags | 372 GrXferProcessor::OptFlags |
| 284 PorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPOI, | 373 PorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPOI, |
| 285 const GrProcOptInfo& coverageP
OI, | 374 const GrProcOptInfo& coverageP
OI, |
| 286 bool doesStencilWrite) { | 375 bool doesStencilWrite) { |
| 287 bool srcAIsOne; | 376 if (this->willReadDstColor()) { |
| 288 bool hasCoverage; | 377 return GrXferProcessor::kNone_Opt; |
| 378 } |
| 289 | 379 |
| 290 srcAIsOne = colorPOI.isOpaque(); | 380 bool srcAIsOne = colorPOI.isOpaque(); |
| 291 hasCoverage = !coveragePOI.isSolidWhite(); | 381 bool hasCoverage = !coveragePOI.isSolidWhite(); |
| 292 | 382 |
| 293 bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstBlend || | 383 bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstBlend || |
| 294 (kSA_GrBlendCoeff == fDstBlend && srcAIsOne); | 384 (kSA_GrBlendCoeff == fDstBlend && srcAIsOne); |
| 295 bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstBlend || | 385 bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstBlend || |
| 296 (kISA_GrBlendCoeff == fDstBlend && srcAIsOne); | 386 (kISA_GrBlendCoeff == fDstBlend && srcAIsOne); |
| 297 | 387 |
| 298 // When coeffs are (0,1) there is no reason to draw at all, unless | 388 // When coeffs are (0,1) there is no reason to draw at all, unless |
| 299 // stenciling is enabled. Having color writes disabled is effectively | 389 // stenciling is enabled. Having color writes disabled is effectively |
| 300 // (0,1). | 390 // (0,1). |
| 301 if ((kZero_GrBlendCoeff == fSrcBlend && dstCoeffIsOne)) { | 391 if ((kZero_GrBlendCoeff == fSrcBlend && dstCoeffIsOne)) { |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 static GrPorterDuffXPFactory gScreenPDXPF(kOne_GrBlendCoeff, kISC_Gr
BlendCoeff); | 555 static GrPorterDuffXPFactory gScreenPDXPF(kOne_GrBlendCoeff, kISC_Gr
BlendCoeff); |
| 466 return SkRef(&gScreenPDXPF); | 556 return SkRef(&gScreenPDXPF); |
| 467 break; | 557 break; |
| 468 } | 558 } |
| 469 default: | 559 default: |
| 470 return NULL; | 560 return NULL; |
| 471 } | 561 } |
| 472 } | 562 } |
| 473 | 563 |
| 474 GrXferProcessor* | 564 GrXferProcessor* |
| 475 GrPorterDuffXPFactory::onCreateXferProcessor(const GrProcOptInfo& colorPOI, | 565 GrPorterDuffXPFactory::onCreateXferProcessor(const GrDrawTargetCaps& caps, |
| 566 const GrProcOptInfo& colorPOI, |
| 476 const GrProcOptInfo& covPOI, | 567 const GrProcOptInfo& covPOI, |
| 477 const GrDeviceCoordTexture* dstCopy
) const { | 568 const GrDeviceCoordTexture* dstCopy
) const { |
| 478 if (!covPOI.isFourChannelOutput()) { | 569 if (!covPOI.isFourChannelOutput()) { |
| 479 return PorterDuffXferProcessor::Create(fSrcCoeff, fDstCoeff, 0, dstCopy, | 570 return PorterDuffXferProcessor::Create(fSrcCoeff, fDstCoeff, 0, dstCopy, |
| 480 this->willReadDstColor(colorPOI,
covPOI)); | 571 this->willReadDstColor(caps, colo
rPOI, covPOI)); |
| 481 } else { | 572 } else { |
| 482 if (this->supportsRGBCoverage(colorPOI.color(), colorPOI.validFlags()))
{ | 573 if (this->supportsRGBCoverage(colorPOI.color(), colorPOI.validFlags()))
{ |
| 483 SkASSERT(kRGBA_GrColorComponentFlags == colorPOI.validFlags()); | 574 SkASSERT(kRGBA_GrColorComponentFlags == colorPOI.validFlags()); |
| 484 GrColor blendConstant = GrUnPreMulColor(colorPOI.color()); | 575 GrColor blendConstant = GrUnPreMulColor(colorPOI.color()); |
| 485 return PorterDuffXferProcessor::Create(kConstC_GrBlendCoeff, kISC_Gr
BlendCoeff, | 576 return PorterDuffXferProcessor::Create(kConstC_GrBlendCoeff, kISC_Gr
BlendCoeff, |
| 486 blendConstant, dstCopy, | 577 blendConstant, dstCopy, |
| 487 this->willReadDstColor(colorP
OI, covPOI)); | 578 this->willReadDstColor(caps,
colorPOI, covPOI)); |
| 488 } else { | 579 } else { |
| 489 return NULL; | 580 return NULL; |
| 490 } | 581 } |
| 491 } | 582 } |
| 492 } | 583 } |
| 493 | 584 |
| 494 bool GrPorterDuffXPFactory::supportsRGBCoverage(GrColor /*knownColor*/, | 585 bool GrPorterDuffXPFactory::supportsRGBCoverage(GrColor /*knownColor*/, |
| 495 uint32_t knownColorFlags) const
{ | 586 uint32_t knownColorFlags) const
{ |
| 496 if (kOne_GrBlendCoeff == fSrcCoeff && kISA_GrBlendCoeff == fDstCoeff && | 587 if (kOne_GrBlendCoeff == fSrcCoeff && kISA_GrBlendCoeff == fDstCoeff && |
| 497 kRGBA_GrColorComponentFlags == knownColorFlags) { | 588 kRGBA_GrColorComponentFlags == knownColorFlags) { |
| 498 return true; | 589 return true; |
| 499 } | 590 } |
| 500 return false; | 591 return false; |
| 501 } | 592 } |
| 502 | 593 |
| 503 bool GrPorterDuffXPFactory::canApplyCoverage(const GrProcOptInfo& colorPOI, | |
| 504 const GrProcOptInfo& coveragePOI) c
onst { | |
| 505 bool srcAIsOne = colorPOI.isOpaque(); | |
| 506 | |
| 507 bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstCoeff || | |
| 508 (kSA_GrBlendCoeff == fDstCoeff && srcAIsOne); | |
| 509 bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstCoeff || | |
| 510 (kISA_GrBlendCoeff == fDstCoeff && srcAIsOne); | |
| 511 | |
| 512 if ((kZero_GrBlendCoeff == fSrcCoeff && dstCoeffIsOne)) { | |
| 513 return true; | |
| 514 } | |
| 515 | |
| 516 // if we don't have coverage we can check whether the dst | |
| 517 // has to read at all. | |
| 518 // check whether coverage can be safely rolled into alpha | |
| 519 // of if we can skip color computation and just emit coverage | |
| 520 if (this->canTweakAlphaForCoverage()) { | |
| 521 return true; | |
| 522 } | |
| 523 if (dstCoeffIsZero) { | |
| 524 if (kZero_GrBlendCoeff == fSrcCoeff) { | |
| 525 return true; | |
| 526 } else if (srcAIsOne) { | |
| 527 return true; | |
| 528 } | |
| 529 } else if (dstCoeffIsOne) { | |
| 530 return true; | |
| 531 } | |
| 532 | |
| 533 return false; | |
| 534 } | |
| 535 | |
| 536 bool GrPorterDuffXPFactory::canTweakAlphaForCoverage() const { | 594 bool GrPorterDuffXPFactory::canTweakAlphaForCoverage() const { |
| 537 return can_tweak_alpha_for_coverage(fDstCoeff); | 595 return can_tweak_alpha_for_coverage(fDstCoeff); |
| 538 } | 596 } |
| 539 | 597 |
| 540 void GrPorterDuffXPFactory::getInvariantOutput(const GrProcOptInfo& colorPOI, | 598 void GrPorterDuffXPFactory::getInvariantOutput(const GrProcOptInfo& colorPOI, |
| 541 const GrProcOptInfo& coveragePOI, | 599 const GrProcOptInfo& coveragePOI, |
| 542 GrXPFactory::InvariantOutput* out
put) const { | 600 GrXPFactory::InvariantOutput* out
put) const { |
| 543 if (!coveragePOI.isSolidWhite()) { | 601 if (!coveragePOI.isSolidWhite()) { |
| 544 output->fWillBlendWithDst = true; | 602 output->fWillBlendWithDst = true; |
| 545 output->fBlendedColorFlags = 0; | 603 output->fBlendedColorFlags = 0; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 599 case kIConstC_GrBlendCoeff: | 657 case kIConstC_GrBlendCoeff: |
| 600 case kConstA_GrBlendCoeff: | 658 case kConstA_GrBlendCoeff: |
| 601 case kIConstA_GrBlendCoeff: | 659 case kIConstA_GrBlendCoeff: |
| 602 output->fBlendedColorFlags = 0; | 660 output->fBlendedColorFlags = 0; |
| 603 break; | 661 break; |
| 604 } | 662 } |
| 605 | 663 |
| 606 output->fWillBlendWithDst = false; | 664 output->fWillBlendWithDst = false; |
| 607 } | 665 } |
| 608 | 666 |
| 609 bool GrPorterDuffXPFactory::willReadDstColor(const GrProcOptInfo& colorPOI, | 667 bool GrPorterDuffXPFactory::willReadDstColor(const GrDrawTargetCaps& caps, |
| 668 const GrProcOptInfo& colorPOI, |
| 610 const GrProcOptInfo& coveragePOI) c
onst { | 669 const GrProcOptInfo& coveragePOI) c
onst { |
| 611 return false; | 670 // We can always blend correctly if we have dual source blending. |
| 671 if (caps.dualSourceBlendingSupport()) { |
| 672 return false; |
| 673 } |
| 674 |
| 675 if (this->canTweakAlphaForCoverage()) { |
| 676 return false; |
| 677 } |
| 678 |
| 679 bool srcAIsOne = colorPOI.isOpaque(); |
| 680 |
| 681 if (kZero_GrBlendCoeff == fDstCoeff) { |
| 682 if (kZero_GrBlendCoeff == fSrcCoeff || srcAIsOne) { |
| 683 return false; |
| 684 } |
| 685 } |
| 686 |
| 687 // Reduces to: coeffS * (Cov*S) + D |
| 688 if (kSA_GrBlendCoeff == fDstCoeff && srcAIsOne) { |
| 689 return false; |
| 690 } |
| 691 |
| 692 // We can always blend correctly if we have solid coverage. |
| 693 if (coveragePOI.isSolidWhite()) { |
| 694 return false; |
| 695 } |
| 696 |
| 697 return true; |
| 612 } | 698 } |
| 613 | 699 |
| 614 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory); | 700 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory); |
| 615 | 701 |
| 616 GrXPFactory* GrPorterDuffXPFactory::TestCreate(SkRandom* random, | 702 GrXPFactory* GrPorterDuffXPFactory::TestCreate(SkRandom* random, |
| 617 GrContext*, | 703 GrContext*, |
| 618 const GrDrawTargetCaps&, | 704 const GrDrawTargetCaps&, |
| 619 GrTexture*[]) { | 705 GrTexture*[]) { |
| 620 SkXfermode::Mode mode = SkXfermode::Mode(random->nextULessThan(SkXfermode::k
LastCoeffMode)); | 706 SkXfermode::Mode mode = SkXfermode::Mode(random->nextULessThan(SkXfermode::k
LastCoeffMode)); |
| 621 return GrPorterDuffXPFactory::Create(mode); | 707 return GrPorterDuffXPFactory::Create(mode); |
| 622 } | 708 } |
| 623 | 709 |
| OLD | NEW |