aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrBlend.cpp
blob: 436829ce63af300b8d458304e801dac1ad2de7af (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/*
* Copyright 2015 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"
#include "../private/GrColor.h"

/**
 * MaskedColor is used to evaluate the color and valid color component flags through the
 * blending equation. Could possibly extend this to be used more broadly.
 */
class MaskedColor {
public:
    MaskedColor(GrColor color, GrColorComponentFlags flags)
        : fColor(color)
        , fFlags(flags) {}

    MaskedColor() {}

    void set(GrColor color, GrColorComponentFlags flags) {
        fColor = color;
        fFlags = flags;
    }

    static MaskedColor Invert(const MaskedColor& in) {
        return MaskedColor(GrInvertColor(in.fColor), in.fFlags);
    }

    static MaskedColor ExtractAlpha(const MaskedColor& in) {
        GrColorComponentFlags flags = (in.fFlags & kA_GrColorComponentFlag) ?
            kRGBA_GrColorComponentFlags : kNone_GrColorComponentFlags;
        return MaskedColor(GrColorPackA4(GrColorUnpackA(in.fColor)), flags);
    }

    static MaskedColor ExtractInverseAlpha(const MaskedColor& in) {
        GrColorComponentFlags flags = (in.fFlags & kA_GrColorComponentFlag) ?
            kRGBA_GrColorComponentFlags : kNone_GrColorComponentFlags;
        return MaskedColor(GrColorPackA4(0xFF - GrColorUnpackA(in.fColor)), flags);
    }

    static MaskedColor Mul(const MaskedColor& a, const MaskedColor& b) {
        GrColorComponentFlags outFlags = (a.fFlags & b.fFlags) | a.componentsWithValue(0) |
                                         b.componentsWithValue(0);
        return MaskedColor(GrColorMul(a.fColor, b.fColor), outFlags);
    }

    static MaskedColor SatAdd(const MaskedColor& a, const MaskedColor& b) {
        GrColorComponentFlags outFlags = (a.fFlags & b.fFlags) | a.componentsWithValue(0xFF) |
                                         b.componentsWithValue(0xFF);
        return MaskedColor(GrColorSatAdd(a.fColor, b.fColor), outFlags);
    }

    GrColor color() const { return fColor; }

    GrColorComponentFlags validFlags () const { return fFlags; }

private:
    GrColorComponentFlags componentsWithValue(unsigned value) const {
        GrColorComponentFlags flags = kNone_GrColorComponentFlags;
        if ((kR_GrColorComponentFlag & fFlags) && value == GrColorUnpackR(fColor)) {
            flags |= kR_GrColorComponentFlag;
        }
        if ((kG_GrColorComponentFlag & fFlags) && value == GrColorUnpackG(fColor)) {
            flags |= kG_GrColorComponentFlag;
        }
        if ((kB_GrColorComponentFlag & fFlags) && value == GrColorUnpackB(fColor)) {
            flags |= kB_GrColorComponentFlag;
        }
        if ((kA_GrColorComponentFlag & fFlags) && value == GrColorUnpackA(fColor)) {
            flags |= kA_GrColorComponentFlag;
        }
        return flags;
    }

    GrColor                 fColor;
    GrColorComponentFlags   fFlags;
};

static MaskedColor get_term(GrBlendCoeff coeff, const MaskedColor& src, const MaskedColor& dst,
                            const MaskedColor& value) {
    switch (coeff) {
        case kZero_GrBlendCoeff:
            return MaskedColor(0, kRGBA_GrColorComponentFlags);
        case kOne_GrBlendCoeff:
            return value;
        case kDC_GrBlendCoeff:
            return MaskedColor::Mul(dst, value);
        case kIDC_GrBlendCoeff:
            return MaskedColor::Mul(MaskedColor::Invert(dst), value);
        case kDA_GrBlendCoeff:
            return MaskedColor::Mul(MaskedColor::ExtractAlpha(dst), value);
        case kIDA_GrBlendCoeff:
            return MaskedColor::Mul(MaskedColor::ExtractInverseAlpha(dst), value);
        case kSC_GrBlendCoeff:
            return MaskedColor::Mul(src, value);
        case kISC_GrBlendCoeff:
            return MaskedColor::Mul(MaskedColor::Invert(src), value);
        case kSA_GrBlendCoeff:
            return MaskedColor::Mul(MaskedColor::ExtractAlpha(src), value);
        case kISA_GrBlendCoeff:
            return MaskedColor::Mul(MaskedColor::ExtractInverseAlpha(src), value);
        default:
            SK_ABORT("Illegal coefficient");
            return MaskedColor();
    }
}

void GrGetCoeffBlendKnownComponents(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff,
                                    GrColor srcColor, GrColorComponentFlags srcColorFlags,
                                    GrColor dstColor, GrColorComponentFlags dstColorFlags,
                                    GrColor* outColor,
                                    GrColorComponentFlags* outFlags) {
    MaskedColor src(srcColor, srcColorFlags);
    MaskedColor dst(dstColor, dstColorFlags);

    MaskedColor srcTerm = get_term(srcCoeff, src, dst, src);
    MaskedColor dstTerm = get_term(dstCoeff, src, dst, dst);

    MaskedColor output = MaskedColor::SatAdd(srcTerm, dstTerm);
    *outColor = output.color();
    *outFlags = output.validFlags();
}