bool GrPorterDuffXPFactory::willReadDstColor(const GrDrawTargetCaps& caps, const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI) const { // We can always blend correctly if we have dual source blending. if (caps.shaderCaps()->dualSourceBlendingSupport()) { return false; } if (can_tweak_alpha_for_coverage(fDstCoeff)) { return false; } bool srcAIsOne = colorPOI.isOpaque(); if (kZero_GrBlendCoeff == fDstCoeff) { if (kZero_GrBlendCoeff == fSrcCoeff || srcAIsOne) { return false; } } // Reduces to: coeffS * (Cov*S) + D if (kSA_GrBlendCoeff == fDstCoeff && srcAIsOne) { return false; } // We can always blend correctly if we have solid coverage. if (coveragePOI.isSolidWhite()) { return false; } return true; }
void GrPorterDuffXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorPOI, InvariantBlendedColor* blendedColor) const { // Find the blended color info based on the formula that does not have coverage. BlendFormula colorFormula = gBlendTable[colorPOI.isOpaque()][0][fXfermode]; if (colorFormula.usesDstColor()) { blendedColor->fWillBlendWithDst = true; blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags; return; } blendedColor->fWillBlendWithDst = false; SkASSERT(kAdd_GrBlendEquation == colorFormula.fBlendEquation); switch (colorFormula.fSrcCoeff) { case kZero_GrBlendCoeff: blendedColor->fKnownColor = 0; blendedColor->fKnownColorFlags = kRGBA_GrColorComponentFlags; return; case kOne_GrBlendCoeff: blendedColor->fKnownColor = colorPOI.color(); blendedColor->fKnownColorFlags = colorPOI.validFlags(); return; default: blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags; return; } }
static BlendFormula get_blend_formula(SkXfermode::Mode xfermode, const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI) { SkASSERT(xfermode >= 0 && xfermode <= SkXfermode::kLastCoeffMode); SkASSERT(!coveragePOI.isFourChannelOutput()); return gBlendTable[colorPOI.isOpaque()][!coveragePOI.isSolidWhite()][xfermode]; }
static BlendFormula get_blend_formula(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI, bool hasMixedSamples, SkXfermode::Mode xfermode) { SkASSERT(xfermode >= 0 && xfermode <= SkXfermode::kLastCoeffMode); SkASSERT(!coveragePOI.isFourChannelOutput()); bool conflatesCoverage = !coveragePOI.isSolidWhite() || hasMixedSamples; return gBlendTable[colorPOI.isOpaque()][conflatesCoverage][xfermode]; }
bool GrPaint::isConstantBlendedColor(GrColor* color) const { GrProcOptInfo colorProcInfo; colorProcInfo.calcWithInitialValues(fColorFragmentProcessors.begin(), this->numColorFragmentProcessors(), fColor, kRGBA_GrColorComponentFlags, false); GrXPFactory::InvariantBlendedColor blendedColor; if (fXPFactory) { fXPFactory->getInvariantBlendedColor(colorProcInfo, &blendedColor); } else { GrPorterDuffXPFactory::SrcOverInvariantBlendedColor(colorProcInfo.color(), colorProcInfo.validFlags(), colorProcInfo.isOpaque(), &blendedColor); } if (kRGBA_GrColorComponentFlags == blendedColor.fKnownColorFlags) { *color = blendedColor.fKnownColor; return true; } return false; }
void GrPorterDuffXPFactory::getInvariantOutput(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI, GrXPFactory::InvariantOutput* output) const { if (!coveragePOI.isSolidWhite()) { output->fWillBlendWithDst = true; output->fBlendedColorFlags = 0; return; } GrBlendCoeff srcCoeff = fSrcCoeff; GrBlendCoeff dstCoeff = fDstCoeff; // TODO: figure out to merge this simplify with other current optimization code paths and // eventually remove from GrBlend GrSimplifyBlend(&srcCoeff, &dstCoeff, colorPOI.color(), colorPOI.validFlags(), 0, 0, 0); if (GrBlendCoeffRefsDst(srcCoeff)) { output->fWillBlendWithDst = true; output->fBlendedColorFlags = 0; return; } if (kZero_GrBlendCoeff != dstCoeff) { bool srcAIsOne = colorPOI.isOpaque(); if (kISA_GrBlendCoeff != dstCoeff || !srcAIsOne) { output->fWillBlendWithDst = true; } output->fBlendedColorFlags = 0; return; } switch (srcCoeff) { case kZero_GrBlendCoeff: output->fBlendedColor = 0; output->fBlendedColorFlags = kRGBA_GrColorComponentFlags; break; case kOne_GrBlendCoeff: output->fBlendedColor = colorPOI.color(); output->fBlendedColorFlags = colorPOI.validFlags(); break; // The src coeff should never refer to the src and if it refers to dst then opaque // should have been false. case kSC_GrBlendCoeff: case kISC_GrBlendCoeff: case kDC_GrBlendCoeff: case kIDC_GrBlendCoeff: case kSA_GrBlendCoeff: case kISA_GrBlendCoeff: case kDA_GrBlendCoeff: case kIDA_GrBlendCoeff: default: SkFAIL("srcCoeff should not refer to src or dst."); break; // TODO: update this once GrPaint actually has a const color. case kConstC_GrBlendCoeff: case kIConstC_GrBlendCoeff: case kConstA_GrBlendCoeff: case kIConstA_GrBlendCoeff: output->fBlendedColorFlags = 0; break; } output->fWillBlendWithDst = false; }
GrXferProcessor::OptFlags PorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI, bool doesStencilWrite) { if (this->willReadDstColor()) { return GrXferProcessor::kNone_Opt; } bool srcAIsOne = colorPOI.isOpaque(); bool hasCoverage = !coveragePOI.isSolidWhite(); bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstBlend || (kSA_GrBlendCoeff == fDstBlend && srcAIsOne); bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstBlend || (kISA_GrBlendCoeff == fDstBlend && srcAIsOne); // When coeffs are (0,1) there is no reason to draw at all, unless // stenciling is enabled. Having color writes disabled is effectively // (0,1). if ((kZero_GrBlendCoeff == fSrcBlend && dstCoeffIsOne)) { if (doesStencilWrite) { return GrXferProcessor::kIgnoreColor_OptFlag | GrXferProcessor::kSetCoverageDrawing_OptFlag; } else { fDstBlend = kOne_GrBlendCoeff; return GrXferProcessor::kSkipDraw_OptFlag; } } // if we don't have coverage we can check whether the dst // has to read at all. If not, we'll disable blending. if (!hasCoverage) { if (dstCoeffIsZero) { if (kOne_GrBlendCoeff == fSrcBlend) { // if there is no coverage and coeffs are (1,0) then we // won't need to read the dst at all, it gets replaced by src fDstBlend = kZero_GrBlendCoeff; return GrXferProcessor::kNone_Opt; } else if (kZero_GrBlendCoeff == fSrcBlend) { // if the op is "clear" then we don't need to emit a color // or blend, just write transparent black into the dst. fSrcBlend = kOne_GrBlendCoeff; fDstBlend = kZero_GrBlendCoeff; return GrXferProcessor::kIgnoreColor_OptFlag | GrXferProcessor::kIgnoreCoverage_OptFlag; } } } else { // check whether coverage can be safely rolled into alpha // of if we can skip color computation and just emit coverage if (can_tweak_alpha_for_coverage(fDstBlend)) { if (colorPOI.allStagesMultiplyInput()) { return GrXferProcessor::kSetCoverageDrawing_OptFlag | GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag; } else { return GrXferProcessor::kSetCoverageDrawing_OptFlag; } } if (dstCoeffIsZero) { if (kZero_GrBlendCoeff == fSrcBlend) { // the source color is not included in the blend // the dst coeff is effectively zero so blend works out to: // (c)(0)D + (1-c)D = (1-c)D. fDstBlend = kISA_GrBlendCoeff; return GrXferProcessor::kIgnoreColor_OptFlag | GrXferProcessor::kSetCoverageDrawing_OptFlag; } else if (srcAIsOne) { // the dst coeff is effectively zero so blend works out to: // cS + (c)(0)D + (1-c)D = cS + (1-c)D. // If Sa is 1 then we can replace Sa with c // and set dst coeff to 1-Sa. fDstBlend = kISA_GrBlendCoeff; if (colorPOI.allStagesMultiplyInput()) { return GrXferProcessor::kSetCoverageDrawing_OptFlag | GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag; } else { return GrXferProcessor::kSetCoverageDrawing_OptFlag; } } } else if (dstCoeffIsOne) { // the dst coeff is effectively one so blend works out to: // cS + (c)(1)D + (1-c)D = cS + D. fDstBlend = kOne_GrBlendCoeff; if (colorPOI.allStagesMultiplyInput()) { return GrXferProcessor::kSetCoverageDrawing_OptFlag | GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag; } else { return GrXferProcessor::kSetCoverageDrawing_OptFlag; } return GrXferProcessor::kSetCoverageDrawing_OptFlag; } } return GrXferProcessor::kNone_Opt; }