1 2 /* 3 * Copyright 2013 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 #ifndef GrBlend_DEFINED 10 #define GrBlend_DEFINED 11 12 #include "GrColor.h" 13 #include "../private/SkTLogic.h" 14 15 /** 16 * Equations for alpha-blending. 17 */ 18 enum GrBlendEquation { 19 // Basic blend equations. 20 kAdd_GrBlendEquation, //<! Cs*S + Cd*D 21 kSubtract_GrBlendEquation, //<! Cs*S - Cd*D 22 kReverseSubtract_GrBlendEquation, //<! Cd*D - Cs*S 23 24 // Advanced blend equations. These are described in the SVG and PDF specs. 25 kScreen_GrBlendEquation, 26 kOverlay_GrBlendEquation, 27 kDarken_GrBlendEquation, 28 kLighten_GrBlendEquation, 29 kColorDodge_GrBlendEquation, 30 kColorBurn_GrBlendEquation, 31 kHardLight_GrBlendEquation, 32 kSoftLight_GrBlendEquation, 33 kDifference_GrBlendEquation, 34 kExclusion_GrBlendEquation, 35 kMultiply_GrBlendEquation, 36 kHSLHue_GrBlendEquation, 37 kHSLSaturation_GrBlendEquation, 38 kHSLColor_GrBlendEquation, 39 kHSLLuminosity_GrBlendEquation, 40 41 kFirstAdvancedGrBlendEquation = kScreen_GrBlendEquation, 42 kLast_GrBlendEquation = kHSLLuminosity_GrBlendEquation 43 }; 44 45 static const int kGrBlendEquationCnt = kLast_GrBlendEquation + 1; 46 47 48 /** 49 * Coefficients for alpha-blending. 50 */ 51 enum GrBlendCoeff { 52 kZero_GrBlendCoeff, //<! 0 53 kOne_GrBlendCoeff, //<! 1 54 kSC_GrBlendCoeff, //<! src color 55 kISC_GrBlendCoeff, //<! one minus src color 56 kDC_GrBlendCoeff, //<! dst color 57 kIDC_GrBlendCoeff, //<! one minus dst color 58 kSA_GrBlendCoeff, //<! src alpha 59 kISA_GrBlendCoeff, //<! one minus src alpha 60 kDA_GrBlendCoeff, //<! dst alpha 61 kIDA_GrBlendCoeff, //<! one minus dst alpha 62 kConstC_GrBlendCoeff, //<! constant color 63 kIConstC_GrBlendCoeff, //<! one minus constant color 64 kConstA_GrBlendCoeff, //<! constant color alpha 65 kIConstA_GrBlendCoeff, //<! one minus constant color alpha 66 kS2C_GrBlendCoeff, 67 kIS2C_GrBlendCoeff, 68 kS2A_GrBlendCoeff, 69 kIS2A_GrBlendCoeff, 70 71 kLast_GrBlendCoeff = kIS2A_GrBlendCoeff 72 }; 73 74 static const int kGrBlendCoeffCnt = kLast_GrBlendCoeff + 1; 75 76 /** 77 * Given a known blend equation in the form of srcCoeff * srcColor + dstCoeff * dstColor where 78 * there may be partial knowledge of the srcColor and dstColor component values, determine what 79 * components of the blended output color are known. Coeffs must not refer to the constant or 80 * secondary src color. 81 */ 82 void GrGetCoeffBlendKnownComponents(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff, 83 GrColor srcColor, 84 GrColorComponentFlags srcColorFlags, 85 GrColor dstColor, 86 GrColorComponentFlags dstColorFlags, 87 GrColor* outColor, 88 GrColorComponentFlags* outFlags); 89 90 template<GrBlendCoeff Coeff> 91 struct GrTBlendCoeffRefsSrc : skstd::bool_constant<kSC_GrBlendCoeff == Coeff || 92 kISC_GrBlendCoeff == Coeff || 93 kSA_GrBlendCoeff == Coeff || 94 kISA_GrBlendCoeff == Coeff> {}; 95 96 #define GR_BLEND_COEFF_REFS_SRC(COEFF) \ 97 GrTBlendCoeffRefsSrc<COEFF>::value 98 99 inline bool GrBlendCoeffRefsSrc(GrBlendCoeff coeff) { 100 switch (coeff) { 101 case kSC_GrBlendCoeff: 102 case kISC_GrBlendCoeff: 103 case kSA_GrBlendCoeff: 104 case kISA_GrBlendCoeff: 105 return true; 106 default: 107 return false; 108 } 109 } 110 111 template<GrBlendCoeff Coeff> 112 struct GrTBlendCoeffRefsDst : skstd::bool_constant<kDC_GrBlendCoeff == Coeff || 113 kIDC_GrBlendCoeff == Coeff || 114 kDA_GrBlendCoeff == Coeff || 115 kIDA_GrBlendCoeff == Coeff> {}; 116 117 #define GR_BLEND_COEFF_REFS_DST(COEFF) \ 118 GrTBlendCoeffRefsDst<COEFF>::value 119 120 inline bool GrBlendCoeffRefsDst(GrBlendCoeff coeff) { 121 switch (coeff) { 122 case kDC_GrBlendCoeff: 123 case kIDC_GrBlendCoeff: 124 case kDA_GrBlendCoeff: 125 case kIDA_GrBlendCoeff: 126 return true; 127 default: 128 return false; 129 } 130 } 131 132 133 template<GrBlendCoeff Coeff> 134 struct GrTBlendCoeffRefsSrc2 : skstd::bool_constant<kS2C_GrBlendCoeff == Coeff || 135 kIS2C_GrBlendCoeff == Coeff || 136 kS2A_GrBlendCoeff == Coeff || 137 kIS2A_GrBlendCoeff == Coeff> {}; 138 139 #define GR_BLEND_COEFF_REFS_SRC2(COEFF) \ 140 GrTBlendCoeffRefsSrc2<COEFF>::value 141 142 inline bool GrBlendCoeffRefsSrc2(GrBlendCoeff coeff) { 143 switch (coeff) { 144 case kS2C_GrBlendCoeff: 145 case kIS2C_GrBlendCoeff: 146 case kS2A_GrBlendCoeff: 147 case kIS2A_GrBlendCoeff: 148 return true; 149 default: 150 return false; 151 } 152 } 153 154 155 template<GrBlendCoeff SrcCoeff, GrBlendCoeff DstCoeff> 156 struct GrTBlendCoeffsUseSrcColor : skstd::bool_constant<kZero_GrBlendCoeff != SrcCoeff || 157 GR_BLEND_COEFF_REFS_SRC(DstCoeff)> {}; 158 159 #define GR_BLEND_COEFFS_USE_SRC_COLOR(SRC_COEFF, DST_COEFF) \ 160 GrTBlendCoeffsUseSrcColor<SRC_COEFF, DST_COEFF>::value 161 162 163 template<GrBlendCoeff SrcCoeff, GrBlendCoeff DstCoeff> 164 struct GrTBlendCoeffsUseDstColor : skstd::bool_constant<GR_BLEND_COEFF_REFS_DST(SrcCoeff) || 165 kZero_GrBlendCoeff != DstCoeff> {}; 166 167 #define GR_BLEND_COEFFS_USE_DST_COLOR(SRC_COEFF, DST_COEFF) \ 168 GrTBlendCoeffsUseDstColor<SRC_COEFF, DST_COEFF>::value 169 170 171 template<GrBlendEquation Equation> 172 struct GrTBlendEquationIsAdvanced : skstd::bool_constant<Equation >= kFirstAdvancedGrBlendEquation> {}; 173 174 #define GR_BLEND_EQUATION_IS_ADVANCED(EQUATION) \ 175 GrTBlendEquationIsAdvanced<EQUATION>::value 176 177 inline bool GrBlendEquationIsAdvanced(GrBlendEquation equation) { 178 return equation >= kFirstAdvancedGrBlendEquation; 179 } 180 181 182 template<GrBlendEquation BlendEquation, GrBlendCoeff SrcCoeff, GrBlendCoeff DstCoeff> 183 struct GrTBlendModifiesDst : skstd::bool_constant< 184 (kAdd_GrBlendEquation != BlendEquation && kReverseSubtract_GrBlendEquation != BlendEquation) || 185 kZero_GrBlendCoeff != SrcCoeff || 186 kOne_GrBlendCoeff != DstCoeff> {}; 187 188 #define GR_BLEND_MODIFIES_DST(EQUATION, SRC_COEFF, DST_COEFF) \ 189 GrTBlendModifiesDst<EQUATION, SRC_COEFF, DST_COEFF>::value 190 191 192 /** 193 * Advanced blend equations can always tweak alpha for coverage. (See GrCustomXfermode.cpp) 194 * 195 * For "add" and "reverse subtract" the blend equation with f=coverage is: 196 * 197 * D' = f * (S * srcCoeff + D * dstCoeff) + (1-f) * D 198 * = f * S * srcCoeff + D * (f * dstCoeff + (1 - f)) 199 * 200 * (Let srcCoeff be negative for reverse subtract.) We can tweak alpha for coverage when the 201 * following relationship holds: 202 * 203 * (f*S) * srcCoeff' + D * dstCoeff' == f * S * srcCoeff + D * (f * dstCoeff + (1 - f)) 204 * 205 * (Where srcCoeff' and dstCoeff' have any reference to S pre-multiplied by f.) 206 * 207 * It's easy to see this works for the src term as long as srcCoeff' == srcCoeff (meaning srcCoeff 208 * does not reference S). For the dst term, this will work as long as the following is true: 209 *| 210 * dstCoeff' == f * dstCoeff + (1 - f) 211 * dstCoeff' == 1 - f * (1 - dstCoeff) 212 * 213 * By inspection we can see this will work as long as dstCoeff has a 1, and any other term in 214 * dstCoeff references S. 215 */ 216 template<GrBlendEquation Equation, GrBlendCoeff SrcCoeff, GrBlendCoeff DstCoeff> 217 struct GrTBlendCanTweakAlphaForCoverage : skstd::bool_constant< 218 GR_BLEND_EQUATION_IS_ADVANCED(Equation) || 219 ((kAdd_GrBlendEquation == Equation || kReverseSubtract_GrBlendEquation == Equation) && 220 !GR_BLEND_COEFF_REFS_SRC(SrcCoeff) && 221 (kOne_GrBlendCoeff == DstCoeff || 222 kISC_GrBlendCoeff == DstCoeff || 223 kISA_GrBlendCoeff == DstCoeff))> {}; 224 225 #define GR_BLEND_CAN_TWEAK_ALPHA_FOR_COVERAGE(EQUATION, SRC_COEFF, DST_COEFF) \ 226 GrTBlendCanTweakAlphaForCoverage<EQUATION, SRC_COEFF, DST_COEFF>::value 227 228 #endif 229