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/GrCaps.h" |
9 | #include "src/gpu/GrColor.h" |
10 | #include "src/gpu/GrPipeline.h" |
11 | #include "src/gpu/GrProcessor.h" |
12 | #include "src/gpu/GrRenderTargetContext.h" |
13 | #include "src/gpu/effects/GrCoverageSetOpXP.h" |
14 | #include "src/gpu/glsl/GrGLSLBlend.h" |
15 | #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" |
16 | #include "src/gpu/glsl/GrGLSLUniformHandler.h" |
17 | #include "src/gpu/glsl/GrGLSLXferProcessor.h" |
18 | |
19 | class CoverageSetOpXP : public GrXferProcessor { |
20 | public: |
21 | CoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage) |
22 | : INHERITED(kCoverageSetOpXP_ClassID) |
23 | , fRegionOp(regionOp) |
24 | , fInvertCoverage(invertCoverage) {} |
25 | |
26 | const char* name() const override { return "Coverage Set Op" ; } |
27 | |
28 | GrGLSLXferProcessor* createGLSLInstance() const override; |
29 | |
30 | bool invertCoverage() const { return fInvertCoverage; } |
31 | |
32 | private: |
33 | |
34 | void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override; |
35 | |
36 | void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override; |
37 | |
38 | bool onIsEqual(const GrXferProcessor& xpBase) const override { |
39 | const CoverageSetOpXP& xp = xpBase.cast<CoverageSetOpXP>(); |
40 | return (fRegionOp == xp.fRegionOp && |
41 | fInvertCoverage == xp.fInvertCoverage); |
42 | } |
43 | |
44 | SkRegion::Op fRegionOp; |
45 | bool fInvertCoverage; |
46 | |
47 | typedef GrXferProcessor INHERITED; |
48 | }; |
49 | |
50 | /////////////////////////////////////////////////////////////////////////////// |
51 | |
52 | class GLCoverageSetOpXP : public GrGLSLXferProcessor { |
53 | public: |
54 | GLCoverageSetOpXP(const GrProcessor&) {} |
55 | |
56 | ~GLCoverageSetOpXP() override {} |
57 | |
58 | static void GenKey(const GrProcessor& processor, const GrShaderCaps& caps, |
59 | GrProcessorKeyBuilder* b) { |
60 | const CoverageSetOpXP& xp = processor.cast<CoverageSetOpXP>(); |
61 | uint32_t key = xp.invertCoverage() ? 0x0 : 0x1; |
62 | b->add32(key); |
63 | } |
64 | |
65 | private: |
66 | void emitOutputsForBlendState(const EmitArgs& args) override { |
67 | const CoverageSetOpXP& xp = args.fXP.cast<CoverageSetOpXP>(); |
68 | GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder; |
69 | |
70 | if (xp.invertCoverage()) { |
71 | fragBuilder->codeAppendf("%s = 1.0 - %s;" , args.fOutputPrimary, args.fInputCoverage); |
72 | } else { |
73 | fragBuilder->codeAppendf("%s = %s;" , args.fOutputPrimary, args.fInputCoverage); |
74 | } |
75 | } |
76 | |
77 | void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {} |
78 | |
79 | typedef GrGLSLXferProcessor INHERITED; |
80 | }; |
81 | |
82 | /////////////////////////////////////////////////////////////////////////////// |
83 | |
84 | void CoverageSetOpXP::onGetGLSLProcessorKey(const GrShaderCaps& caps, |
85 | GrProcessorKeyBuilder* b) const { |
86 | GLCoverageSetOpXP::GenKey(*this, caps, b); |
87 | } |
88 | |
89 | GrGLSLXferProcessor* CoverageSetOpXP::createGLSLInstance() const { |
90 | return new GLCoverageSetOpXP(*this); |
91 | } |
92 | |
93 | void CoverageSetOpXP::onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const { |
94 | switch (fRegionOp) { |
95 | case SkRegion::kReplace_Op: |
96 | blendInfo->fSrcBlend = kOne_GrBlendCoeff; |
97 | blendInfo->fDstBlend = kZero_GrBlendCoeff; |
98 | break; |
99 | case SkRegion::kIntersect_Op: |
100 | blendInfo->fSrcBlend = kDC_GrBlendCoeff; |
101 | blendInfo->fDstBlend = kZero_GrBlendCoeff; |
102 | break; |
103 | case SkRegion::kUnion_Op: |
104 | blendInfo->fSrcBlend = kOne_GrBlendCoeff; |
105 | blendInfo->fDstBlend = kISC_GrBlendCoeff; |
106 | break; |
107 | case SkRegion::kXOR_Op: |
108 | blendInfo->fSrcBlend = kIDC_GrBlendCoeff; |
109 | blendInfo->fDstBlend = kISC_GrBlendCoeff; |
110 | break; |
111 | case SkRegion::kDifference_Op: |
112 | blendInfo->fSrcBlend = kZero_GrBlendCoeff; |
113 | blendInfo->fDstBlend = kISC_GrBlendCoeff; |
114 | break; |
115 | case SkRegion::kReverseDifference_Op: |
116 | blendInfo->fSrcBlend = kIDC_GrBlendCoeff; |
117 | blendInfo->fDstBlend = kZero_GrBlendCoeff; |
118 | break; |
119 | } |
120 | blendInfo->fBlendConstant = SK_PMColor4fTRANSPARENT; |
121 | } |
122 | |
123 | /////////////////////////////////////////////////////////////////////////////// |
124 | |
125 | constexpr GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp, |
126 | bool invertCoverage) |
127 | : fRegionOp(regionOp), fInvertCoverage(invertCoverage) {} |
128 | |
129 | const GrXPFactory* GrCoverageSetOpXPFactory::Get(SkRegion::Op regionOp, bool invertCoverage) { |
130 | // If these objects are constructed as static constexpr by cl.exe (2015 SP2) the vtables are |
131 | // null. |
132 | #ifdef SK_BUILD_FOR_WIN |
133 | #define _CONSTEXPR_ |
134 | #else |
135 | #define _CONSTEXPR_ constexpr |
136 | #endif |
137 | switch (regionOp) { |
138 | case SkRegion::kReplace_Op: { |
139 | if (invertCoverage) { |
140 | static _CONSTEXPR_ const GrCoverageSetOpXPFactory gReplaceCDXPFI( |
141 | SkRegion::kReplace_Op, true); |
142 | return &gReplaceCDXPFI; |
143 | } else { |
144 | static _CONSTEXPR_ const GrCoverageSetOpXPFactory gReplaceCDXPF( |
145 | SkRegion::kReplace_Op, false); |
146 | return &gReplaceCDXPF; |
147 | } |
148 | } |
149 | case SkRegion::kIntersect_Op: { |
150 | if (invertCoverage) { |
151 | static _CONSTEXPR_ const GrCoverageSetOpXPFactory gIntersectCDXPFI( |
152 | SkRegion::kIntersect_Op, true); |
153 | return &gIntersectCDXPFI; |
154 | } else { |
155 | static _CONSTEXPR_ const GrCoverageSetOpXPFactory gIntersectCDXPF( |
156 | SkRegion::kIntersect_Op, false); |
157 | return &gIntersectCDXPF; |
158 | } |
159 | } |
160 | case SkRegion::kUnion_Op: { |
161 | if (invertCoverage) { |
162 | static _CONSTEXPR_ const GrCoverageSetOpXPFactory gUnionCDXPFI(SkRegion::kUnion_Op, |
163 | true); |
164 | return &gUnionCDXPFI; |
165 | } else { |
166 | static _CONSTEXPR_ const GrCoverageSetOpXPFactory gUnionCDXPF(SkRegion::kUnion_Op, |
167 | false); |
168 | return &gUnionCDXPF; |
169 | } |
170 | } |
171 | case SkRegion::kXOR_Op: { |
172 | if (invertCoverage) { |
173 | static _CONSTEXPR_ const GrCoverageSetOpXPFactory gXORCDXPFI(SkRegion::kXOR_Op, |
174 | true); |
175 | return &gXORCDXPFI; |
176 | } else { |
177 | static _CONSTEXPR_ const GrCoverageSetOpXPFactory gXORCDXPF(SkRegion::kXOR_Op, |
178 | false); |
179 | return &gXORCDXPF; |
180 | } |
181 | } |
182 | case SkRegion::kDifference_Op: { |
183 | if (invertCoverage) { |
184 | static _CONSTEXPR_ const GrCoverageSetOpXPFactory gDifferenceCDXPFI( |
185 | SkRegion::kDifference_Op, true); |
186 | return &gDifferenceCDXPFI; |
187 | } else { |
188 | static _CONSTEXPR_ const GrCoverageSetOpXPFactory gDifferenceCDXPF( |
189 | SkRegion::kDifference_Op, false); |
190 | return &gDifferenceCDXPF; |
191 | } |
192 | } |
193 | case SkRegion::kReverseDifference_Op: { |
194 | if (invertCoverage) { |
195 | static _CONSTEXPR_ const GrCoverageSetOpXPFactory gRevDiffCDXPFI( |
196 | SkRegion::kReverseDifference_Op, true); |
197 | return &gRevDiffCDXPFI; |
198 | } else { |
199 | static _CONSTEXPR_ const GrCoverageSetOpXPFactory gRevDiffCDXPF( |
200 | SkRegion::kReverseDifference_Op, false); |
201 | return &gRevDiffCDXPF; |
202 | } |
203 | } |
204 | } |
205 | #undef _CONSTEXPR_ |
206 | SK_ABORT("Unknown region op." ); |
207 | } |
208 | |
209 | sk_sp<const GrXferProcessor> GrCoverageSetOpXPFactory::makeXferProcessor( |
210 | const GrProcessorAnalysisColor&, |
211 | GrProcessorAnalysisCoverage, |
212 | bool hasMixedSamples, |
213 | const GrCaps& caps, |
214 | GrClampType) const { |
215 | // We don't support inverting coverage with mixed samples. We don't expect to ever want this in |
216 | // the future, however we could at some point make this work using an inverted coverage |
217 | // modulation table. Note that an inverted table still won't work if there are coverage procs. |
218 | if (fInvertCoverage && hasMixedSamples) { |
219 | SkASSERT(false); |
220 | return nullptr; |
221 | } |
222 | |
223 | return sk_sp<GrXferProcessor>(new CoverageSetOpXP(fRegionOp, fInvertCoverage)); |
224 | } |
225 | |
226 | GR_DEFINE_XP_FACTORY_TEST(GrCoverageSetOpXPFactory); |
227 | |
228 | #if GR_TEST_UTILS |
229 | const GrXPFactory* GrCoverageSetOpXPFactory::TestGet(GrProcessorTestData* d) { |
230 | SkRegion::Op regionOp = SkRegion::Op(d->fRandom->nextULessThan(SkRegion::kLastOp + 1)); |
231 | bool invertCoverage = d->fRandom->nextBool(); |
232 | return GrCoverageSetOpXPFactory::Get(regionOp, invertCoverage); |
233 | } |
234 | #endif |
235 | |