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