Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / gpu / GrBlend.cpp
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(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 }