Home | History | Annotate | Download | only in gpu
      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