Index: src/gpu/GrBlend.cpp |
diff --git a/src/gpu/GrBlend.cpp b/src/gpu/GrBlend.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..52e335e9b0461cd7132ce97abdcb26cb0f91dbef |
--- /dev/null |
+++ b/src/gpu/GrBlend.cpp |
@@ -0,0 +1,154 @@ |
+ |
+/* |
+ * Copyright 2013 Google Inc. |
+ * |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+ |
+#include "GrBlend.h" |
+ |
+static inline GrBlendCoeff swap_coeff_src_dst(GrBlendCoeff coeff) { |
+ switch (coeff) { |
+ case kDC_GrBlendCoeff: |
+ return kSC_GrBlendCoeff; |
+ case kIDC_GrBlendCoeff: |
+ return kISC_GrBlendCoeff; |
+ case kDA_GrBlendCoeff: |
+ return kSA_GrBlendCoeff; |
+ case kIDA_GrBlendCoeff: |
+ return kISA_GrBlendCoeff; |
+ case kSC_GrBlendCoeff: |
+ return kDC_GrBlendCoeff; |
+ case kISC_GrBlendCoeff: |
+ return kIDC_GrBlendCoeff; |
+ case kSA_GrBlendCoeff: |
+ return kDA_GrBlendCoeff; |
+ case kISA_GrBlendCoeff: |
+ return kIDA_GrBlendCoeff; |
+ default: |
+ return coeff; |
+ } |
+} |
+ |
+static inline unsigned saturated_add(unsigned a, unsigned b) { |
+ SkASSERT(a <= 255); |
+ SkASSERT(b <= 255); |
+ unsigned sum = a + b; |
+ if (sum > 255) { |
+ sum = 255; |
+ } |
+ return sum; |
+} |
+ |
+static GrColor add_colors(GrColor src, GrColor dst) { |
+ unsigned r = saturated_add(GrColorUnpackR(src), GrColorUnpackR(dst)); |
+ unsigned g = saturated_add(GrColorUnpackG(src), GrColorUnpackG(dst)); |
+ unsigned b = saturated_add(GrColorUnpackB(src), GrColorUnpackB(dst)); |
+ unsigned a = saturated_add(GrColorUnpackA(src), GrColorUnpackA(dst)); |
+ return GrColorPackRGBA(r, g, b, a); |
+} |
+ |
+static inline bool valid_color(uint32_t compFlags) { |
+ return (kRGBA_GrColorComponentFlags & compFlags) == kRGBA_GrColorComponentFlags; |
+} |
+ |
+static GrColor simplify_blend_term(GrBlendCoeff* srcCoeff, |
+ GrColor srcColor, uint32_t srcCompFlags, |
+ GrColor dstColor, uint32_t dstCompFlags, |
+ GrColor constantColor) { |
+ |
+ SkASSERT(!GrBlendCoeffRefsSrc(*srcCoeff)); |
+ SkASSERT(srcCoeff); |
+ |
+ // Check whether srcCoeff can be reduced to kOne or kZero based on known color inputs. |
+ // We could pick out the coeff r,g,b,a values here and use them to compute the blend term color, |
+ // if possible, below but that is not implemented now. |
+ switch (*srcCoeff) { |
+ case kIDC_GrBlendCoeff: |
+ dstColor = ~dstColor; // fallthrough |
+ case kDC_GrBlendCoeff: |
+ if (valid_color(dstCompFlags)) { |
+ if (0xffffffff == dstColor) { |
+ *srcCoeff = kOne_GrBlendCoeff; |
+ } else if (0 == dstColor) { |
+ *srcCoeff = kZero_GrBlendCoeff; |
+ } |
+ } |
+ break; |
+ |
+ case kIDA_GrBlendCoeff: |
+ dstColor = ~dstColor; // fallthrough |
+ case kDA_GrBlendCoeff: |
+ if (kA_GrColorComponentFlag & dstCompFlags) { |
+ if (0xff == GrColorUnpackA(dstColor)) { |
+ *srcCoeff = kOne_GrBlendCoeff; |
+ } else if (0 == GrColorUnpackA(dstColor)) { |
+ *srcCoeff = kZero_GrBlendCoeff; |
+ } |
+ } |
+ break; |
+ |
+ case kIConstC_GrBlendCoeff: |
+ constantColor = ~constantColor; // fallthrough |
+ case kConstC_GrBlendCoeff: |
+ if (0xffffffff == constantColor) { |
+ *srcCoeff = kOne_GrBlendCoeff; |
+ } else if (0 == constantColor) { |
+ *srcCoeff = kZero_GrBlendCoeff; |
+ } |
+ break; |
+ |
+ case kIConstA_GrBlendCoeff: |
+ constantColor = ~constantColor; // fallthrough |
+ case kConstA_GrBlendCoeff: |
+ if (0xff == GrColorUnpackA(constantColor)) { |
+ *srcCoeff = kOne_GrBlendCoeff; |
+ } else if (0 == GrColorUnpackA(constantColor)) { |
+ *srcCoeff = kZero_GrBlendCoeff; |
+ } |
+ break; |
+ |
+ default: |
+ break; |
+ } |
+ // We may have invalidated these above and shouldn't read them again. |
+ SkDEBUGCODE(dstColor = constantColor = GrColor_ILLEGAL;) |
+ |
+ if (kZero_GrBlendCoeff == *srcCoeff || (valid_color(srcCompFlags) && 0 == srcColor)) { |
+ *srcCoeff = kZero_GrBlendCoeff; |
+ return 0; |
+ } |
+ |
+ if (kOne_GrBlendCoeff == *srcCoeff && valid_color(srcCompFlags)) { |
+ return srcColor; |
+ } else { |
+ return GrColor_ILLEGAL; |
+ } |
+} |
+ |
+GrColor GrSimplifyBlend(GrBlendCoeff* srcCoeff, |
+ GrBlendCoeff* dstCoeff, |
+ GrColor srcColor, uint32_t srcCompFlags, |
+ GrColor dstColor, uint32_t dstCompFlags, |
+ GrColor constantColor) { |
+ GrColor srcTermColor = simplify_blend_term(srcCoeff, |
+ srcColor, srcCompFlags, |
+ dstColor, dstCompFlags, |
+ constantColor); |
+ |
+ // We call the same function to simplify the dst blend coeff. We trick it out by swapping the |
+ // src and dst. |
+ GrBlendCoeff spoofedCoeff = swap_coeff_src_dst(*dstCoeff); |
+ GrColor dstTermColor = simplify_blend_term(&spoofedCoeff, |
+ dstColor, dstCompFlags, |
+ srcColor, srcCompFlags, |
+ constantColor); |
+ *dstCoeff = swap_coeff_src_dst(spoofedCoeff); |
+ |
+ if (GrColor_ILLEGAL != srcTermColor && GrColor_ILLEGAL != dstTermColor) { |
+ return add_colors(srcTermColor, dstTermColor); |
+ } else { |
+ return GrColor_ILLEGAL; |
+ } |
+} |