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