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 #include "GrBlend.h" 10 11 static inline GrBlendCoeff swap_coeff_src_dst(GrBlendCoeff coeff) { 12 switch (coeff) { 13 case kDC_GrBlendCoeff: 14 return kSC_GrBlendCoeff; 15 case kIDC_GrBlendCoeff: 16 return kISC_GrBlendCoeff; 17 case kDA_GrBlendCoeff: 18 return kSA_GrBlendCoeff; 19 case kIDA_GrBlendCoeff: 20 return kISA_GrBlendCoeff; 21 case kSC_GrBlendCoeff: 22 return kDC_GrBlendCoeff; 23 case kISC_GrBlendCoeff: 24 return kIDC_GrBlendCoeff; 25 case kSA_GrBlendCoeff: 26 return kDA_GrBlendCoeff; 27 case kISA_GrBlendCoeff: 28 return kIDA_GrBlendCoeff; 29 default: 30 return coeff; 31 } 32 } 33 34 static inline unsigned saturated_add(unsigned a, unsigned b) { 35 SkASSERT(a <= 255); 36 SkASSERT(b <= 255); 37 unsigned sum = a + b; 38 if (sum > 255) { 39 sum = 255; 40 } 41 return sum; 42 } 43 44 static GrColor add_colors(GrColor src, GrColor dst) { 45 unsigned r = saturated_add(GrColorUnpackR(src), GrColorUnpackR(dst)); 46 unsigned g = saturated_add(GrColorUnpackG(src), GrColorUnpackG(dst)); 47 unsigned b = saturated_add(GrColorUnpackB(src), GrColorUnpackB(dst)); 48 unsigned a = saturated_add(GrColorUnpackA(src), GrColorUnpackA(dst)); 49 return GrColorPackRGBA(r, g, b, a); 50 } 51 52 static inline bool valid_color(uint32_t compFlags) { 53 return (kRGBA_GrColorComponentFlags & compFlags) == kRGBA_GrColorComponentFlags; 54 } 55 56 static GrColor simplify_blend_term(GrBlendCoeff* srcCoeff, 57 GrColor srcColor, uint32_t srcCompFlags, 58 GrColor dstColor, uint32_t dstCompFlags, 59 GrColor constantColor) { 60 61 SkASSERT(!GrBlendCoeffRefsSrc(*srcCoeff)); 62 SkASSERT(NULL != srcCoeff); 63 64 // Check whether srcCoeff can be reduced to kOne or kZero based on known color inputs. 65 // We could pick out the coeff r,g,b,a values here and use them to compute the blend term color, 66 // if possible, below but that is not implemented now. 67 switch (*srcCoeff) { 68 case kIDC_GrBlendCoeff: 69 dstColor = ~dstColor; // fallthrough 70 case kDC_GrBlendCoeff: 71 if (valid_color(dstCompFlags)) { 72 if (0xffffffff == dstColor) { 73 *srcCoeff = kOne_GrBlendCoeff; 74 } else if (0 == dstColor) { 75 *srcCoeff = kZero_GrBlendCoeff; 76 } 77 } 78 break; 79 80 case kIDA_GrBlendCoeff: 81 dstColor = ~dstColor; // fallthrough 82 case kDA_GrBlendCoeff: 83 if (kA_GrColorComponentFlag & dstCompFlags) { 84 if (0xff == GrColorUnpackA(dstColor)) { 85 *srcCoeff = kOne_GrBlendCoeff; 86 } else if (0 == GrColorUnpackA(dstColor)) { 87 *srcCoeff = kZero_GrBlendCoeff; 88 } 89 } 90 break; 91 92 case kIConstC_GrBlendCoeff: 93 constantColor = ~constantColor; // fallthrough 94 case kConstC_GrBlendCoeff: 95 if (0xffffffff == constantColor) { 96 *srcCoeff = kOne_GrBlendCoeff; 97 } else if (0 == constantColor) { 98 *srcCoeff = kZero_GrBlendCoeff; 99 } 100 break; 101 102 case kIConstA_GrBlendCoeff: 103 constantColor = ~constantColor; // fallthrough 104 case kConstA_GrBlendCoeff: 105 if (0xff == GrColorUnpackA(constantColor)) { 106 *srcCoeff = kOne_GrBlendCoeff; 107 } else if (0 == GrColorUnpackA(constantColor)) { 108 *srcCoeff = kZero_GrBlendCoeff; 109 } 110 break; 111 112 default: 113 break; 114 } 115 // We may have invalidated these above and shouldn't read them again. 116 SkDEBUGCODE(dstColor = constantColor = GrColor_ILLEGAL;) 117 118 if (kZero_GrBlendCoeff == *srcCoeff || (valid_color(srcCompFlags) && 0 == srcColor)) { 119 *srcCoeff = kZero_GrBlendCoeff; 120 return 0; 121 } 122 123 if (kOne_GrBlendCoeff == *srcCoeff && valid_color(srcCompFlags)) { 124 return srcColor; 125 } else { 126 return GrColor_ILLEGAL; 127 } 128 } 129 130 GrColor GrSimplifyBlend(GrBlendCoeff* srcCoeff, 131 GrBlendCoeff* dstCoeff, 132 GrColor srcColor, uint32_t srcCompFlags, 133 GrColor dstColor, uint32_t dstCompFlags, 134 GrColor constantColor) { 135 GrColor srcTermColor = simplify_blend_term(srcCoeff, 136 srcColor, srcCompFlags, 137 dstColor, dstCompFlags, 138 constantColor); 139 140 // We call the same function to simplify the dst blend coeff. We trick it out by swapping the 141 // src and dst. 142 GrBlendCoeff spoofedCoeff = swap_coeff_src_dst(*dstCoeff); 143 GrColor dstTermColor = simplify_blend_term(&spoofedCoeff, 144 dstColor, dstCompFlags, 145 srcColor, srcCompFlags, 146 constantColor); 147 *dstCoeff = swap_coeff_src_dst(spoofedCoeff); 148 149 if (GrColor_ILLEGAL != srcTermColor && GrColor_ILLEGAL != dstTermColor) { 150 return add_colors(srcTermColor, dstTermColor); 151 } else { 152 return GrColor_ILLEGAL; 153 } 154 } 155