Line data Source code
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 "effects/GrCoverageSetOpXP.h"
9 : #include "GrCaps.h"
10 : #include "GrColor.h"
11 : #include "GrPipeline.h"
12 : #include "GrProcessor.h"
13 : #include "GrRenderTargetContext.h"
14 : #include "glsl/GrGLSLBlend.h"
15 : #include "glsl/GrGLSLFragmentShaderBuilder.h"
16 : #include "glsl/GrGLSLUniformHandler.h"
17 : #include "glsl/GrGLSLXferProcessor.h"
18 :
19 0 : class CoverageSetOpXP : public GrXferProcessor {
20 : public:
21 0 : CoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage)
22 0 : : fRegionOp(regionOp), fInvertCoverage(invertCoverage) {
23 0 : this->initClassID<CoverageSetOpXP>();
24 0 : }
25 :
26 0 : const char* name() const override { return "Coverage Set Op"; }
27 :
28 : GrGLSLXferProcessor* createGLSLInstance() const override;
29 :
30 0 : 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 0 : bool onIsEqual(const GrXferProcessor& xpBase) const override {
39 0 : const CoverageSetOpXP& xp = xpBase.cast<CoverageSetOpXP>();
40 0 : return (fRegionOp == xp.fRegionOp &&
41 0 : 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 0 : GLCoverageSetOpXP(const GrProcessor&) {}
55 :
56 0 : ~GLCoverageSetOpXP() override {}
57 :
58 0 : static void GenKey(const GrProcessor& processor, const GrShaderCaps& caps,
59 : GrProcessorKeyBuilder* b) {
60 0 : const CoverageSetOpXP& xp = processor.cast<CoverageSetOpXP>();
61 0 : uint32_t key = xp.invertCoverage() ? 0x0 : 0x1;
62 0 : b->add32(key);
63 0 : }
64 :
65 : private:
66 0 : void emitOutputsForBlendState(const EmitArgs& args) override {
67 0 : const CoverageSetOpXP& xp = args.fXP.cast<CoverageSetOpXP>();
68 0 : GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
69 :
70 0 : if (xp.invertCoverage()) {
71 0 : fragBuilder->codeAppendf("%s = 1.0 - %s;", args.fOutputPrimary, args.fInputCoverage);
72 : } else {
73 0 : fragBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputCoverage);
74 : }
75 0 : }
76 :
77 0 : void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
78 :
79 : typedef GrGLSLXferProcessor INHERITED;
80 : };
81 :
82 : ///////////////////////////////////////////////////////////////////////////////
83 :
84 0 : void CoverageSetOpXP::onGetGLSLProcessorKey(const GrShaderCaps& caps,
85 : GrProcessorKeyBuilder* b) const {
86 0 : GLCoverageSetOpXP::GenKey(*this, caps, b);
87 0 : }
88 :
89 0 : GrGLSLXferProcessor* CoverageSetOpXP::createGLSLInstance() const {
90 0 : return new GLCoverageSetOpXP(*this);
91 : }
92 :
93 0 : void CoverageSetOpXP::onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const {
94 0 : switch (fRegionOp) {
95 : case SkRegion::kReplace_Op:
96 0 : blendInfo->fSrcBlend = kOne_GrBlendCoeff;
97 0 : blendInfo->fDstBlend = kZero_GrBlendCoeff;
98 0 : break;
99 : case SkRegion::kIntersect_Op:
100 0 : blendInfo->fSrcBlend = kDC_GrBlendCoeff;
101 0 : blendInfo->fDstBlend = kZero_GrBlendCoeff;
102 0 : break;
103 : case SkRegion::kUnion_Op:
104 0 : blendInfo->fSrcBlend = kOne_GrBlendCoeff;
105 0 : blendInfo->fDstBlend = kISC_GrBlendCoeff;
106 0 : break;
107 : case SkRegion::kXOR_Op:
108 0 : blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
109 0 : blendInfo->fDstBlend = kISC_GrBlendCoeff;
110 0 : break;
111 : case SkRegion::kDifference_Op:
112 0 : blendInfo->fSrcBlend = kZero_GrBlendCoeff;
113 0 : blendInfo->fDstBlend = kISC_GrBlendCoeff;
114 0 : break;
115 : case SkRegion::kReverseDifference_Op:
116 0 : blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
117 0 : blendInfo->fDstBlend = kZero_GrBlendCoeff;
118 0 : break;
119 : }
120 0 : blendInfo->fBlendConstant = 0;
121 0 : }
122 :
123 : ///////////////////////////////////////////////////////////////////////////////
124 :
125 : constexpr GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp,
126 : bool invertCoverage)
127 : : fRegionOp(regionOp), fInvertCoverage(invertCoverage) {}
128 :
129 0 : 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 0 : switch (regionOp) {
138 : case SkRegion::kReplace_Op: {
139 0 : if (invertCoverage) {
140 : static _CONSTEXPR_ const GrCoverageSetOpXPFactory gReplaceCDXPFI(
141 : SkRegion::kReplace_Op, true);
142 0 : return &gReplaceCDXPFI;
143 : } else {
144 : static _CONSTEXPR_ const GrCoverageSetOpXPFactory gReplaceCDXPF(
145 : SkRegion::kReplace_Op, false);
146 0 : return &gReplaceCDXPF;
147 : }
148 : }
149 : case SkRegion::kIntersect_Op: {
150 0 : if (invertCoverage) {
151 : static _CONSTEXPR_ const GrCoverageSetOpXPFactory gIntersectCDXPFI(
152 : SkRegion::kIntersect_Op, true);
153 0 : return &gIntersectCDXPFI;
154 : } else {
155 : static _CONSTEXPR_ const GrCoverageSetOpXPFactory gIntersectCDXPF(
156 : SkRegion::kIntersect_Op, false);
157 0 : return &gIntersectCDXPF;
158 : }
159 : }
160 : case SkRegion::kUnion_Op: {
161 0 : if (invertCoverage) {
162 : static _CONSTEXPR_ const GrCoverageSetOpXPFactory gUnionCDXPFI(SkRegion::kUnion_Op,
163 : true);
164 0 : return &gUnionCDXPFI;
165 : } else {
166 : static _CONSTEXPR_ const GrCoverageSetOpXPFactory gUnionCDXPF(SkRegion::kUnion_Op,
167 : false);
168 0 : return &gUnionCDXPF;
169 : }
170 : }
171 : case SkRegion::kXOR_Op: {
172 0 : if (invertCoverage) {
173 : static _CONSTEXPR_ const GrCoverageSetOpXPFactory gXORCDXPFI(SkRegion::kXOR_Op,
174 : true);
175 0 : return &gXORCDXPFI;
176 : } else {
177 : static _CONSTEXPR_ const GrCoverageSetOpXPFactory gXORCDXPF(SkRegion::kXOR_Op,
178 : false);
179 0 : return &gXORCDXPF;
180 : }
181 : }
182 : case SkRegion::kDifference_Op: {
183 0 : if (invertCoverage) {
184 : static _CONSTEXPR_ const GrCoverageSetOpXPFactory gDifferenceCDXPFI(
185 : SkRegion::kDifference_Op, true);
186 0 : return &gDifferenceCDXPFI;
187 : } else {
188 : static _CONSTEXPR_ const GrCoverageSetOpXPFactory gDifferenceCDXPF(
189 : SkRegion::kDifference_Op, false);
190 0 : return &gDifferenceCDXPF;
191 : }
192 : }
193 : case SkRegion::kReverseDifference_Op: {
194 0 : if (invertCoverage) {
195 : static _CONSTEXPR_ const GrCoverageSetOpXPFactory gRevDiffCDXPFI(
196 : SkRegion::kReverseDifference_Op, true);
197 0 : return &gRevDiffCDXPFI;
198 : } else {
199 : static _CONSTEXPR_ const GrCoverageSetOpXPFactory gRevDiffCDXPF(
200 : SkRegion::kReverseDifference_Op, false);
201 0 : return &gRevDiffCDXPF;
202 : }
203 : }
204 : }
205 : #undef _CONSTEXPR_
206 0 : SkFAIL("Unknown region op.");
207 0 : return nullptr;
208 : }
209 :
210 0 : sk_sp<const GrXferProcessor> GrCoverageSetOpXPFactory::makeXferProcessor(
211 : const GrProcessorAnalysisColor&,
212 : GrProcessorAnalysisCoverage,
213 : bool hasMixedSamples,
214 : const GrCaps& caps) 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 0 : if (fInvertCoverage && hasMixedSamples) {
219 0 : SkASSERT(false);
220 0 : return nullptr;
221 : }
222 :
223 0 : return sk_sp<GrXferProcessor>(new CoverageSetOpXP(fRegionOp, fInvertCoverage));
224 : }
225 :
226 : GR_DEFINE_XP_FACTORY_TEST(GrCoverageSetOpXPFactory);
227 :
228 : #if GR_TEST_UTILS
229 0 : const GrXPFactory* GrCoverageSetOpXPFactory::TestGet(GrProcessorTestData* d) {
230 0 : SkRegion::Op regionOp = SkRegion::Op(d->fRandom->nextULessThan(SkRegion::kLastOp + 1));
231 0 : bool invertCoverage = !d->fRenderTargetContext->hasMixedSamples() && d->fRandom->nextBool();
232 0 : return GrCoverageSetOpXPFactory::Get(regionOp, invertCoverage);
233 : }
234 : #endif
|