1 /*
2  * Copyright 2014 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "src/gpu/effects/GrCoverageSetOpXP.h"
9 
10 #include "src/gpu/GrCaps.h"
11 #include "src/gpu/GrColor.h"
12 #include "src/gpu/GrPipeline.h"
13 #include "src/gpu/GrXferProcessor.h"
14 #include "src/gpu/glsl/GrGLSLBlend.h"
15 #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
16 #include "src/gpu/glsl/GrGLSLUniformHandler.h"
17 
18 class CoverageSetOpXP : public GrXferProcessor {
19 public:
CoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage)20     CoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage)
21             : INHERITED(kCoverageSetOpXP_ClassID)
22             , fRegionOp(regionOp)
23             , fInvertCoverage(invertCoverage) {}
24 
25     const char* name() const override { return "Coverage Set Op"; }
26 
27     SkString getShaderDfxInfo() const override;
28 
29     std::unique_ptr<ProgramImpl> makeProgramImpl() const override;
30 
31 private:
32     void onAddToKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
33 
34     void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override;
35 
36     bool onIsEqual(const GrXferProcessor& xpBase) const override {
37         const CoverageSetOpXP& xp = xpBase.cast<CoverageSetOpXP>();
38         return (fRegionOp == xp.fRegionOp &&
39                 fInvertCoverage == xp.fInvertCoverage);
40     }
41 
42     SkRegion::Op fRegionOp;
43     bool         fInvertCoverage;
44 
45     using INHERITED = GrXferProcessor;
46 };
47 
getShaderDfxInfo() const48 SkString CoverageSetOpXP::getShaderDfxInfo() const
49 {
50     SkString format;
51     format.printf("ShaderDfx_CoverageSetOpXP_%d", fInvertCoverage);
52     return format;
53 }
54 
onAddToKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const55 void CoverageSetOpXP::onAddToKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
56     b->addBool(fInvertCoverage, "invert coverage");
57 }
58 
makeProgramImpl() const59 std::unique_ptr<GrXferProcessor::ProgramImpl> CoverageSetOpXP::makeProgramImpl() const {
60     class Impl : public ProgramImpl {
61     private:
62         void emitOutputsForBlendState(const EmitArgs& args) override {
63             const CoverageSetOpXP& xp = args.fXP.cast<CoverageSetOpXP>();
64             GrGLSLXPFragmentBuilder* fb = args.fXPFragBuilder;
65             if (xp.fInvertCoverage) {
66                 fb->codeAppendf("%s = 1.0 - %s;", args.fOutputPrimary, args.fInputCoverage);
67             } else {
68                 fb->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputCoverage);
69             }
70         }
71     };
72     return std::make_unique<Impl>();
73 }
74 
onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const75 void CoverageSetOpXP::onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const {
76     switch (fRegionOp) {
77         case SkRegion::kReplace_Op:
78             blendInfo->fSrcBlend = kOne_GrBlendCoeff;
79             blendInfo->fDstBlend = kZero_GrBlendCoeff;
80             break;
81         case SkRegion::kIntersect_Op:
82             blendInfo->fSrcBlend = kDC_GrBlendCoeff;
83             blendInfo->fDstBlend = kZero_GrBlendCoeff;
84             break;
85         case SkRegion::kUnion_Op:
86             blendInfo->fSrcBlend = kOne_GrBlendCoeff;
87             blendInfo->fDstBlend = kISC_GrBlendCoeff;
88             break;
89         case SkRegion::kXOR_Op:
90             blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
91             blendInfo->fDstBlend = kISC_GrBlendCoeff;
92             break;
93         case SkRegion::kDifference_Op:
94             blendInfo->fSrcBlend = kZero_GrBlendCoeff;
95             blendInfo->fDstBlend = kISC_GrBlendCoeff;
96             break;
97         case SkRegion::kReverseDifference_Op:
98             blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
99             blendInfo->fDstBlend = kZero_GrBlendCoeff;
100             break;
101     }
102     blendInfo->fBlendConstant = SK_PMColor4fTRANSPARENT;
103 }
104 
105 ///////////////////////////////////////////////////////////////////////////////
106 
GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage)107 constexpr GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp,
108                                                              bool invertCoverage)
109         : fRegionOp(regionOp), fInvertCoverage(invertCoverage) {}
110 
Get(SkRegion::Op regionOp, bool invertCoverage)111 const GrXPFactory* GrCoverageSetOpXPFactory::Get(SkRegion::Op regionOp, bool invertCoverage) {
112     switch (regionOp) {
113         case SkRegion::kReplace_Op: {
114             if (invertCoverage) {
115                 static constexpr const GrCoverageSetOpXPFactory gReplaceCDXPFI(
116                         SkRegion::kReplace_Op, true);
117                 return &gReplaceCDXPFI;
118             } else {
119                 static constexpr const GrCoverageSetOpXPFactory gReplaceCDXPF(SkRegion::kReplace_Op,
120                                                                               false);
121                 return &gReplaceCDXPF;
122             }
123         }
124         case SkRegion::kIntersect_Op: {
125             if (invertCoverage) {
126                 static constexpr const GrCoverageSetOpXPFactory gIntersectCDXPFI(
127                         SkRegion::kIntersect_Op, true);
128                 return &gIntersectCDXPFI;
129             } else {
130                 static constexpr const GrCoverageSetOpXPFactory gIntersectCDXPF(
131                         SkRegion::kIntersect_Op, false);
132                 return &gIntersectCDXPF;
133             }
134         }
135         case SkRegion::kUnion_Op: {
136             if (invertCoverage) {
137                 static constexpr const GrCoverageSetOpXPFactory gUnionCDXPFI(SkRegion::kUnion_Op,
138                                                                              true);
139                 return &gUnionCDXPFI;
140             } else {
141                 static constexpr const GrCoverageSetOpXPFactory gUnionCDXPF(SkRegion::kUnion_Op,
142                                                                             false);
143                 return &gUnionCDXPF;
144             }
145         }
146         case SkRegion::kXOR_Op: {
147             if (invertCoverage) {
148                 static constexpr const GrCoverageSetOpXPFactory gXORCDXPFI(SkRegion::kXOR_Op, true);
149                 return &gXORCDXPFI;
150             } else {
151                 static constexpr const GrCoverageSetOpXPFactory gXORCDXPF(SkRegion::kXOR_Op, false);
152                 return &gXORCDXPF;
153             }
154         }
155         case SkRegion::kDifference_Op: {
156             if (invertCoverage) {
157                 static constexpr const GrCoverageSetOpXPFactory gDifferenceCDXPFI(
158                         SkRegion::kDifference_Op, true);
159                 return &gDifferenceCDXPFI;
160             } else {
161                 static constexpr const GrCoverageSetOpXPFactory gDifferenceCDXPF(
162                         SkRegion::kDifference_Op, false);
163                 return &gDifferenceCDXPF;
164             }
165         }
166         case SkRegion::kReverseDifference_Op: {
167             if (invertCoverage) {
168                 static constexpr const GrCoverageSetOpXPFactory gRevDiffCDXPFI(
169                         SkRegion::kReverseDifference_Op, true);
170                 return &gRevDiffCDXPFI;
171             } else {
172                 static constexpr const GrCoverageSetOpXPFactory gRevDiffCDXPF(
173                         SkRegion::kReverseDifference_Op, false);
174                 return &gRevDiffCDXPF;
175             }
176         }
177     }
178     SK_ABORT("Unknown region op.");
179 }
180 
makeXferProcessor( const GrProcessorAnalysisColor&, GrProcessorAnalysisCoverage, const GrCaps& caps, GrClampType) const181 sk_sp<const GrXferProcessor> GrCoverageSetOpXPFactory::makeXferProcessor(
182         const GrProcessorAnalysisColor&,
183         GrProcessorAnalysisCoverage,
184         const GrCaps& caps,
185         GrClampType) const {
186     return sk_sp<GrXferProcessor>(new CoverageSetOpXP(fRegionOp, fInvertCoverage));
187 }
188 
189 GR_DEFINE_XP_FACTORY_TEST(GrCoverageSetOpXPFactory);
190 
191 #if GR_TEST_UTILS
TestGet(GrProcessorTestData* d)192 const GrXPFactory* GrCoverageSetOpXPFactory::TestGet(GrProcessorTestData* d) {
193     SkRegion::Op regionOp = SkRegion::Op(d->fRandom->nextULessThan(SkRegion::kLastOp + 1));
194     bool invertCoverage = d->fRandom->nextBool();
195     return GrCoverageSetOpXPFactory::Get(regionOp, invertCoverage);
196 }
197 #endif
198