• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/KeyBuilder.h"
15 #include "src/gpu/glsl/GrGLSLBlend.h"
16 #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
17 #include "src/gpu/glsl/GrGLSLUniformHandler.h"
18 
19 class CoverageSetOpXP : public GrXferProcessor {
20 public:
CoverageSetOpXP(SkRegion::Op regionOp,bool invertCoverage)21     CoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage)
22             : INHERITED(kCoverageSetOpXP_ClassID)
23             , fRegionOp(regionOp)
24             , fInvertCoverage(invertCoverage) {}
25 
name() const26     const char* name() const override { return "Coverage Set Op"; }
27 
28     std::unique_ptr<ProgramImpl> makeProgramImpl() const override;
29 
30 private:
31     void onAddToKey(const GrShaderCaps&, skgpu::KeyBuilder*) const override;
32 
33     void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override;
34 
onIsEqual(const GrXferProcessor & xpBase) const35     bool onIsEqual(const GrXferProcessor& xpBase) const override {
36         const CoverageSetOpXP& xp = xpBase.cast<CoverageSetOpXP>();
37         return (fRegionOp == xp.fRegionOp &&
38                 fInvertCoverage == xp.fInvertCoverage);
39     }
40 
41     SkRegion::Op fRegionOp;
42     bool         fInvertCoverage;
43 
44     using INHERITED = GrXferProcessor;
45 };
46 
onAddToKey(const GrShaderCaps & caps,skgpu::KeyBuilder * b) const47 void CoverageSetOpXP::onAddToKey(const GrShaderCaps& caps, skgpu::KeyBuilder* b) const {
48     b->addBool(fInvertCoverage, "invert coverage");
49 }
50 
makeProgramImpl() const51 std::unique_ptr<GrXferProcessor::ProgramImpl> CoverageSetOpXP::makeProgramImpl() const {
52     class Impl : public ProgramImpl {
53     private:
54         void emitOutputsForBlendState(const EmitArgs& args) override {
55             const CoverageSetOpXP& xp = args.fXP.cast<CoverageSetOpXP>();
56             GrGLSLXPFragmentBuilder* fb = args.fXPFragBuilder;
57             if (xp.fInvertCoverage) {
58                 fb->codeAppendf("%s = 1.0 - %s;", args.fOutputPrimary, args.fInputCoverage);
59             } else {
60                 fb->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputCoverage);
61             }
62         }
63     };
64     return std::make_unique<Impl>();
65 }
66 
onGetBlendInfo(GrXferProcessor::BlendInfo * blendInfo) const67 void CoverageSetOpXP::onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const {
68     switch (fRegionOp) {
69         case SkRegion::kReplace_Op:
70             blendInfo->fSrcBlend = kOne_GrBlendCoeff;
71             blendInfo->fDstBlend = kZero_GrBlendCoeff;
72             break;
73         case SkRegion::kIntersect_Op:
74             blendInfo->fSrcBlend = kDC_GrBlendCoeff;
75             blendInfo->fDstBlend = kZero_GrBlendCoeff;
76             break;
77         case SkRegion::kUnion_Op:
78             blendInfo->fSrcBlend = kOne_GrBlendCoeff;
79             blendInfo->fDstBlend = kISC_GrBlendCoeff;
80             break;
81         case SkRegion::kXOR_Op:
82             blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
83             blendInfo->fDstBlend = kISC_GrBlendCoeff;
84             break;
85         case SkRegion::kDifference_Op:
86             blendInfo->fSrcBlend = kZero_GrBlendCoeff;
87             blendInfo->fDstBlend = kISC_GrBlendCoeff;
88             break;
89         case SkRegion::kReverseDifference_Op:
90             blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
91             blendInfo->fDstBlend = kZero_GrBlendCoeff;
92             break;
93     }
94     blendInfo->fBlendConstant = SK_PMColor4fTRANSPARENT;
95 }
96 
97 ///////////////////////////////////////////////////////////////////////////////
98 
GrCoverageSetOpXPFactory(SkRegion::Op regionOp,bool invertCoverage)99 constexpr GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp,
100                                                              bool invertCoverage)
101         : fRegionOp(regionOp), fInvertCoverage(invertCoverage) {}
102 
Get(SkRegion::Op regionOp,bool invertCoverage)103 const GrXPFactory* GrCoverageSetOpXPFactory::Get(SkRegion::Op regionOp, bool invertCoverage) {
104     switch (regionOp) {
105         case SkRegion::kReplace_Op: {
106             if (invertCoverage) {
107                 static constexpr const GrCoverageSetOpXPFactory gReplaceCDXPFI(
108                         SkRegion::kReplace_Op, true);
109                 return &gReplaceCDXPFI;
110             } else {
111                 static constexpr const GrCoverageSetOpXPFactory gReplaceCDXPF(SkRegion::kReplace_Op,
112                                                                               false);
113                 return &gReplaceCDXPF;
114             }
115         }
116         case SkRegion::kIntersect_Op: {
117             if (invertCoverage) {
118                 static constexpr const GrCoverageSetOpXPFactory gIntersectCDXPFI(
119                         SkRegion::kIntersect_Op, true);
120                 return &gIntersectCDXPFI;
121             } else {
122                 static constexpr const GrCoverageSetOpXPFactory gIntersectCDXPF(
123                         SkRegion::kIntersect_Op, false);
124                 return &gIntersectCDXPF;
125             }
126         }
127         case SkRegion::kUnion_Op: {
128             if (invertCoverage) {
129                 static constexpr const GrCoverageSetOpXPFactory gUnionCDXPFI(SkRegion::kUnion_Op,
130                                                                              true);
131                 return &gUnionCDXPFI;
132             } else {
133                 static constexpr const GrCoverageSetOpXPFactory gUnionCDXPF(SkRegion::kUnion_Op,
134                                                                             false);
135                 return &gUnionCDXPF;
136             }
137         }
138         case SkRegion::kXOR_Op: {
139             if (invertCoverage) {
140                 static constexpr const GrCoverageSetOpXPFactory gXORCDXPFI(SkRegion::kXOR_Op, true);
141                 return &gXORCDXPFI;
142             } else {
143                 static constexpr const GrCoverageSetOpXPFactory gXORCDXPF(SkRegion::kXOR_Op, false);
144                 return &gXORCDXPF;
145             }
146         }
147         case SkRegion::kDifference_Op: {
148             if (invertCoverage) {
149                 static constexpr const GrCoverageSetOpXPFactory gDifferenceCDXPFI(
150                         SkRegion::kDifference_Op, true);
151                 return &gDifferenceCDXPFI;
152             } else {
153                 static constexpr const GrCoverageSetOpXPFactory gDifferenceCDXPF(
154                         SkRegion::kDifference_Op, false);
155                 return &gDifferenceCDXPF;
156             }
157         }
158         case SkRegion::kReverseDifference_Op: {
159             if (invertCoverage) {
160                 static constexpr const GrCoverageSetOpXPFactory gRevDiffCDXPFI(
161                         SkRegion::kReverseDifference_Op, true);
162                 return &gRevDiffCDXPFI;
163             } else {
164                 static constexpr const GrCoverageSetOpXPFactory gRevDiffCDXPF(
165                         SkRegion::kReverseDifference_Op, false);
166                 return &gRevDiffCDXPF;
167             }
168         }
169     }
170     SK_ABORT("Unknown region op.");
171 }
172 
makeXferProcessor(const GrProcessorAnalysisColor &,GrProcessorAnalysisCoverage,const GrCaps & caps,GrClampType) const173 sk_sp<const GrXferProcessor> GrCoverageSetOpXPFactory::makeXferProcessor(
174         const GrProcessorAnalysisColor&,
175         GrProcessorAnalysisCoverage,
176         const GrCaps& caps,
177         GrClampType) const {
178     return sk_sp<GrXferProcessor>(new CoverageSetOpXP(fRegionOp, fInvertCoverage));
179 }
180 
181 GR_DEFINE_XP_FACTORY_TEST(GrCoverageSetOpXPFactory);
182 
183 #if GR_TEST_UTILS
TestGet(GrProcessorTestData * d)184 const GrXPFactory* GrCoverageSetOpXPFactory::TestGet(GrProcessorTestData* d) {
185     SkRegion::Op regionOp = SkRegion::Op(d->fRandom->nextULessThan(SkRegion::kLastOp + 1));
186     bool invertCoverage = d->fRandom->nextBool();
187     return GrCoverageSetOpXPFactory::Get(regionOp, invertCoverage);
188 }
189 #endif
190