/* * Copyright 2013 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef GrBlend_DEFINED #define GrBlend_DEFINED #include "GrColor.h" #include "../private/SkTLogic.h" /** * Equations for alpha-blending. */ enum GrBlendEquation { // Basic blend equations. kAdd_GrBlendEquation, // struct GrTBlendCoeffRefsSrc : skstd::bool_constant {}; #define GR_BLEND_COEFF_REFS_SRC(COEFF) \ GrTBlendCoeffRefsSrc::value inline bool GrBlendCoeffRefsSrc(GrBlendCoeff coeff) { switch (coeff) { case kSC_GrBlendCoeff: case kISC_GrBlendCoeff: case kSA_GrBlendCoeff: case kISA_GrBlendCoeff: return true; default: return false; } } template struct GrTBlendCoeffRefsDst : skstd::bool_constant {}; #define GR_BLEND_COEFF_REFS_DST(COEFF) \ GrTBlendCoeffRefsDst::value inline bool GrBlendCoeffRefsDst(GrBlendCoeff coeff) { switch (coeff) { case kDC_GrBlendCoeff: case kIDC_GrBlendCoeff: case kDA_GrBlendCoeff: case kIDA_GrBlendCoeff: return true; default: return false; } } template struct GrTBlendCoeffRefsSrc2 : skstd::bool_constant {}; #define GR_BLEND_COEFF_REFS_SRC2(COEFF) \ GrTBlendCoeffRefsSrc2::value inline bool GrBlendCoeffRefsSrc2(GrBlendCoeff coeff) { switch (coeff) { case kS2C_GrBlendCoeff: case kIS2C_GrBlendCoeff: case kS2A_GrBlendCoeff: case kIS2A_GrBlendCoeff: return true; default: return false; } } template struct GrTBlendCoeffsUseSrcColor : skstd::bool_constant {}; #define GR_BLEND_COEFFS_USE_SRC_COLOR(SRC_COEFF, DST_COEFF) \ GrTBlendCoeffsUseSrcColor::value template struct GrTBlendCoeffsUseDstColor : skstd::bool_constant {}; #define GR_BLEND_COEFFS_USE_DST_COLOR(SRC_COEFF, DST_COEFF) \ GrTBlendCoeffsUseDstColor::value template struct GrTBlendEquationIsAdvanced : skstd::bool_constant= kFirstAdvancedGrBlendEquation> {}; #define GR_BLEND_EQUATION_IS_ADVANCED(EQUATION) \ GrTBlendEquationIsAdvanced::value inline bool GrBlendEquationIsAdvanced(GrBlendEquation equation) { return equation >= kFirstAdvancedGrBlendEquation; } template struct GrTBlendModifiesDst : skstd::bool_constant< (kAdd_GrBlendEquation != BlendEquation && kReverseSubtract_GrBlendEquation != BlendEquation) || kZero_GrBlendCoeff != SrcCoeff || kOne_GrBlendCoeff != DstCoeff> {}; #define GR_BLEND_MODIFIES_DST(EQUATION, SRC_COEFF, DST_COEFF) \ GrTBlendModifiesDst::value /** * Advanced blend equations can always tweak alpha for coverage. (See GrCustomXfermode.cpp) * * For "add" and "reverse subtract" the blend equation with f=coverage is: * * D' = f * (S * srcCoeff + D * dstCoeff) + (1-f) * D * = f * S * srcCoeff + D * (f * dstCoeff + (1 - f)) * * (Let srcCoeff be negative for reverse subtract.) We can tweak alpha for coverage when the * following relationship holds: * * (f*S) * srcCoeff' + D * dstCoeff' == f * S * srcCoeff + D * (f * dstCoeff + (1 - f)) * * (Where srcCoeff' and dstCoeff' have any reference to S pre-multiplied by f.) * * It's easy to see this works for the src term as long as srcCoeff' == srcCoeff (meaning srcCoeff * does not reference S). For the dst term, this will work as long as the following is true: *| * dstCoeff' == f * dstCoeff + (1 - f) * dstCoeff' == 1 - f * (1 - dstCoeff) * * By inspection we can see this will work as long as dstCoeff has a 1, and any other term in * dstCoeff references S. * * Moreover, if the blend doesn't modify the dst at all then it is ok to arbitrarily modify the src * color so folding in coverage is allowed. */ template struct GrTBlendCanTweakAlphaForCoverage : skstd::bool_constant< GR_BLEND_EQUATION_IS_ADVANCED(Equation) || ((kAdd_GrBlendEquation == Equation || kReverseSubtract_GrBlendEquation == Equation) && !GR_BLEND_COEFF_REFS_SRC(SrcCoeff) && (kOne_GrBlendCoeff == DstCoeff || kISC_GrBlendCoeff == DstCoeff || kISA_GrBlendCoeff == DstCoeff)) || !GrTBlendModifiesDst::value> {}; #define GR_BLEND_CAN_TWEAK_ALPHA_FOR_COVERAGE(EQUATION, SRC_COEFF, DST_COEFF) \ GrTBlendCanTweakAlphaForCoverage::value #endif