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