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