1
2/*
3 * Copyright 2014 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 "effects/GrCoverageSetOpXP.h"
10#include "GrColor.h"
11#include "GrDrawTargetCaps.h"
12#include "GrProcessor.h"
13#include "GrProcOptInfo.h"
14#include "gl/GrGLXferProcessor.h"
15#include "gl/builders/GrGLFragmentShaderBuilder.h"
16#include "gl/builders/GrGLProgramBuilder.h"
17
18class CoverageSetOpXP : public GrXferProcessor {
19public:
20    static GrXferProcessor* Create(SkRegion::Op regionOp, bool invertCoverage) {
21        return SkNEW_ARGS(CoverageSetOpXP, (regionOp, invertCoverage));
22    }
23
24    ~CoverageSetOpXP() override;
25
26    const char* name() const override { return "Coverage Set Op"; }
27
28    GrGLXferProcessor* createGLInstance() const override;
29
30    bool hasSecondaryOutput() const override { return false; }
31
32    bool invertCoverage() const { return fInvertCoverage; }
33
34private:
35    CoverageSetOpXP(SkRegion::Op regionOp, bool fInvertCoverage);
36
37    GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI,
38                                                 const GrProcOptInfo& coveragePOI,
39                                                 bool doesStencilWrite,
40                                                 GrColor* color,
41                                                 const GrDrawTargetCaps& caps) override;
42
43    void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
44
45    void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override;
46
47    bool onIsEqual(const GrXferProcessor& xpBase) const override {
48        const CoverageSetOpXP& xp = xpBase.cast<CoverageSetOpXP>();
49        return (fRegionOp == xp.fRegionOp &&
50                fInvertCoverage == xp.fInvertCoverage);
51    }
52
53    SkRegion::Op fRegionOp;
54    bool         fInvertCoverage;
55
56    typedef GrXferProcessor INHERITED;
57};
58
59///////////////////////////////////////////////////////////////////////////////
60
61class GLCoverageSetOpXP : public GrGLXferProcessor {
62public:
63    GLCoverageSetOpXP(const GrProcessor&) {}
64
65    ~GLCoverageSetOpXP() override {}
66
67    static void GenKey(const GrProcessor& processor, const GrGLSLCaps& caps,
68                       GrProcessorKeyBuilder* b) {
69        const CoverageSetOpXP& xp = processor.cast<CoverageSetOpXP>();
70        uint32_t key = xp.invertCoverage() ?  0x0 : 0x1;
71        b->add32(key);
72    };
73
74private:
75    void onEmitCode(const EmitArgs& args) override {
76        const CoverageSetOpXP& xp = args.fXP.cast<CoverageSetOpXP>();
77        GrGLXPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
78
79        if (xp.invertCoverage()) {
80            fsBuilder->codeAppendf("%s = 1.0 - %s;", args.fOutputPrimary, args.fInputCoverage);
81        } else {
82            fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputCoverage);
83        }
84    }
85
86    void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) override {};
87
88    typedef GrGLXferProcessor INHERITED;
89};
90
91///////////////////////////////////////////////////////////////////////////////
92
93CoverageSetOpXP::CoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage)
94    : fRegionOp(regionOp)
95    , fInvertCoverage(invertCoverage) {
96    this->initClassID<CoverageSetOpXP>();
97}
98
99CoverageSetOpXP::~CoverageSetOpXP() {
100}
101
102void CoverageSetOpXP::onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const {
103    GLCoverageSetOpXP::GenKey(*this, caps, b);
104}
105
106GrGLXferProcessor* CoverageSetOpXP::createGLInstance() const {
107    return SkNEW_ARGS(GLCoverageSetOpXP, (*this));
108}
109
110GrXferProcessor::OptFlags
111CoverageSetOpXP::onGetOptimizations(const GrProcOptInfo& colorPOI,
112                                    const GrProcOptInfo& coveragePOI,
113                                    bool doesStencilWrite,
114                                    GrColor* color,
115                                    const GrDrawTargetCaps& caps) {
116    // We never look at the color input
117    return GrXferProcessor::kIgnoreColor_OptFlag;
118}
119
120void CoverageSetOpXP::onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const {
121    switch (fRegionOp) {
122        case SkRegion::kReplace_Op:
123            blendInfo->fSrcBlend = kOne_GrBlendCoeff;
124            blendInfo->fDstBlend = kZero_GrBlendCoeff;
125            break;
126        case SkRegion::kIntersect_Op:
127            blendInfo->fSrcBlend = kDC_GrBlendCoeff;
128            blendInfo->fDstBlend = kZero_GrBlendCoeff;
129            break;
130        case SkRegion::kUnion_Op:
131            blendInfo->fSrcBlend = kOne_GrBlendCoeff;
132            blendInfo->fDstBlend = kISC_GrBlendCoeff;
133            break;
134        case SkRegion::kXOR_Op:
135            blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
136            blendInfo->fDstBlend = kISC_GrBlendCoeff;
137            break;
138        case SkRegion::kDifference_Op:
139            blendInfo->fSrcBlend = kZero_GrBlendCoeff;
140            blendInfo->fDstBlend = kISC_GrBlendCoeff;
141            break;
142        case SkRegion::kReverseDifference_Op:
143            blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
144            blendInfo->fDstBlend = kZero_GrBlendCoeff;
145            break;
146    }
147    blendInfo->fBlendConstant = 0;
148}
149
150///////////////////////////////////////////////////////////////////////////////
151
152GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage)
153    : fRegionOp(regionOp)
154    , fInvertCoverage(invertCoverage) {
155    this->initClassID<GrCoverageSetOpXPFactory>();
156}
157
158GrXPFactory* GrCoverageSetOpXPFactory::Create(SkRegion::Op regionOp, bool invertCoverage) {
159    switch (regionOp) {
160        case SkRegion::kReplace_Op: {
161            if (invertCoverage) {
162                static GrCoverageSetOpXPFactory gReplaceCDXPFI(regionOp, invertCoverage);
163                return SkRef(&gReplaceCDXPFI);
164            } else {
165                static GrCoverageSetOpXPFactory gReplaceCDXPF(regionOp, invertCoverage);
166                return SkRef(&gReplaceCDXPF);
167            }
168            break;
169        }
170        case SkRegion::kIntersect_Op: {
171            if (invertCoverage) {
172                static GrCoverageSetOpXPFactory gIntersectCDXPFI(regionOp, invertCoverage);
173                return SkRef(&gIntersectCDXPFI);
174            } else {
175                static GrCoverageSetOpXPFactory gIntersectCDXPF(regionOp, invertCoverage);
176                return SkRef(&gIntersectCDXPF);
177            }
178            break;
179        }
180        case SkRegion::kUnion_Op: {
181            if (invertCoverage) {
182                static GrCoverageSetOpXPFactory gUnionCDXPFI(regionOp, invertCoverage);
183                return SkRef(&gUnionCDXPFI);
184            } else {
185                static GrCoverageSetOpXPFactory gUnionCDXPF(regionOp, invertCoverage);
186                return SkRef(&gUnionCDXPF);
187            }
188            break;
189        }
190        case SkRegion::kXOR_Op: {
191            if (invertCoverage) {
192                static GrCoverageSetOpXPFactory gXORCDXPFI(regionOp, invertCoverage);
193                return SkRef(&gXORCDXPFI);
194            } else {
195                static GrCoverageSetOpXPFactory gXORCDXPF(regionOp, invertCoverage);
196                return SkRef(&gXORCDXPF);
197            }
198            break;
199        }
200        case SkRegion::kDifference_Op: {
201            if (invertCoverage) {
202                static GrCoverageSetOpXPFactory gDifferenceCDXPFI(regionOp, invertCoverage);
203                return SkRef(&gDifferenceCDXPFI);
204            } else {
205                static GrCoverageSetOpXPFactory gDifferenceCDXPF(regionOp, invertCoverage);
206                return SkRef(&gDifferenceCDXPF);
207            }
208            break;
209        }
210        case SkRegion::kReverseDifference_Op: {
211            if (invertCoverage) {
212                static GrCoverageSetOpXPFactory gRevDiffCDXPFI(regionOp, invertCoverage);
213                return SkRef(&gRevDiffCDXPFI);
214            } else {
215                static GrCoverageSetOpXPFactory gRevDiffCDXPF(regionOp, invertCoverage);
216                return SkRef(&gRevDiffCDXPF);
217            }
218            break;
219        }
220        default:
221            return NULL;
222    }
223}
224
225GrXferProcessor*
226GrCoverageSetOpXPFactory::onCreateXferProcessor(const GrDrawTargetCaps& caps,
227                                                const GrProcOptInfo& colorPOI,
228                                                const GrProcOptInfo& covPOI,
229                                                const GrDeviceCoordTexture* dstCopy) const {
230    return CoverageSetOpXP::Create(fRegionOp, fInvertCoverage);
231}
232
233void GrCoverageSetOpXPFactory::getInvariantOutput(const GrProcOptInfo& colorPOI,
234                                                  const GrProcOptInfo& coveragePOI,
235                                                  GrXPFactory::InvariantOutput* output) const {
236    if (SkRegion::kReplace_Op == fRegionOp) {
237        if (coveragePOI.isSolidWhite()) {
238            output->fBlendedColor = GrColor_WHITE;
239            output->fBlendedColorFlags = kRGBA_GrColorComponentFlags;
240        } else {
241            output->fBlendedColorFlags = 0;
242        }
243
244        output->fWillBlendWithDst = false;
245    } else {
246        output->fBlendedColorFlags = 0;
247        output->fWillBlendWithDst = true;
248    }
249}
250
251GR_DEFINE_XP_FACTORY_TEST(GrCoverageSetOpXPFactory);
252
253GrXPFactory* GrCoverageSetOpXPFactory::TestCreate(SkRandom* random,
254                                                  GrContext*,
255                                                  const GrDrawTargetCaps&,
256                                                  GrTexture*[]) {
257    SkRegion::Op regionOp = SkRegion::Op(random->nextULessThan(SkRegion::kLastOp + 1));
258    bool invertCoverage = random->nextBool();
259    return GrCoverageSetOpXPFactory::Create(regionOp, invertCoverage);
260}
261
262