| 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 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 114 void GrPorterDuffXferProcessor::onComputeInvariantOutput(GrInvariantOutput* inou
t) const { | 114 void GrPorterDuffXferProcessor::onComputeInvariantOutput(GrInvariantOutput* inou
t) const { |
| 115 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); | 115 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); |
| 116 } | 116 } |
| 117 | 117 |
| 118 GrXferProcessor::OptFlags | 118 GrXferProcessor::OptFlags |
| 119 GrPorterDuffXferProcessor::getOptimizations(const GrProcOptInfo& colorPOI, | 119 GrPorterDuffXferProcessor::getOptimizations(const GrProcOptInfo& colorPOI, |
| 120 const GrProcOptInfo& coveragePOI, | 120 const GrProcOptInfo& coveragePOI, |
| 121 bool isCoverageDrawing, | 121 bool isCoverageDrawing, |
| 122 bool colorWriteDisabled, | 122 bool colorWriteDisabled, |
| 123 bool doesStencilWrite, | 123 bool doesStencilWrite, |
| 124 GrColor* color, uint8_t* coverage, | 124 GrColor* overrideColor, |
| 125 uint8_t* overrideCoverage, |
| 125 const GrDrawTargetCaps& caps) { | 126 const GrDrawTargetCaps& caps) { |
| 126 GrXferProcessor::OptFlags optFlags = this->internalGetOptimizations(colorPOI
, | 127 GrXferProcessor::OptFlags optFlags; |
| 127 coverage
POI, | 128 // Optimizations when doing RGB Coverage |
| 128 isCovera
geDrawing, | 129 if (coveragePOI.isFourChannelOutput()) { |
| 129 colorWri
teDisabled, | 130 // We want to force our primary output to be alpha * Coverage, where alp
ha is the alpha |
| 130 doesSten
cilWrite, | 131 // value of the blend the constant. We should already have valid blend c
oeff's if we are at |
| 131 color, | 132 // a point where we have RGB coverage. We don't need any color stages si
nce the known color |
| 132 coverage
); | 133 // output is already baked into the blendConstant. |
| 133 | 134 uint8_t alpha = GrColorUnpackA(fBlendConstant); |
| 135 *overrideColor = GrColorPackRGBA(alpha, alpha, alpha, alpha); |
| 136 optFlags = GrXferProcessor::kOverrideColor_OptFlag; |
| 137 } else { |
| 138 optFlags = this->internalGetOptimizations(colorPOI, |
| 139 coveragePOI, |
| 140 isCoverageDrawing, |
| 141 colorWriteDisabled, |
| 142 doesStencilWrite, |
| 143 overrideColor, |
| 144 overrideCoverage); |
| 145 } |
| 134 this->calcOutputTypes(optFlags, caps, isCoverageDrawing || coveragePOI.isSol
idWhite(), | 146 this->calcOutputTypes(optFlags, caps, isCoverageDrawing || coveragePOI.isSol
idWhite(), |
| 135 colorPOI.readsDst() || coveragePOI.readsDst()); | 147 colorPOI.readsDst() || coveragePOI.readsDst()); |
| 136 return optFlags; | 148 return optFlags; |
| 137 } | 149 } |
| 138 | 150 |
| 139 void GrPorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFla
gs, | 151 void GrPorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFla
gs, |
| 140 const GrDrawTargetCaps& caps, | 152 const GrDrawTargetCaps& caps, |
| 141 bool hasSolidCoverage, bool read
sDst) { | 153 bool hasSolidCoverage, bool read
sDst) { |
| 142 // If we do have coverage determine whether it matters. Dual source blendin
g is expensive so | 154 // If we do have coverage determine whether it matters. Dual source blendin
g is expensive so |
| 143 // we don't do it if we are doing coverage drawing. If we aren't then We al
ways do dual source | 155 // we don't do it if we are doing coverage drawing. If we aren't then We al
ways do dual source |
| (...skipping 21 matching lines...) Expand all Loading... |
| 165 } | 177 } |
| 166 } | 178 } |
| 167 } | 179 } |
| 168 | 180 |
| 169 GrXferProcessor::OptFlags | 181 GrXferProcessor::OptFlags |
| 170 GrPorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPO
I, | 182 GrPorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPO
I, |
| 171 const GrProcOptInfo& coverag
ePOI, | 183 const GrProcOptInfo& coverag
ePOI, |
| 172 bool isCoverageDrawing, | 184 bool isCoverageDrawing, |
| 173 bool colorWriteDisabled, | 185 bool colorWriteDisabled, |
| 174 bool doesStencilWrite, | 186 bool doesStencilWrite, |
| 175 GrColor* color, uint8_t* cov
erage) { | 187 GrColor* overrideColor, |
| 188 uint8_t* overrideCoverage) { |
| 176 if (colorWriteDisabled) { | 189 if (colorWriteDisabled) { |
| 177 fSrcBlend = kZero_GrBlendCoeff; | 190 fSrcBlend = kZero_GrBlendCoeff; |
| 178 fDstBlend = kOne_GrBlendCoeff; | 191 fDstBlend = kOne_GrBlendCoeff; |
| 179 } | 192 } |
| 180 | 193 |
| 181 bool srcAIsOne; | 194 bool srcAIsOne; |
| 182 bool hasCoverage; | 195 bool hasCoverage; |
| 183 if (isCoverageDrawing) { | 196 if (isCoverageDrawing) { |
| 184 srcAIsOne = colorPOI.isOpaque() && coveragePOI.isOpaque(); | 197 srcAIsOne = colorPOI.isOpaque() && coveragePOI.isOpaque(); |
| 185 hasCoverage = false; | 198 hasCoverage = false; |
| 186 } else { | 199 } else { |
| 187 srcAIsOne = colorPOI.isOpaque(); | 200 srcAIsOne = colorPOI.isOpaque(); |
| 188 hasCoverage = !coveragePOI.isSolidWhite(); | 201 hasCoverage = !coveragePOI.isSolidWhite(); |
| 189 } | 202 } |
| 190 | 203 |
| 191 bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstBlend || | 204 bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstBlend || |
| 192 (kSA_GrBlendCoeff == fDstBlend && srcAIsOne); | 205 (kSA_GrBlendCoeff == fDstBlend && srcAIsOne); |
| 193 bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstBlend || | 206 bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstBlend || |
| 194 (kISA_GrBlendCoeff == fDstBlend && srcAIsOne); | 207 (kISA_GrBlendCoeff == fDstBlend && srcAIsOne); |
| 195 | 208 |
| 196 // Optimizations when doing RGB Coverage | |
| 197 if (coveragePOI.isFourChannelOutput()) { | |
| 198 // We want to force our primary output to be alpha * Coverage, where alp
ha is the alpha | |
| 199 // value of the blend the constant. We should already have valid blend c
oeff's if we are at | |
| 200 // a point where we have RGB coverage. We don't need any color stages si
nce the known color | |
| 201 // output is already baked into the blendConstant. | |
| 202 uint8_t alpha = GrColorUnpackA(fBlendConstant); | |
| 203 *color = GrColorPackRGBA(alpha, alpha, alpha, alpha); | |
| 204 return GrXferProcessor::kClearColorStages_OptFlag; | |
| 205 } | |
| 206 | |
| 207 // When coeffs are (0,1) there is no reason to draw at all, unless | 209 // When coeffs are (0,1) there is no reason to draw at all, unless |
| 208 // stenciling is enabled. Having color writes disabled is effectively | 210 // stenciling is enabled. Having color writes disabled is effectively |
| 209 // (0,1). | 211 // (0,1). |
| 210 if ((kZero_GrBlendCoeff == fSrcBlend && dstCoeffIsOne)) { | 212 if ((kZero_GrBlendCoeff == fSrcBlend && dstCoeffIsOne)) { |
| 211 if (doesStencilWrite) { | 213 if (doesStencilWrite) { |
| 212 *color = 0xffffffff; | 214 *overrideColor = 0xffffffff; |
| 213 return GrXferProcessor::kClearColorStages_OptFlag | | 215 return GrXferProcessor::kClearColorStages_OptFlag | |
| 214 GrXferProcessor::kSetCoverageDrawing_OptFlag; | 216 GrXferProcessor::kSetCoverageDrawing_OptFlag; |
| 215 } else { | 217 } else { |
| 216 fDstBlend = kOne_GrBlendCoeff; | 218 fDstBlend = kOne_GrBlendCoeff; |
| 217 return GrXferProcessor::kSkipDraw_OptFlag; | 219 return GrXferProcessor::kSkipDraw_OptFlag; |
| 218 } | 220 } |
| 219 } | 221 } |
| 220 | 222 |
| 221 // if we don't have coverage we can check whether the dst | 223 // if we don't have coverage we can check whether the dst |
| 222 // has to read at all. If not, we'll disable blending. | 224 // has to read at all. If not, we'll disable blending. |
| 223 if (!hasCoverage) { | 225 if (!hasCoverage) { |
| 224 if (dstCoeffIsZero) { | 226 if (dstCoeffIsZero) { |
| 225 if (kOne_GrBlendCoeff == fSrcBlend) { | 227 if (kOne_GrBlendCoeff == fSrcBlend) { |
| 226 // if there is no coverage and coeffs are (1,0) then we | 228 // if there is no coverage and coeffs are (1,0) then we |
| 227 // won't need to read the dst at all, it gets replaced by src | 229 // won't need to read the dst at all, it gets replaced by src |
| 228 fDstBlend = kZero_GrBlendCoeff; | 230 fDstBlend = kZero_GrBlendCoeff; |
| 229 return GrXferProcessor::kNone_Opt; | 231 return GrXferProcessor::kNone_Opt; |
| 230 } else if (kZero_GrBlendCoeff == fSrcBlend) { | 232 } else if (kZero_GrBlendCoeff == fSrcBlend) { |
| 231 // if the op is "clear" then we don't need to emit a color | 233 // if the op is "clear" then we don't need to emit a color |
| 232 // or blend, just write transparent black into the dst. | 234 // or blend, just write transparent black into the dst. |
| 233 fSrcBlend = kOne_GrBlendCoeff; | 235 fSrcBlend = kOne_GrBlendCoeff; |
| 234 fDstBlend = kZero_GrBlendCoeff; | 236 fDstBlend = kZero_GrBlendCoeff; |
| 235 *color = 0; | 237 *overrideColor = 0; |
| 236 *coverage = 0xff; | 238 *overrideCoverage = 0xff; |
| 237 return GrXferProcessor::kClearColorStages_OptFlag | | 239 return GrXferProcessor::kClearColorStages_OptFlag | |
| 238 GrXferProcessor::kClearCoverageStages_OptFlag; | 240 GrXferProcessor::kClearCoverageStages_OptFlag; |
| 239 } | 241 } |
| 240 } | 242 } |
| 241 } else if (isCoverageDrawing) { | 243 } else if (isCoverageDrawing) { |
| 242 // we have coverage but we aren't distinguishing it from alpha by reques
t. | 244 // we have coverage but we aren't distinguishing it from alpha by reques
t. |
| 243 return GrXferProcessor::kSetCoverageDrawing_OptFlag; | 245 return GrXferProcessor::kSetCoverageDrawing_OptFlag; |
| 244 } else { | 246 } else { |
| 245 // check whether coverage can be safely rolled into alpha | 247 // check whether coverage can be safely rolled into alpha |
| 246 // of if we can skip color computation and just emit coverage | 248 // of if we can skip color computation and just emit coverage |
| 247 if (can_tweak_alpha_for_coverage(fDstBlend, isCoverageDrawing)) { | 249 if (can_tweak_alpha_for_coverage(fDstBlend, isCoverageDrawing)) { |
| 248 return GrXferProcessor::kSetCoverageDrawing_OptFlag; | 250 return GrXferProcessor::kSetCoverageDrawing_OptFlag; |
| 249 } | 251 } |
| 250 if (dstCoeffIsZero) { | 252 if (dstCoeffIsZero) { |
| 251 if (kZero_GrBlendCoeff == fSrcBlend) { | 253 if (kZero_GrBlendCoeff == fSrcBlend) { |
| 252 // the source color is not included in the blend | 254 // the source color is not included in the blend |
| 253 // the dst coeff is effectively zero so blend works out to: | 255 // the dst coeff is effectively zero so blend works out to: |
| 254 // (c)(0)D + (1-c)D = (1-c)D. | 256 // (c)(0)D + (1-c)D = (1-c)D. |
| 255 fDstBlend = kISA_GrBlendCoeff; | 257 fDstBlend = kISA_GrBlendCoeff; |
| 256 *color = 0xffffffff; | 258 *overrideColor = 0xffffffff; |
| 257 return GrXferProcessor::kClearColorStages_OptFlag | | 259 return GrXferProcessor::kClearColorStages_OptFlag | |
| 258 GrXferProcessor::kSetCoverageDrawing_OptFlag; | 260 GrXferProcessor::kSetCoverageDrawing_OptFlag; |
| 259 } else if (srcAIsOne) { | 261 } else if (srcAIsOne) { |
| 260 // the dst coeff is effectively zero so blend works out to: | 262 // the dst coeff is effectively zero so blend works out to: |
| 261 // cS + (c)(0)D + (1-c)D = cS + (1-c)D. | 263 // cS + (c)(0)D + (1-c)D = cS + (1-c)D. |
| 262 // If Sa is 1 then we can replace Sa with c | 264 // If Sa is 1 then we can replace Sa with c |
| 263 // and set dst coeff to 1-Sa. | 265 // and set dst coeff to 1-Sa. |
| 264 fDstBlend = kISA_GrBlendCoeff; | 266 fDstBlend = kISA_GrBlendCoeff; |
| 265 return GrXferProcessor::kSetCoverageDrawing_OptFlag; | 267 return GrXferProcessor::kSetCoverageDrawing_OptFlag; |
| 266 } | 268 } |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 549 } while (GrBlendCoeffRefsSrc(src)); | 551 } while (GrBlendCoeffRefsSrc(src)); |
| 550 | 552 |
| 551 GrBlendCoeff dst; | 553 GrBlendCoeff dst; |
| 552 do { | 554 do { |
| 553 dst = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPub
licGrBlendCoeff)); | 555 dst = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPub
licGrBlendCoeff)); |
| 554 } while (GrBlendCoeffRefsDst(dst)); | 556 } while (GrBlendCoeffRefsDst(dst)); |
| 555 | 557 |
| 556 return GrPorterDuffXPFactory::Create(src, dst); | 558 return GrPorterDuffXPFactory::Create(src, dst); |
| 557 } | 559 } |
| 558 | 560 |
| OLD | NEW |