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