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 static constexpr bool GrBlendCoeffRefsSrc(const GrBlendCoeff coeff) {
     77     return kSC_GrBlendCoeff == coeff || kISC_GrBlendCoeff == coeff || kSA_GrBlendCoeff == coeff ||
     78            kISA_GrBlendCoeff == coeff;
     79 }
     80 
     81 static constexpr bool GrBlendCoeffRefsDst(const GrBlendCoeff coeff) {
     82     return kDC_GrBlendCoeff == coeff || kIDC_GrBlendCoeff == coeff || kDA_GrBlendCoeff == coeff ||
     83            kIDA_GrBlendCoeff == coeff;
     84 }
     85 
     86 static constexpr bool GrBlendCoeffRefsSrc2(const GrBlendCoeff coeff) {
     87     return kS2C_GrBlendCoeff == coeff || kIS2C_GrBlendCoeff == coeff ||
     88            kS2A_GrBlendCoeff == coeff || kIS2A_GrBlendCoeff == coeff;
     89 }
     90 
     91 static constexpr bool GrBlendCoeffsUseSrcColor(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
     92     return kZero_GrBlendCoeff != srcCoeff || GrBlendCoeffRefsSrc(dstCoeff);
     93 }
     94 
     95 static constexpr bool GrBlendCoeffsUseDstColor(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
     96     return GrBlendCoeffRefsDst(srcCoeff) || kZero_GrBlendCoeff != dstCoeff;
     97 }
     98 
     99 static constexpr bool GrBlendEquationIsAdvanced(GrBlendEquation equation) {
    100     return equation >= kFirstAdvancedGrBlendEquation;
    101 }
    102 
    103 static constexpr bool GrBlendModifiesDst(GrBlendEquation equation, GrBlendCoeff srcCoeff,
    104                                          GrBlendCoeff dstCoeff) {
    105     return (kAdd_GrBlendEquation != equation && kReverseSubtract_GrBlendEquation != equation) ||
    106            kZero_GrBlendCoeff != srcCoeff || kOne_GrBlendCoeff != dstCoeff;
    107 }
    108 
    109 /**
    110  * Advanced blend equations can always tweak alpha for coverage. (See GrCustomXfermode.cpp)
    111  *
    112  * For "add" and "reverse subtract" the blend equation with f=coverage is:
    113  *
    114  *   D' = f * (S * srcCoeff + D * dstCoeff) + (1-f) * D
    115  *      = f * S * srcCoeff + D * (f * dstCoeff + (1 - f))
    116  *
    117  * (Let srcCoeff be negative for reverse subtract.) We can tweak alpha for coverage when the
    118  * following relationship holds:
    119  *
    120  *   (f*S) * srcCoeff' + D * dstCoeff' == f * S * srcCoeff + D * (f * dstCoeff + (1 - f))
    121  *
    122  * (Where srcCoeff' and dstCoeff' have any reference to S pre-multiplied by f.)
    123  *
    124  * It's easy to see this works for the src term as long as srcCoeff' == srcCoeff (meaning srcCoeff
    125  * does not reference S). For the dst term, this will work as long as the following is true:
    126  *|
    127  *   dstCoeff' == f * dstCoeff + (1 - f)
    128  *   dstCoeff' == 1 - f * (1 - dstCoeff)
    129  *
    130  * By inspection we can see this will work as long as dstCoeff has a 1, and any other term in
    131  * dstCoeff references S.
    132  *
    133  * Moreover, if the blend doesn't modify the dst at all then it is ok to arbitrarily modify the src
    134  * color so folding in coverage is allowed.
    135  */
    136 static constexpr bool GrBlendAllowsCoverageAsAlpha(GrBlendEquation equation,
    137                                                    GrBlendCoeff srcCoeff,
    138                                                    GrBlendCoeff dstCoeff) {
    139     return GrBlendEquationIsAdvanced(equation) ||
    140            !GrBlendModifiesDst(equation, srcCoeff, dstCoeff) ||
    141            ((kAdd_GrBlendEquation == equation || kReverseSubtract_GrBlendEquation == equation) &&
    142             !GrBlendCoeffRefsSrc(srcCoeff) &&
    143             (kOne_GrBlendCoeff == dstCoeff || kISC_GrBlendCoeff == dstCoeff ||
    144              kISA_GrBlendCoeff == dstCoeff));
    145 }
    146 
    147 #endif
    148