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 "include/core/SkTypes.h" 13 14/** 15 * Equations for alpha-blending. 16 */ 17enum GrBlendEquation { 18 // Basic blend equations. 19 kAdd_GrBlendEquation, //<! Cs*S + Cd*D 20 kSubtract_GrBlendEquation, //<! Cs*S - Cd*D 21 kReverseSubtract_GrBlendEquation, //<! Cd*D - Cs*S 22 23 // Advanced blend equations. These are described in the SVG and PDF specs. 24 kScreen_GrBlendEquation, 25 kOverlay_GrBlendEquation, 26 kDarken_GrBlendEquation, 27 kLighten_GrBlendEquation, 28 kColorDodge_GrBlendEquation, 29 kColorBurn_GrBlendEquation, 30 kHardLight_GrBlendEquation, 31 kSoftLight_GrBlendEquation, 32 kDifference_GrBlendEquation, 33 kExclusion_GrBlendEquation, 34 kMultiply_GrBlendEquation, 35 kHSLHue_GrBlendEquation, 36 kHSLSaturation_GrBlendEquation, 37 kHSLColor_GrBlendEquation, 38 kHSLLuminosity_GrBlendEquation, 39 40 kIllegal_GrBlendEquation, 41 42 kFirstAdvancedGrBlendEquation = kScreen_GrBlendEquation, 43 kLast_GrBlendEquation = kIllegal_GrBlendEquation, 44}; 45 46static const int kGrBlendEquationCnt = kLast_GrBlendEquation + 1; 47 48 49/** 50 * Coefficients for alpha-blending. 51 */ 52enum GrBlendCoeff { 53 kZero_GrBlendCoeff, //<! 0 54 kOne_GrBlendCoeff, //<! 1 55 kSC_GrBlendCoeff, //<! src color 56 kISC_GrBlendCoeff, //<! one minus src color 57 kDC_GrBlendCoeff, //<! dst color 58 kIDC_GrBlendCoeff, //<! one minus dst color 59 kSA_GrBlendCoeff, //<! src alpha 60 kISA_GrBlendCoeff, //<! one minus src alpha 61 kDA_GrBlendCoeff, //<! dst alpha 62 kIDA_GrBlendCoeff, //<! one minus dst alpha 63 kConstC_GrBlendCoeff, //<! constant color 64 kIConstC_GrBlendCoeff, //<! one minus constant color 65 kS2C_GrBlendCoeff, 66 kIS2C_GrBlendCoeff, 67 kS2A_GrBlendCoeff, 68 kIS2A_GrBlendCoeff, 69 70 kIllegal_GrBlendCoeff, 71 72 kLast_GrBlendCoeff = kIllegal_GrBlendCoeff, 73}; 74 75static const int kGrBlendCoeffCnt = kLast_GrBlendCoeff + 1; 76 77static constexpr bool GrBlendCoeffRefsSrc(const GrBlendCoeff coeff) { 78 return kSC_GrBlendCoeff == coeff || kISC_GrBlendCoeff == coeff || kSA_GrBlendCoeff == coeff || 79 kISA_GrBlendCoeff == coeff; 80} 81 82static constexpr bool GrBlendCoeffRefsDst(const GrBlendCoeff coeff) { 83 return kDC_GrBlendCoeff == coeff || kIDC_GrBlendCoeff == coeff || kDA_GrBlendCoeff == coeff || 84 kIDA_GrBlendCoeff == coeff; 85} 86 87static constexpr bool GrBlendCoeffRefsSrc2(const GrBlendCoeff coeff) { 88 return kS2C_GrBlendCoeff == coeff || kIS2C_GrBlendCoeff == coeff || 89 kS2A_GrBlendCoeff == coeff || kIS2A_GrBlendCoeff == coeff; 90} 91 92static constexpr bool GrBlendCoeffsUseSrcColor(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) { 93 return kZero_GrBlendCoeff != srcCoeff || GrBlendCoeffRefsSrc(dstCoeff); 94} 95 96static constexpr bool GrBlendCoeffsUseDstColor(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff, 97 bool srcColorIsOpaque) { 98 return GrBlendCoeffRefsDst(srcCoeff) || 99 (dstCoeff != kZero_GrBlendCoeff && !(dstCoeff == kISA_GrBlendCoeff && srcColorIsOpaque)); 100} 101 102static constexpr bool GrBlendEquationIsAdvanced(GrBlendEquation equation) { 103 return equation >= kFirstAdvancedGrBlendEquation 104 && equation != kIllegal_GrBlendEquation; 105} 106 107static constexpr bool GrBlendModifiesDst(GrBlendEquation equation, GrBlendCoeff srcCoeff, 108 GrBlendCoeff dstCoeff) { 109 return (kAdd_GrBlendEquation != equation && kReverseSubtract_GrBlendEquation != equation) || 110 kZero_GrBlendCoeff != srcCoeff || kOne_GrBlendCoeff != dstCoeff; 111} 112 113static constexpr bool GrBlendCoeffRefsConstant(const GrBlendCoeff coeff) { 114 return coeff == kConstC_GrBlendCoeff || coeff == kIConstC_GrBlendCoeff; 115} 116 117static constexpr bool GrBlendShouldDisable(GrBlendEquation equation, GrBlendCoeff srcCoeff, 118 GrBlendCoeff dstCoeff) { 119 return (kAdd_GrBlendEquation == equation || kSubtract_GrBlendEquation == equation) && 120 kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff; 121} 122 123/** 124 * Advanced blend equations can always tweak alpha for coverage. (See GrCustomXfermode.cpp) 125 * 126 * For "add" and "reverse subtract" the blend equation with f=coverage is: 127 * 128 * D' = f * (S * srcCoeff + D * dstCoeff) + (1-f) * D 129 * = f * S * srcCoeff + D * (f * dstCoeff + (1 - f)) 130 * 131 * (Let srcCoeff be negative for reverse subtract.) We can tweak alpha for coverage when the 132 * following relationship holds: 133 * 134 * (f*S) * srcCoeff' + D * dstCoeff' == f * S * srcCoeff + D * (f * dstCoeff + (1 - f)) 135 * 136 * (Where srcCoeff' and dstCoeff' have any reference to S pre-multiplied by f.) 137 * 138 * It's easy to see this works for the src term as long as srcCoeff' == srcCoeff (meaning srcCoeff 139 * does not reference S). For the dst term, this will work as long as the following is true: 140 *| 141 * dstCoeff' == f * dstCoeff + (1 - f) 142 * dstCoeff' == 1 - f * (1 - dstCoeff) 143 * 144 * By inspection we can see this will work as long as dstCoeff has a 1, and any other term in 145 * dstCoeff references S. 146 * 147 * Moreover, if the blend doesn't modify the dst at all then it is ok to arbitrarily modify the src 148 * color so folding in coverage is allowed. 149 */ 150static constexpr bool GrBlendAllowsCoverageAsAlpha(GrBlendEquation equation, 151 GrBlendCoeff srcCoeff, 152 GrBlendCoeff dstCoeff) { 153 return GrBlendEquationIsAdvanced(equation) || 154 !GrBlendModifiesDst(equation, srcCoeff, dstCoeff) || 155 ((kAdd_GrBlendEquation == equation || kReverseSubtract_GrBlendEquation == equation) && 156 !GrBlendCoeffRefsSrc(srcCoeff) && 157 (kOne_GrBlendCoeff == dstCoeff || kISC_GrBlendCoeff == dstCoeff || 158 kISA_GrBlendCoeff == dstCoeff)); 159} 160 161#endif 162