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